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