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