Fix the return status when physical presence variable and MemoryOverwriteRequestContr...
[mirror_edk2.git] / SecurityPkg / Library / DxeTrEEPhysicalPresenceLib / DxeTrEEPhysicalPresenceLib.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Execute pending TPM2 requests from OS or BIOS.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This driver will have external input - variable.\r
6 This external input must be validated carefully to avoid security issue.\r
7\r
8 TrEEExecutePendingTpmRequest() will receive untrusted input and do validation.\r
9\r
8a8c6c96 10Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>\r
c1d93242
JY
11This program and the accompanying materials \r
12are licensed and made available under the terms and conditions of the BSD License \r
13which accompanies this distribution. The full text of the license may be found at \r
14http://opensource.org/licenses/bsd-license.php\r
15\r
16THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
17WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
18\r
19**/\r
20\r
21#include <PiDxe.h>\r
22\r
23#include <Protocol/TrEEProtocol.h>\r
24#include <Protocol/VariableLock.h>\r
25#include <Library/DebugLib.h>\r
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/UefiRuntimeServicesTableLib.h>\r
28#include <Library/UefiDriverEntryPoint.h>\r
29#include <Library/UefiBootServicesTableLib.h>\r
30#include <Library/UefiLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
32#include <Library/PrintLib.h>\r
33#include <Library/HiiLib.h>\r
34#include <Guid/EventGroup.h>\r
35#include <Guid/TrEEPhysicalPresenceData.h>\r
36#include <Library/Tpm2CommandLib.h>\r
37\r
38#define TPM_PP_SUCCESS 0\r
39#define TPM_PP_USER_ABORT ((TPM_RESULT)(-0x10))\r
40#define TPM_PP_BIOS_FAILURE ((TPM_RESULT)(-0x0f))\r
41\r
42#define CONFIRM_BUFFER_SIZE 4096\r
43\r
44EFI_HII_HANDLE mTrEEPpStringPackHandle;\r
45\r
46/**\r
47 Get string by string id from HII Interface.\r
48\r
49 @param[in] Id String ID.\r
50\r
51 @retval CHAR16 * String from ID.\r
52 @retval NULL If error occurs.\r
53\r
54**/\r
55CHAR16 *\r
56TrEEPhysicalPresenceGetStringById (\r
57 IN EFI_STRING_ID Id\r
58 )\r
59{\r
60 return HiiGetString (mTrEEPpStringPackHandle, Id, NULL);\r
61}\r
62\r
63/**\r
64 Send ClearControl and Clear command to TPM.\r
65\r
66 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
67\r
68 @retval EFI_SUCCESS Operation completed successfully.\r
69 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
70 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
71 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
72\r
73**/\r
74EFI_STATUS\r
75EFIAPI\r
76TpmCommandClear (\r
77 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
78 )\r
79{\r
80 EFI_STATUS Status;\r
81 TPMS_AUTH_COMMAND *AuthSession;\r
82 TPMS_AUTH_COMMAND LocalAuthSession;\r
83\r
84 if (PlatformAuth == NULL) {\r
85 AuthSession = NULL;\r
86 } else {\r
87 AuthSession = &LocalAuthSession;\r
88 ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));\r
89 LocalAuthSession.sessionHandle = TPM_RS_PW;\r
90 LocalAuthSession.hmac.size = PlatformAuth->size;\r
91 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
92 }\r
93\r
94 DEBUG ((EFI_D_ERROR, "Tpm2ClearControl ... \n"));\r
95 Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);\r
96 DEBUG ((EFI_D_ERROR, "Tpm2ClearControl - %r\n", Status));\r
97 if (EFI_ERROR (Status)) {\r
98 goto Done;\r
99 }\r
100 DEBUG ((EFI_D_ERROR, "Tpm2Clear ... \n"));\r
101 Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);\r
102 DEBUG ((EFI_D_ERROR, "Tpm2Clear - %r\n", Status));\r
103\r
104Done:\r
105 ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));\r
106 return Status;\r
107}\r
108\r
109/**\r
110 Execute physical presence operation requested by the OS.\r
111\r
112 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
113 @param[in] CommandCode Physical presence operation value.\r
114 @param[in, out] PpiFlags The physical presence interface flags.\r
115 \r
116 @retval TPM_PP_BIOS_FAILURE Unknown physical presence operation.\r
117 @retval TPM_PP_BIOS_FAILURE Error occurred during sending command to TPM or \r
118 receiving response from TPM.\r
119 @retval Others Return code from the TPM device after command execution.\r
120**/\r
121TPM_RESULT\r
122TrEEExecutePhysicalPresence (\r
123 IN TPM2B_AUTH *PlatformAuth, OPTIONAL\r
124 IN UINT8 CommandCode,\r
125 IN OUT UINT8 *PpiFlags\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129\r
130 switch (CommandCode) {\r
131 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
132 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
133 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
134 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
135 Status = TpmCommandClear (PlatformAuth);\r
136 if (EFI_ERROR (Status)) {\r
137 return TPM_PP_BIOS_FAILURE;\r
138 } else {\r
139 return TPM_PP_SUCCESS;\r
140 }\r
141\r
142 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
143 *PpiFlags &= ~TREE_FLAG_NO_PPI_CLEAR;\r
144 return TPM_PP_SUCCESS;\r
145\r
146 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
147 *PpiFlags |= TREE_FLAG_NO_PPI_CLEAR;\r
148 return TPM_PP_SUCCESS;\r
149\r
150 default:\r
151 if (CommandCode <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
152 return TPM_PP_SUCCESS;\r
153 } else {\r
154 return TPM_PP_BIOS_FAILURE;\r
155 }\r
156 }\r
157}\r
158\r
159\r
160/**\r
161 Read the specified key for user confirmation.\r
162\r
163 @param[in] CautionKey If true, F12 is used as confirm key;\r
164 If false, F10 is used as confirm key.\r
165\r
166 @retval TRUE User confirmed the changes by input.\r
167 @retval FALSE User discarded the changes.\r
168**/\r
169BOOLEAN\r
170TrEEReadUserKey (\r
171 IN BOOLEAN CautionKey\r
172 )\r
173{\r
174 EFI_STATUS Status;\r
175 EFI_INPUT_KEY Key;\r
176 UINT16 InputKey;\r
177 \r
178 InputKey = 0; \r
179 do {\r
180 Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
181 if (!EFI_ERROR (Status)) {\r
182 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
183 if (Key.ScanCode == SCAN_ESC) {\r
184 InputKey = Key.ScanCode;\r
185 }\r
186 if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
187 InputKey = Key.ScanCode;\r
188 }\r
189 if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
190 InputKey = Key.ScanCode;\r
191 }\r
192 } \r
193 } while (InputKey == 0);\r
194\r
195 if (InputKey != SCAN_ESC) {\r
196 return TRUE;\r
197 }\r
198 \r
199 return FALSE;\r
200}\r
201\r
202/**\r
203 The constructor function register UNI strings into imageHandle.\r
204 \r
205 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
206\r
207 @param ImageHandle The firmware allocated handle for the EFI image.\r
208 @param SystemTable A pointer to the EFI System Table.\r
209 \r
210 @retval EFI_SUCCESS The constructor successfully added string package.\r
211 @retval Other value The constructor can't add string package.\r
212**/\r
213EFI_STATUS\r
214EFIAPI\r
215TrEEPhysicalPresenceLibConstructor (\r
216 IN EFI_HANDLE ImageHandle,\r
217 IN EFI_SYSTEM_TABLE *SystemTable\r
218 )\r
219{\r
220 mTrEEPpStringPackHandle = HiiAddPackages (&gEfiTrEEPhysicalPresenceGuid, ImageHandle, DxeTrEEPhysicalPresenceLibStrings, NULL);\r
221 ASSERT (mTrEEPpStringPackHandle != NULL);\r
222\r
223 return EFI_SUCCESS;\r
224}\r
225\r
226/**\r
227 Display the confirm text and get user confirmation.\r
228\r
229 @param[in] TpmPpCommand The requested TPM physical presence command.\r
230\r
231 @retval TRUE The user has confirmed the changes.\r
232 @retval FALSE The user doesn't confirm the changes.\r
233**/\r
234BOOLEAN\r
235TrEEUserConfirm (\r
236 IN UINT8 TpmPpCommand\r
237 )\r
238{\r
239 CHAR16 *ConfirmText;\r
240 CHAR16 *TmpStr1;\r
241 CHAR16 *TmpStr2; \r
242 UINTN BufSize;\r
243 BOOLEAN CautionKey;\r
244 UINT16 Index;\r
245 CHAR16 DstStr[81];\r
246 \r
247 TmpStr2 = NULL;\r
248 CautionKey = FALSE;\r
249 BufSize = CONFIRM_BUFFER_SIZE;\r
250 ConfirmText = AllocateZeroPool (BufSize);\r
251 ASSERT (ConfirmText != NULL);\r
252\r
253 switch (TpmPpCommand) {\r
254\r
255 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
256 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
257 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
258 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
259 CautionKey = TRUE;\r
260 TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
261\r
262 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
263 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
264 FreePool (TmpStr1);\r
265\r
266 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
267 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
268 StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
269 FreePool (TmpStr1); \r
270\r
271 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
272 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
273 FreePool (TmpStr1);\r
274 break;\r
275\r
276 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
277 CautionKey = TRUE;\r
278 TmpStr2 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
279\r
280 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));\r
281 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
282 FreePool (TmpStr1);\r
283\r
284 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));\r
285 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
286 FreePool (TmpStr1);\r
287\r
288 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
289 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
290 StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
291 FreePool (TmpStr1); \r
292\r
293 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
294 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
295 FreePool (TmpStr1);\r
296\r
297 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));\r
298 StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16 *)) - StrLen (ConfirmText) - 1);\r
299 FreePool (TmpStr1);\r
300 break;\r
301\r
302 default:\r
303 ;\r
304 }\r
305\r
306 if (TmpStr2 == NULL) {\r
307 FreePool (ConfirmText);\r
308 return FALSE;\r
309 }\r
310\r
311 TmpStr1 = TrEEPhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));\r
312 BufSize -= StrSize (ConfirmText);\r
313 UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);\r
314\r
315 DstStr[80] = L'\0';\r
316 for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {\r
317 StrnCpy(DstStr, ConfirmText + Index, 80); \r
318 Print (DstStr); \r
319 }\r
320 \r
321 FreePool (TmpStr1);\r
322 FreePool (TmpStr2);\r
323 FreePool (ConfirmText);\r
324\r
325 if (TrEEReadUserKey (CautionKey)) {\r
326 return TRUE;\r
327 }\r
328\r
329 return FALSE; \r
330}\r
331\r
332/**\r
333 Check if there is a valid physical presence command request. Also updates parameter value \r
334 to whether the requested physical presence command already confirmed by user\r
335 \r
336 @param[in] TcgPpData EFI TrEE Physical Presence request data. \r
337 @param[in] Flags The physical presence interface flags.\r
338 @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.\r
339 True, it indicates the command doesn't require user confirm, or already confirmed \r
340 in last boot cycle by user.\r
341 False, it indicates the command need user confirm from UI.\r
342\r
343 @retval TRUE Physical Presence operation command is valid.\r
344 @retval FALSE Physical Presence operation command is invalid.\r
345\r
346**/\r
347BOOLEAN\r
348TrEEHaveValidTpmRequest (\r
349 IN EFI_TREE_PHYSICAL_PRESENCE *TcgPpData,\r
350 IN UINT8 Flags,\r
351 OUT BOOLEAN *RequestConfirmed\r
352 )\r
353{\r
354 *RequestConfirmed = FALSE;\r
355\r
356 switch (TcgPpData->PPRequest) {\r
357 case TREE_PHYSICAL_PRESENCE_NO_ACTION:\r
358 *RequestConfirmed = TRUE;\r
359 return TRUE;\r
360 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
361 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
362 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
363 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
364 if ((Flags & TREE_FLAG_NO_PPI_CLEAR) != 0) {\r
365 *RequestConfirmed = TRUE;\r
366 }\r
367 break;\r
368\r
369 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
370 *RequestConfirmed = TRUE;\r
371 break;\r
372\r
373 case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
374 break;\r
375\r
376 default:\r
377 //\r
378 // Wrong Physical Presence command\r
379 //\r
380 return FALSE;\r
381 }\r
382\r
383 if ((Flags & TREE_FLAG_RESET_TRACK) != 0) {\r
384 //\r
385 // It had been confirmed in last boot, it doesn't need confirm again.\r
386 //\r
387 *RequestConfirmed = TRUE;\r
388 }\r
389\r
390 //\r
391 // Physical Presence command is correct\r
392 //\r
393 return TRUE;\r
394}\r
395\r
396\r
397/**\r
398 Check and execute the requested physical presence command.\r
399\r
400 Caution: This function may receive untrusted input.\r
401 TcgPpData variable is external input, so this function will validate\r
402 its data structure to be valid value.\r
403\r
404 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
405 @param[in] TcgPpData Point to the physical presence NV variable.\r
406 @param[in] Flags The physical presence interface flags.\r
407**/\r
408VOID\r
409TrEEExecutePendingTpmRequest (\r
410 IN TPM2B_AUTH *PlatformAuth, OPTIONAL\r
411 IN EFI_TREE_PHYSICAL_PRESENCE *TcgPpData,\r
412 IN UINT8 Flags\r
413 )\r
414{\r
415 EFI_STATUS Status;\r
416 UINTN DataSize;\r
417 BOOLEAN RequestConfirmed;\r
418 UINT8 NewFlags;\r
419\r
420 if (TcgPpData->PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
421 //\r
422 // No operation request\r
423 //\r
424 return;\r
425 }\r
426\r
427 if (!TrEEHaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {\r
428 //\r
429 // Invalid operation request.\r
430 //\r
431 if (TcgPpData->PPRequest <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
432 TcgPpData->PPResponse = TPM_PP_SUCCESS;\r
433 } else {\r
434 TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE;\r
435 }\r
436 TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
437 TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION;\r
438 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
439 Status = gRT->SetVariable (\r
440 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
441 &gEfiTrEEPhysicalPresenceGuid,\r
442 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
443 DataSize,\r
444 TcgPpData\r
445 );\r
446 return;\r
447 }\r
448\r
449 if (!RequestConfirmed) {\r
450 //\r
451 // Print confirm text and wait for approval. \r
452 //\r
453 RequestConfirmed = TrEEUserConfirm (TcgPpData->PPRequest\r
454 );\r
455 }\r
456\r
457 //\r
458 // Execute requested physical presence command\r
459 //\r
460 TcgPpData->PPResponse = TPM_PP_USER_ABORT;\r
461 NewFlags = Flags;\r
462 if (RequestConfirmed) {\r
463 TcgPpData->PPResponse = TrEEExecutePhysicalPresence (PlatformAuth, TcgPpData->PPRequest, \r
464 &NewFlags);\r
465 }\r
466\r
467 //\r
468 // Save the flags if it is updated.\r
469 //\r
470 if (Flags != NewFlags) {\r
471 Status = gRT->SetVariable (\r
472 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
473 &gEfiTrEEPhysicalPresenceGuid,\r
474 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
475 sizeof (UINT8),\r
476 &NewFlags\r
477 ); \r
478 }\r
479\r
480 //\r
481 // Clear request\r
482 //\r
483 if ((NewFlags & TREE_FLAG_RESET_TRACK) == 0) {\r
484 TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
485 TcgPpData->PPRequest = TREE_PHYSICAL_PRESENCE_NO_ACTION; \r
486 }\r
487\r
488 //\r
489 // Save changes\r
490 //\r
491 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
492 Status = gRT->SetVariable (\r
493 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
494 &gEfiTrEEPhysicalPresenceGuid,\r
495 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
496 DataSize,\r
497 TcgPpData\r
498 );\r
499 if (EFI_ERROR (Status)) {\r
500 return;\r
501 }\r
502\r
503 if (TcgPpData->PPResponse == TPM_PP_USER_ABORT) {\r
504 return;\r
505 }\r
506\r
507 //\r
508 // Reset system to make new TPM settings in effect\r
509 //\r
510 switch (TcgPpData->LastPPRequest) {\r
511 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:\r
512 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:\r
513 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:\r
514 case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:\r
515 break;\r
516 default:\r
517 if (TcgPpData->PPRequest != TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
518 break;\r
519 }\r
520 return;\r
521 }\r
522\r
523 Print (L"Rebooting system to make TPM2 settings in effect\n");\r
524 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
525 ASSERT (FALSE); \r
526}\r
527\r
528/**\r
529 Check and execute the pending TPM request.\r
530\r
531 The TPM request may come from OS or BIOS. This API will display request information and wait \r
532 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
533 the TPM request is confirmed, and one or more reset may be required to make TPM request to \r
534 take effect.\r
535 \r
536 This API should be invoked after console in and console out are all ready as they are required\r
537 to display request information and get user input to confirm the request. \r
538\r
539 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
540**/\r
541VOID\r
542EFIAPI\r
543TrEEPhysicalPresenceLibProcessRequest (\r
544 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
545 )\r
546{\r
547 EFI_STATUS Status;\r
548 UINTN DataSize;\r
549 EFI_TREE_PHYSICAL_PRESENCE TcgPpData;\r
550 EFI_TREE_PROTOCOL *TreeProtocol;\r
551 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;\r
552 UINT8 PpiFlags;\r
553\r
554 Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
555 if (EFI_ERROR (Status)) {\r
556 return ;\r
557 }\r
558\r
559 //\r
560 // Initialize physical presence flags.\r
561 //\r
562 DataSize = sizeof (UINT8);\r
563 Status = gRT->GetVariable (\r
564 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
565 &gEfiTrEEPhysicalPresenceGuid,\r
566 NULL,\r
567 &DataSize,\r
568 &PpiFlags\r
569 );\r
570 if (EFI_ERROR (Status)) {\r
8a8c6c96
DG
571 PpiFlags = 0;\r
572 Status = gRT->SetVariable (\r
573 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
574 &gEfiTrEEPhysicalPresenceGuid,\r
575 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
576 sizeof (UINT8),\r
577 &PpiFlags\r
578 );\r
579 if (EFI_ERROR (Status)) {\r
580 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));\r
581 return ;\r
c1d93242 582 }\r
c1d93242 583 }\r
8a8c6c96 584 DEBUG ((EFI_D_INFO, "[TPM2] PpiFlags = %x\n", PpiFlags));\r
c1d93242
JY
585\r
586 //\r
587 // This flags variable controls whether physical presence is required for TPM command. \r
588 // It should be protected from malicious software. We set it as read-only variable here.\r
589 //\r
590 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);\r
591 if (!EFI_ERROR (Status)) {\r
592 Status = VariableLockProtocol->RequestToLock (\r
593 VariableLockProtocol,\r
594 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
595 &gEfiTrEEPhysicalPresenceGuid\r
596 );\r
597 if (EFI_ERROR (Status)) {\r
598 DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));\r
599 ASSERT_EFI_ERROR (Status);\r
600 }\r
601 }\r
602 \r
603 //\r
604 // Initialize physical presence variable.\r
605 //\r
606 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
607 Status = gRT->GetVariable (\r
608 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
609 &gEfiTrEEPhysicalPresenceGuid,\r
610 NULL,\r
611 &DataSize,\r
612 &TcgPpData\r
613 );\r
614 if (EFI_ERROR (Status)) {\r
8a8c6c96
DG
615 ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));\r
616 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
617 Status = gRT->SetVariable (\r
618 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
619 &gEfiTrEEPhysicalPresenceGuid,\r
620 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
621 DataSize,\r
622 &TcgPpData\r
623 );\r
624 if (EFI_ERROR (Status)) {\r
625 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));\r
626 return ;\r
c1d93242 627 }\r
c1d93242
JY
628 }\r
629\r
8a8c6c96 630 DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));\r
c1d93242
JY
631\r
632 //\r
633 // Execute pending TPM request.\r
634 // \r
635 TrEEExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags);\r
8a8c6c96 636 DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags));\r
c1d93242
JY
637\r
638}\r
639\r
640/**\r
641 Check if the pending TPM request needs user input to confirm.\r
642\r
643 The TPM request may come from OS. This API will check if TPM request exists and need user\r
644 input to confirmation.\r
645 \r
646 @retval TRUE TPM needs input to confirm user physical presence.\r
647 @retval FALSE TPM doesn't need input to confirm user physical presence.\r
648\r
649**/\r
650BOOLEAN\r
651EFIAPI\r
652TrEEPhysicalPresenceLibNeedUserConfirm(\r
653 VOID\r
654 )\r
655{\r
656 EFI_STATUS Status;\r
657 EFI_TREE_PHYSICAL_PRESENCE TcgPpData;\r
658 UINTN DataSize;\r
659 BOOLEAN RequestConfirmed;\r
660 EFI_TREE_PROTOCOL *TreeProtocol;\r
661 UINT8 PpiFlags;\r
662\r
663 Status = gBS->LocateProtocol (&gEfiTrEEProtocolGuid, NULL, (VOID **) &TreeProtocol);\r
664 if (EFI_ERROR (Status)) {\r
665 return FALSE;\r
666 }\r
667\r
668 //\r
669 // Check Tpm requests\r
670 //\r
671 DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);\r
672 Status = gRT->GetVariable (\r
673 TREE_PHYSICAL_PRESENCE_VARIABLE,\r
674 &gEfiTrEEPhysicalPresenceGuid,\r
675 NULL,\r
676 &DataSize,\r
677 &TcgPpData\r
678 );\r
679 if (EFI_ERROR (Status)) {\r
680 return FALSE;\r
681 }\r
682\r
683 DataSize = sizeof (UINT8);\r
684 Status = gRT->GetVariable (\r
685 TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,\r
686 &gEfiTrEEPhysicalPresenceGuid,\r
687 NULL,\r
688 &DataSize,\r
689 &PpiFlags\r
690 );\r
691 if (EFI_ERROR (Status)) {\r
692 return FALSE;\r
693 }\r
694 \r
695 if (TcgPpData.PPRequest == TREE_PHYSICAL_PRESENCE_NO_ACTION) {\r
696 //\r
697 // No operation request\r
698 //\r
699 return FALSE;\r
700 }\r
701\r
702 if (!TrEEHaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {\r
703 //\r
704 // Invalid operation request.\r
705 //\r
706 return FALSE;\r
707 }\r
708\r
709 if (!RequestConfirmed) {\r
710 //\r
711 // Need UI to confirm\r
712 //\r
713 return TRUE;\r
714 }\r
715\r
716 return FALSE;\r
717}\r
718\r