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