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