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