2 Execute pending TPM2 requests from OS or BIOS.
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.
8 Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
10 Copyright (c) 2013 - 2016, 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
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.
23 #include <Protocol/Tcg2Protocol.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 <Library/HobLib.h>
35 #include <Guid/EventGroup.h>
36 #include <Guid/Tcg2PhysicalPresenceData.h>
37 #include <Library/Tpm2CommandLib.h>
38 #include <Library/Tcg2PhysicalPresenceLib.h>
39 #include <Library/Tcg2PpVendorLib.h>
40 #include <Library/TcgPhysicalPresenceStorageLib.h>
42 #define CONFIRM_BUFFER_SIZE 4096
44 EFI_HII_HANDLE mTcg2PpStringPackHandle
;
47 Get string by string id from HII Interface.
49 @param[in] Id String ID.
51 @retval CHAR16 * String from ID.
52 @retval NULL If error occurs.
56 Tcg2PhysicalPresenceGetStringById (
60 return HiiGetString (mTcg2PpStringPackHandle
, Id
, NULL
);
64 Send ClearControl and Clear command to TPM.
66 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
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.
77 IN TPM2B_AUTH
*PlatformAuth OPTIONAL
81 TPMS_AUTH_COMMAND
*AuthSession
;
82 TPMS_AUTH_COMMAND LocalAuthSession
;
84 if (PlatformAuth
== NULL
) {
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
);
94 DEBUG ((EFI_D_INFO
, "Tpm2ClearControl ... \n"));
95 Status
= Tpm2ClearControl (TPM_RH_PLATFORM
, AuthSession
, NO
);
96 DEBUG ((EFI_D_INFO
, "Tpm2ClearControl - %r\n", Status
));
97 if (EFI_ERROR (Status
)) {
100 DEBUG ((EFI_D_INFO
, "Tpm2Clear ... \n"));
101 Status
= Tpm2Clear (TPM_RH_PLATFORM
, AuthSession
);
102 DEBUG ((EFI_D_INFO
, "Tpm2Clear - %r\n", Status
));
105 ZeroMem (&LocalAuthSession
.hmac
, sizeof(LocalAuthSession
.hmac
));
112 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
114 @retval EFI_SUCCESS Operation completed successfully.
117 Tpm2CommandChangeEps (
118 IN TPM2B_AUTH
*PlatformAuth OPTIONAL
122 TPMS_AUTH_COMMAND
*AuthSession
;
123 TPMS_AUTH_COMMAND LocalAuthSession
;
125 if (PlatformAuth
== NULL
) {
128 AuthSession
= &LocalAuthSession
;
129 ZeroMem (&LocalAuthSession
, sizeof(LocalAuthSession
));
130 LocalAuthSession
.sessionHandle
= TPM_RS_PW
;
131 LocalAuthSession
.hmac
.size
= PlatformAuth
->size
;
132 CopyMem (LocalAuthSession
.hmac
.buffer
, PlatformAuth
->buffer
, PlatformAuth
->size
);
135 Status
= Tpm2ChangeEPS (TPM_RH_PLATFORM
, AuthSession
);
136 DEBUG ((EFI_D_INFO
, "Tpm2ChangeEPS - %r\n", Status
));
138 ZeroMem(&LocalAuthSession
.hmac
, sizeof(LocalAuthSession
.hmac
));
143 Execute physical presence operation requested by the OS.
145 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
146 @param[in] CommandCode Physical presence operation value.
147 @param[in] CommandParameter Physical presence operation parameter.
148 @param[in, out] PpiFlags The physical presence interface flags.
150 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation.
151 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or
152 receiving response from TPM.
153 @retval Others Return code from the TPM device after command execution.
156 Tcg2ExecutePhysicalPresence (
157 IN TPM2B_AUTH
*PlatformAuth
, OPTIONAL
158 IN UINT32 CommandCode
,
159 IN UINT32 CommandParameter
,
160 IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
*PpiFlags
164 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap
;
165 UINT32 ActivePcrBanks
;
167 Status
= Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap
, &ActivePcrBanks
);
168 ASSERT_EFI_ERROR (Status
);
170 switch (CommandCode
) {
171 case TCG2_PHYSICAL_PRESENCE_CLEAR
:
172 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR
:
173 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2
:
174 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3
:
175 Status
= Tpm2CommandClear (PlatformAuth
);
176 if (EFI_ERROR (Status
)) {
177 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
179 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
182 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE
:
183 PpiFlags
->PPFlags
|= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR
;
184 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
186 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE
:
187 PpiFlags
->PPFlags
&= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR
;
188 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
190 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS
:
191 Status
= Tpm2PcrAllocateBanks (PlatformAuth
, TpmHashAlgorithmBitmap
, CommandParameter
);
192 if (EFI_ERROR (Status
)) {
193 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
195 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
198 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS
:
199 Status
= Tpm2CommandChangeEps (PlatformAuth
);
200 if (EFI_ERROR (Status
)) {
201 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
203 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
206 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS
:
207 Status
= Tpm2PcrAllocateBanks (PlatformAuth
, TpmHashAlgorithmBitmap
, TpmHashAlgorithmBitmap
);
208 if (EFI_ERROR (Status
)) {
209 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
211 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
215 if (CommandCode
<= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX
) {
216 return TCG_PP_OPERATION_RESPONSE_SUCCESS
;
218 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
225 Read the specified key for user confirmation.
227 @param[in] CautionKey If true, F12 is used as confirm key;
228 If false, F10 is used as confirm key.
230 @retval TRUE User confirmed the changes by input.
231 @retval FALSE User discarded the changes.
235 IN BOOLEAN CautionKey
244 Status
= gBS
->CheckEvent (gST
->ConIn
->WaitForKey
);
245 if (!EFI_ERROR (Status
)) {
246 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
247 if (Key
.ScanCode
== SCAN_ESC
) {
248 InputKey
= Key
.ScanCode
;
250 if ((Key
.ScanCode
== SCAN_F10
) && !CautionKey
) {
251 InputKey
= Key
.ScanCode
;
253 if ((Key
.ScanCode
== SCAN_F12
) && CautionKey
) {
254 InputKey
= Key
.ScanCode
;
257 } while (InputKey
== 0);
259 if (InputKey
!= SCAN_ESC
) {
267 Fill Buffer With BootHashAlg.
269 @param[in] Buffer Buffer to be filled.
270 @param[in] BufferSize Size of buffer.
271 @param[in] BootHashAlg BootHashAlg.
275 Tcg2FillBufferWithBootHashAlg (
278 IN UINT32 BootHashAlg
282 if ((BootHashAlg
& EFI_TCG2_BOOT_HASH_ALG_SHA1
) != 0) {
283 if (Buffer
[0] != 0) {
284 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
", ", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
286 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
"SHA1", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
288 if ((BootHashAlg
& EFI_TCG2_BOOT_HASH_ALG_SHA256
) != 0) {
289 if (Buffer
[0] != 0) {
290 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
", ", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
292 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
"SHA256", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
294 if ((BootHashAlg
& EFI_TCG2_BOOT_HASH_ALG_SHA384
) != 0) {
295 if (Buffer
[0] != 0) {
296 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
", ", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
298 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
"SHA384", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
300 if ((BootHashAlg
& EFI_TCG2_BOOT_HASH_ALG_SHA512
) != 0) {
301 if (Buffer
[0] != 0) {
302 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
", ", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
304 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
"SHA512", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
306 if ((BootHashAlg
& EFI_TCG2_BOOT_HASH_ALG_SM3_256
) != 0) {
307 if (Buffer
[0] != 0) {
308 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
", ", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
310 StrnCatS (Buffer
, BufferSize
/ sizeof (CHAR16
), L
"SM3_256", (BufferSize
/ sizeof (CHAR16
)) - StrLen (Buffer
) - 1);
315 Display the confirm text and get user confirmation.
317 @param[in] TpmPpCommand The requested TPM physical presence command.
318 @param[in] TpmPpCommandParameter The requested TPM physical presence command parameter.
320 @retval TRUE The user has confirmed the changes.
321 @retval FALSE The user doesn't confirm the changes.
325 IN UINT32 TpmPpCommand
,
326 IN UINT32 TpmPpCommandParameter
337 CHAR16 TempBuffer
[1024];
338 CHAR16 TempBuffer2
[1024];
339 EFI_TCG2_PROTOCOL
*Tcg2Protocol
;
340 EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability
;
341 UINT32 CurrentPCRBanks
;
344 Status
= gBS
->LocateProtocol (&gEfiTcg2ProtocolGuid
, NULL
, (VOID
**) &Tcg2Protocol
);
345 ASSERT_EFI_ERROR (Status
);
347 ProtocolCapability
.Size
= sizeof(ProtocolCapability
);
348 Status
= Tcg2Protocol
->GetCapability (
352 ASSERT_EFI_ERROR (Status
);
354 Status
= Tcg2Protocol
->GetActivePcrBanks (
358 ASSERT_EFI_ERROR (Status
);
363 BufSize
= CONFIRM_BUFFER_SIZE
;
364 ConfirmText
= AllocateZeroPool (BufSize
);
365 ASSERT (ConfirmText
!= NULL
);
367 switch (TpmPpCommand
) {
369 case TCG2_PHYSICAL_PRESENCE_CLEAR
:
370 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR
:
371 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2
:
372 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3
:
374 TmpStr2
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR
));
376 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR
));
377 UnicodeSPrint (ConfirmText
, BufSize
, TmpStr1
, TmpStr2
);
380 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR
));
381 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
382 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), L
" \n\n", (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
387 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE
:
390 TmpStr2
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR
));
392 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR
));
393 UnicodeSPrint (ConfirmText
, BufSize
, TmpStr1
, TmpStr2
);
396 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR
));
397 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
400 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR
));
401 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
402 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), L
" \n\n", (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
407 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS
:
409 TmpStr2
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS
));
411 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR
));
412 UnicodeSPrint (ConfirmText
, BufSize
, TmpStr1
, TmpStr2
);
415 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1
));
416 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
419 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2
));
420 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
423 Tcg2FillBufferWithBootHashAlg (TempBuffer
, sizeof(TempBuffer
), TpmPpCommandParameter
);
424 Tcg2FillBufferWithBootHashAlg (TempBuffer2
, sizeof(TempBuffer2
), CurrentPCRBanks
);
426 TmpStr1
= AllocateZeroPool (BufSize
);
427 ASSERT (TmpStr1
!= NULL
);
428 UnicodeSPrint (TmpStr1
, BufSize
, L
"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks
, TempBuffer2
, TpmPpCommandParameter
, TempBuffer
);
430 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
431 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), L
" \n", (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
436 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS
:
438 TmpStr2
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS
));
440 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR
));
441 UnicodeSPrint (ConfirmText
, BufSize
, TmpStr1
, TmpStr2
);
444 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1
));
445 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
448 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2
));
449 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
459 if (TmpStr2
== NULL
) {
460 FreePool (ConfirmText
);
464 if (TpmPpCommand
< TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN
) {
466 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY
));
468 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY
));
470 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
474 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO
));
475 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
479 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY
));
482 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY
));
484 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY
));
486 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
490 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO
));
491 StrnCatS (ConfirmText
, BufSize
/ sizeof (CHAR16
), TmpStr1
, (BufSize
/ sizeof (CHAR16
)) - StrLen (ConfirmText
) - 1);
495 TmpStr1
= Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY
));
497 BufSize
-= StrSize (ConfirmText
);
498 UnicodeSPrint (ConfirmText
+ StrLen (ConfirmText
), BufSize
, TmpStr1
, TmpStr2
);
501 for (Index
= 0; Index
< StrLen (ConfirmText
); Index
+= 80) {
502 StrnCpyS (DstStr
, sizeof (DstStr
) / sizeof (CHAR16
), ConfirmText
+ Index
, sizeof (DstStr
) / sizeof (CHAR16
) - 1);
508 FreePool (ConfirmText
);
510 if (Tcg2ReadUserKey (CautionKey
)) {
518 Check if there is a valid physical presence command request. Also updates parameter value
519 to whether the requested physical presence command already confirmed by user
521 @param[in] TcgPpData EFI Tcg2 Physical Presence request data.
522 @param[in] Flags The physical presence interface flags.
523 @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.
524 True, it indicates the command doesn't require user confirm, or already confirmed
525 in last boot cycle by user.
526 False, it indicates the command need user confirm from UI.
528 @retval TRUE Physical Presence operation command is valid.
529 @retval FALSE Physical Presence operation command is invalid.
533 Tcg2HaveValidTpmRequest (
534 IN EFI_TCG2_PHYSICAL_PRESENCE
*TcgPpData
,
535 IN EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags
,
536 OUT BOOLEAN
*RequestConfirmed
539 BOOLEAN IsRequestValid
;
541 *RequestConfirmed
= FALSE
;
543 switch (TcgPpData
->PPRequest
) {
544 case TCG2_PHYSICAL_PRESENCE_NO_ACTION
:
545 *RequestConfirmed
= TRUE
;
548 case TCG2_PHYSICAL_PRESENCE_CLEAR
:
549 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR
:
550 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2
:
551 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3
:
552 if ((Flags
.PPFlags
& TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR
) == 0) {
553 *RequestConfirmed
= TRUE
;
557 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE
:
558 *RequestConfirmed
= TRUE
;
561 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE
:
564 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS
:
565 if ((Flags
.PPFlags
& TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS
) == 0) {
566 *RequestConfirmed
= TRUE
;
570 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS
:
571 if ((Flags
.PPFlags
& TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS
) == 0) {
572 *RequestConfirmed
= TRUE
;
576 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS
:
577 *RequestConfirmed
= TRUE
;
581 if (TcgPpData
->PPRequest
>= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION
) {
582 IsRequestValid
= Tcg2PpVendorLibHasValidRequest (TcgPpData
->PPRequest
, Flags
.PPFlags
, RequestConfirmed
);
583 if (!IsRequestValid
) {
590 // Wrong Physical Presence command
596 if ((Flags
.PPFlags
& TCG2_LIB_PP_FLAG_RESET_TRACK
) != 0) {
598 // It had been confirmed in last boot, it doesn't need confirm again.
600 *RequestConfirmed
= TRUE
;
604 // Physical Presence command is correct
611 Check and execute the requested physical presence command.
613 Caution: This function may receive untrusted input.
614 TcgPpData variable is external input, so this function will validate
615 its data structure to be valid value.
617 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
618 @param[in] TcgPpData Point to the physical presence NV variable.
619 @param[in] Flags The physical presence interface flags.
622 Tcg2ExecutePendingTpmRequest (
623 IN TPM2B_AUTH
*PlatformAuth
, OPTIONAL
624 IN EFI_TCG2_PHYSICAL_PRESENCE
*TcgPpData
,
625 IN EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags
630 BOOLEAN RequestConfirmed
;
631 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS NewFlags
;
632 BOOLEAN ResetRequired
;
635 if (TcgPpData
->PPRequest
== TCG2_PHYSICAL_PRESENCE_NO_ACTION
) {
637 // No operation request
642 if (!Tcg2HaveValidTpmRequest(TcgPpData
, Flags
, &RequestConfirmed
)) {
644 // Invalid operation request.
646 if (TcgPpData
->PPRequest
<= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX
) {
647 TcgPpData
->PPResponse
= TCG_PP_OPERATION_RESPONSE_SUCCESS
;
649 TcgPpData
->PPResponse
= TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE
;
651 TcgPpData
->LastPPRequest
= TcgPpData
->PPRequest
;
652 TcgPpData
->PPRequest
= TCG2_PHYSICAL_PRESENCE_NO_ACTION
;
653 TcgPpData
->PPRequestParameter
= 0;
655 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
656 Status
= gRT
->SetVariable (
657 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
658 &gEfiTcg2PhysicalPresenceGuid
,
659 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
666 ResetRequired
= FALSE
;
667 if (TcgPpData
->PPRequest
>= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION
) {
669 NewPPFlags
= NewFlags
.PPFlags
;
670 TcgPpData
->PPResponse
= Tcg2PpVendorLibExecutePendingRequest (PlatformAuth
, TcgPpData
->PPRequest
, &NewPPFlags
, &ResetRequired
);
671 NewFlags
.PPFlags
= NewPPFlags
;
673 if (!RequestConfirmed
) {
675 // Print confirm text and wait for approval.
677 RequestConfirmed
= Tcg2UserConfirm (TcgPpData
->PPRequest
, TcgPpData
->PPRequestParameter
);
681 // Execute requested physical presence command
683 TcgPpData
->PPResponse
= TCG_PP_OPERATION_RESPONSE_USER_ABORT
;
685 if (RequestConfirmed
) {
686 TcgPpData
->PPResponse
= Tcg2ExecutePhysicalPresence (
688 TcgPpData
->PPRequest
,
689 TcgPpData
->PPRequestParameter
,
696 // Save the flags if it is updated.
698 if (CompareMem (&Flags
, &NewFlags
, sizeof(EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
)) != 0) {
699 Status
= gRT
->SetVariable (
700 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
701 &gEfiTcg2PhysicalPresenceGuid
,
702 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
703 sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
),
711 if ((NewFlags
.PPFlags
& TCG2_LIB_PP_FLAG_RESET_TRACK
) == 0) {
712 TcgPpData
->LastPPRequest
= TcgPpData
->PPRequest
;
713 TcgPpData
->PPRequest
= TCG2_PHYSICAL_PRESENCE_NO_ACTION
;
714 TcgPpData
->PPRequestParameter
= 0;
720 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
721 Status
= gRT
->SetVariable (
722 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
723 &gEfiTcg2PhysicalPresenceGuid
,
724 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
728 if (EFI_ERROR (Status
)) {
732 if (TcgPpData
->PPResponse
== TCG_PP_OPERATION_RESPONSE_USER_ABORT
) {
737 // Reset system to make new TPM settings in effect
739 switch (TcgPpData
->LastPPRequest
) {
740 case TCG2_PHYSICAL_PRESENCE_CLEAR
:
741 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR
:
742 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2
:
743 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3
:
744 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS
:
745 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS
:
746 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS
:
750 if (TcgPpData
->LastPPRequest
>= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION
) {
757 if (TcgPpData
->PPRequest
!= TCG2_PHYSICAL_PRESENCE_NO_ACTION
) {
763 Print (L
"Rebooting system to make TPM2 settings in effect\n");
764 gRT
->ResetSystem (EfiResetCold
, EFI_SUCCESS
, 0, NULL
);
769 Check and execute the pending TPM request.
771 The TPM request may come from OS or BIOS. This API will display request information and wait
772 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
773 the TPM request is confirmed, and one or more reset may be required to make TPM request to
776 This API should be invoked after console in and console out are all ready as they are required
777 to display request information and get user input to confirm the request.
779 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
783 Tcg2PhysicalPresenceLibProcessRequest (
784 IN TPM2B_AUTH
*PlatformAuth OPTIONAL
789 EFI_TCG2_PHYSICAL_PRESENCE TcgPpData
;
790 EFI_TCG2_PROTOCOL
*Tcg2Protocol
;
791 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLockProtocol
;
792 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags
;
795 // Process the storage related action first.
797 TcgPhysicalPresenceStorageLibProcessRequest();
799 Status
= gBS
->LocateProtocol (&gEfiTcg2ProtocolGuid
, NULL
, (VOID
**) &Tcg2Protocol
);
800 if (EFI_ERROR (Status
)) {
807 if (GetBootModeHob () == BOOT_ON_S4_RESUME
) {
808 DEBUG ((EFI_D_INFO
, "S4 Resume, Skip TPM PP process!\n"));
812 mTcg2PpStringPackHandle
= HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid
, gImageHandle
, DxeTcg2PhysicalPresenceLibStrings
, NULL
);
813 ASSERT (mTcg2PpStringPackHandle
!= NULL
);
816 // Initialize physical presence flags.
818 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
);
819 Status
= gRT
->GetVariable (
820 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
821 &gEfiTcg2PhysicalPresenceGuid
,
826 if (EFI_ERROR (Status
)) {
827 PpiFlags
.PPFlags
= TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT
;
828 Status
= gRT
->SetVariable (
829 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
830 &gEfiTcg2PhysicalPresenceGuid
,
831 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
832 sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
),
835 if (EFI_ERROR (Status
)) {
836 DEBUG ((EFI_D_ERROR
, "[TPM2] Set physical presence flag failed, Status = %r\n", Status
));
840 DEBUG ((EFI_D_INFO
, "[TPM2] PpiFlags = %x\n", PpiFlags
.PPFlags
));
843 // This flags variable controls whether physical presence is required for TPM command.
844 // It should be protected from malicious software. We set it as read-only variable here.
846 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**)&VariableLockProtocol
);
847 if (!EFI_ERROR (Status
)) {
848 Status
= VariableLockProtocol
->RequestToLock (
849 VariableLockProtocol
,
850 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
851 &gEfiTcg2PhysicalPresenceGuid
853 if (EFI_ERROR (Status
)) {
854 DEBUG ((EFI_D_ERROR
, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
, Status
));
855 ASSERT_EFI_ERROR (Status
);
860 // Initialize physical presence variable.
862 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
863 Status
= gRT
->GetVariable (
864 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
865 &gEfiTcg2PhysicalPresenceGuid
,
870 if (EFI_ERROR (Status
)) {
871 ZeroMem ((VOID
*)&TcgPpData
, sizeof (TcgPpData
));
872 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
873 Status
= gRT
->SetVariable (
874 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
875 &gEfiTcg2PhysicalPresenceGuid
,
876 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
880 if (EFI_ERROR (Status
)) {
881 DEBUG ((EFI_D_ERROR
, "[TPM2] Set physical presence variable failed, Status = %r\n", Status
));
886 DEBUG ((EFI_D_INFO
, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags
.PPFlags
, TcgPpData
.PPRequest
, TcgPpData
.LastPPRequest
));
889 // Execute pending TPM request.
891 Tcg2ExecutePendingTpmRequest (PlatformAuth
, &TcgPpData
, PpiFlags
);
892 DEBUG ((EFI_D_INFO
, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData
.PPResponse
, TcgPpData
.LastPPRequest
, PpiFlags
.PPFlags
));
897 Check if the pending TPM request needs user input to confirm.
899 The TPM request may come from OS. This API will check if TPM request exists and need user
900 input to confirmation.
902 @retval TRUE TPM needs input to confirm user physical presence.
903 @retval FALSE TPM doesn't need input to confirm user physical presence.
908 Tcg2PhysicalPresenceLibNeedUserConfirm(
913 EFI_TCG2_PHYSICAL_PRESENCE TcgPpData
;
915 BOOLEAN RequestConfirmed
;
916 EFI_TCG2_PROTOCOL
*Tcg2Protocol
;
917 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags
;
920 // Process the storage related action first.
921 // If confirm need user confirm, just return TRUE.
922 // else continue check other actions.
924 if (TcgPhysicalPresenceStorageLibNeedUserConfirm()) {
928 Status
= gBS
->LocateProtocol (&gEfiTcg2ProtocolGuid
, NULL
, (VOID
**) &Tcg2Protocol
);
929 if (EFI_ERROR (Status
)) {
936 if (GetBootModeHob () == BOOT_ON_S4_RESUME
) {
937 DEBUG ((EFI_D_INFO
, "S4 Resume, Skip TPM PP process!\n"));
942 // Check Tpm requests
944 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
945 Status
= gRT
->GetVariable (
946 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
947 &gEfiTcg2PhysicalPresenceGuid
,
952 if (EFI_ERROR (Status
)) {
956 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
);
957 Status
= gRT
->GetVariable (
958 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
959 &gEfiTcg2PhysicalPresenceGuid
,
964 if (EFI_ERROR (Status
)) {
968 if (TcgPpData
.PPRequest
== TCG2_PHYSICAL_PRESENCE_NO_ACTION
) {
970 // No operation request
975 if (!Tcg2HaveValidTpmRequest(&TcgPpData
, PpiFlags
, &RequestConfirmed
)) {
977 // Invalid operation request.
982 if (!RequestConfirmed
) {
984 // Need UI to confirm
994 The handler for TPM physical presence function:
995 Return TPM Operation Response to OS Environment.
997 @param[out] MostRecentRequest Most recent operation request.
998 @param[out] Response Response to the most recent operation request.
1000 @return Return Code for Return TPM Operation Response to OS Environment.
1004 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
1005 OUT UINT32
*MostRecentRequest
,
1006 OUT UINT32
*Response
1011 EFI_TCG2_PHYSICAL_PRESENCE PpData
;
1013 DEBUG ((EFI_D_INFO
, "[TPM2] ReturnOperationResponseToOsFunction\n"));
1016 // Get the Physical Presence variable
1018 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
1019 Status
= gRT
->GetVariable (
1020 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
1021 &gEfiTcg2PhysicalPresenceGuid
,
1026 if (EFI_ERROR (Status
)) {
1027 *MostRecentRequest
= 0;
1029 DEBUG ((EFI_D_ERROR
, "[TPM2] Get PP variable failure! Status = %r\n", Status
));
1030 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE
;
1033 *MostRecentRequest
= PpData
.LastPPRequest
;
1034 *Response
= PpData
.PPResponse
;
1036 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS
;
1040 The handler for TPM physical presence function:
1041 Submit TPM Operation Request to Pre-OS Environment and
1042 Submit TPM Operation Request to Pre-OS Environment 2.
1044 Caution: This function may receive untrusted input.
1046 @param[in] OperationRequest TPM physical presence operation request.
1047 @param[in] RequestParameter TPM physical presence operation request parameter.
1049 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
1050 Submit TPM Operation Request to Pre-OS Environment 2.
1054 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
1055 IN UINT32 OperationRequest
,
1056 IN UINT32 RequestParameter
1061 EFI_TCG2_PHYSICAL_PRESENCE PpData
;
1062 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags
;
1064 DEBUG ((EFI_D_INFO
, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest
, RequestParameter
));
1067 // Get the Physical Presence variable
1069 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
1070 Status
= gRT
->GetVariable (
1071 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
1072 &gEfiTcg2PhysicalPresenceGuid
,
1077 if (EFI_ERROR (Status
)) {
1078 DEBUG ((EFI_D_ERROR
, "[TPM2] Get PP variable failure! Status = %r\n", Status
));
1079 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE
;
1082 if (((OperationRequest
> TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX
) &&
1083 (OperationRequest
< TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN
)) ||
1084 ((OperationRequest
> TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE
) &&
1085 (OperationRequest
< TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION
))) {
1087 // This command requires UI to prompt user for Auth data.
1089 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED
;
1092 if ((PpData
.PPRequest
!= OperationRequest
) ||
1093 (PpData
.PPRequestParameter
!= RequestParameter
)) {
1094 PpData
.PPRequest
= (UINT8
)OperationRequest
;
1095 PpData
.PPRequestParameter
= RequestParameter
;
1096 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE
);
1097 Status
= gRT
->SetVariable (
1098 TCG2_PHYSICAL_PRESENCE_VARIABLE
,
1099 &gEfiTcg2PhysicalPresenceGuid
,
1100 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
1106 if (EFI_ERROR (Status
)) {
1107 DEBUG ((EFI_D_ERROR
, "[TPM2] Set PP variable failure! Status = %r\n", Status
));
1108 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE
;
1111 if (OperationRequest
>= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION
) {
1112 DataSize
= sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS
);
1113 Status
= gRT
->GetVariable (
1114 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE
,
1115 &gEfiTcg2PhysicalPresenceGuid
,
1120 if (EFI_ERROR (Status
)) {
1121 Flags
.PPFlags
= TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT
;
1123 return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest
, Flags
.PPFlags
, RequestParameter
);
1126 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS
;