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