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