1 /** @file
2 
3   Execute pending TPM requests from OS or BIOS and Lock TPM.
4 
5   Caution: This module requires additional review when modified.
6   This driver will have external input - variable.
7   This external input must be validated carefully to avoid security issue.
8 
9   ExecutePendingTpmRequest() will receive untrusted input and do validation.
10 
11 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution.  The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
16 
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 **/
21 
22 #include <PiDxe.h>
23 
24 #include <Protocol/TcgService.h>
25 #include <Protocol/VariableLock.h>
26 #include <Library/DebugLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/UefiRuntimeServicesTableLib.h>
29 #include <Library/UefiDriverEntryPoint.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/UefiLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/PrintLib.h>
34 #include <Library/HiiLib.h>
35 #include <Guid/EventGroup.h>
36 #include <Guid/PhysicalPresenceData.h>
37 #include <Library/TcgPpVendorLib.h>
38 
39 #define CONFIRM_BUFFER_SIZE         4096
40 
41 EFI_HII_HANDLE mPpStringPackHandle;
42 
43 /**
44   Get string by string id from HII Interface.
45 
46   @param[in] Id          String ID.
47 
48   @retval    CHAR16 *    String from ID.
49   @retval    NULL        If error occurs.
50 
51 **/
52 CHAR16 *
PhysicalPresenceGetStringById(IN EFI_STRING_ID Id)53 PhysicalPresenceGetStringById (
54   IN  EFI_STRING_ID   Id
55   )
56 {
57   return HiiGetString (mPpStringPackHandle, Id, NULL);
58 }
59 
60 /**
61   Get TPM physical presence permanent flags.
62 
63   @param[in]  TcgProtocol   EFI TCG Protocol instance.
64   @param[out] LifetimeLock  physicalPresenceLifetimeLock permanent flag.
65   @param[out] CmdEnable     physicalPresenceCMDEnable permanent flag.
66 
67   @retval EFI_SUCCESS       Flags were returns successfully.
68   @retval other             Failed to locate EFI TCG Protocol.
69 
70 **/
71 EFI_STATUS
GetTpmCapability(IN EFI_TCG_PROTOCOL * TcgProtocol,OUT BOOLEAN * LifetimeLock,OUT BOOLEAN * CmdEnable)72 GetTpmCapability (
73   IN   EFI_TCG_PROTOCOL             *TcgProtocol,
74   OUT  BOOLEAN                      *LifetimeLock,
75   OUT  BOOLEAN                      *CmdEnable
76   )
77 {
78   EFI_STATUS                        Status;
79   TPM_RQU_COMMAND_HDR               *TpmRqu;
80   TPM_RSP_COMMAND_HDR               *TpmRsp;
81   UINT32                            *SendBufPtr;
82   UINT8                             SendBuffer[sizeof (*TpmRqu) + sizeof (UINT32) * 3];
83   TPM_PERMANENT_FLAGS               *TpmPermanentFlags;
84   UINT8                             RecvBuffer[40];
85 
86   //
87   // Fill request header
88   //
89   TpmRsp = (TPM_RSP_COMMAND_HDR*)RecvBuffer;
90   TpmRqu = (TPM_RQU_COMMAND_HDR*)SendBuffer;
91 
92   TpmRqu->tag       = SwapBytes16 (TPM_TAG_RQU_COMMAND);
93   TpmRqu->paramSize = SwapBytes32 (sizeof (SendBuffer));
94   TpmRqu->ordinal   = SwapBytes32 (TPM_ORD_GetCapability);
95 
96   //
97   // Set request parameter
98   //
99   SendBufPtr      = (UINT32*)(TpmRqu + 1);
100   WriteUnaligned32 (SendBufPtr++, SwapBytes32 (TPM_CAP_FLAG));
101   WriteUnaligned32 (SendBufPtr++, SwapBytes32 (sizeof (TPM_CAP_FLAG_PERMANENT)));
102   WriteUnaligned32 (SendBufPtr, SwapBytes32 (TPM_CAP_FLAG_PERMANENT));
103 
104   Status = TcgProtocol->PassThroughToTpm (
105                           TcgProtocol,
106                           sizeof (SendBuffer),
107                           (UINT8*)TpmRqu,
108                           sizeof (RecvBuffer),
109                           (UINT8*)&RecvBuffer
110                           );
111   ASSERT_EFI_ERROR (Status);
112   ASSERT (TpmRsp->tag == SwapBytes16 (TPM_TAG_RSP_COMMAND));
113   ASSERT (TpmRsp->returnCode == 0);
114 
115   TpmPermanentFlags = (TPM_PERMANENT_FLAGS *)&RecvBuffer[sizeof (TPM_RSP_COMMAND_HDR) + sizeof (UINT32)];
116 
117   if (LifetimeLock != NULL) {
118     *LifetimeLock = TpmPermanentFlags->physicalPresenceLifetimeLock;
119   }
120 
121   if (CmdEnable != NULL) {
122     *CmdEnable = TpmPermanentFlags->physicalPresenceCMDEnable;
123   }
124 
125   return Status;
126 }
127 
128 /**
129   Issue TSC_PhysicalPresence command to TPM.
130 
131   @param[in] TcgProtocol          EFI TCG Protocol instance.
132   @param[in] PhysicalPresence     The state to set the TPM's Physical Presence flags.
133 
134   @retval EFI_SUCCESS             TPM executed the command successfully.
135   @retval EFI_SECURITY_VIOLATION  TPM returned error when executing the command.
136   @retval other                   Failed to locate EFI TCG Protocol.
137 
138 **/
139 EFI_STATUS
TpmPhysicalPresence(IN EFI_TCG_PROTOCOL * TcgProtocol,IN TPM_PHYSICAL_PRESENCE PhysicalPresence)140 TpmPhysicalPresence (
141   IN      EFI_TCG_PROTOCOL          *TcgProtocol,
142   IN      TPM_PHYSICAL_PRESENCE     PhysicalPresence
143   )
144 {
145   EFI_STATUS                        Status;
146   TPM_RQU_COMMAND_HDR               *TpmRqu;
147   TPM_PHYSICAL_PRESENCE             *TpmPp;
148   TPM_RSP_COMMAND_HDR               TpmRsp;
149   UINT8                             Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)];
150 
151   TpmRqu = (TPM_RQU_COMMAND_HDR*)Buffer;
152   TpmPp = (TPM_PHYSICAL_PRESENCE*)(TpmRqu + 1);
153 
154   TpmRqu->tag       = SwapBytes16 (TPM_TAG_RQU_COMMAND);
155   TpmRqu->paramSize = SwapBytes32 (sizeof (Buffer));
156   TpmRqu->ordinal   = SwapBytes32 (TSC_ORD_PhysicalPresence);
157   WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE) SwapBytes16 (PhysicalPresence));
158 
159   Status = TcgProtocol->PassThroughToTpm (
160                           TcgProtocol,
161                           sizeof (Buffer),
162                           (UINT8*)TpmRqu,
163                           sizeof (TpmRsp),
164                           (UINT8*)&TpmRsp
165                           );
166   ASSERT_EFI_ERROR (Status);
167   ASSERT (TpmRsp.tag == SwapBytes16 (TPM_TAG_RSP_COMMAND));
168   if (TpmRsp.returnCode != 0) {
169     //
170     // If it fails, some requirements may be needed for this command.
171     //
172     return EFI_SECURITY_VIOLATION;
173   }
174 
175   return Status;
176 }
177 
178 /**
179   Issue a TPM command for which no additional output data will be returned.
180 
181   @param[in] TcgProtocol              EFI TCG Protocol instance.
182   @param[in] Ordinal                  TPM command code.
183   @param[in] AdditionalParameterSize  Additional parameter size.
184   @param[in] AdditionalParameters     Pointer to the Additional paramaters.
185 
186   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE  Error occurred during sending command to TPM or
187                                                   receiving response from TPM.
188   @retval Others                                  Return code from the TPM device after command execution.
189 
190 **/
191 UINT32
TpmCommandNoReturnData(IN EFI_TCG_PROTOCOL * TcgProtocol,IN TPM_COMMAND_CODE Ordinal,IN UINTN AdditionalParameterSize,IN VOID * AdditionalParameters)192 TpmCommandNoReturnData (
193   IN      EFI_TCG_PROTOCOL          *TcgProtocol,
194   IN      TPM_COMMAND_CODE          Ordinal,
195   IN      UINTN                     AdditionalParameterSize,
196   IN      VOID                      *AdditionalParameters
197   )
198 {
199   EFI_STATUS                        Status;
200   TPM_RQU_COMMAND_HDR               *TpmRqu;
201   TPM_RSP_COMMAND_HDR               TpmRsp;
202   UINT32                            Size;
203 
204   TpmRqu = (TPM_RQU_COMMAND_HDR*) AllocatePool (sizeof (*TpmRqu) + AdditionalParameterSize);
205   if (TpmRqu == NULL) {
206     return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
207   }
208 
209   TpmRqu->tag       = SwapBytes16 (TPM_TAG_RQU_COMMAND);
210   Size              = (UINT32)(sizeof (*TpmRqu) + AdditionalParameterSize);
211   TpmRqu->paramSize = SwapBytes32 (Size);
212   TpmRqu->ordinal   = SwapBytes32 (Ordinal);
213   CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize);
214 
215   Status = TcgProtocol->PassThroughToTpm (
216                           TcgProtocol,
217                           Size,
218                           (UINT8*)TpmRqu,
219                           (UINT32)sizeof (TpmRsp),
220                           (UINT8*)&TpmRsp
221                           );
222   FreePool (TpmRqu);
223   if (EFI_ERROR (Status) || (TpmRsp.tag != SwapBytes16 (TPM_TAG_RSP_COMMAND))) {
224     return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
225   }
226   return SwapBytes32 (TpmRsp.returnCode);
227 }
228 
229 /**
230   Execute physical presence operation requested by the OS.
231 
232   @param[in]      TcgProtocol         EFI TCG Protocol instance.
233   @param[in]      CommandCode         Physical presence operation value.
234   @param[in, out] PpiFlags            The physical presence interface flags.
235 
236   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE  Unknown physical presence operation.
237   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE  Error occurred during sending command to TPM or
238                                                   receiving response from TPM.
239   @retval Others                                  Return code from the TPM device after command execution.
240 
241 **/
242 UINT32
ExecutePhysicalPresence(IN EFI_TCG_PROTOCOL * TcgProtocol,IN UINT32 CommandCode,IN OUT EFI_PHYSICAL_PRESENCE_FLAGS * PpiFlags)243 ExecutePhysicalPresence (
244   IN      EFI_TCG_PROTOCOL            *TcgProtocol,
245   IN      UINT32                      CommandCode,
246   IN OUT  EFI_PHYSICAL_PRESENCE_FLAGS *PpiFlags
247   )
248 {
249   BOOLEAN                           BoolVal;
250   UINT32                            TpmResponse;
251   UINT32                            InData[5];
252 
253   switch (CommandCode) {
254     case PHYSICAL_PRESENCE_ENABLE:
255       return TpmCommandNoReturnData (
256                TcgProtocol,
257                TPM_ORD_PhysicalEnable,
258                0,
259                NULL
260                );
261 
262     case PHYSICAL_PRESENCE_DISABLE:
263       return TpmCommandNoReturnData (
264                TcgProtocol,
265                TPM_ORD_PhysicalDisable,
266                0,
267                NULL
268                );
269 
270     case PHYSICAL_PRESENCE_ACTIVATE:
271       BoolVal = FALSE;
272       return TpmCommandNoReturnData (
273                TcgProtocol,
274                TPM_ORD_PhysicalSetDeactivated,
275                sizeof (BoolVal),
276                &BoolVal
277                );
278 
279     case PHYSICAL_PRESENCE_DEACTIVATE:
280       BoolVal = TRUE;
281       return TpmCommandNoReturnData (
282                TcgProtocol,
283                TPM_ORD_PhysicalSetDeactivated,
284                sizeof (BoolVal),
285                &BoolVal
286                );
287 
288     case PHYSICAL_PRESENCE_CLEAR:
289       return TpmCommandNoReturnData (
290                TcgProtocol,
291                TPM_ORD_ForceClear,
292                0,
293                NULL
294                );
295 
296     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE:
297       TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE, PpiFlags);
298       if (TpmResponse == 0) {
299         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ACTIVATE, PpiFlags);
300       }
301       return TpmResponse;
302 
303     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE:
304       TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE, PpiFlags);
305       if (TpmResponse == 0) {
306         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DISABLE, PpiFlags);
307       }
308       return TpmResponse;
309 
310     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE:
311       BoolVal = TRUE;
312       return TpmCommandNoReturnData (
313                TcgProtocol,
314                TPM_ORD_SetOwnerInstall,
315                sizeof (BoolVal),
316                &BoolVal
317                );
318 
319     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE:
320       BoolVal = FALSE;
321       return TpmCommandNoReturnData (
322                TcgProtocol,
323                TPM_ORD_SetOwnerInstall,
324                sizeof (BoolVal),
325                &BoolVal
326                );
327 
328     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE:
329       //
330       // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE
331       // PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE will be executed after reboot
332       //
333       if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) {
334         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags);
335         PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK;
336       } else {
337         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE, PpiFlags);
338         PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK;
339       }
340       return TpmResponse;
341 
342     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:
343       TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE, PpiFlags);
344       if (TpmResponse == 0) {
345         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE_DISABLE, PpiFlags);
346       }
347       return TpmResponse;
348 
349     case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
350       InData[0] = SwapBytes32 (TPM_SET_STCLEAR_DATA);            // CapabilityArea
351       InData[1] = SwapBytes32 (sizeof(UINT32));                  // SubCapSize
352       InData[2] = SwapBytes32 (TPM_SD_DEFERREDPHYSICALPRESENCE); // SubCap
353       InData[3] = SwapBytes32 (sizeof(UINT32));                  // SetValueSize
354       InData[4] = SwapBytes32 (1);                               // UnownedFieldUpgrade; bit0
355       return TpmCommandNoReturnData (
356                TcgProtocol,
357                TPM_ORD_SetCapability,
358                sizeof (UINT32) * 5,
359                InData
360                );
361 
362     case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:
363       //
364       // TPM_SetOperatorAuth
365       // This command requires UI to prompt user for Auth data
366       // Here it is NOT implemented
367       //
368       return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
369 
370     case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:
371       TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags);
372       if (TpmResponse == 0) {
373         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags);
374       }
375       return TpmResponse;
376 
377     case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE:
378       PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION;
379       return 0;
380 
381     case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE:
382       PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION;
383       return 0;
384 
385     case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:
386       PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR;
387       return 0;
388 
389     case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:
390       PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR;
391       return 0;
392 
393     case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE:
394       PpiFlags->PPFlags &= ~TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE;
395       return 0;
396 
397     case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE:
398       PpiFlags->PPFlags |= TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE;
399       return 0;
400 
401     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:
402       //
403       // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR
404       // PHYSICAL_PRESENCE_CLEAR will be executed after reboot.
405       //
406       if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) {
407         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags);
408         PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK;
409       } else {
410         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags);
411         PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK;
412       }
413       return TpmResponse;
414 
415     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
416       //
417       // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE
418       // PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE will be executed after reboot.
419       //
420       if ((PpiFlags->PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) {
421         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags);
422         PpiFlags->PPFlags |= TCG_VENDOR_LIB_FLAG_RESET_TRACK;
423       } else {
424         TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE, PpiFlags);
425         PpiFlags->PPFlags &= ~TCG_VENDOR_LIB_FLAG_RESET_TRACK;
426       }
427       return TpmResponse;
428 
429     default:
430       ;
431   }
432   return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
433 }
434 
435 
436 /**
437   Read the specified key for user confirmation.
438 
439   @param[in]  CautionKey  If true,  F12 is used as confirm key;
440                           If false, F10 is used as confirm key.
441 
442   @retval     TRUE        User confirmed the changes by input.
443   @retval     FALSE       User discarded the changes or device error.
444 
445 **/
446 BOOLEAN
ReadUserKey(IN BOOLEAN CautionKey)447 ReadUserKey (
448   IN     BOOLEAN                    CautionKey
449   )
450 {
451   EFI_STATUS                        Status;
452   EFI_INPUT_KEY                     Key;
453   UINT16                            InputKey;
454   UINTN                             Index;
455 
456   InputKey = 0;
457   do {
458     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
459     if (Status == EFI_NOT_READY) {
460       gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
461       continue;
462     }
463 
464     if (Status == EFI_DEVICE_ERROR) {
465       return FALSE;
466     }
467 
468     if (Key.ScanCode == SCAN_ESC) {
469       InputKey = Key.ScanCode;
470     }
471     if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
472       InputKey = Key.ScanCode;
473     }
474     if ((Key.ScanCode == SCAN_F12) && CautionKey) {
475       InputKey = Key.ScanCode;
476     }
477   } while (InputKey == 0);
478 
479   if (InputKey != SCAN_ESC) {
480     return TRUE;
481   }
482 
483   return FALSE;
484 }
485 
486 /**
487   The constructor function register UNI strings into imageHandle.
488 
489   It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
490 
491   @param  ImageHandle   The firmware allocated handle for the EFI image.
492   @param  SystemTable   A pointer to the EFI System Table.
493 
494   @retval EFI_SUCCESS   The constructor successfully added string package.
495   @retval Other value   The constructor can't add string package.
496 
497 **/
498 EFI_STATUS
499 EFIAPI
TcgPhysicalPresenceLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)500 TcgPhysicalPresenceLibConstructor (
501   IN EFI_HANDLE        ImageHandle,
502   IN EFI_SYSTEM_TABLE  *SystemTable
503   )
504 {
505   mPpStringPackHandle = HiiAddPackages (&gEfiPhysicalPresenceGuid, ImageHandle, DxeTcgPhysicalPresenceLibStrings, NULL);
506   ASSERT (mPpStringPackHandle != NULL);
507 
508   return EFI_SUCCESS;
509 }
510 
511 /**
512   Display the confirm text and get user confirmation.
513 
514   @param[in] TpmPpCommand  The requested TPM physical presence command.
515 
516   @retval    TRUE          The user has confirmed the changes.
517   @retval    FALSE         The user doesn't confirm the changes.
518 **/
519 BOOLEAN
UserConfirm(IN UINT32 TpmPpCommand)520 UserConfirm (
521   IN      UINT32                    TpmPpCommand
522   )
523 {
524   CHAR16                            *ConfirmText;
525   CHAR16                            *TmpStr1;
526   CHAR16                            *TmpStr2;
527   UINTN                             BufSize;
528   BOOLEAN                           CautionKey;
529   UINT16                            Index;
530   CHAR16                            DstStr[81];
531 
532   TmpStr2     = NULL;
533   CautionKey  = FALSE;
534   BufSize     = CONFIRM_BUFFER_SIZE;
535   ConfirmText = AllocateZeroPool (BufSize);
536   ASSERT (ConfirmText != NULL);
537 
538   switch (TpmPpCommand) {
539     case PHYSICAL_PRESENCE_ENABLE:
540       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE));
541 
542       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
543       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
544       FreePool (TmpStr1);
545 
546       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
547       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
548       FreePool (TmpStr1);
549       break;
550 
551     case PHYSICAL_PRESENCE_DISABLE:
552       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DISABLE));
553 
554       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
555       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
556       FreePool (TmpStr1);
557 
558       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING));
559       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
560       FreePool (TmpStr1);
561 
562       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
563       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
564       FreePool (TmpStr1);
565       break;
566 
567     case PHYSICAL_PRESENCE_ACTIVATE:
568       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACTIVATE));
569 
570       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
571       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
572       FreePool (TmpStr1);
573 
574       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
575       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
576       FreePool (TmpStr1);
577       break;
578 
579     case PHYSICAL_PRESENCE_DEACTIVATE:
580       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DEACTIVATE));
581 
582       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
583       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
584       FreePool (TmpStr1);
585 
586       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING));
587       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
588       FreePool (TmpStr1);
589 
590       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
591       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
592       FreePool (TmpStr1);
593       break;
594 
595     case PHYSICAL_PRESENCE_CLEAR:
596       CautionKey = TRUE;
597       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
598 
599       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
600       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
601       FreePool (TmpStr1);
602 
603       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
604       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
605       StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
606       FreePool (TmpStr1);
607 
608       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
609       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
610       FreePool (TmpStr1);
611       break;
612 
613     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE:
614       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE));
615 
616       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
617       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
618       FreePool (TmpStr1);
619 
620       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON));
621       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
622       FreePool (TmpStr1);
623 
624       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
625       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
626       FreePool (TmpStr1);
627       break;
628 
629     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE:
630       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DEACTIVATE_DISABLE));
631 
632       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
633       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
634       FreePool (TmpStr1);
635 
636       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_OFF));
637       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
638       FreePool (TmpStr1);
639 
640       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING));
641       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
642       FreePool (TmpStr1);
643 
644       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
645       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
646       FreePool (TmpStr1);
647       break;
648 
649     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE:
650       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ALLOW_TAKE_OWNERSHIP));
651 
652       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
653       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
654       FreePool (TmpStr1);
655 
656       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
657       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
658       FreePool (TmpStr1);
659       break;
660 
661     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE:
662       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_DISALLOW_TAKE_OWNERSHIP));
663 
664       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
665       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
666       FreePool (TmpStr1);
667 
668       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
669       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
670       FreePool (TmpStr1);
671       break;
672 
673     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE:
674       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_TURN_ON));
675 
676       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
677       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
678       FreePool (TmpStr1);
679 
680       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON));
681       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
682       FreePool (TmpStr1);
683 
684       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
685       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
686       FreePool (TmpStr1);
687       break;
688 
689     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:
690       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_TURN_OFF));
691 
692       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
693       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
694       FreePool (TmpStr1);
695 
696       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_OFF));
697       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
698       FreePool (TmpStr1);
699 
700       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING));
701       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
702       FreePool (TmpStr1);
703 
704       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
705       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
706       FreePool (TmpStr1);
707       break;
708 
709     case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
710       CautionKey = TRUE;
711       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_UNOWNED_FIELD_UPGRADE));
712 
713       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_UPGRADE_HEAD_STR));
714       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
715       FreePool (TmpStr1);
716 
717       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_MAINTAIN));
718       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
719       FreePool (TmpStr1);
720 
721       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
722       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
723       FreePool (TmpStr1);
724       break;
725 
726     case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:
727       //
728       // TPM_SetOperatorAuth
729       // This command requires UI to prompt user for Auth data
730       // Here it is NOT implemented
731       //
732       break;
733 
734     case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:
735       CautionKey = TRUE;
736       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR_TURN_ON));
737 
738       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
739       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
740       FreePool (TmpStr1);
741 
742       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON));
743       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
744       FreePool (TmpStr1);
745 
746       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
747       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
748       FreePool (TmpStr1);
749 
750       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR_CONT));
751       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
752       FreePool (TmpStr1);
753 
754       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
755       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
756       FreePool (TmpStr1);
757       break;
758 
759     case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE:
760       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_PROVISION));
761 
762       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
763       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
764       FreePool (TmpStr1);
765 
766       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
767       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
768       FreePool (TmpStr1);
769 
770       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
771       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
772       FreePool (TmpStr1);
773       break;
774 
775     case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:
776       CautionKey = TRUE;
777       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
778 
779       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
780       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
781       FreePool (TmpStr1);
782 
783       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
784       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
785       FreePool (TmpStr1);
786 
787       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
788       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
789       StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
790       FreePool (TmpStr1);
791 
792       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
793       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
794       FreePool (TmpStr1);
795 
796       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
797       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
798       FreePool (TmpStr1);
799       break;
800 
801     case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE:
802       CautionKey = TRUE;
803       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_MAINTAIN));
804 
805       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
806       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
807       FreePool (TmpStr1);
808 
809       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_MAINTAIN));
810       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
811       FreePool (TmpStr1);
812 
813       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
814       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
815       FreePool (TmpStr1);
816 
817       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
818       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
819       FreePool (TmpStr1);
820       break;
821 
822     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:
823       CautionKey = TRUE;
824       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR));
825 
826       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
827       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
828       FreePool (TmpStr1);
829 
830       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
831       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
832       StrnCat (ConfirmText, L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
833       FreePool (TmpStr1);
834 
835       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
836       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
837       FreePool (TmpStr1);
838       break;
839 
840     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
841       CautionKey = TRUE;
842       TmpStr2 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE));
843 
844       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
845       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
846       FreePool (TmpStr1);
847 
848       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_ON));
849       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
850       FreePool (TmpStr1);
851 
852       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
853       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
854       FreePool (TmpStr1);
855 
856       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR_CONT));
857       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
858       FreePool (TmpStr1);
859 
860       TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
861       StrnCat (ConfirmText, TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
862       FreePool (TmpStr1);
863       break;
864 
865     default:
866       ;
867   }
868 
869   if (TmpStr2 == NULL) {
870     FreePool (ConfirmText);
871     return FALSE;
872   }
873 
874   TmpStr1 = PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
875   BufSize -= StrSize (ConfirmText);
876   UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
877 
878   DstStr[80] = L'\0';
879   for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
880     StrnCpy(DstStr, ConfirmText + Index, 80);
881     Print (DstStr);
882   }
883 
884   FreePool (TmpStr1);
885   FreePool (TmpStr2);
886   FreePool (ConfirmText);
887 
888   if (ReadUserKey (CautionKey)) {
889     return TRUE;
890   }
891 
892   return FALSE;
893 }
894 
895 /**
896   Check if there is a valid physical presence command request. Also updates parameter value
897   to whether the requested physical presence command already confirmed by user
898 
899    @param[in]  TcgPpData           EFI TCG Physical Presence request data.
900    @param[in]  Flags               The physical presence interface flags.
901    @param[out] RequestConfirmed    If the physical presence operation command required user confirm from UI.
902                                    True, it indicates the command doesn't require user confirm, or already confirmed
903                                    in last boot cycle by user.
904                                    False, it indicates the command need user confirm from UI.
905 
906    @retval  TRUE        Physical Presence operation command is valid.
907    @retval  FALSE       Physical Presence operation command is invalid.
908 
909 **/
910 BOOLEAN
HaveValidTpmRequest(IN EFI_PHYSICAL_PRESENCE * TcgPpData,IN EFI_PHYSICAL_PRESENCE_FLAGS Flags,OUT BOOLEAN * RequestConfirmed)911 HaveValidTpmRequest  (
912   IN      EFI_PHYSICAL_PRESENCE       *TcgPpData,
913   IN      EFI_PHYSICAL_PRESENCE_FLAGS Flags,
914   OUT     BOOLEAN                     *RequestConfirmed
915   )
916 {
917   BOOLEAN  IsRequestValid;
918 
919   *RequestConfirmed = FALSE;
920 
921   switch (TcgPpData->PPRequest) {
922     case PHYSICAL_PRESENCE_NO_ACTION:
923       *RequestConfirmed = TRUE;
924       return TRUE;
925     case PHYSICAL_PRESENCE_ENABLE:
926     case PHYSICAL_PRESENCE_DISABLE:
927     case PHYSICAL_PRESENCE_ACTIVATE:
928     case PHYSICAL_PRESENCE_DEACTIVATE:
929     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE:
930     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE:
931     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE:
932     case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE:
933     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE:
934     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:
935     case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:
936       if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION) != 0) {
937         *RequestConfirmed = TRUE;
938       }
939       break;
940 
941     case PHYSICAL_PRESENCE_CLEAR:
942     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:
943       if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0) {
944         *RequestConfirmed = TRUE;
945       }
946       break;
947 
948     case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
949       if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_MAINTENANCE) != 0) {
950         *RequestConfirmed = TRUE;
951       }
952       break;
953 
954     case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:
955     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
956       if ((Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0 && (Flags.PPFlags & TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION) != 0) {
957         *RequestConfirmed = TRUE;
958       }
959       break;
960 
961     case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE:
962     case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:
963     case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE:
964       *RequestConfirmed = TRUE;
965       break;
966 
967     case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE:
968     case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:
969     case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE:
970       break;
971 
972     default:
973       if (TcgPpData->PPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
974         IsRequestValid = TcgPpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
975         if (!IsRequestValid) {
976           return FALSE;
977         } else {
978           break;
979         }
980       } else {
981         //
982         // Wrong Physical Presence command
983         //
984         return FALSE;
985       }
986   }
987 
988   if ((Flags.PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) != 0) {
989     //
990     // It had been confirmed in last boot, it doesn't need confirm again.
991     //
992     *RequestConfirmed = TRUE;
993   }
994 
995   //
996   // Physical Presence command is correct
997   //
998   return TRUE;
999 }
1000 
1001 
1002 /**
1003   Check and execute the requested physical presence command.
1004 
1005   Caution: This function may receive untrusted input.
1006   TcgPpData variable is external input, so this function will validate
1007   its data structure to be valid value.
1008 
1009   @param[in] TcgProtocol          EFI TCG Protocol instance.
1010   @param[in] TcgPpData            Point to the physical presence NV variable.
1011   @param[in] Flags                The physical presence interface flags.
1012 
1013 **/
1014 VOID
ExecutePendingTpmRequest(IN EFI_TCG_PROTOCOL * TcgProtocol,IN EFI_PHYSICAL_PRESENCE * TcgPpData,IN EFI_PHYSICAL_PRESENCE_FLAGS Flags)1015 ExecutePendingTpmRequest (
1016   IN      EFI_TCG_PROTOCOL            *TcgProtocol,
1017   IN      EFI_PHYSICAL_PRESENCE       *TcgPpData,
1018   IN      EFI_PHYSICAL_PRESENCE_FLAGS Flags
1019   )
1020 {
1021   EFI_STATUS                        Status;
1022   UINTN                             DataSize;
1023   BOOLEAN                           RequestConfirmed;
1024   EFI_PHYSICAL_PRESENCE_FLAGS       NewFlags;
1025   BOOLEAN                           ResetRequired;
1026   UINT32                            NewPPFlags;
1027 
1028   if (!HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {
1029     //
1030     // Invalid operation request.
1031     //
1032     TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
1033     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
1034     TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION;
1035     DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
1036     Status = gRT->SetVariable (
1037                     PHYSICAL_PRESENCE_VARIABLE,
1038                     &gEfiPhysicalPresenceGuid,
1039                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1040                     DataSize,
1041                     TcgPpData
1042                     );
1043     return;
1044   }
1045 
1046   ResetRequired = FALSE;
1047   if (TcgPpData->PPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
1048     NewFlags = Flags;
1049     NewPPFlags = NewFlags.PPFlags;
1050     TcgPpData->PPResponse = TcgPpVendorLibExecutePendingRequest (TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
1051     NewFlags.PPFlags = (UINT8)NewPPFlags;
1052   } else {
1053     if (!RequestConfirmed) {
1054       //
1055       // Print confirm text and wait for approval.
1056       //
1057       RequestConfirmed = UserConfirm (TcgPpData->PPRequest);
1058     }
1059 
1060     //
1061     // Execute requested physical presence command
1062     //
1063     TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
1064     NewFlags = Flags;
1065     if (RequestConfirmed) {
1066       TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &NewFlags);
1067     }
1068   }
1069 
1070   //
1071   // Save the flags if it is updated.
1072   //
1073   if (CompareMem (&Flags, &NewFlags, sizeof(EFI_PHYSICAL_PRESENCE_FLAGS)) != 0) {
1074     Status   = gRT->SetVariable (
1075                       PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1076                       &gEfiPhysicalPresenceGuid,
1077                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1078                       sizeof (EFI_PHYSICAL_PRESENCE_FLAGS),
1079                       &NewFlags
1080                       );
1081     if (EFI_ERROR (Status)) {
1082       return;
1083     }
1084   }
1085 
1086   //
1087   // Clear request
1088   //
1089   if ((NewFlags.PPFlags & TCG_VENDOR_LIB_FLAG_RESET_TRACK) == 0) {
1090     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
1091     TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION;
1092   }
1093 
1094   //
1095   // Save changes
1096   //
1097   DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
1098   Status = gRT->SetVariable (
1099                   PHYSICAL_PRESENCE_VARIABLE,
1100                   &gEfiPhysicalPresenceGuid,
1101                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1102                   DataSize,
1103                   TcgPpData
1104                   );
1105   if (EFI_ERROR (Status)) {
1106     return;
1107   }
1108 
1109   if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
1110     return;
1111   }
1112 
1113   //
1114   // Reset system to make new TPM settings in effect
1115   //
1116   switch (TcgPpData->LastPPRequest) {
1117     case PHYSICAL_PRESENCE_ACTIVATE:
1118     case PHYSICAL_PRESENCE_DEACTIVATE:
1119     case PHYSICAL_PRESENCE_CLEAR:
1120     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE:
1121     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE:
1122     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE:
1123     case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:
1124     case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
1125     case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:
1126     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:
1127     case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:
1128       break;
1129     default:
1130       if (TcgPpData->LastPPRequest >= TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
1131         if (ResetRequired) {
1132           break;
1133         } else {
1134           return ;
1135         }
1136       }
1137       if (TcgPpData->PPRequest != PHYSICAL_PRESENCE_NO_ACTION) {
1138         break;
1139       }
1140       return;
1141   }
1142 
1143   Print (L"Rebooting system to make TPM settings in effect\n");
1144   gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
1145   ASSERT (FALSE);
1146 }
1147 
1148 /**
1149   Check and execute the pending TPM request and Lock TPM.
1150 
1151   The TPM request may come from OS or BIOS. This API will display request information and wait
1152   for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
1153   the TPM request is confirmed, and one or more reset may be required to make TPM request to
1154   take effect. At last, it will lock TPM to prevent TPM state change by malware.
1155 
1156   This API should be invoked after console in and console out are all ready as they are required
1157   to display request information and get user input to confirm the request. This API should also
1158   be invoked as early as possible as TPM is locked in this function.
1159 
1160 **/
1161 VOID
1162 EFIAPI
TcgPhysicalPresenceLibProcessRequest(VOID)1163 TcgPhysicalPresenceLibProcessRequest (
1164   VOID
1165   )
1166 {
1167   EFI_STATUS                        Status;
1168   BOOLEAN                           LifetimeLock;
1169   BOOLEAN                           CmdEnable;
1170   UINTN                             DataSize;
1171   EFI_PHYSICAL_PRESENCE             TcgPpData;
1172   EFI_TCG_PROTOCOL                  *TcgProtocol;
1173   EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
1174   EFI_PHYSICAL_PRESENCE_FLAGS       PpiFlags;
1175 
1176   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
1177   if (EFI_ERROR (Status)) {
1178     return ;
1179   }
1180 
1181   //
1182   // Initialize physical presence flags.
1183   //
1184   DataSize = sizeof (EFI_PHYSICAL_PRESENCE_FLAGS);
1185   Status = gRT->GetVariable (
1186                   PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1187                   &gEfiPhysicalPresenceGuid,
1188                   NULL,
1189                   &DataSize,
1190                   &PpiFlags
1191                   );
1192   if (EFI_ERROR (Status)) {
1193     PpiFlags.PPFlags = TCG_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_PROVISION;
1194     Status   = gRT->SetVariable (
1195                       PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1196                       &gEfiPhysicalPresenceGuid,
1197                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1198                       sizeof (EFI_PHYSICAL_PRESENCE_FLAGS),
1199                       &PpiFlags
1200                       );
1201     if (EFI_ERROR (Status)) {
1202       DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence flag failed, Status = %r\n", Status));
1203       return ;
1204     }
1205   }
1206   DEBUG ((EFI_D_INFO, "[TPM] PpiFlags = %x\n", PpiFlags.PPFlags));
1207 
1208   //
1209   // This flags variable controls whether physical presence is required for TPM command.
1210   // It should be protected from malicious software. We set it as read-only variable here.
1211   //
1212   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
1213   if (!EFI_ERROR (Status)) {
1214     Status = VariableLockProtocol->RequestToLock (
1215                                      VariableLockProtocol,
1216                                      PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1217                                      &gEfiPhysicalPresenceGuid
1218                                      );
1219     if (EFI_ERROR (Status)) {
1220       DEBUG ((EFI_D_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
1221       ASSERT_EFI_ERROR (Status);
1222     }
1223   }
1224 
1225   //
1226   // Initialize physical presence variable.
1227   //
1228   DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
1229   Status = gRT->GetVariable (
1230                   PHYSICAL_PRESENCE_VARIABLE,
1231                   &gEfiPhysicalPresenceGuid,
1232                   NULL,
1233                   &DataSize,
1234                   &TcgPpData
1235                   );
1236   if (EFI_ERROR (Status)) {
1237     ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
1238     DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
1239     Status   = gRT->SetVariable (
1240                       PHYSICAL_PRESENCE_VARIABLE,
1241                       &gEfiPhysicalPresenceGuid,
1242                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1243                       DataSize,
1244                       &TcgPpData
1245                       );
1246     if (EFI_ERROR (Status)) {
1247       DEBUG ((EFI_D_ERROR, "[TPM] Set physical presence variable failed, Status = %r\n", Status));
1248       return;
1249     }
1250   }
1251 
1252   DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags.PPFlags, TcgPpData.PPRequest));
1253 
1254   if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {
1255     //
1256     // No operation request
1257     //
1258     return;
1259   }
1260 
1261   Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable);
1262   if (EFI_ERROR (Status)) {
1263     return ;
1264   }
1265 
1266   if (!CmdEnable) {
1267     if (LifetimeLock) {
1268       //
1269       // physicalPresenceCMDEnable is locked, can't execute physical presence command.
1270       //
1271       return ;
1272     }
1273     Status = TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
1274     if (EFI_ERROR (Status)) {
1275       return ;
1276     }
1277   }
1278 
1279   //
1280   // Set operator physical presence flags
1281   //
1282   TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_PRESENT);
1283 
1284   //
1285   // Execute pending TPM request.
1286   //
1287   ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags);
1288   DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse));
1289 
1290   //
1291   // Lock physical presence.
1292   //
1293   TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK);
1294 }
1295 
1296 /**
1297   Check if the pending TPM request needs user input to confirm.
1298 
1299   The TPM request may come from OS. This API will check if TPM request exists and need user
1300   input to confirmation.
1301 
1302   @retval    TRUE        TPM needs input to confirm user physical presence.
1303   @retval    FALSE       TPM doesn't need input to confirm user physical presence.
1304 
1305 **/
1306 BOOLEAN
1307 EFIAPI
TcgPhysicalPresenceLibNeedUserConfirm(VOID)1308 TcgPhysicalPresenceLibNeedUserConfirm(
1309   VOID
1310   )
1311 {
1312   EFI_STATUS                   Status;
1313   EFI_PHYSICAL_PRESENCE        TcgPpData;
1314   UINTN                        DataSize;
1315   BOOLEAN                      RequestConfirmed;
1316   BOOLEAN                      LifetimeLock;
1317   BOOLEAN                      CmdEnable;
1318   EFI_TCG_PROTOCOL             *TcgProtocol;
1319   EFI_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
1320 
1321   Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
1322   if (EFI_ERROR (Status)) {
1323     return FALSE;
1324   }
1325 
1326   //
1327   // Check Tpm requests
1328   //
1329   DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
1330   Status = gRT->GetVariable (
1331                   PHYSICAL_PRESENCE_VARIABLE,
1332                   &gEfiPhysicalPresenceGuid,
1333                   NULL,
1334                   &DataSize,
1335                   &TcgPpData
1336                   );
1337   if (EFI_ERROR (Status)) {
1338     return FALSE;
1339   }
1340 
1341   DataSize = sizeof (EFI_PHYSICAL_PRESENCE_FLAGS);
1342   Status = gRT->GetVariable (
1343                   PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1344                   &gEfiPhysicalPresenceGuid,
1345                   NULL,
1346                   &DataSize,
1347                   &PpiFlags
1348                   );
1349   if (EFI_ERROR (Status)) {
1350     return FALSE;
1351   }
1352 
1353   if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {
1354     //
1355     // No operation request
1356     //
1357     return FALSE;
1358   }
1359 
1360   if (!HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {
1361     //
1362     // Invalid operation request.
1363     //
1364     return FALSE;
1365   }
1366 
1367   //
1368   // Check Tpm Capability
1369   //
1370   Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable);
1371   if (EFI_ERROR (Status)) {
1372     return FALSE;
1373   }
1374 
1375   if (!CmdEnable) {
1376     if (LifetimeLock) {
1377       //
1378       // physicalPresenceCMDEnable is locked, can't execute physical presence command.
1379       //
1380       return FALSE;
1381     }
1382   }
1383 
1384   if (!RequestConfirmed) {
1385     //
1386     // Need UI to confirm
1387     //
1388     return TRUE;
1389   }
1390 
1391   return FALSE;
1392 }
1393 
1394