]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
5ece8e513abc5921095c583b326d587c013ed2a9
[mirror_edk2.git] / SecurityPkg / Library / DxeTcg2PhysicalPresenceLib / 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 Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
9
10 Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
11 This program and the accompanying materials
12 are licensed and made available under the terms and conditions of the BSD License
13 which accompanies this distribution. The full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
15
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18
19 **/
20
21 #include <PiDxe.h>
22
23 #include <Protocol/Tcg2Protocol.h>
24 #include <Protocol/VariableLock.h>
25 #include <Library/DebugLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/UefiRuntimeServicesTableLib.h>
28 #include <Library/UefiDriverEntryPoint.h>
29 #include <Library/UefiBootServicesTableLib.h>
30 #include <Library/UefiLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/PrintLib.h>
33 #include <Library/HiiLib.h>
34 #include <Library/HobLib.h>
35 #include <Guid/EventGroup.h>
36 #include <Guid/Tcg2PhysicalPresenceData.h>
37 #include <Library/Tpm2CommandLib.h>
38 #include <Library/Tcg2PhysicalPresenceLib.h>
39 #include <Library/Tcg2PpVendorLib.h>
40
41 #define CONFIRM_BUFFER_SIZE 4096
42
43 EFI_HII_HANDLE mTcg2PpStringPackHandle;
44
45 /**
46 Get string by string id from HII Interface.
47
48 @param[in] Id String ID.
49
50 @retval CHAR16 * String from ID.
51 @retval NULL If error occurs.
52
53 **/
54 CHAR16 *
55 Tcg2PhysicalPresenceGetStringById (
56 IN EFI_STRING_ID Id
57 )
58 {
59 return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);
60 }
61
62 /**
63 Send ClearControl and Clear command to TPM.
64
65 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
66
67 @retval EFI_SUCCESS Operation completed successfully.
68 @retval EFI_TIMEOUT The register can't run into the expected status in time.
69 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.
70 @retval EFI_DEVICE_ERROR Unexpected device behavior.
71
72 **/
73 EFI_STATUS
74 EFIAPI
75 Tpm2CommandClear (
76 IN TPM2B_AUTH *PlatformAuth OPTIONAL
77 )
78 {
79 EFI_STATUS Status;
80 TPMS_AUTH_COMMAND *AuthSession;
81 TPMS_AUTH_COMMAND LocalAuthSession;
82
83 if (PlatformAuth == NULL) {
84 AuthSession = NULL;
85 } else {
86 AuthSession = &LocalAuthSession;
87 ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
88 LocalAuthSession.sessionHandle = TPM_RS_PW;
89 LocalAuthSession.hmac.size = PlatformAuth->size;
90 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
91 }
92
93 DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n"));
94 Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);
95 DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status));
96 if (EFI_ERROR (Status)) {
97 goto Done;
98 }
99 DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n"));
100 Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);
101 DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status));
102
103 Done:
104 ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
105 return Status;
106 }
107
108 /**
109 Change EPS.
110
111 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
112
113 @retval EFI_SUCCESS Operation completed successfully.
114 **/
115 EFI_STATUS
116 Tpm2CommandChangeEps (
117 IN TPM2B_AUTH *PlatformAuth OPTIONAL
118 )
119 {
120 EFI_STATUS Status;
121 TPMS_AUTH_COMMAND *AuthSession;
122 TPMS_AUTH_COMMAND LocalAuthSession;
123
124 if (PlatformAuth == NULL) {
125 AuthSession = NULL;
126 } else {
127 AuthSession = &LocalAuthSession;
128 ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
129 LocalAuthSession.sessionHandle = TPM_RS_PW;
130 LocalAuthSession.hmac.size = PlatformAuth->size;
131 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
132 }
133
134 Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);
135 DEBUG ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status));
136
137 ZeroMem(&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
138 return Status;
139 }
140
141 /**
142 Execute physical presence operation requested by the OS.
143
144 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
145 @param[in] CommandCode Physical presence operation value.
146 @param[in] CommandParameter Physical presence operation parameter.
147 @param[in, out] PpiFlags The physical presence interface flags.
148
149 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Unknown physical presence operation.
150 @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE Error occurred during sending command to TPM or
151 receiving response from TPM.
152 @retval Others Return code from the TPM device after command execution.
153 **/
154 UINT32
155 Tcg2ExecutePhysicalPresence (
156 IN TPM2B_AUTH *PlatformAuth, OPTIONAL
157 IN UINT32 CommandCode,
158 IN UINT32 CommandParameter,
159 IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
160 )
161 {
162 EFI_STATUS Status;
163 EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
164 UINT32 ActivePcrBanks;
165
166 switch (CommandCode) {
167 case TCG2_PHYSICAL_PRESENCE_CLEAR:
168 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
169 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
170 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
171 Status = Tpm2CommandClear (PlatformAuth);
172 if (EFI_ERROR (Status)) {
173 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
174 } else {
175 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
176 }
177
178 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
179 PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
180 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
181
182 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
183 PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
184 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
185
186 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
187 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
188 ASSERT_EFI_ERROR (Status);
189
190 //
191 // PP spec requirements:
192 // Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks.
193 // Firmware has to ensure that at least one PCR banks is active.
194 // If not, an error is returned and no action is taken.
195 //
196 if (CommandParameter == 0 || (CommandParameter & (~TpmHashAlgorithmBitmap)) != 0) {
197 DEBUG((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter));
198 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
199 }
200
201 Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter);
202 if (EFI_ERROR (Status)) {
203 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
204 } else {
205 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
206 }
207
208 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
209 Status = Tpm2CommandChangeEps (PlatformAuth);
210 if (EFI_ERROR (Status)) {
211 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
212 } else {
213 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
214 }
215
216 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
217 Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
218 ASSERT_EFI_ERROR (Status);
219 Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap);
220 if (EFI_ERROR (Status)) {
221 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
222 } else {
223 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
224 }
225
226 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
227 PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
228 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
229
230 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
231 PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
232 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
233
234 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
235 PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
236 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
237
238 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
239 PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
240 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
241
242 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
243 PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
244 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
245
246 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
247 PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
248 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
249
250 default:
251 if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
252 return TCG_PP_OPERATION_RESPONSE_SUCCESS;
253 } else {
254 return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
255 }
256 }
257 }
258
259
260 /**
261 Read the specified key for user confirmation.
262
263 @param[in] CautionKey If true, F12 is used as confirm key;
264 If false, F10 is used as confirm key.
265
266 @retval TRUE User confirmed the changes by input.
267 @retval FALSE User discarded the changes.
268 **/
269 BOOLEAN
270 Tcg2ReadUserKey (
271 IN BOOLEAN CautionKey
272 )
273 {
274 EFI_STATUS Status;
275 EFI_INPUT_KEY Key;
276 UINT16 InputKey;
277
278 InputKey = 0;
279 do {
280 Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
281 if (!EFI_ERROR (Status)) {
282 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
283 if (Key.ScanCode == SCAN_ESC) {
284 InputKey = Key.ScanCode;
285 }
286 if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
287 InputKey = Key.ScanCode;
288 }
289 if ((Key.ScanCode == SCAN_F12) && CautionKey) {
290 InputKey = Key.ScanCode;
291 }
292 }
293 } while (InputKey == 0);
294
295 if (InputKey != SCAN_ESC) {
296 return TRUE;
297 }
298
299 return FALSE;
300 }
301
302 /**
303 Fill Buffer With BootHashAlg.
304
305 @param[in] Buffer Buffer to be filled.
306 @param[in] BufferSize Size of buffer.
307 @param[in] BootHashAlg BootHashAlg.
308
309 **/
310 VOID
311 Tcg2FillBufferWithBootHashAlg (
312 IN UINT16 *Buffer,
313 IN UINTN BufferSize,
314 IN UINT32 BootHashAlg
315 )
316 {
317 Buffer[0] = 0;
318 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
319 if (Buffer[0] != 0) {
320 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
321 }
322 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
323 }
324 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
325 if (Buffer[0] != 0) {
326 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
327 }
328 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
329 }
330 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
331 if (Buffer[0] != 0) {
332 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
333 }
334 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
335 }
336 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
337 if (Buffer[0] != 0) {
338 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
339 }
340 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
341 }
342 if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
343 if (Buffer[0] != 0) {
344 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
345 }
346 StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
347 }
348 }
349
350 /**
351 Display the confirm text and get user confirmation.
352
353 @param[in] TpmPpCommand The requested TPM physical presence command.
354 @param[in] TpmPpCommandParameter The requested TPM physical presence command parameter.
355
356 @retval TRUE The user has confirmed the changes.
357 @retval FALSE The user doesn't confirm the changes.
358 **/
359 BOOLEAN
360 Tcg2UserConfirm (
361 IN UINT32 TpmPpCommand,
362 IN UINT32 TpmPpCommandParameter
363 )
364 {
365 CHAR16 *ConfirmText;
366 CHAR16 *TmpStr1;
367 CHAR16 *TmpStr2;
368 UINTN BufSize;
369 BOOLEAN CautionKey;
370 BOOLEAN NoPpiInfo;
371 UINT16 Index;
372 CHAR16 DstStr[81];
373 CHAR16 TempBuffer[1024];
374 CHAR16 TempBuffer2[1024];
375 EFI_TCG2_PROTOCOL *Tcg2Protocol;
376 EFI_TCG2_BOOT_SERVICE_CAPABILITY ProtocolCapability;
377 UINT32 CurrentPCRBanks;
378 EFI_STATUS Status;
379
380 TmpStr2 = NULL;
381 CautionKey = FALSE;
382 NoPpiInfo = FALSE;
383 BufSize = CONFIRM_BUFFER_SIZE;
384 ConfirmText = AllocateZeroPool (BufSize);
385 ASSERT (ConfirmText != NULL);
386
387 mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);
388 ASSERT (mTcg2PpStringPackHandle != NULL);
389
390 switch (TpmPpCommand) {
391
392 case TCG2_PHYSICAL_PRESENCE_CLEAR:
393 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
394 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
395 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
396 CautionKey = TRUE;
397 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
398
399 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
400 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
401 FreePool (TmpStr1);
402
403 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
404 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
405 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
406 FreePool (TmpStr1);
407
408 break;
409
410 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
411 CautionKey = TRUE;
412 NoPpiInfo = TRUE;
413 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
414
415 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
416 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
417 FreePool (TmpStr1);
418
419 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
420 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
421 FreePool (TmpStr1);
422
423 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
424 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
425 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
426 FreePool (TmpStr1);
427
428 break;
429
430 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
431 Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
432 ASSERT_EFI_ERROR (Status);
433
434 ProtocolCapability.Size = sizeof(ProtocolCapability);
435 Status = Tcg2Protocol->GetCapability (
436 Tcg2Protocol,
437 &ProtocolCapability
438 );
439 ASSERT_EFI_ERROR (Status);
440
441 Status = Tcg2Protocol->GetActivePcrBanks (
442 Tcg2Protocol,
443 &CurrentPCRBanks
444 );
445 ASSERT_EFI_ERROR (Status);
446
447 CautionKey = TRUE;
448 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));
449
450 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
451 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
452 FreePool (TmpStr1);
453
454 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));
455 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
456 FreePool (TmpStr1);
457
458 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));
459 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
460 FreePool (TmpStr1);
461
462 Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter);
463 Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks);
464
465 TmpStr1 = AllocateZeroPool (BufSize);
466 ASSERT (TmpStr1 != NULL);
467 UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);
468
469 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
470 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
471 FreePool (TmpStr1);
472
473 break;
474
475 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
476 CautionKey = TRUE;
477 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));
478
479 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
480 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
481 FreePool (TmpStr1);
482
483 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));
484 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
485 FreePool (TmpStr1);
486
487 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));
488 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
489 FreePool (TmpStr1);
490
491 break;
492
493 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
494 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID));
495
496 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
497 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
498 FreePool (TmpStr1);
499 break;
500
501 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
502 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID));
503
504 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
505 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
506 FreePool (TmpStr1);
507 break;
508
509 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
510 NoPpiInfo = TRUE;
511 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_ENABLE_BLOCK_SID));
512
513 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
514 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
515 FreePool (TmpStr1);
516 break;
517
518 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
519 NoPpiInfo = TRUE;
520 TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_DISABLE_BLOCK_SID));
521
522 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
523 UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
524 FreePool (TmpStr1);
525 break;
526
527 default:
528 ;
529 }
530
531 if (TmpStr2 == NULL) {
532 FreePool (ConfirmText);
533 return FALSE;
534 }
535
536 if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {
537 if (CautionKey) {
538 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
539 } else {
540 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
541 }
542 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
543 FreePool (TmpStr1);
544
545 if (NoPpiInfo) {
546 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
547 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
548 FreePool (TmpStr1);
549 }
550
551 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
552 } else {
553 if (CautionKey) {
554 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));
555 } else {
556 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));
557 }
558 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
559 FreePool (TmpStr1);
560
561 if (NoPpiInfo) {
562 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));
563 StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
564 FreePool (TmpStr1);
565 }
566
567 TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));
568 }
569 BufSize -= StrSize (ConfirmText);
570 UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
571
572 DstStr[80] = L'\0';
573 for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
574 StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);
575 Print (DstStr);
576 }
577
578 FreePool (TmpStr1);
579 FreePool (TmpStr2);
580 FreePool (ConfirmText);
581 HiiRemovePackages (mTcg2PpStringPackHandle);
582
583 if (Tcg2ReadUserKey (CautionKey)) {
584 return TRUE;
585 }
586
587 return FALSE;
588 }
589
590 /**
591 Check if there is a valid physical presence command request. Also updates parameter value
592 to whether the requested physical presence command already confirmed by user
593
594 @param[in] TcgPpData EFI Tcg2 Physical Presence request data.
595 @param[in] Flags The physical presence interface flags.
596 @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.
597 True, it indicates the command doesn't require user confirm, or already confirmed
598 in last boot cycle by user.
599 False, it indicates the command need user confirm from UI.
600
601 @retval TRUE Physical Presence operation command is valid.
602 @retval FALSE Physical Presence operation command is invalid.
603
604 **/
605 BOOLEAN
606 Tcg2HaveValidTpmRequest (
607 IN EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData,
608 IN EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags,
609 OUT BOOLEAN *RequestConfirmed
610 )
611 {
612 EFI_TCG2_PROTOCOL *Tcg2Protocol;
613 EFI_STATUS Status;
614 BOOLEAN IsRequestValid;
615
616 *RequestConfirmed = FALSE;
617
618 if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
619 //
620 // Need TCG2 protocol.
621 //
622 Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
623 if (EFI_ERROR (Status)) {
624 return FALSE;
625 }
626 }
627
628 switch (TcgPpData->PPRequest) {
629 case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
630 *RequestConfirmed = TRUE;
631 return TRUE;
632
633 case TCG2_PHYSICAL_PRESENCE_CLEAR:
634 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
635 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
636 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
637 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
638 *RequestConfirmed = TRUE;
639 }
640 break;
641
642 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
643 *RequestConfirmed = TRUE;
644 break;
645
646 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
647 break;
648
649 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
650 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
651 *RequestConfirmed = TRUE;
652 }
653 break;
654
655 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
656 if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
657 *RequestConfirmed = TRUE;
658 }
659 break;
660
661 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
662 *RequestConfirmed = TRUE;
663 break;
664
665 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
666 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
667 *RequestConfirmed = TRUE;
668 }
669 break;
670
671 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
672 if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
673 *RequestConfirmed = TRUE;
674 }
675 break;
676
677 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
678 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
679 *RequestConfirmed = TRUE;
680 break;
681
682 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
683 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
684 break;
685
686 default:
687 if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
688 IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
689 if (!IsRequestValid) {
690 return FALSE;
691 } else {
692 break;
693 }
694 } else {
695 //
696 // Wrong Physical Presence command
697 //
698 return FALSE;
699 }
700 }
701
702 if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {
703 //
704 // It had been confirmed in last boot, it doesn't need confirm again.
705 //
706 *RequestConfirmed = TRUE;
707 }
708
709 //
710 // Physical Presence command is correct
711 //
712 return TRUE;
713 }
714
715
716 /**
717 Check and execute the requested physical presence command.
718
719 Caution: This function may receive untrusted input.
720 TcgPpData variable is external input, so this function will validate
721 its data structure to be valid value.
722
723 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
724 @param[in, out] TcgPpData Pointer to the physical presence NV variable.
725 @param[in, out] Flags Pointer to the physical presence interface flags.
726 **/
727 VOID
728 Tcg2ExecutePendingTpmRequest (
729 IN TPM2B_AUTH *PlatformAuth, OPTIONAL
730 IN OUT EFI_TCG2_PHYSICAL_PRESENCE *TcgPpData,
731 IN OUT EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags
732 )
733 {
734 EFI_STATUS Status;
735 UINTN DataSize;
736 BOOLEAN RequestConfirmed;
737 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS NewFlags;
738 BOOLEAN ResetRequired;
739 UINT32 NewPPFlags;
740
741 if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
742 //
743 // No operation request
744 //
745 return;
746 }
747
748 if (!Tcg2HaveValidTpmRequest(TcgPpData, *Flags, &RequestConfirmed)) {
749 //
750 // Invalid operation request.
751 //
752 if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
753 TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;
754 } else {
755 TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
756 }
757 TcgPpData->LastPPRequest = TcgPpData->PPRequest;
758 TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
759 TcgPpData->PPRequestParameter = 0;
760
761 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
762 Status = gRT->SetVariable (
763 TCG2_PHYSICAL_PRESENCE_VARIABLE,
764 &gEfiTcg2PhysicalPresenceGuid,
765 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
766 DataSize,
767 TcgPpData
768 );
769 return;
770 }
771
772 ResetRequired = FALSE;
773 if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
774 NewFlags = *Flags;
775 NewPPFlags = NewFlags.PPFlags;
776 TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
777 NewFlags.PPFlags = NewPPFlags;
778 } else {
779 if (!RequestConfirmed) {
780 //
781 // Print confirm text and wait for approval.
782 //
783 RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);
784 }
785
786 //
787 // Execute requested physical presence command
788 //
789 TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
790 NewFlags = *Flags;
791 if (RequestConfirmed) {
792 TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (
793 PlatformAuth,
794 TcgPpData->PPRequest,
795 TcgPpData->PPRequestParameter,
796 &NewFlags
797 );
798 }
799 }
800
801 //
802 // Save the flags if it is updated.
803 //
804 if (CompareMem (Flags, &NewFlags, sizeof(EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {
805 *Flags = NewFlags;
806 Status = gRT->SetVariable (
807 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
808 &gEfiTcg2PhysicalPresenceGuid,
809 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
810 sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
811 &NewFlags
812 );
813 }
814
815 //
816 // Clear request
817 //
818 if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {
819 TcgPpData->LastPPRequest = TcgPpData->PPRequest;
820 TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
821 TcgPpData->PPRequestParameter = 0;
822 }
823
824 //
825 // Save changes
826 //
827 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
828 Status = gRT->SetVariable (
829 TCG2_PHYSICAL_PRESENCE_VARIABLE,
830 &gEfiTcg2PhysicalPresenceGuid,
831 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
832 DataSize,
833 TcgPpData
834 );
835 if (EFI_ERROR (Status)) {
836 return;
837 }
838
839 if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
840 return;
841 }
842
843 //
844 // Reset system to make new TPM settings in effect
845 //
846 switch (TcgPpData->LastPPRequest) {
847 case TCG2_PHYSICAL_PRESENCE_CLEAR:
848 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
849 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
850 case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
851 case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
852 case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
853 case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
854 break;
855
856 case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
857 case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
858 break;
859
860 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
861 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
862 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
863 case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
864 return;
865
866 default:
867 if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
868 if (ResetRequired) {
869 break;
870 } else {
871 return ;
872 }
873 }
874 if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
875 break;
876 }
877 return;
878 }
879
880 Print (L"Rebooting system to make TPM2 settings in effect\n");
881 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
882 ASSERT (FALSE);
883 }
884
885 /**
886 Check and execute the pending TPM request.
887
888 The TPM request may come from OS or BIOS. This API will display request information and wait
889 for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
890 the TPM request is confirmed, and one or more reset may be required to make TPM request to
891 take effect.
892
893 This API should be invoked after console in and console out are all ready as they are required
894 to display request information and get user input to confirm the request.
895
896 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
897 **/
898 VOID
899 EFIAPI
900 Tcg2PhysicalPresenceLibProcessRequest (
901 IN TPM2B_AUTH *PlatformAuth OPTIONAL
902 )
903 {
904 EFI_STATUS Status;
905 UINTN DataSize;
906 EFI_TCG2_PHYSICAL_PRESENCE TcgPpData;
907 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol;
908 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags;
909
910 //
911 // This flags variable controls whether physical presence is required for TPM command.
912 // It should be protected from malicious software. We set it as read-only variable here.
913 //
914 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
915 if (!EFI_ERROR (Status)) {
916 Status = VariableLockProtocol->RequestToLock (
917 VariableLockProtocol,
918 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
919 &gEfiTcg2PhysicalPresenceGuid
920 );
921 if (EFI_ERROR (Status)) {
922 DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
923 ASSERT_EFI_ERROR (Status);
924 }
925 }
926
927 //
928 // Check S4 resume
929 //
930 if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
931 DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
932 return ;
933 }
934
935 //
936 // Initialize physical presence flags.
937 //
938 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
939 Status = gRT->GetVariable (
940 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
941 &gEfiTcg2PhysicalPresenceGuid,
942 NULL,
943 &DataSize,
944 &PpiFlags
945 );
946 if (EFI_ERROR (Status)) {
947 PpiFlags.PPFlags = PcdGet32(PcdTcg2PhysicalPresenceFlags);
948 Status = gRT->SetVariable (
949 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
950 &gEfiTcg2PhysicalPresenceGuid,
951 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
952 sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
953 &PpiFlags
954 );
955 if (EFI_ERROR (Status)) {
956 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));
957 return ;
958 }
959 DEBUG((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags));
960 }
961
962 //
963 // Initialize physical presence variable.
964 //
965 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
966 Status = gRT->GetVariable (
967 TCG2_PHYSICAL_PRESENCE_VARIABLE,
968 &gEfiTcg2PhysicalPresenceGuid,
969 NULL,
970 &DataSize,
971 &TcgPpData
972 );
973 if (EFI_ERROR (Status)) {
974 ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
975 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
976 Status = gRT->SetVariable (
977 TCG2_PHYSICAL_PRESENCE_VARIABLE,
978 &gEfiTcg2PhysicalPresenceGuid,
979 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
980 DataSize,
981 &TcgPpData
982 );
983 if (EFI_ERROR (Status)) {
984 DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));
985 return ;
986 }
987 }
988
989 DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
990
991 //
992 // Execute pending TPM request.
993 //
994 Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags);
995 DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
996
997 }
998
999 /**
1000 Check if the pending TPM request needs user input to confirm.
1001
1002 The TPM request may come from OS. This API will check if TPM request exists and need user
1003 input to confirmation.
1004
1005 @retval TRUE TPM needs input to confirm user physical presence.
1006 @retval FALSE TPM doesn't need input to confirm user physical presence.
1007
1008 **/
1009 BOOLEAN
1010 EFIAPI
1011 Tcg2PhysicalPresenceLibNeedUserConfirm(
1012 VOID
1013 )
1014 {
1015 EFI_STATUS Status;
1016 EFI_TCG2_PHYSICAL_PRESENCE TcgPpData;
1017 UINTN DataSize;
1018 BOOLEAN RequestConfirmed;
1019 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags;
1020
1021 //
1022 // Check S4 resume
1023 //
1024 if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
1025 DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
1026 return FALSE;
1027 }
1028
1029 //
1030 // Check Tpm requests
1031 //
1032 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1033 Status = gRT->GetVariable (
1034 TCG2_PHYSICAL_PRESENCE_VARIABLE,
1035 &gEfiTcg2PhysicalPresenceGuid,
1036 NULL,
1037 &DataSize,
1038 &TcgPpData
1039 );
1040 if (EFI_ERROR (Status)) {
1041 return FALSE;
1042 }
1043
1044 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1045 Status = gRT->GetVariable (
1046 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1047 &gEfiTcg2PhysicalPresenceGuid,
1048 NULL,
1049 &DataSize,
1050 &PpiFlags
1051 );
1052 if (EFI_ERROR (Status)) {
1053 return FALSE;
1054 }
1055
1056 if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
1057 //
1058 // No operation request
1059 //
1060 return FALSE;
1061 }
1062
1063 if (!Tcg2HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {
1064 //
1065 // Invalid operation request.
1066 //
1067 return FALSE;
1068 }
1069
1070 if (!RequestConfirmed) {
1071 //
1072 // Need UI to confirm
1073 //
1074 return TRUE;
1075 }
1076
1077 return FALSE;
1078 }
1079
1080
1081 /**
1082 The handler for TPM physical presence function:
1083 Return TPM Operation Response to OS Environment.
1084
1085 @param[out] MostRecentRequest Most recent operation request.
1086 @param[out] Response Response to the most recent operation request.
1087
1088 @return Return Code for Return TPM Operation Response to OS Environment.
1089 **/
1090 UINT32
1091 EFIAPI
1092 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
1093 OUT UINT32 *MostRecentRequest,
1094 OUT UINT32 *Response
1095 )
1096 {
1097 EFI_STATUS Status;
1098 UINTN DataSize;
1099 EFI_TCG2_PHYSICAL_PRESENCE PpData;
1100
1101 DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
1102
1103 //
1104 // Get the Physical Presence variable
1105 //
1106 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1107 Status = gRT->GetVariable (
1108 TCG2_PHYSICAL_PRESENCE_VARIABLE,
1109 &gEfiTcg2PhysicalPresenceGuid,
1110 NULL,
1111 &DataSize,
1112 &PpData
1113 );
1114 if (EFI_ERROR (Status)) {
1115 *MostRecentRequest = 0;
1116 *Response = 0;
1117 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
1118 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
1119 }
1120
1121 *MostRecentRequest = PpData.LastPPRequest;
1122 *Response = PpData.PPResponse;
1123
1124 return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
1125 }
1126
1127 /**
1128 The handler for TPM physical presence function:
1129 Submit TPM Operation Request to Pre-OS Environment and
1130 Submit TPM Operation Request to Pre-OS Environment 2.
1131
1132 Caution: This function may receive untrusted input.
1133
1134 @param[in] OperationRequest TPM physical presence operation request.
1135 @param[in] RequestParameter TPM physical presence operation request parameter.
1136
1137 @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
1138 Submit TPM Operation Request to Pre-OS Environment 2.
1139 **/
1140 UINT32
1141 EFIAPI
1142 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
1143 IN UINT32 OperationRequest,
1144 IN UINT32 RequestParameter
1145 )
1146 {
1147 EFI_STATUS Status;
1148 UINTN DataSize;
1149 EFI_TCG2_PHYSICAL_PRESENCE PpData;
1150 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
1151
1152 DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
1153
1154 //
1155 // Get the Physical Presence variable
1156 //
1157 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1158 Status = gRT->GetVariable (
1159 TCG2_PHYSICAL_PRESENCE_VARIABLE,
1160 &gEfiTcg2PhysicalPresenceGuid,
1161 NULL,
1162 &DataSize,
1163 &PpData
1164 );
1165 if (EFI_ERROR (Status)) {
1166 DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
1167 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
1168 }
1169
1170 if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
1171 (OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
1172 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
1173 }
1174
1175 if ((PpData.PPRequest != OperationRequest) ||
1176 (PpData.PPRequestParameter != RequestParameter)) {
1177 PpData.PPRequest = (UINT8)OperationRequest;
1178 PpData.PPRequestParameter = RequestParameter;
1179 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
1180 Status = gRT->SetVariable (
1181 TCG2_PHYSICAL_PRESENCE_VARIABLE,
1182 &gEfiTcg2PhysicalPresenceGuid,
1183 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
1184 DataSize,
1185 &PpData
1186 );
1187 if (EFI_ERROR (Status)) {
1188 DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
1189 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
1190 }
1191 }
1192
1193 if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
1194 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1195 Status = gRT->GetVariable (
1196 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1197 &gEfiTcg2PhysicalPresenceGuid,
1198 NULL,
1199 &DataSize,
1200 &Flags
1201 );
1202 if (EFI_ERROR (Status)) {
1203 Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
1204 }
1205 return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
1206 }
1207
1208 return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
1209 }
1210
1211 /**
1212 Return TPM2 ManagementFlags set by PP interface.
1213
1214 @retval ManagementFlags TPM2 Management Flags.
1215 **/
1216 UINT32
1217 EFIAPI
1218 Tcg2PhysicalPresenceLibGetManagementFlags (
1219 VOID
1220 )
1221 {
1222 EFI_STATUS Status;
1223 EFI_TCG2_PHYSICAL_PRESENCE_FLAGS PpiFlags;
1224 UINTN DataSize;
1225
1226 DEBUG ((EFI_D_INFO, "[TPM2] GetManagementFlags\n"));
1227
1228 DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
1229 Status = gRT->GetVariable (
1230 TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
1231 &gEfiTcg2PhysicalPresenceGuid,
1232 NULL,
1233 &DataSize,
1234 &PpiFlags
1235 );
1236 if (EFI_ERROR (Status)) {
1237 PpiFlags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT | TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_DEFAULT;
1238 }
1239 return PpiFlags.PPFlags;
1240 }