]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2Integrity.c
1 /** @file
2 Implement TPM2 Integrity related command.
3
4 Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <IndustryStandard/UefiTcgPlatform.h>
10 #include <Library/Tpm2CommandLib.h>
11 #include <Library/Tpm2DeviceLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/BaseLib.h>
14 #include <Library/DebugLib.h>
15
16 #pragma pack(1)
17
18 typedef struct {
19 TPM2_COMMAND_HEADER Header;
20 TPMI_DH_PCR PcrHandle;
21 UINT32 AuthorizationSize;
22 TPMS_AUTH_COMMAND AuthSessionPcr;
23 TPML_DIGEST_VALUES DigestValues;
24 } TPM2_PCR_EXTEND_COMMAND;
25
26 typedef struct {
27 TPM2_RESPONSE_HEADER Header;
28 UINT32 ParameterSize;
29 TPMS_AUTH_RESPONSE AuthSessionPcr;
30 } TPM2_PCR_EXTEND_RESPONSE;
31
32 typedef struct {
33 TPM2_COMMAND_HEADER Header;
34 TPMI_DH_PCR PcrHandle;
35 UINT32 AuthorizationSize;
36 TPMS_AUTH_COMMAND AuthSessionPcr;
37 TPM2B_EVENT EventData;
38 } TPM2_PCR_EVENT_COMMAND;
39
40 typedef struct {
41 TPM2_RESPONSE_HEADER Header;
42 UINT32 ParameterSize;
43 TPML_DIGEST_VALUES Digests;
44 TPMS_AUTH_RESPONSE AuthSessionPcr;
45 } TPM2_PCR_EVENT_RESPONSE;
46
47 typedef struct {
48 TPM2_COMMAND_HEADER Header;
49 TPML_PCR_SELECTION PcrSelectionIn;
50 } TPM2_PCR_READ_COMMAND;
51
52 typedef struct {
53 TPM2_RESPONSE_HEADER Header;
54 UINT32 PcrUpdateCounter;
55 TPML_PCR_SELECTION PcrSelectionOut;
56 TPML_DIGEST PcrValues;
57 } TPM2_PCR_READ_RESPONSE;
58
59 typedef struct {
60 TPM2_COMMAND_HEADER Header;
61 TPMI_RH_PLATFORM AuthHandle;
62 UINT32 AuthSessionSize;
63 TPMS_AUTH_COMMAND AuthSession;
64 TPML_PCR_SELECTION PcrAllocation;
65 } TPM2_PCR_ALLOCATE_COMMAND;
66
67 typedef struct {
68 TPM2_RESPONSE_HEADER Header;
69 UINT32 AuthSessionSize;
70 TPMI_YES_NO AllocationSuccess;
71 UINT32 MaxPCR;
72 UINT32 SizeNeeded;
73 UINT32 SizeAvailable;
74 TPMS_AUTH_RESPONSE AuthSession;
75 } TPM2_PCR_ALLOCATE_RESPONSE;
76
77 #pragma pack()
78
79 /**
80 This command is used to cause an update to the indicated PCR.
81 The digests parameter contains one or more tagged digest value identified by an algorithm ID.
82 For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
83
84 @param[in] PcrHandle Handle of the PCR
85 @param[in] Digests List of tagged digest values to be extended
86
87 @retval EFI_SUCCESS Operation completed successfully.
88 @retval EFI_DEVICE_ERROR Unexpected device behavior.
89 **/
90 EFI_STATUS
91 EFIAPI
92 Tpm2PcrExtend (
93 IN TPMI_DH_PCR PcrHandle,
94 IN TPML_DIGEST_VALUES *Digests
95 )
96 {
97 EFI_STATUS Status;
98 TPM2_PCR_EXTEND_COMMAND Cmd;
99 TPM2_PCR_EXTEND_RESPONSE Res;
100 UINT32 CmdSize;
101 UINT32 RespSize;
102 UINT32 ResultBufSize;
103 UINT8 *Buffer;
104 UINTN Index;
105 UINT32 SessionInfoSize;
106 UINT16 DigestSize;
107
108 Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
109 Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Extend);
110 Cmd.PcrHandle = SwapBytes32 (PcrHandle);
111
112 //
113 // Add in Auth session
114 //
115 Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
116
117 // sessionInfoSize
118 SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
119 Buffer += SessionInfoSize;
120 Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
121
122 // Digest Count
123 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Digests->count));
124 Buffer += sizeof (UINT32);
125
126 // Digest
127 for (Index = 0; Index < Digests->count; Index++) {
128 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Digests->digests[Index].hashAlg));
129 Buffer += sizeof (UINT16);
130 DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
131 if (DigestSize == 0) {
132 DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
133 return EFI_DEVICE_ERROR;
134 }
135
136 CopyMem (
137 Buffer,
138 &Digests->digests[Index].digest,
139 DigestSize
140 );
141
142 DEBUG_CODE_BEGIN ();
143 UINTN Index2;
144 DEBUG ((
145 DEBUG_VERBOSE,
146 "Tpm2PcrExtend - Hash = 0x%04x, Pcr[%02d], digest = ",
147 Digests->digests[Index].hashAlg,
148 (UINT8)PcrHandle
149 ));
150
151 for (Index2 = 0; Index2 < DigestSize; Index2++) {
152 DEBUG ((DEBUG_VERBOSE, "%02x ", Buffer[Index2]));
153 }
154
155 DEBUG ((DEBUG_VERBOSE, "\n"));
156 DEBUG_CODE_END ();
157
158 Buffer += DigestSize;
159 }
160
161 CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
162 Cmd.Header.paramSize = SwapBytes32 (CmdSize);
163
164 ResultBufSize = sizeof (Res);
165 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
166 if (EFI_ERROR (Status)) {
167 return Status;
168 }
169
170 if (ResultBufSize > sizeof (Res)) {
171 DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
172 return EFI_BUFFER_TOO_SMALL;
173 }
174
175 //
176 // Validate response headers
177 //
178 RespSize = SwapBytes32 (Res.Header.paramSize);
179 if (RespSize > sizeof (Res)) {
180 DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
181 return EFI_BUFFER_TOO_SMALL;
182 }
183
184 //
185 // Fail if command failed
186 //
187 if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
188 DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
189 return EFI_DEVICE_ERROR;
190 }
191
192 DEBUG_CODE_BEGIN ();
193 DEBUG ((DEBUG_VERBOSE, "Tpm2PcrExtend: PCR read after extend...\n"));
194 Tpm2PcrReadForActiveBank (PcrHandle, NULL);
195 DEBUG_CODE_END ();
196
197 //
198 // Unmarshal the response
199 //
200
201 // None
202
203 return EFI_SUCCESS;
204 }
205
206 /**
207 This command is used to cause an update to the indicated PCR.
208 The data in eventData is hashed using the hash algorithm associated with each bank in which the
209 indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
210 references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
211 TPM2_PCR_Extend().
212 A TPM shall support an Event.size of zero through 1,024 inclusive.
213
214 @param[in] PcrHandle Handle of the PCR
215 @param[in] EventData Event data in sized buffer
216 @param[out] Digests List of digest
217
218 @retval EFI_SUCCESS Operation completed successfully.
219 @retval EFI_DEVICE_ERROR Unexpected device behavior.
220 **/
221 EFI_STATUS
222 EFIAPI
223 Tpm2PcrEvent (
224 IN TPMI_DH_PCR PcrHandle,
225 IN TPM2B_EVENT *EventData,
226 OUT TPML_DIGEST_VALUES *Digests
227 )
228 {
229 EFI_STATUS Status;
230 TPM2_PCR_EVENT_COMMAND Cmd;
231 TPM2_PCR_EVENT_RESPONSE Res;
232 UINT32 CmdSize;
233 UINT32 RespSize;
234 UINT32 ResultBufSize;
235 UINT8 *Buffer;
236 UINTN Index;
237 UINT32 SessionInfoSize;
238 UINT16 DigestSize;
239
240 Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
241 Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Event);
242 Cmd.PcrHandle = SwapBytes32 (PcrHandle);
243
244 //
245 // Add in Auth session
246 //
247 Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
248
249 // sessionInfoSize
250 SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
251 Buffer += SessionInfoSize;
252 Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
253
254 // Event
255 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (EventData->size));
256 Buffer += sizeof (UINT16);
257
258 CopyMem (Buffer, EventData->buffer, EventData->size);
259 Buffer += EventData->size;
260
261 CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
262 Cmd.Header.paramSize = SwapBytes32 (CmdSize);
263
264 ResultBufSize = sizeof (Res);
265 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
266 if (EFI_ERROR (Status)) {
267 return Status;
268 }
269
270 if (ResultBufSize > sizeof (Res)) {
271 DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
272 return EFI_BUFFER_TOO_SMALL;
273 }
274
275 //
276 // Validate response headers
277 //
278 RespSize = SwapBytes32 (Res.Header.paramSize);
279 if (RespSize > sizeof (Res)) {
280 DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
281 return EFI_BUFFER_TOO_SMALL;
282 }
283
284 //
285 // Fail if command failed
286 //
287 if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
288 DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
289 return EFI_DEVICE_ERROR;
290 }
291
292 //
293 // Unmarshal the response
294 //
295 Buffer = (UINT8 *)&Res.Digests;
296
297 Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
298 if (Digests->count > HASH_COUNT) {
299 DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent - Digests->count error %x\n", Digests->count));
300 return EFI_DEVICE_ERROR;
301 }
302
303 Buffer += sizeof (UINT32);
304 for (Index = 0; Index < Digests->count; Index++) {
305 Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
306 Buffer += sizeof (UINT16);
307 DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
308 if (DigestSize == 0) {
309 DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
310 return EFI_DEVICE_ERROR;
311 }
312
313 CopyMem (
314 &Digests->digests[Index].digest,
315 Buffer,
316 DigestSize
317 );
318 Buffer += DigestSize;
319 }
320
321 return EFI_SUCCESS;
322 }
323
324 /**
325 This command returns the values of all PCR specified in pcrSelect.
326
327 @param[in] PcrSelectionIn The selection of PCR to read.
328 @param[out] PcrUpdateCounter The current value of the PCR update counter.
329 @param[out] PcrSelectionOut The PCR in the returned list.
330 @param[out] PcrValues The contents of the PCR indicated in pcrSelect.
331
332 @retval EFI_SUCCESS Operation completed successfully.
333 @retval EFI_DEVICE_ERROR The command was unsuccessful.
334 **/
335 EFI_STATUS
336 EFIAPI
337 Tpm2PcrRead (
338 IN TPML_PCR_SELECTION *PcrSelectionIn,
339 OUT UINT32 *PcrUpdateCounter,
340 OUT TPML_PCR_SELECTION *PcrSelectionOut,
341 OUT TPML_DIGEST *PcrValues
342 )
343 {
344 EFI_STATUS Status;
345 TPM2_PCR_READ_COMMAND SendBuffer;
346 TPM2_PCR_READ_RESPONSE RecvBuffer;
347 UINT32 SendBufferSize;
348 UINT32 RecvBufferSize;
349 UINTN Index;
350 TPML_DIGEST *PcrValuesOut;
351 TPM2B_DIGEST *Digests;
352
353 //
354 // Construct command
355 //
356 SendBuffer.Header.tag = SwapBytes16 (TPM_ST_NO_SESSIONS);
357 SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Read);
358
359 SendBuffer.PcrSelectionIn.count = SwapBytes32 (PcrSelectionIn->count);
360 for (Index = 0; Index < PcrSelectionIn->count; Index++) {
361 SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16 (PcrSelectionIn->pcrSelections[Index].hash);
362 SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
363 CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
364 }
365
366 SendBufferSize = sizeof (SendBuffer.Header) + sizeof (SendBuffer.PcrSelectionIn.count) + sizeof (SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
367 SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
368
369 //
370 // send Tpm command
371 //
372 RecvBufferSize = sizeof (RecvBuffer);
373 Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
374 if (EFI_ERROR (Status)) {
375 return Status;
376 }
377
378 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
379 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
380 return EFI_DEVICE_ERROR;
381 }
382
383 if (SwapBytes32 (RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
384 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
385 return EFI_NOT_FOUND;
386 }
387
388 //
389 // Return the response
390 //
391
392 //
393 // PcrUpdateCounter
394 //
395 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter)) {
396 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
397 return EFI_DEVICE_ERROR;
398 }
399
400 *PcrUpdateCounter = SwapBytes32 (RecvBuffer.PcrUpdateCounter);
401
402 //
403 // PcrSelectionOut
404 //
405 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count)) {
406 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
407 return EFI_DEVICE_ERROR;
408 }
409
410 PcrSelectionOut->count = SwapBytes32 (RecvBuffer.PcrSelectionOut.count);
411 if (PcrSelectionOut->count > HASH_COUNT) {
412 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrSelectionOut->count error %x\n", PcrSelectionOut->count));
413 return EFI_DEVICE_ERROR;
414 }
415
416 if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
417 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
418 return EFI_DEVICE_ERROR;
419 }
420
421 for (Index = 0; Index < PcrSelectionOut->count; Index++) {
422 PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16 (RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
423 PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
424 if (PcrSelectionOut->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {
425 return EFI_DEVICE_ERROR;
426 }
427
428 CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
429 }
430
431 //
432 // PcrValues
433 //
434 PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
435 PcrValues->count = SwapBytes32 (PcrValuesOut->count);
436 //
437 // The number of digests in list is not greater than 8 per TPML_DIGEST definition
438 //
439 if (PcrValues->count > 8) {
440 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrValues->count error %x\n", PcrValues->count));
441 return EFI_DEVICE_ERROR;
442 }
443
444 Digests = PcrValuesOut->digests;
445 for (Index = 0; Index < PcrValues->count; Index++) {
446 PcrValues->digests[Index].size = SwapBytes16 (Digests->size);
447 if (PcrValues->digests[Index].size > sizeof (TPMU_HA)) {
448 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - Digest.size error %x\n", PcrValues->digests[Index].size));
449 return EFI_DEVICE_ERROR;
450 }
451
452 CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
453 Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof (Digests->size) + PcrValues->digests[Index].size);
454 }
455
456 return EFI_SUCCESS;
457 }
458
459 /**
460 This command is used to set the desired PCR allocation of PCR and algorithms.
461
462 @param[in] AuthHandle TPM_RH_PLATFORM+{PP}
463 @param[in] AuthSession Auth Session context
464 @param[in] PcrAllocation The requested allocation
465 @param[out] AllocationSuccess YES if the allocation succeeded
466 @param[out] MaxPCR maximum number of PCR that may be in a bank
467 @param[out] SizeNeeded number of octets required to satisfy the request
468 @param[out] SizeAvailable Number of octets available. Computed before the allocation
469
470 @retval EFI_SUCCESS Operation completed successfully.
471 @retval EFI_DEVICE_ERROR The command was unsuccessful.
472 **/
473 EFI_STATUS
474 EFIAPI
475 Tpm2PcrAllocate (
476 IN TPMI_RH_PLATFORM AuthHandle,
477 IN TPMS_AUTH_COMMAND *AuthSession,
478 IN TPML_PCR_SELECTION *PcrAllocation,
479 OUT TPMI_YES_NO *AllocationSuccess,
480 OUT UINT32 *MaxPCR,
481 OUT UINT32 *SizeNeeded,
482 OUT UINT32 *SizeAvailable
483 )
484 {
485 EFI_STATUS Status;
486 TPM2_PCR_ALLOCATE_COMMAND Cmd;
487 TPM2_PCR_ALLOCATE_RESPONSE Res;
488 UINT32 CmdSize;
489 UINT32 RespSize;
490 UINT8 *Buffer;
491 UINT32 SessionInfoSize;
492 UINT8 *ResultBuf;
493 UINT32 ResultBufSize;
494 UINTN Index;
495
496 //
497 // Construct command
498 //
499 Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
500 Cmd.Header.paramSize = SwapBytes32 (sizeof (Cmd));
501 Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Allocate);
502 Cmd.AuthHandle = SwapBytes32 (AuthHandle);
503
504 //
505 // Add in Auth session
506 //
507 Buffer = (UINT8 *)&Cmd.AuthSession;
508
509 // sessionInfoSize
510 SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
511 Buffer += SessionInfoSize;
512 Cmd.AuthSessionSize = SwapBytes32 (SessionInfoSize);
513
514 // Count
515 WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (PcrAllocation->count));
516 Buffer += sizeof (UINT32);
517 for (Index = 0; Index < PcrAllocation->count; Index++) {
518 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (PcrAllocation->pcrSelections[Index].hash));
519 Buffer += sizeof (UINT16);
520 *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
521 Buffer++;
522 CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
523 Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
524 }
525
526 CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
527 Cmd.Header.paramSize = SwapBytes32 (CmdSize);
528
529 ResultBuf = (UINT8 *)&Res;
530 ResultBufSize = sizeof (Res);
531
532 //
533 // Call the TPM
534 //
535 Status = Tpm2SubmitCommand (
536 CmdSize,
537 (UINT8 *)&Cmd,
538 &ResultBufSize,
539 ResultBuf
540 );
541 if (EFI_ERROR (Status)) {
542 goto Done;
543 }
544
545 if (ResultBufSize > sizeof (Res)) {
546 DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
547 Status = EFI_BUFFER_TOO_SMALL;
548 goto Done;
549 }
550
551 //
552 // Validate response headers
553 //
554 RespSize = SwapBytes32 (Res.Header.paramSize);
555 if (RespSize > sizeof (Res)) {
556 DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
557 Status = EFI_BUFFER_TOO_SMALL;
558 goto Done;
559 }
560
561 //
562 // Fail if command failed
563 //
564 if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
565 DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
566 Status = EFI_DEVICE_ERROR;
567 goto Done;
568 }
569
570 //
571 // Return the response
572 //
573 *AllocationSuccess = Res.AllocationSuccess;
574 *MaxPCR = SwapBytes32 (Res.MaxPCR);
575 *SizeNeeded = SwapBytes32 (Res.SizeNeeded);
576 *SizeAvailable = SwapBytes32 (Res.SizeAvailable);
577
578 Done:
579 //
580 // Clear AuthSession Content
581 //
582 ZeroMem (&Cmd, sizeof (Cmd));
583 ZeroMem (&Res, sizeof (Res));
584 return Status;
585 }
586
587 /**
588 Alloc PCR data.
589
590 @param[in] PlatformAuth platform auth value. NULL means no platform auth change.
591 @param[in] SupportedPCRBanks Supported PCR banks
592 @param[in] PCRBanks PCR banks
593
594 @retval EFI_SUCCESS Operation completed successfully.
595 **/
596 EFI_STATUS
597 EFIAPI
598 Tpm2PcrAllocateBanks (
599 IN TPM2B_AUTH *PlatformAuth OPTIONAL,
600 IN UINT32 SupportedPCRBanks,
601 IN UINT32 PCRBanks
602 )
603 {
604 EFI_STATUS Status;
605 TPMS_AUTH_COMMAND *AuthSession;
606 TPMS_AUTH_COMMAND LocalAuthSession;
607 TPML_PCR_SELECTION PcrAllocation;
608 TPMI_YES_NO AllocationSuccess;
609 UINT32 MaxPCR;
610 UINT32 SizeNeeded;
611 UINT32 SizeAvailable;
612
613 if (PlatformAuth == NULL) {
614 AuthSession = NULL;
615 } else {
616 AuthSession = &LocalAuthSession;
617 ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
618 LocalAuthSession.sessionHandle = TPM_RS_PW;
619 LocalAuthSession.hmac.size = PlatformAuth->size;
620 CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
621 }
622
623 //
624 // Fill input
625 //
626 ZeroMem (&PcrAllocation, sizeof (PcrAllocation));
627 if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
628 PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
629 PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
630 if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
631 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
632 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
633 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
634 } else {
635 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
636 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
637 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
638 }
639
640 PcrAllocation.count++;
641 }
642
643 if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
644 PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
645 PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
646 if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
647 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
648 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
649 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
650 } else {
651 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
652 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
653 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
654 }
655
656 PcrAllocation.count++;
657 }
658
659 if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
660 PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
661 PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
662 if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
663 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
664 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
665 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
666 } else {
667 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
668 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
669 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
670 }
671
672 PcrAllocation.count++;
673 }
674
675 if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
676 PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
677 PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
678 if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
679 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
680 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
681 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
682 } else {
683 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
684 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
685 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
686 }
687
688 PcrAllocation.count++;
689 }
690
691 if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
692 PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
693 PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
694 if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
695 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
696 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
697 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
698 } else {
699 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
700 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
701 PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
702 }
703
704 PcrAllocation.count++;
705 }
706
707 Status = Tpm2PcrAllocate (
708 TPM_RH_PLATFORM,
709 AuthSession,
710 &PcrAllocation,
711 &AllocationSuccess,
712 &MaxPCR,
713 &SizeNeeded,
714 &SizeAvailable
715 );
716 DEBUG ((DEBUG_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
717 if (EFI_ERROR (Status)) {
718 goto Done;
719 }
720
721 DEBUG ((DEBUG_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
722 DEBUG ((DEBUG_INFO, "MaxPCR - %08x\n", MaxPCR));
723 DEBUG ((DEBUG_INFO, "SizeNeeded - %08x\n", SizeNeeded));
724 DEBUG ((DEBUG_INFO, "SizeAvailable - %08x\n", SizeAvailable));
725
726 Done:
727 ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
728 return Status;
729 }
730
731 /**
732 This function will query the TPM to determine which hashing algorithms and
733 get the digests of all active and supported PCR banks of a specific PCR register.
734
735 @param[in] PcrHandle The index of the PCR register to be read.
736 @param[out] HashList List of digests from PCR register being read.
737
738 @retval EFI_SUCCESS The Pcr was read successfully.
739 @retval EFI_DEVICE_ERROR The command was unsuccessful.
740 **/
741 EFI_STATUS
742 EFIAPI
743 Tpm2PcrReadForActiveBank (
744 IN TPMI_DH_PCR PcrHandle,
745 OUT TPML_DIGEST *HashList
746 )
747 {
748 EFI_STATUS Status;
749 TPML_PCR_SELECTION Pcrs;
750 TPML_PCR_SELECTION PcrSelectionIn;
751 TPML_PCR_SELECTION PcrSelectionOut;
752 TPML_DIGEST PcrValues;
753 UINT32 PcrUpdateCounter;
754 UINT8 PcrIndex;
755 UINT32 TpmHashAlgorithmBitmap;
756 TPMI_ALG_HASH CurrentPcrBankHash;
757 UINT32 ActivePcrBanks;
758 UINT32 TcgRegistryHashAlg;
759 UINTN Index;
760 UINTN Index2;
761
762 PcrIndex = (UINT8)PcrHandle;
763
764 if ((PcrIndex < 0) ||
765 (PcrIndex >= IMPLEMENTATION_PCR))
766 {
767 return EFI_INVALID_PARAMETER;
768 }
769
770 ZeroMem (&PcrSelectionIn, sizeof (PcrSelectionIn));
771 ZeroMem (&PcrUpdateCounter, sizeof (UINT32));
772 ZeroMem (&PcrSelectionOut, sizeof (PcrSelectionOut));
773 ZeroMem (&PcrValues, sizeof (PcrValues));
774 ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
775
776 DEBUG ((DEBUG_INFO, "ReadPcr - %02d\n", PcrIndex));
777
778 //
779 // Read TPM capabilities
780 //
781 Status = Tpm2GetCapabilityPcrs (&Pcrs);
782
783 if (EFI_ERROR (Status)) {
784 DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities\n"));
785 return EFI_DEVICE_ERROR;
786 }
787
788 //
789 // Get Active Pcrs
790 //
791 Status = Tpm2GetCapabilitySupportedAndActivePcrs (
792 &TpmHashAlgorithmBitmap,
793 &ActivePcrBanks
794 );
795
796 if (EFI_ERROR (Status)) {
797 DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities and active PCRs\n"));
798 return EFI_DEVICE_ERROR;
799 }
800
801 //
802 // Select from Active PCRs
803 //
804 for (Index = 0; Index < Pcrs.count; Index++) {
805 CurrentPcrBankHash = Pcrs.pcrSelections[Index].hash;
806
807 switch (CurrentPcrBankHash) {
808 case TPM_ALG_SHA1:
809 DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA1 Present\n"));
810 TcgRegistryHashAlg = HASH_ALG_SHA1;
811 break;
812 case TPM_ALG_SHA256:
813 DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA256 Present\n"));
814 TcgRegistryHashAlg = HASH_ALG_SHA256;
815 break;
816 case TPM_ALG_SHA384:
817 DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA384 Present\n"));
818 TcgRegistryHashAlg = HASH_ALG_SHA384;
819 break;
820 case TPM_ALG_SHA512:
821 DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA512 Present\n"));
822 TcgRegistryHashAlg = HASH_ALG_SHA512;
823 break;
824 case TPM_ALG_SM3_256:
825 DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SM3 Present\n"));
826 TcgRegistryHashAlg = HASH_ALG_SM3_256;
827 break;
828 default:
829 //
830 // Unsupported algorithm
831 //
832 DEBUG ((DEBUG_VERBOSE, "Unknown algorithm present\n"));
833 TcgRegistryHashAlg = 0;
834 break;
835 }
836
837 //
838 // Skip unsupported and inactive PCR banks
839 //
840 if ((TcgRegistryHashAlg & ActivePcrBanks) == 0) {
841 DEBUG ((DEBUG_VERBOSE, "Skipping unsupported or inactive bank: 0x%04x\n", CurrentPcrBankHash));
842 continue;
843 }
844
845 //
846 // Select PCR from current active bank
847 //
848 PcrSelectionIn.pcrSelections[PcrSelectionIn.count].hash = Pcrs.pcrSelections[Index].hash;
849 PcrSelectionIn.pcrSelections[PcrSelectionIn.count].sizeofSelect = PCR_SELECT_MAX;
850 PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[0] = (PcrIndex < 8) ? 1 << PcrIndex : 0;
851 PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[1] = (PcrIndex > 7) && (PcrIndex < 16) ? 1 << (PcrIndex - 8) : 0;
852 PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[2] = (PcrIndex > 15) ? 1 << (PcrIndex - 16) : 0;
853 PcrSelectionIn.count++;
854 }
855
856 //
857 // Read PCRs
858 //
859 Status = Tpm2PcrRead (
860 &PcrSelectionIn,
861 &PcrUpdateCounter,
862 &PcrSelectionOut,
863 &PcrValues
864 );
865
866 if (EFI_ERROR (Status)) {
867 DEBUG ((DEBUG_ERROR, "Tpm2PcrRead failed Status = %r \n", Status));
868 return EFI_DEVICE_ERROR;
869 }
870
871 for (Index = 0; Index < PcrValues.count; Index++) {
872 DEBUG ((
873 DEBUG_INFO,
874 "ReadPcr - HashAlg = 0x%04x, Pcr[%02d], digest = ",
875 PcrSelectionOut.pcrSelections[Index].hash,
876 PcrIndex
877 ));
878
879 for (Index2 = 0; Index2 < PcrValues.digests[Index].size; Index2++) {
880 DEBUG ((DEBUG_INFO, "%02x ", PcrValues.digests[Index].buffer[Index2]));
881 }
882
883 DEBUG ((DEBUG_INFO, "\n"));
884 }
885
886 if (HashList != NULL) {
887 CopyMem (
888 HashList,
889 &PcrValues,
890 sizeof (TPML_DIGEST)
891 );
892 }
893
894 return EFI_SUCCESS;
895 }