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