]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c
OvmfPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / OvmfPkg / Library / Tcg2PhysicalPresenceLibQemu / DxeTcg2PhysicalPresenceLib.c
CommitLineData
b9777bb4
MAL
1/** @file\r
2 Execute pending TPM2 requests from OS or BIOS.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This driver will have external input - variable.\r
6 This external input must be validated carefully to avoid security issue.\r
7\r
8 Tcg2ExecutePendingTpmRequest() will receive untrusted input and do validation.\r
9\r
10Copyright (C) 2018, Red Hat, Inc.\r
11Copyright (c) 2018, IBM Corporation. All rights reserved.<BR>\r
12Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>\r
b26f0cf9 13SPDX-License-Identifier: BSD-2-Clause-Patent\r
b9777bb4
MAL
14\r
15**/\r
16\r
17#include <PiDxe.h>\r
18\r
19#include <Guid/Tcg2PhysicalPresenceData.h>\r
20#include <IndustryStandard/QemuTpm.h>\r
21#include <Protocol/Tcg2Protocol.h>\r
22\r
23#include <Library/BaseMemoryLib.h>\r
24#include <Library/DebugLib.h>\r
25#include <Library/DxeServicesTableLib.h>\r
26#include <Library/HiiLib.h>\r
27#include <Library/HobLib.h>\r
28#include <Library/MemoryAllocationLib.h>\r
29#include <Library/PrintLib.h>\r
30#include <Library/QemuFwCfgLib.h>\r
31#include <Library/Tpm2CommandLib.h>\r
32#include <Library/UefiBootServicesTableLib.h>\r
33#include <Library/UefiLib.h>\r
34#include <Library/UefiRuntimeServicesTableLib.h>\r
35\r
36#include <Library/Tcg2PhysicalPresenceLib.h>\r
37\r
38#define CONFIRM_BUFFER_SIZE 4096\r
39\r
40EFI_HII_HANDLE mTcg2PpStringPackHandle;\r
41\r
42#define TPM_PPI_FLAGS (QEMU_TPM_PPI_FUNC_ALLOWED_USR_REQ)\r
43\r
44STATIC volatile QEMU_TPM_PPI *mPpi;\r
45\r
46\r
47/**\r
48 Reads QEMU PPI config from fw_cfg.\r
49\r
50 @param[out] The Config structure to read to.\r
51\r
52 @retval EFI_SUCCESS Operation completed successfully.\r
53 @retval EFI_PROTOCOL_ERROR Invalid fw_cfg entry size.\r
54**/\r
55STATIC\r
56EFI_STATUS\r
57QemuTpmReadConfig (\r
58 OUT QEMU_FWCFG_TPM_CONFIG *Config\r
59 )\r
60{\r
61 EFI_STATUS Status;\r
62 FIRMWARE_CONFIG_ITEM FwCfgItem;\r
63 UINTN FwCfgSize;\r
64\r
65 Status = QemuFwCfgFindFile ("etc/tpm/config", &FwCfgItem, &FwCfgSize);\r
66 if (EFI_ERROR (Status)) {\r
67 return Status;\r
68 }\r
69\r
70 if (FwCfgSize != sizeof (*Config)) {\r
71 return EFI_PROTOCOL_ERROR;\r
72 }\r
73\r
74 QemuFwCfgSelectItem (FwCfgItem);\r
75 QemuFwCfgReadBytes (sizeof (*Config), Config);\r
76 return EFI_SUCCESS;\r
77}\r
78\r
79\r
80/**\r
81 Initializes QEMU PPI memory region.\r
82\r
83 @retval EFI_SUCCESS Operation completed successfully.\r
84 @retval EFI_PROTOCOL_ERROR PPI address is invalid.\r
85**/\r
86STATIC\r
87EFI_STATUS\r
88QemuTpmInitPPI (\r
89 VOID\r
90 )\r
91{\r
92 EFI_STATUS Status;\r
93 QEMU_FWCFG_TPM_CONFIG Config;\r
94 EFI_PHYSICAL_ADDRESS PpiAddress64;\r
95 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
96 UINTN Idx;\r
97\r
98 if (mPpi != NULL) {\r
99 return EFI_SUCCESS;\r
100 }\r
101\r
102 Status = QemuTpmReadConfig (&Config);\r
103 if (EFI_ERROR (Status)) {\r
104 return Status;\r
105 }\r
106\r
107 mPpi = (QEMU_TPM_PPI *)(UINTN)Config.PpiAddress;\r
108 if (mPpi == NULL) {\r
109 return EFI_PROTOCOL_ERROR;\r
110 }\r
111\r
112 DEBUG ((DEBUG_INFO, "[TPM2PP] mPpi=%p version=%d\n", mPpi, Config.TpmVersion));\r
113\r
114 PpiAddress64 = (UINTN)mPpi;\r
115 if ((PpiAddress64 & ~(UINT64)EFI_PAGE_MASK) !=\r
116 ((PpiAddress64 + sizeof *mPpi - 1) & ~(UINT64)EFI_PAGE_MASK)) {\r
117 DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi crosses a page boundary\n"));\r
118 goto InvalidPpiAddress;\r
119 }\r
120\r
121 Status = gDS->GetMemorySpaceDescriptor (PpiAddress64, &Descriptor);\r
122 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
123 ASSERT_EFI_ERROR (Status);\r
124 goto InvalidPpiAddress;\r
125 }\r
126 if (!EFI_ERROR (Status) &&\r
127 (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo &&\r
128 Descriptor.GcdMemoryType != EfiGcdMemoryTypeNonExistent)) {\r
129 DEBUG ((DEBUG_ERROR, "[TPM2PP] mPpi has an invalid memory type\n"));\r
130 goto InvalidPpiAddress;\r
131 }\r
132\r
133 for (Idx = 0; Idx < ARRAY_SIZE (mPpi->Func); Idx++) {\r
134 mPpi->Func[Idx] = 0;\r
135 }\r
136 if (Config.TpmVersion == QEMU_TPM_VERSION_2) {\r
137 mPpi->Func[TCG2_PHYSICAL_PRESENCE_NO_ACTION] = TPM_PPI_FLAGS;\r
138 mPpi->Func[TCG2_PHYSICAL_PRESENCE_CLEAR] = TPM_PPI_FLAGS;\r
139 mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR] = TPM_PPI_FLAGS;\r
140 mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2] = TPM_PPI_FLAGS;\r
141 mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3] = TPM_PPI_FLAGS;\r
142 mPpi->Func[TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS] = TPM_PPI_FLAGS;\r
143 mPpi->Func[TCG2_PHYSICAL_PRESENCE_CHANGE_EPS] = TPM_PPI_FLAGS;\r
144 mPpi->Func[TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS] = TPM_PPI_FLAGS;\r
145 mPpi->Func[TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID] = TPM_PPI_FLAGS;\r
146 mPpi->Func[TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID] = TPM_PPI_FLAGS;\r
147 }\r
148\r
149 if (mPpi->In == 0) {\r
150 mPpi->In = 1;\r
151 mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
152 mPpi->LastRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
153 mPpi->NextStep = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
154 }\r
155\r
156 return EFI_SUCCESS;\r
157\r
158InvalidPpiAddress:\r
159 mPpi = NULL;\r
160 return EFI_PROTOCOL_ERROR;\r
161}\r
162\r
163\r
164/**\r
165 Get string by string id from HII Interface.\r
166\r
167 @param[in] Id String ID.\r
168\r
169 @retval CHAR16 * String from ID.\r
170 @retval NULL If error occurs.\r
171\r
172**/\r
173STATIC\r
174CHAR16 *\r
175Tcg2PhysicalPresenceGetStringById (\r
176 IN EFI_STRING_ID Id\r
177 )\r
178{\r
179 return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);\r
180}\r
181\r
182\r
183/**\r
184 Send ClearControl and Clear command to TPM.\r
185\r
186 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
187\r
188 @retval EFI_SUCCESS Operation completed successfully.\r
189 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
190 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
191 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
192\r
193**/\r
194EFI_STATUS\r
195EFIAPI\r
196Tpm2CommandClear (\r
197 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
198 )\r
199{\r
200 EFI_STATUS Status;\r
201 TPMS_AUTH_COMMAND *AuthSession;\r
202 TPMS_AUTH_COMMAND LocalAuthSession;\r
203\r
204 if (PlatformAuth == NULL) {\r
205 AuthSession = NULL;\r
206 } else {\r
207 AuthSession = &LocalAuthSession;\r
208 ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));\r
209 LocalAuthSession.sessionHandle = TPM_RS_PW;\r
210 LocalAuthSession.hmac.size = PlatformAuth->size;\r
211 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
212 }\r
213\r
214 DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n"));\r
215 Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);\r
216 DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status));\r
217 if (EFI_ERROR (Status)) {\r
218 goto Done;\r
219 }\r
220 DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n"));\r
221 Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);\r
222 DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status));\r
223\r
224Done:\r
225 ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));\r
226 return Status;\r
227}\r
228\r
229\r
230/**\r
231 Change EPS.\r
232\r
233 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
234\r
235 @retval EFI_SUCCESS Operation completed successfully.\r
236**/\r
237STATIC\r
238EFI_STATUS\r
239Tpm2CommandChangeEps (\r
240 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
241 )\r
242{\r
243 EFI_STATUS Status;\r
244 TPMS_AUTH_COMMAND *AuthSession;\r
245 TPMS_AUTH_COMMAND LocalAuthSession;\r
246\r
247 if (PlatformAuth == NULL) {\r
248 AuthSession = NULL;\r
249 } else {\r
250 AuthSession = &LocalAuthSession;\r
251 ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));\r
252 LocalAuthSession.sessionHandle = TPM_RS_PW;\r
253 LocalAuthSession.hmac.size = PlatformAuth->size;\r
254 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);\r
255 }\r
256\r
257 Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);\r
258 DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status));\r
259\r
260 ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));\r
261 return Status;\r
262}\r
263\r
264\r
265/**\r
266 Execute physical presence operation requested by the OS.\r
267\r
268 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
269 @param[in] CommandCode Physical presence operation value.\r
270 @param[in] CommandParameter Physical presence operation parameter.\r
271\r
272 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation.\r
273 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or\r
274 receiving response from TPM.\r
275 @retval Others Return code from the TPM device after command execution.\r
276**/\r
277STATIC\r
278UINT32\r
279Tcg2ExecutePhysicalPresence (\r
280 IN TPM2B_AUTH *PlatformAuth, OPTIONAL\r
281 IN UINT32 CommandCode,\r
282 IN UINT32 CommandParameter\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;\r
287 UINT32 ActivePcrBanks;\r
288\r
289 switch (CommandCode) {\r
290 case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
291 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
292 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
293 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
294 Status = Tpm2CommandClear (PlatformAuth);\r
295 if (EFI_ERROR (Status)) {\r
296 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
297 } else {\r
298 return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
299 }\r
300\r
301 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
302 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);\r
303 ASSERT_EFI_ERROR (Status);\r
304\r
305 //\r
306 // PP spec requirements:\r
307 // Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks.\r
308 // Firmware has to ensure that at least one PCR banks is active.\r
309 // If not, an error is returned and no action is taken.\r
310 //\r
311 if (CommandParameter == 0 || (CommandParameter & (~TpmHashAlgorithmBitmap)) != 0) {\r
312 DEBUG((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter));\r
313 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
314 }\r
315\r
316 Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter);\r
317 if (EFI_ERROR (Status)) {\r
318 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
319 } else {\r
320 return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
321 }\r
322\r
323 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
324 Status = Tpm2CommandChangeEps (PlatformAuth);\r
325 if (EFI_ERROR (Status)) {\r
326 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
327 } else {\r
328 return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
329 }\r
330\r
331 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
332 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);\r
333 ASSERT_EFI_ERROR (Status);\r
334 Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap);\r
335 if (EFI_ERROR (Status)) {\r
336 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
337 } else {\r
338 return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
339 }\r
340\r
341 default:\r
342 if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
343 return TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
344 } else {\r
345 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
346 }\r
347 }\r
348}\r
349\r
350\r
351/**\r
352 Read the specified key for user confirmation.\r
353\r
354 @param[in] CautionKey If true, F12 is used as confirm key;\r
355 If false, F10 is used as confirm key.\r
356\r
357 @retval TRUE User confirmed the changes by input.\r
358 @retval FALSE User discarded the changes.\r
359**/\r
360STATIC\r
361BOOLEAN\r
362Tcg2ReadUserKey (\r
363 IN BOOLEAN CautionKey\r
364 )\r
365{\r
366 EFI_STATUS Status;\r
367 EFI_INPUT_KEY Key;\r
368 UINT16 InputKey;\r
369\r
370 InputKey = 0;\r
371 do {\r
372 Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
373 if (!EFI_ERROR (Status)) {\r
374 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
375 if (Key.ScanCode == SCAN_ESC) {\r
376 InputKey = Key.ScanCode;\r
377 }\r
378 if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
379 InputKey = Key.ScanCode;\r
380 }\r
381 if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
382 InputKey = Key.ScanCode;\r
383 }\r
384 }\r
385 } while (InputKey == 0);\r
386\r
387 if (InputKey != SCAN_ESC) {\r
388 return TRUE;\r
389 }\r
390\r
391 return FALSE;\r
392}\r
393\r
394\r
395/**\r
396 Fill Buffer With BootHashAlg.\r
397\r
398 @param[in] Buffer Buffer to be filled.\r
399 @param[in] BufferSize Size of buffer.\r
400 @param[in] BootHashAlg BootHashAlg.\r
401\r
402**/\r
403STATIC\r
404VOID\r
405Tcg2FillBufferWithBootHashAlg (\r
406 IN UINT16 *Buffer,\r
407 IN UINTN BufferSize,\r
408 IN UINT32 BootHashAlg\r
409 )\r
410{\r
411 Buffer[0] = 0;\r
412 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {\r
413 if (Buffer[0] != 0) {\r
414 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
415 }\r
416 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
417 }\r
418 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {\r
419 if (Buffer[0] != 0) {\r
420 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
421 }\r
422 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
423 }\r
424 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {\r
425 if (Buffer[0] != 0) {\r
426 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
427 }\r
428 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
429 }\r
430 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {\r
431 if (Buffer[0] != 0) {\r
432 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
433 }\r
434 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
435 }\r
436 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {\r
437 if (Buffer[0] != 0) {\r
438 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
439 }\r
440 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);\r
441 }\r
442}\r
443\r
444\r
445/**\r
446 Display the confirm text and get user confirmation.\r
447\r
448 @param[in] TpmPpCommand The requested TPM physical presence command.\r
449 @param[in] TpmPpCommandParameter The requested TPM physical presence command parameter.\r
450\r
451 @retval TRUE The user has confirmed the changes.\r
452 @retval FALSE The user doesn't confirm the changes.\r
453**/\r
454STATIC\r
455BOOLEAN\r
456Tcg2UserConfirm (\r
457 IN UINT32 TpmPpCommand,\r
458 IN UINT32 TpmPpCommandParameter\r
459 )\r
460{\r
461 CHAR16 *ConfirmText;\r
462 CHAR16 *TmpStr1;\r
463 CHAR16 *TmpStr2;\r
464 UINTN BufSize;\r
465 BOOLEAN CautionKey;\r
466 BOOLEAN NoPpiInfo;\r
467 UINT16 Index;\r
468 CHAR16 DstStr[81];\r
469 CHAR16 TempBuffer[1024];\r
470 CHAR16 TempBuffer2[1024];\r
471 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
472 EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability;\r
473 UINT32 CurrentPCRBanks;\r
474 EFI_STATUS Status;\r
475\r
476 TmpStr2 = NULL;\r
477 CautionKey = FALSE;\r
478 NoPpiInfo = FALSE;\r
479 BufSize = CONFIRM_BUFFER_SIZE;\r
480 ConfirmText = AllocateZeroPool (BufSize);\r
481 ASSERT (ConfirmText != NULL);\r
482\r
483 mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, Tcg2PhysicalPresenceLibQemuStrings, NULL);\r
484 ASSERT (mTcg2PpStringPackHandle != NULL);\r
485\r
486 switch (TpmPpCommand) {\r
487\r
488 case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
489 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
490 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
491 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
492 CautionKey = TRUE;\r
493 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));\r
494\r
495 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
496 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
497 FreePool (TmpStr1);\r
498\r
499 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));\r
500 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
501 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
502 FreePool (TmpStr1);\r
503\r
504 break;\r
505\r
506 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
507 Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
508 ASSERT_EFI_ERROR (Status);\r
509\r
510 ProtocolCapability.Size = sizeof(ProtocolCapability);\r
511 Status = Tcg2Protocol->GetCapability (\r
512 Tcg2Protocol,\r
513 &ProtocolCapability\r
514 );\r
515 ASSERT_EFI_ERROR (Status);\r
516\r
517 Status = Tcg2Protocol->GetActivePcrBanks (\r
518 Tcg2Protocol,\r
519 &CurrentPCRBanks\r
520 );\r
521 ASSERT_EFI_ERROR (Status);\r
522\r
523 CautionKey = TRUE;\r
524 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));\r
525\r
526 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
527 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
528 FreePool (TmpStr1);\r
529\r
530 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));\r
531 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
532 FreePool (TmpStr1);\r
533\r
534 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));\r
535 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
536 FreePool (TmpStr1);\r
537\r
538 Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter);\r
539 Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks);\r
540\r
541 TmpStr1 = AllocateZeroPool (BufSize);\r
542 ASSERT (TmpStr1 != NULL);\r
543 UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);\r
544\r
545 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
546 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
547 FreePool (TmpStr1);\r
548\r
549 break;\r
550\r
551 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
552 CautionKey = TRUE;\r
553 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));\r
554\r
555 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));\r
556 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
557 FreePool (TmpStr1);\r
558\r
559 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));\r
560 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
561 FreePool (TmpStr1);\r
562\r
563 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));\r
564 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
565 FreePool (TmpStr1);\r
566\r
567 break;\r
568\r
569 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:\r
570 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID));\r
571\r
572 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));\r
573 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
574 FreePool (TmpStr1);\r
575 break;\r
576\r
577 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:\r
578 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID));\r
579\r
580 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));\r
581 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);\r
582 FreePool (TmpStr1);\r
583 break;\r
584\r
585 default:\r
586 ;\r
587 }\r
588\r
589 if (TmpStr2 == NULL) {\r
590 FreePool (ConfirmText);\r
591 return FALSE;\r
592 }\r
593\r
594 if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {\r
595 if (CautionKey) {\r
596 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));\r
597 } else {\r
598 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));\r
599 }\r
600 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
601 FreePool (TmpStr1);\r
602\r
603 if (NoPpiInfo) {\r
604 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));\r
605 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
606 FreePool (TmpStr1);\r
607 }\r
608\r
609 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));\r
610 } else {\r
611 if (CautionKey) {\r
612 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));\r
613 } else {\r
614 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));\r
615 }\r
616 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
617 FreePool (TmpStr1);\r
618\r
619 if (NoPpiInfo) {\r
620 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));\r
621 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);\r
622 FreePool (TmpStr1);\r
623 }\r
624\r
625 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));\r
626 }\r
627 BufSize -= StrSize (ConfirmText);\r
628 UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);\r
629\r
630 DstStr[80] = L'\0';\r
631 for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {\r
632 StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);\r
633 Print (DstStr);\r
634 }\r
635\r
636 FreePool (TmpStr1);\r
637 FreePool (TmpStr2);\r
638 FreePool (ConfirmText);\r
639 HiiRemovePackages (mTcg2PpStringPackHandle);\r
640\r
641 if (Tcg2ReadUserKey (CautionKey)) {\r
642 return TRUE;\r
643 }\r
644\r
645 return FALSE;\r
646}\r
647\r
648\r
649/**\r
650 Check if there is a valid physical presence command request. Also updates parameter value\r
651 to whether the requested physical presence command already confirmed by user\r
652\r
653 @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.\r
654 True, it indicates the command doesn't require user confirm, or already confirmed\r
655 in last boot cycle by user.\r
656 False, it indicates the command need user confirm from UI.\r
657\r
658 @retval TRUE Physical Presence operation command is valid.\r
659 @retval FALSE Physical Presence operation command is invalid.\r
660\r
661**/\r
662STATIC\r
663BOOLEAN\r
664Tcg2HaveValidTpmRequest (\r
665 OUT BOOLEAN *RequestConfirmed\r
666 )\r
667{\r
668 EFI_TCG2_PROTOCOL *Tcg2Protocol;\r
669 EFI_STATUS Status;\r
670\r
671 *RequestConfirmed = FALSE;\r
672\r
673 if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
674 //\r
675 // Need TCG2 protocol.\r
676 //\r
677 Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);\r
678 if (EFI_ERROR (Status)) {\r
679 return FALSE;\r
680 }\r
681 }\r
682\r
683 switch (mPpi->Request) {\r
684 case TCG2_PHYSICAL_PRESENCE_NO_ACTION:\r
685 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
686 *RequestConfirmed = TRUE;\r
687 return TRUE;\r
688\r
689 case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
690 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
691 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
692 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
693 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
694 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
695 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:\r
696 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:\r
697 break;\r
698\r
699 default:\r
700 //\r
701 // Wrong Physical Presence command\r
702 //\r
703 return FALSE;\r
704 }\r
705\r
706 //\r
707 // Physical Presence command is correct\r
708 //\r
709 return TRUE;\r
710}\r
711\r
712\r
713/**\r
714 Check and execute the requested physical presence command.\r
715\r
716 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
717**/\r
718STATIC\r
719VOID\r
720Tcg2ExecutePendingTpmRequest (\r
721 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
722 )\r
723{\r
724 BOOLEAN RequestConfirmed;\r
725\r
726 if (mPpi->Request == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {\r
727 //\r
728 // No operation request\r
729 //\r
730 return;\r
731 }\r
732\r
733 if (!Tcg2HaveValidTpmRequest (&RequestConfirmed)) {\r
734 //\r
735 // Invalid operation request.\r
736 //\r
737 if (mPpi->Request <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {\r
738 mPpi->Response = TCG_PP_OPERATION_RESPONSE_SUCCESS;\r
739 } else {\r
740 mPpi->Response = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;\r
741 }\r
742 mPpi->LastRequest = mPpi->Request;\r
743 mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
744 mPpi->RequestParameter = 0;\r
745 return;\r
746 }\r
747\r
748 if (!RequestConfirmed) {\r
749 //\r
750 // Print confirm text and wait for approval.\r
751 //\r
752 RequestConfirmed = Tcg2UserConfirm (mPpi->Request, mPpi->RequestParameter);\r
753 }\r
754\r
755 //\r
756 // Execute requested physical presence command\r
757 //\r
758 mPpi->Response = TCG_PP_OPERATION_RESPONSE_USER_ABORT;\r
759 if (RequestConfirmed) {\r
760 mPpi->Response = Tcg2ExecutePhysicalPresence (\r
761 PlatformAuth,\r
762 mPpi->Request,\r
763 mPpi->RequestParameter\r
764 );\r
765 }\r
766\r
767 //\r
768 // Clear request\r
769 //\r
770 mPpi->LastRequest = mPpi->Request;\r
771 mPpi->Request = TCG2_PHYSICAL_PRESENCE_NO_ACTION;\r
772 mPpi->RequestParameter = 0;\r
773\r
774 if (mPpi->Response == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {\r
775 return;\r
776 }\r
777\r
778 //\r
779 // Reset system to make new TPM settings in effect\r
780 //\r
781 switch (mPpi->LastRequest) {\r
782 case TCG2_PHYSICAL_PRESENCE_CLEAR:\r
783 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:\r
784 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:\r
785 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:\r
786 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:\r
787 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:\r
788 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:\r
789 break;\r
790\r
791 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:\r
792 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:\r
793 break;\r
794\r
795 default:\r
796 if (mPpi->Request != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {\r
797 break;\r
798 }\r
799 return;\r
800 }\r
801\r
802 Print (L"Rebooting system to make TPM2 settings in effect\n");\r
803 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
804 ASSERT (FALSE);\r
805}\r
806\r
807\r
808/**\r
809 Check and execute the pending TPM request.\r
810\r
811 The TPM request may come from OS or BIOS. This API will display request information and wait\r
812 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after\r
813 the TPM request is confirmed, and one or more reset may be required to make TPM request to\r
814 take effect.\r
815\r
816 This API should be invoked after console in and console out are all ready as they are required\r
817 to display request information and get user input to confirm the request.\r
818\r
819 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.\r
820**/\r
821VOID\r
822EFIAPI\r
823Tcg2PhysicalPresenceLibProcessRequest (\r
824 IN TPM2B_AUTH *PlatformAuth OPTIONAL\r
825 )\r
826{\r
827 EFI_STATUS Status;\r
828\r
829 Status = QemuTpmInitPPI ();\r
830 if (EFI_ERROR (Status)) {\r
831 DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n"));\r
832 return ;\r
833 }\r
834\r
835 //\r
836 // Check S4 resume\r
837 //\r
838 if (GetBootModeHob () == BOOT_ON_S4_RESUME) {\r
839 DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n"));\r
840 return ;\r
841 }\r
842\r
843 DEBUG ((DEBUG_INFO, "[TPM2PP] PPRequest=%x (PPRequestParameter=%x)\n", mPpi->Request, mPpi->RequestParameter));\r
844 Tcg2ExecutePendingTpmRequest (PlatformAuth);\r
845}\r
846\r
847\r
848/**\r
849 The handler for TPM physical presence function:\r
850 Return TPM Operation Response to OS Environment.\r
851\r
852 @param[out] MostRecentRequest Most recent operation request.\r
853 @param[out] Response Response to the most recent operation request.\r
854\r
855 @return Return Code for Return TPM Operation Response to OS Environment.\r
856**/\r
857UINT32\r
858EFIAPI\r
859Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
860 OUT UINT32 *MostRecentRequest,\r
861 OUT UINT32 *Response\r
862 )\r
863{\r
864 EFI_STATUS Status;\r
865\r
866 DEBUG ((DEBUG_INFO, "[TPM2PP] ReturnOperationResponseToOsFunction\n"));\r
867\r
868 Status = QemuTpmInitPPI ();\r
869 if (EFI_ERROR (Status)) {\r
870 DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n"));\r
871 *MostRecentRequest = 0;\r
872 *Response = 0;\r
873 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;\r
874 }\r
875\r
876 *MostRecentRequest = mPpi->LastRequest;\r
877 *Response = mPpi->Response;\r
878\r
879 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;\r
880}\r
881\r
882\r
883/**\r
884 The handler for TPM physical presence function:\r
885 Submit TPM Operation Request to Pre-OS Environment and\r
886 Submit TPM Operation Request to Pre-OS Environment 2.\r
887\r
888 Caution: This function may receive untrusted input.\r
889\r
890 @param[in] OperationRequest TPM physical presence operation request.\r
891 @param[in] RequestParameter TPM physical presence operation request parameter.\r
892\r
893 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and\r
894 Submit TPM Operation Request to Pre-OS Environment 2.\r
895**/\r
896UINT32\r
897EFIAPI\r
898Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (\r
899 IN UINT32 OperationRequest,\r
900 IN UINT32 RequestParameter\r
901 )\r
902{\r
903 EFI_STATUS Status;\r
904\r
905 DEBUG ((DEBUG_INFO, "[TPM2PP] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));\r
906\r
907 Status = QemuTpmInitPPI ();\r
908 if (EFI_ERROR (Status)) {\r
909 DEBUG ((DEBUG_INFO, "[TPM2PP] no PPI\n"));\r
910 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;\r
911 }\r
912\r
913 mPpi->Request = OperationRequest;\r
914 mPpi->RequestParameter = RequestParameter;\r
915\r
916 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;\r
917}\r