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   Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
9 
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
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/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 
41 #define CONFIRM_BUFFER_SIZE         4096
42 
43 EFI_HII_HANDLE mTcg2PpStringPackHandle;
44 
45 /**
46   Get string by string id from HII Interface.
47 
48   @param[in] Id          String ID.
49 
50   @retval    CHAR16 *    String from ID.
51   @retval    NULL        If error occurs.
52 
53 **/
54 CHAR16 *
Tcg2PhysicalPresenceGetStringById(IN EFI_STRING_ID Id)55 Tcg2PhysicalPresenceGetStringById (
56   IN  EFI_STRING_ID   Id
57   )
58 {
59   return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);
60 }
61 
62 /**
63   Send ClearControl and Clear command to TPM.
64 
65   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
66 
67   @retval EFI_SUCCESS           Operation completed successfully.
68   @retval EFI_TIMEOUT           The register can't run into the expected status in time.
69   @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.
70   @retval EFI_DEVICE_ERROR      Unexpected device behavior.
71 
72 **/
73 EFI_STATUS
74 EFIAPI
Tpm2CommandClear(IN TPM2B_AUTH * PlatformAuth OPTIONAL)75 Tpm2CommandClear (
76   IN TPM2B_AUTH                *PlatformAuth  OPTIONAL
77   )
78 {
79   EFI_STATUS                Status;
80   TPMS_AUTH_COMMAND         *AuthSession;
81   TPMS_AUTH_COMMAND         LocalAuthSession;
82 
83   if (PlatformAuth == NULL) {
84     AuthSession = NULL;
85   } else {
86     AuthSession = &LocalAuthSession;
87     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
88     LocalAuthSession.sessionHandle = TPM_RS_PW;
89     LocalAuthSession.hmac.size = PlatformAuth->size;
90     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
91   }
92 
93   DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n"));
94   Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);
95   DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status));
96   if (EFI_ERROR (Status)) {
97     goto Done;
98   }
99   DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n"));
100   Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);
101   DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status));
102 
103 Done:
104   ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
105   return Status;
106 }
107 
108 /**
109   Change EPS.
110 
111   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
112 
113   @retval EFI_SUCCESS Operation completed successfully.
114 **/
115 EFI_STATUS
Tpm2CommandChangeEps(IN TPM2B_AUTH * PlatformAuth OPTIONAL)116 Tpm2CommandChangeEps (
117   IN TPM2B_AUTH                *PlatformAuth  OPTIONAL
118   )
119 {
120   EFI_STATUS                Status;
121   TPMS_AUTH_COMMAND         *AuthSession;
122   TPMS_AUTH_COMMAND         LocalAuthSession;
123 
124   if (PlatformAuth == NULL) {
125     AuthSession = NULL;
126   } else {
127     AuthSession = &LocalAuthSession;
128     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
129     LocalAuthSession.sessionHandle = TPM_RS_PW;
130     LocalAuthSession.hmac.size = PlatformAuth->size;
131     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
132   }
133 
134   Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);
135   DEBUG ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status));
136 
137   ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
138   return Status;
139 }
140 
141 /**
142   Execute physical presence operation requested by the OS.
143 
144   @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.
145   @param[in]      CommandCode         Physical presence operation value.
146   @param[in]      CommandParameter    Physical presence operation parameter.
147   @param[in, out] PpiFlags            The physical presence interface flags.
148 
149   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Unknown physical presence operation.
150   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Error occurred during sending command to TPM or
151                                                    receiving response from TPM.
152   @retval Others                                   Return code from the TPM device after command execution.
153 **/
154 UINT32
Tcg2ExecutePhysicalPresence(IN TPM2B_AUTH * PlatformAuth,OPTIONAL IN UINT32 CommandCode,IN UINT32 CommandParameter,IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS * PpiFlags)155 Tcg2ExecutePhysicalPresence (
156   IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL
157   IN      UINT32                           CommandCode,
158   IN      UINT32                           CommandParameter,
159   IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
160   )
161 {
162   EFI_STATUS                        Status;
163   EFI_TCG2_EVENT_ALGORITHM_BITMAP   TpmHashAlgorithmBitmap;
164   UINT32                            ActivePcrBanks;
165 
166   switch (CommandCode) {
167     case TCG2_PHYSICAL_PRESENCE_CLEAR:
168     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
169     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
170     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
171       Status = Tpm2CommandClear (PlatformAuth);
172       if (EFI_ERROR (Status)) {
173         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
174       } else {
175         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
176       }
177 
178     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
179       PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
180       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
181 
182     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
183       PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
184       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
185 
186     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
187       Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
188       ASSERT_EFI_ERROR (Status);
189       Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter);
190       if (EFI_ERROR (Status)) {
191         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
192       } else {
193         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
194       }
195 
196     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
197       Status = Tpm2CommandChangeEps (PlatformAuth);
198       if (EFI_ERROR (Status)) {
199         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
200       } else {
201         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
202       }
203 
204     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
205       Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
206       ASSERT_EFI_ERROR (Status);
207       Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap);
208       if (EFI_ERROR (Status)) {
209         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
210       } else {
211         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
212       }
213 
214     case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
215       PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
216       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
217 
218     case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
219       PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
220       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
221 
222     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
223       PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
224       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
225 
226     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
227       PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
228       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
229 
230     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
231       PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
232       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
233 
234     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
235       PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
236       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
237 
238     default:
239       if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
240         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
241       } else {
242         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
243       }
244   }
245 }
246 
247 
248 /**
249   Read the specified key for user confirmation.
250 
251   @param[in]  CautionKey  If true,  F12 is used as confirm key;
252                           If false, F10 is used as confirm key.
253 
254   @retval     TRUE        User confirmed the changes by input.
255   @retval     FALSE       User discarded the changes.
256 **/
257 BOOLEAN
Tcg2ReadUserKey(IN BOOLEAN CautionKey)258 Tcg2ReadUserKey (
259   IN     BOOLEAN                    CautionKey
260   )
261 {
262   EFI_STATUS                        Status;
263   EFI_INPUT_KEY                     Key;
264   UINT16                            InputKey;
265 
266   InputKey = 0;
267   do {
268     Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
269     if (!EFI_ERROR (Status)) {
270       Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
271       if (Key.ScanCode == SCAN_ESC) {
272         InputKey = Key.ScanCode;
273       }
274       if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
275         InputKey = Key.ScanCode;
276       }
277       if ((Key.ScanCode == SCAN_F12) && CautionKey) {
278         InputKey = Key.ScanCode;
279       }
280     }
281   } while (InputKey == 0);
282 
283   if (InputKey != SCAN_ESC) {
284     return TRUE;
285   }
286 
287   return FALSE;
288 }
289 
290 /**
291   Fill Buffer With BootHashAlg.
292 
293   @param[in] Buffer               Buffer to be filled.
294   @param[in] BufferSize           Size of buffer.
295   @param[in] BootHashAlg          BootHashAlg.
296 
297 **/
298 VOID
Tcg2FillBufferWithBootHashAlg(IN UINT16 * Buffer,IN UINTN BufferSize,IN UINT32 BootHashAlg)299 Tcg2FillBufferWithBootHashAlg (
300   IN UINT16  *Buffer,
301   IN UINTN   BufferSize,
302   IN UINT32  BootHashAlg
303   )
304 {
305   Buffer[0] = 0;
306   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
307     if (Buffer[0] != 0) {
308       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
309     }
310     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
311   }
312   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
313     if (Buffer[0] != 0) {
314       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
315     }
316     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
317   }
318   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
319     if (Buffer[0] != 0) {
320       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
321     }
322     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
323   }
324   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
325     if (Buffer[0] != 0) {
326       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
327     }
328     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
329   }
330   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
331     if (Buffer[0] != 0) {
332       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
333     }
334     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
335   }
336 }
337 
338 /**
339   Display the confirm text and get user confirmation.
340 
341   @param[in] TpmPpCommand             The requested TPM physical presence command.
342   @param[in] TpmPpCommandParameter    The requested TPM physical presence command parameter.
343 
344   @retval    TRUE          The user has confirmed the changes.
345   @retval    FALSE         The user doesn't confirm the changes.
346 **/
347 BOOLEAN
Tcg2UserConfirm(IN UINT32 TpmPpCommand,IN UINT32 TpmPpCommandParameter)348 Tcg2UserConfirm (
349   IN      UINT32                    TpmPpCommand,
350   IN      UINT32                    TpmPpCommandParameter
351   )
352 {
353   CHAR16                            *ConfirmText;
354   CHAR16                            *TmpStr1;
355   CHAR16                            *TmpStr2;
356   UINTN                             BufSize;
357   BOOLEAN                           CautionKey;
358   BOOLEAN                           NoPpiInfo;
359   UINT16                            Index;
360   CHAR16                            DstStr[81];
361   CHAR16                            TempBuffer[1024];
362   CHAR16                            TempBuffer2[1024];
363   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
364   EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;
365   UINT32                            CurrentPCRBanks;
366   EFI_STATUS                        Status;
367 
368   TmpStr2     = NULL;
369   CautionKey  = FALSE;
370   NoPpiInfo   = FALSE;
371   BufSize     = CONFIRM_BUFFER_SIZE;
372   ConfirmText = AllocateZeroPool (BufSize);
373   ASSERT (ConfirmText != NULL);
374 
375   mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);
376   ASSERT (mTcg2PpStringPackHandle != NULL);
377 
378   switch (TpmPpCommand) {
379 
380     case TCG2_PHYSICAL_PRESENCE_CLEAR:
381     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
382     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
383     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
384       CautionKey = TRUE;
385       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
386 
387       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
388       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
389       FreePool (TmpStr1);
390 
391       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
392       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
393       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
394       FreePool (TmpStr1);
395 
396       break;
397 
398     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
399       CautionKey = TRUE;
400       NoPpiInfo  = TRUE;
401       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
402 
403       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
404       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
405       FreePool (TmpStr1);
406 
407       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
408       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
409       FreePool (TmpStr1);
410 
411       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
412       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
413       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
414       FreePool (TmpStr1);
415 
416       break;
417 
418     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
419       Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
420       ASSERT_EFI_ERROR (Status);
421 
422       ProtocolCapability.Size = sizeof(ProtocolCapability);
423       Status = Tcg2Protocol->GetCapability (
424                                Tcg2Protocol,
425                                &ProtocolCapability
426                                );
427       ASSERT_EFI_ERROR (Status);
428 
429       Status = Tcg2Protocol->GetActivePcrBanks (
430                                Tcg2Protocol,
431                                &CurrentPCRBanks
432                                );
433       ASSERT_EFI_ERROR (Status);
434 
435       CautionKey = TRUE;
436       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));
437 
438       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
439       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
440       FreePool (TmpStr1);
441 
442       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));
443       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
444       FreePool (TmpStr1);
445 
446       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));
447       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
448       FreePool (TmpStr1);
449 
450       Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter);
451       Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks);
452 
453       TmpStr1 = AllocateZeroPool (BufSize);
454       ASSERT (TmpStr1 != NULL);
455       UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);
456 
457       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
458       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
459       FreePool (TmpStr1);
460 
461       break;
462 
463     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
464       CautionKey = TRUE;
465       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));
466 
467       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
468       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
469       FreePool (TmpStr1);
470 
471       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));
472       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
473       FreePool (TmpStr1);
474 
475       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));
476       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
477       FreePool (TmpStr1);
478 
479       break;
480 
481     case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
482       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID));
483 
484       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
485       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
486       FreePool (TmpStr1);
487       break;
488 
489     case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
490       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID));
491 
492       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
493       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
494       FreePool (TmpStr1);
495       break;
496 
497     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
498       NoPpiInfo  = TRUE;
499       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_ENABLE_BLOCK_SID));
500 
501       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
502       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
503       FreePool (TmpStr1);
504       break;
505 
506     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
507       NoPpiInfo  = TRUE;
508       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_DISABLE_BLOCK_SID));
509 
510       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
511       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
512       FreePool (TmpStr1);
513       break;
514 
515     default:
516       ;
517   }
518 
519   if (TmpStr2 == NULL) {
520     FreePool (ConfirmText);
521     return FALSE;
522   }
523 
524   if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {
525     if (CautionKey) {
526       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
527     } else {
528       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
529     }
530     StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
531     FreePool (TmpStr1);
532 
533     if (NoPpiInfo) {
534       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
535       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
536       FreePool (TmpStr1);
537     }
538 
539     TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
540   } else {
541     if (CautionKey) {
542       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));
543     } else {
544       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));
545     }
546     StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
547     FreePool (TmpStr1);
548 
549     if (NoPpiInfo) {
550       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));
551       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
552       FreePool (TmpStr1);
553     }
554 
555     TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));
556   }
557   BufSize -= StrSize (ConfirmText);
558   UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
559 
560   DstStr[80] = L'\0';
561   for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
562     StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);
563     Print (DstStr);
564   }
565 
566   FreePool (TmpStr1);
567   FreePool (TmpStr2);
568   FreePool (ConfirmText);
569   HiiRemovePackages (mTcg2PpStringPackHandle);
570 
571   if (Tcg2ReadUserKey (CautionKey)) {
572     return TRUE;
573   }
574 
575   return FALSE;
576 }
577 
578 /**
579   Check if there is a valid physical presence command request. Also updates parameter value
580   to whether the requested physical presence command already confirmed by user
581 
582    @param[in]  TcgPpData                 EFI Tcg2 Physical Presence request data.
583    @param[in]  Flags                     The physical presence interface flags.
584    @param[out] RequestConfirmed          If the physical presence operation command required user confirm from UI.
585                                            True, it indicates the command doesn't require user confirm, or already confirmed
586                                                  in last boot cycle by user.
587                                            False, it indicates the command need user confirm from UI.
588 
589    @retval  TRUE        Physical Presence operation command is valid.
590    @retval  FALSE       Physical Presence operation command is invalid.
591 
592 **/
593 BOOLEAN
Tcg2HaveValidTpmRequest(IN EFI_TCG2_PHYSICAL_PRESENCE * TcgPpData,IN EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags,OUT BOOLEAN * RequestConfirmed)594 Tcg2HaveValidTpmRequest  (
595   IN      EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
596   IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags,
597   OUT     BOOLEAN                          *RequestConfirmed
598   )
599 {
600   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
601   EFI_STATUS                        Status;
602   BOOLEAN                           IsRequestValid;
603 
604   *RequestConfirmed = FALSE;
605 
606   if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
607     //
608     // Need TCG2 protocol.
609     //
610     Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
611     if (EFI_ERROR (Status)) {
612       return FALSE;
613     }
614   }
615 
616   switch (TcgPpData->PPRequest) {
617     case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
618       *RequestConfirmed = TRUE;
619       return TRUE;
620 
621     case TCG2_PHYSICAL_PRESENCE_CLEAR:
622     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
623     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
624     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
625       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
626         *RequestConfirmed = TRUE;
627       }
628       break;
629 
630     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
631       *RequestConfirmed = TRUE;
632       break;
633 
634     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
635       break;
636 
637     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
638       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
639         *RequestConfirmed = TRUE;
640       }
641       break;
642 
643     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
644       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
645         *RequestConfirmed = TRUE;
646       }
647       break;
648 
649     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
650       *RequestConfirmed = TRUE;
651       break;
652 
653     case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
654       if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
655         *RequestConfirmed = TRUE;
656       }
657       break;
658 
659     case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
660       if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
661         *RequestConfirmed = TRUE;
662       }
663       break;
664 
665     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
666     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
667       *RequestConfirmed = TRUE;
668       break;
669 
670     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
671     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
672       break;
673 
674     default:
675       if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
676         IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
677         if (!IsRequestValid) {
678           return FALSE;
679         } else {
680           break;
681         }
682       } else {
683         //
684         // Wrong Physical Presence command
685         //
686         return FALSE;
687       }
688   }
689 
690   if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {
691     //
692     // It had been confirmed in last boot, it doesn't need confirm again.
693     //
694     *RequestConfirmed = TRUE;
695   }
696 
697   //
698   // Physical Presence command is correct
699   //
700   return TRUE;
701 }
702 
703 
704 /**
705   Check and execute the requested physical presence command.
706 
707   Caution: This function may receive untrusted input.
708   TcgPpData variable is external input, so this function will validate
709   its data structure to be valid value.
710 
711   @param[in]      PlatformAuth      platform auth value. NULL means no platform auth change.
712   @param[in, out] TcgPpData         Pointer to the physical presence NV variable.
713   @param[in, out] Flags             Pointer to the physical presence interface flags.
714 **/
715 VOID
Tcg2ExecutePendingTpmRequest(IN TPM2B_AUTH * PlatformAuth,OPTIONAL IN OUT EFI_TCG2_PHYSICAL_PRESENCE * TcgPpData,IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS * Flags)716 Tcg2ExecutePendingTpmRequest (
717   IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL
718   IN OUT  EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
719   IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags
720   )
721 {
722   EFI_STATUS                        Status;
723   UINTN                             DataSize;
724   BOOLEAN                           RequestConfirmed;
725   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  NewFlags;
726   BOOLEAN                           ResetRequired;
727   UINT32                            NewPPFlags;
728 
729   if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
730     //
731     // No operation request
732     //
733     return;
734   }
735 
736   if (!Tcg2HaveValidTpmRequest(TcgPpData, *Flags, &RequestConfirmed)) {
737     //
738     // Invalid operation request.
739     //
740     if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
741       TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;
742     } else {
743       TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
744     }
745     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
746     TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
747     TcgPpData->PPRequestParameter = 0;
748 
749     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
750     Status = gRT->SetVariable (
751                     TCG2_PHYSICAL_PRESENCE_VARIABLE,
752                     &gEfiTcg2PhysicalPresenceGuid,
753                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
754                     DataSize,
755                     TcgPpData
756                     );
757     return;
758   }
759 
760   ResetRequired = FALSE;
761   if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
762     NewFlags = *Flags;
763     NewPPFlags = NewFlags.PPFlags;
764     TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
765     NewFlags.PPFlags = NewPPFlags;
766   } else {
767     if (!RequestConfirmed) {
768       //
769       // Print confirm text and wait for approval.
770       //
771       RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);
772     }
773 
774     //
775     // Execute requested physical presence command
776     //
777     TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
778     NewFlags = *Flags;
779     if (RequestConfirmed) {
780       TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (
781                                 PlatformAuth,
782                                 TcgPpData->PPRequest,
783                                 TcgPpData->PPRequestParameter,
784                                 &NewFlags
785                                 );
786     }
787   }
788 
789   //
790   // Save the flags if it is updated.
791   //
792   if (CompareMem (Flags, &NewFlags, sizeof(EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {
793     *Flags = NewFlags;
794     Status   = gRT->SetVariable (
795                       TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
796                       &gEfiTcg2PhysicalPresenceGuid,
797                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
798                       sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
799                       &NewFlags
800                       );
801   }
802 
803   //
804   // Clear request
805   //
806   if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {
807     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
808     TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
809     TcgPpData->PPRequestParameter = 0;
810   }
811 
812   //
813   // Save changes
814   //
815   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
816   Status = gRT->SetVariable (
817                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
818                   &gEfiTcg2PhysicalPresenceGuid,
819                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
820                   DataSize,
821                   TcgPpData
822                   );
823   if (EFI_ERROR (Status)) {
824     return;
825   }
826 
827   if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
828     return;
829   }
830 
831   //
832   // Reset system to make new TPM settings in effect
833   //
834   switch (TcgPpData->LastPPRequest) {
835     case TCG2_PHYSICAL_PRESENCE_CLEAR:
836     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
837     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
838     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
839     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
840     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
841     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
842       break;
843 
844     case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
845     case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
846       break;
847 
848     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
849     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
850     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
851     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
852       return;
853 
854     default:
855       if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
856         if (ResetRequired) {
857           break;
858         } else {
859           return ;
860         }
861       }
862       if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
863         break;
864       }
865       return;
866   }
867 
868   Print (L"Rebooting system to make TPM2 settings in effect\n");
869   gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
870   ASSERT (FALSE);
871 }
872 
873 /**
874   Check and execute the pending TPM request.
875 
876   The TPM request may come from OS or BIOS. This API will display request information and wait
877   for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
878   the TPM request is confirmed, and one or more reset may be required to make TPM request to
879   take effect.
880 
881   This API should be invoked after console in and console out are all ready as they are required
882   to display request information and get user input to confirm the request.
883 
884   @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.
885 **/
886 VOID
887 EFIAPI
Tcg2PhysicalPresenceLibProcessRequest(IN TPM2B_AUTH * PlatformAuth OPTIONAL)888 Tcg2PhysicalPresenceLibProcessRequest (
889   IN      TPM2B_AUTH                     *PlatformAuth  OPTIONAL
890   )
891 {
892   EFI_STATUS                        Status;
893   UINTN                             DataSize;
894   EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
895   EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
896   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
897 
898   //
899   // This flags variable controls whether physical presence is required for TPM command.
900   // It should be protected from malicious software. We set it as read-only variable here.
901   //
902   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
903   if (!EFI_ERROR (Status)) {
904     Status = VariableLockProtocol->RequestToLock (
905                                      VariableLockProtocol,
906                                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
907                                      &gEfiTcg2PhysicalPresenceGuid
908                                      );
909     if (EFI_ERROR (Status)) {
910       DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
911       ASSERT_EFI_ERROR (Status);
912     }
913   }
914 
915   //
916   // Check S4 resume
917   //
918   if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
919     DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
920     return ;
921   }
922 
923   //
924   // Initialize physical presence flags.
925   //
926   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
927   Status = gRT->GetVariable (
928                   TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
929                   &gEfiTcg2PhysicalPresenceGuid,
930                   NULL,
931                   &DataSize,
932                   &PpiFlags
933                   );
934   if (EFI_ERROR (Status)) {
935     PpiFlags.PPFlags = PcdGet32(PcdTcg2PhysicalPresenceFlags);
936     Status   = gRT->SetVariable (
937                       TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
938                       &gEfiTcg2PhysicalPresenceGuid,
939                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
940                       sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
941                       &PpiFlags
942                       );
943     if (EFI_ERROR (Status)) {
944       DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));
945       return ;
946     }
947     DEBUG((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags));
948   }
949 
950   //
951   // Initialize physical presence variable.
952   //
953   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
954   Status = gRT->GetVariable (
955                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
956                   &gEfiTcg2PhysicalPresenceGuid,
957                   NULL,
958                   &DataSize,
959                   &TcgPpData
960                   );
961   if (EFI_ERROR (Status)) {
962     ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
963     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
964     Status   = gRT->SetVariable (
965                       TCG2_PHYSICAL_PRESENCE_VARIABLE,
966                       &gEfiTcg2PhysicalPresenceGuid,
967                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
968                       DataSize,
969                       &TcgPpData
970                       );
971     if (EFI_ERROR (Status)) {
972       DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));
973       return ;
974     }
975   }
976 
977   DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
978 
979   //
980   // Execute pending TPM request.
981   //
982   Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags);
983   DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
984 
985 }
986 
987 /**
988   Check if the pending TPM request needs user input to confirm.
989 
990   The TPM request may come from OS. This API will check if TPM request exists and need user
991   input to confirmation.
992 
993   @retval    TRUE        TPM needs input to confirm user physical presence.
994   @retval    FALSE       TPM doesn't need input to confirm user physical presence.
995 
996 **/
997 BOOLEAN
998 EFIAPI
Tcg2PhysicalPresenceLibNeedUserConfirm(VOID)999 Tcg2PhysicalPresenceLibNeedUserConfirm(
1000   VOID
1001   )
1002 {
1003   EFI_STATUS                        Status;
1004   EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
1005   UINTN                             DataSize;
1006   BOOLEAN                           RequestConfirmed;
1007   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
1008 
1009   //
1010   // Check S4 resume
1011   //
1012   if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
1013     DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
1014     return FALSE;
1015   }
1016 
1017   //
1018   // Check Tpm requests
1019   //
1020   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1021   Status = gRT->GetVariable (
1022                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
1023                   &gEfiTcg2PhysicalPresenceGuid,
1024                   NULL,
1025                   &DataSize,
1026                   &TcgPpData
1027                   );
1028   if (EFI_ERROR (Status)) {
1029     return FALSE;
1030   }
1031 
1032   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1033   Status = gRT->GetVariable (
1034                   TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1035                   &gEfiTcg2PhysicalPresenceGuid,
1036                   NULL,
1037                   &DataSize,
1038                   &PpiFlags
1039                   );
1040   if (EFI_ERROR (Status)) {
1041     return FALSE;
1042   }
1043 
1044   if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
1045     //
1046     // No operation request
1047     //
1048     return FALSE;
1049   }
1050 
1051   if (!Tcg2HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {
1052     //
1053     // Invalid operation request.
1054     //
1055     return FALSE;
1056   }
1057 
1058   if (!RequestConfirmed) {
1059     //
1060     // Need UI to confirm
1061     //
1062     return TRUE;
1063   }
1064 
1065   return FALSE;
1066 }
1067 
1068 
1069 /**
1070   The handler for TPM physical presence function:
1071   Return TPM Operation Response to OS Environment.
1072 
1073   @param[out]     MostRecentRequest Most recent operation request.
1074   @param[out]     Response          Response to the most recent operation request.
1075 
1076   @return Return Code for Return TPM Operation Response to OS Environment.
1077 **/
1078 UINT32
1079 EFIAPI
Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction(OUT UINT32 * MostRecentRequest,OUT UINT32 * Response)1080 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
1081   OUT UINT32                *MostRecentRequest,
1082   OUT UINT32                *Response
1083   )
1084 {
1085   EFI_STATUS                        Status;
1086   UINTN                             DataSize;
1087   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
1088 
1089   DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
1090 
1091   //
1092   // Get the Physical Presence variable
1093   //
1094   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1095   Status = gRT->GetVariable (
1096                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
1097                   &gEfiTcg2PhysicalPresenceGuid,
1098                   NULL,
1099                   &DataSize,
1100                   &PpData
1101                   );
1102   if (EFI_ERROR (Status)) {
1103     *MostRecentRequest = 0;
1104     *Response          = 0;
1105     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
1106     return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
1107   }
1108 
1109   *MostRecentRequest = PpData.LastPPRequest;
1110   *Response          = PpData.PPResponse;
1111 
1112   return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
1113 }
1114 
1115 /**
1116   The handler for TPM physical presence function:
1117   Submit TPM Operation Request to Pre-OS Environment and
1118   Submit TPM Operation Request to Pre-OS Environment 2.
1119 
1120   Caution: This function may receive untrusted input.
1121 
1122   @param[in]      OperationRequest TPM physical presence operation request.
1123   @param[in]      RequestParameter TPM physical presence operation request parameter.
1124 
1125   @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
1126           Submit TPM Operation Request to Pre-OS Environment 2.
1127 **/
1128 UINT32
1129 EFIAPI
Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction(IN UINT32 OperationRequest,IN UINT32 RequestParameter)1130 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
1131   IN UINT32                 OperationRequest,
1132   IN UINT32                 RequestParameter
1133   )
1134 {
1135   EFI_STATUS                        Status;
1136   UINTN                             DataSize;
1137   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
1138   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
1139 
1140   DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
1141 
1142   //
1143   // Get the Physical Presence variable
1144   //
1145   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1146   Status = gRT->GetVariable (
1147                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
1148                   &gEfiTcg2PhysicalPresenceGuid,
1149                   NULL,
1150                   &DataSize,
1151                   &PpData
1152                   );
1153   if (EFI_ERROR (Status)) {
1154     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
1155     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
1156   }
1157 
1158   if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
1159       (OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
1160     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
1161   }
1162 
1163   if ((PpData.PPRequest != OperationRequest) ||
1164       (PpData.PPRequestParameter != RequestParameter)) {
1165     PpData.PPRequest = (UINT8)OperationRequest;
1166     PpData.PPRequestParameter = RequestParameter;
1167     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1168     Status = gRT->SetVariable (
1169                     TCG2_PHYSICAL_PRESENCE_VARIABLE,
1170                     &gEfiTcg2PhysicalPresenceGuid,
1171                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1172                     DataSize,
1173                     &PpData
1174                     );
1175     if (EFI_ERROR (Status)) {
1176       DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
1177       return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
1178     }
1179   }
1180 
1181   if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
1182     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1183     Status = gRT->GetVariable (
1184                     TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1185                     &gEfiTcg2PhysicalPresenceGuid,
1186                     NULL,
1187                     &DataSize,
1188                     &Flags
1189                     );
1190     if (EFI_ERROR (Status)) {
1191       Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
1192     }
1193     return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
1194   }
1195 
1196   return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
1197 }
1198 
1199 /**
1200   Return TPM2 ManagementFlags set by PP interface.
1201 
1202   @retval    ManagementFlags    TPM2 Management Flags.
1203 **/
1204 UINT32
1205 EFIAPI
Tcg2PhysicalPresenceLibGetManagementFlags(VOID)1206 Tcg2PhysicalPresenceLibGetManagementFlags (
1207   VOID
1208   )
1209 {
1210   EFI_STATUS                        Status;
1211   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
1212   UINTN                             DataSize;
1213 
1214   DEBUG ((EFI_D_INFO, "[TPM2] GetManagementFlags\n"));
1215 
1216   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1217   Status = gRT->GetVariable (
1218                   TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1219                   &gEfiTcg2PhysicalPresenceGuid,
1220                   NULL,
1221                   &DataSize,
1222                   &PpiFlags
1223                   );
1224   if (EFI_ERROR (Status)) {
1225     PpiFlags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
1226   }
1227   return PpiFlags.PPFlags;
1228 }
1229