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