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