VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.c

Last change on this file was 105674, checked in by vboxsync, 7 months ago

Devices/EFI/FirmwareNew: Fix compiling DxeTcg2PhysicalPresenceLib.c with debugging enabled, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette