1 /** @file
2   Handle TPM 2.0 physical presence requests from OS.
3 
4   This library will handle TPM 2.0 physical presence request from OS.
5 
6   Caution: This module requires additional review when modified.
7   This driver will have external input - variable.
8   This external input must be validated carefully to avoid security issue.
9 
10   Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
11   will receive untrusted input and do validation.
12 
13 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution.  The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
18 
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 
22 **/
23 
24 #include <PiSmm.h>
25 
26 #include <Guid/Tcg2PhysicalPresenceData.h>
27 
28 #include <Protocol/SmmVariable.h>
29 
30 #include <Library/DebugLib.h>
31 #include <Library/Tcg2PpVendorLib.h>
32 #include <Library/SmmServicesTableLib.h>
33 
34 EFI_SMM_VARIABLE_PROTOCOL  *mTcg2PpSmmVariable;
35 
36 /**
37   The handler for TPM physical presence function:
38   Return TPM Operation Response to OS Environment.
39 
40   This API should be invoked in OS runtime phase to interface with ACPI method.
41 
42   @param[out]     MostRecentRequest Most recent operation request.
43   @param[out]     Response          Response to the most recent operation request.
44 
45   @return Return Code for Return TPM Operation Response to OS Environment.
46 **/
47 UINT32
48 EFIAPI
Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction(OUT UINT32 * MostRecentRequest,OUT UINT32 * Response)49 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
50   OUT UINT32                *MostRecentRequest,
51   OUT UINT32                *Response
52   )
53 {
54   EFI_STATUS                        Status;
55   UINTN                             DataSize;
56   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
57 
58   DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
59 
60   //
61   // Get the Physical Presence variable
62   //
63   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
64   Status = mTcg2PpSmmVariable->SmmGetVariable (
65                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
66                                  &gEfiTcg2PhysicalPresenceGuid,
67                                  NULL,
68                                  &DataSize,
69                                  &PpData
70                                  );
71   if (EFI_ERROR (Status)) {
72     *MostRecentRequest = 0;
73     *Response          = 0;
74     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
75     return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
76   }
77 
78   *MostRecentRequest = PpData.LastPPRequest;
79   *Response          = PpData.PPResponse;
80 
81   return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
82 }
83 
84 /**
85   The handler for TPM physical presence function:
86   Submit TPM Operation Request to Pre-OS Environment and
87   Submit TPM Operation Request to Pre-OS Environment 2.
88 
89   This API should be invoked in OS runtime phase to interface with ACPI method.
90 
91   Caution: This function may receive untrusted input.
92 
93   @param[in]      OperationRequest TPM physical presence operation request.
94   @param[in]      RequestParameter TPM physical presence operation request parameter.
95 
96   @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
97           Submit TPM Operation Request to Pre-OS Environment 2.
98 **/
99 UINT32
100 EFIAPI
Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction(IN UINT32 OperationRequest,IN UINT32 RequestParameter)101 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
102   IN UINT32                 OperationRequest,
103   IN UINT32                 RequestParameter
104   )
105 {
106   EFI_STATUS                        Status;
107   UINTN                             DataSize;
108   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
109   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
110 
111   DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
112 
113   //
114   // Get the Physical Presence variable
115   //
116   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
117   Status = mTcg2PpSmmVariable->SmmGetVariable (
118                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
119                                  &gEfiTcg2PhysicalPresenceGuid,
120                                  NULL,
121                                  &DataSize,
122                                  &PpData
123                                  );
124   if (EFI_ERROR (Status)) {
125     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
126     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
127   }
128 
129   if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
130       (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) ) {
131     //
132     // This command requires UI to prompt user for Auth data.
133     //
134     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
135   }
136 
137   if (PpData.PPRequest != OperationRequest) {
138     PpData.PPRequest = (UINT8)OperationRequest;
139     PpData.PPRequestParameter = RequestParameter;
140     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
141     Status = mTcg2PpSmmVariable->SmmSetVariable (
142                                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
143                                    &gEfiTcg2PhysicalPresenceGuid,
144                                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
145                                    DataSize,
146                                    &PpData
147                                    );
148   }
149 
150   if (EFI_ERROR (Status)) {
151     DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
152     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
153   }
154 
155   if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
156     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
157     Status = mTcg2PpSmmVariable->SmmGetVariable (
158                                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
159                                    &gEfiTcg2PhysicalPresenceGuid,
160                                    NULL,
161                                    &DataSize,
162                                    &Flags
163                                    );
164     if (EFI_ERROR (Status)) {
165       Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT;
166     }
167     return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
168   }
169 
170   return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
171 }
172 
173 /**
174   The handler for TPM physical presence function:
175   Get User Confirmation Status for Operation.
176 
177   This API should be invoked in OS runtime phase to interface with ACPI method.
178 
179   Caution: This function may receive untrusted input.
180 
181   @param[in]      OperationRequest TPM physical presence operation request.
182 
183   @return Return Code for Get User Confirmation Status for Operation.
184 **/
185 UINT32
186 EFIAPI
Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction(IN UINT32 OperationRequest)187 Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
188   IN UINT32                 OperationRequest
189   )
190 {
191   EFI_STATUS                        Status;
192   UINTN                             DataSize;
193   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
194   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
195   BOOLEAN                           RequestConfirmed;
196 
197   DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
198 
199   //
200   // Get the Physical Presence variable
201   //
202   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
203   Status = mTcg2PpSmmVariable->SmmGetVariable (
204                                  TCG2_PHYSICAL_PRESENCE_VARIABLE,
205                                  &gEfiTcg2PhysicalPresenceGuid,
206                                  NULL,
207                                  &DataSize,
208                                  &PpData
209                                  );
210   if (EFI_ERROR (Status)) {
211     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
212     return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
213   }
214   //
215   // Get the Physical Presence flags
216   //
217   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
218   Status = mTcg2PpSmmVariable->SmmGetVariable (
219                                  TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
220                                  &gEfiTcg2PhysicalPresenceGuid,
221                                  NULL,
222                                  &DataSize,
223                                  &Flags
224                                  );
225   if (EFI_ERROR (Status)) {
226     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
227     return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
228   }
229 
230   RequestConfirmed = FALSE;
231 
232   switch (OperationRequest) {
233     case TCG2_PHYSICAL_PRESENCE_CLEAR:
234     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
235     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
236     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
237       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
238         RequestConfirmed = TRUE;
239       }
240       break;
241 
242     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
243       RequestConfirmed = TRUE;
244       break;
245 
246     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
247       break;
248 
249     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
250       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
251         RequestConfirmed = TRUE;
252       }
253       break;
254 
255     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
256       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
257         RequestConfirmed = TRUE;
258       }
259       break;
260 
261     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
262       RequestConfirmed = TRUE;
263       break;
264 
265     default:
266       if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
267         RequestConfirmed = TRUE;
268       } else {
269         if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
270           return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
271         }
272       }
273       break;
274   }
275 
276   if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
277     return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
278   }
279 
280   if (RequestConfirmed) {
281     return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
282   } else {
283     return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
284   }
285 }
286 
287 /**
288   The constructor function register UNI strings into imageHandle.
289 
290   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
291 
292   @param  ImageHandle   The firmware allocated handle for the EFI image.
293   @param  SystemTable   A pointer to the EFI System Table.
294 
295   @retval EFI_SUCCESS   The constructor successfully added string package.
296   @retval Other value   The constructor can't add string package.
297 **/
298 EFI_STATUS
299 EFIAPI
Tcg2PhysicalPresenceLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)300 Tcg2PhysicalPresenceLibConstructor (
301   IN EFI_HANDLE        ImageHandle,
302   IN EFI_SYSTEM_TABLE  *SystemTable
303   )
304 {
305   EFI_STATUS  Status;
306 
307   //
308   // Locate SmmVariableProtocol.
309   //
310   Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
311   ASSERT_EFI_ERROR (Status);
312 
313   return EFI_SUCCESS;
314 }
315