2 Implement TPM2 Sequences related command.
4 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
19 TPM2_COMMAND_HEADER Header
;
21 TPMI_ALG_HASH HashAlg
;
22 } TPM2_HASH_SEQUENCE_START_COMMAND
;
25 TPM2_RESPONSE_HEADER Header
;
26 TPMI_DH_OBJECT SequenceHandle
;
27 } TPM2_HASH_SEQUENCE_START_RESPONSE
;
30 TPM2_COMMAND_HEADER Header
;
31 TPMI_DH_OBJECT SequenceHandle
;
32 UINT32 AuthorizationSize
;
33 TPMS_AUTH_COMMAND AuthSessionSeq
;
34 TPM2B_MAX_BUFFER Buffer
;
35 } TPM2_SEQUENCE_UPDATE_COMMAND
;
38 TPM2_RESPONSE_HEADER Header
;
40 TPMS_AUTH_RESPONSE AuthSessionSeq
;
41 } TPM2_SEQUENCE_UPDATE_RESPONSE
;
44 TPM2_COMMAND_HEADER Header
;
45 TPMI_DH_PCR PcrHandle
;
46 TPMI_DH_OBJECT SequenceHandle
;
47 UINT32 AuthorizationSize
;
48 TPMS_AUTH_COMMAND AuthSessionPcr
;
49 TPMS_AUTH_COMMAND AuthSessionSeq
;
50 TPM2B_MAX_BUFFER Buffer
;
51 } TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND
;
54 TPM2_RESPONSE_HEADER Header
;
56 TPML_DIGEST_VALUES Results
;
57 TPMS_AUTH_RESPONSE AuthSessionPcr
;
58 TPMS_AUTH_RESPONSE AuthSessionSeq
;
59 } TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE
;
62 TPM2_COMMAND_HEADER Header
;
63 TPMI_DH_OBJECT SequenceHandle
;
64 UINT32 AuthorizationSize
;
65 TPMS_AUTH_COMMAND AuthSessionSeq
;
66 TPM2B_MAX_BUFFER Buffer
;
67 TPMI_RH_HIERARCHY Hierarchy
;
68 } TPM2_SEQUENCE_COMPLETE_COMMAND
;
71 TPM2_RESPONSE_HEADER Header
;
74 TPMS_AUTH_RESPONSE AuthSessionSeq
;
75 } TPM2_SEQUENCE_COMPLETE_RESPONSE
;
80 This command starts a hash or an Event sequence.
81 If hashAlg is an implemented hash, then a hash sequence is started.
82 If hashAlg is TPM_ALG_NULL, then an Event sequence is started.
84 @param[in] HashAlg The hash algorithm to use for the hash sequence
85 An Event sequence starts if this is TPM_ALG_NULL.
86 @param[out] SequenceHandle A handle to reference the sequence
88 @retval EFI_SUCCESS Operation completed successfully.
89 @retval EFI_DEVICE_ERROR Unexpected device behavior.
93 Tpm2HashSequenceStart (
94 IN TPMI_ALG_HASH HashAlg
,
95 OUT TPMI_DH_OBJECT
*SequenceHandle
99 TPM2_HASH_SEQUENCE_START_COMMAND Cmd
;
100 TPM2_HASH_SEQUENCE_START_RESPONSE Res
;
104 UINT32 ResultBufSize
;
106 ZeroMem(&Cmd
, sizeof(Cmd
));
111 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_NO_SESSIONS
);
112 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_HashSequenceStart
);
114 Buffer
= (UINT8
*)&Cmd
.Auth
;
117 WriteUnaligned16 ((UINT16
*)Buffer
, SwapBytes16(0));
118 Buffer
+= sizeof(UINT16
);
121 WriteUnaligned16 ((UINT16
*)Buffer
, SwapBytes16(HashAlg
));
122 Buffer
+= sizeof(UINT16
);
124 CmdSize
= (UINT32
)(Buffer
- (UINT8
*)&Cmd
);
125 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
130 ResultBufSize
= sizeof(Res
);
131 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
132 if (EFI_ERROR(Status
)) {
136 if (ResultBufSize
> sizeof(Res
)) {
137 DEBUG ((DEBUG_ERROR
, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));
138 return EFI_BUFFER_TOO_SMALL
;
142 // Validate response headers
144 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
145 if (RespSize
> sizeof(Res
)) {
146 DEBUG ((DEBUG_ERROR
, "HashSequenceStart: Response size too large! %d\r\n", RespSize
));
147 return EFI_BUFFER_TOO_SMALL
;
151 // Fail if command failed
153 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
154 DEBUG ((DEBUG_ERROR
, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
155 return EFI_DEVICE_ERROR
;
159 // Unmarshal the response
163 *SequenceHandle
= SwapBytes32(Res
.SequenceHandle
);
169 This command is used to add data to a hash or HMAC sequence.
170 The amount of data in buffer may be any size up to the limits of the TPM.
171 NOTE: In all TPM, a buffer size of 1,024 octets is allowed.
173 @param[in] SequenceHandle Handle for the sequence object
174 @param[in] Buffer Data to be added to hash
176 @retval EFI_SUCCESS Operation completed successfully.
177 @retval EFI_DEVICE_ERROR Unexpected device behavior.
182 IN TPMI_DH_OBJECT SequenceHandle
,
183 IN TPM2B_MAX_BUFFER
*Buffer
187 TPM2_SEQUENCE_UPDATE_COMMAND Cmd
;
188 TPM2_SEQUENCE_UPDATE_RESPONSE Res
;
192 UINT32 SessionInfoSize
;
193 UINT32 ResultBufSize
;
195 ZeroMem(&Cmd
, sizeof(Cmd
));
200 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
201 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_SequenceUpdate
);
202 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
205 // Add in Auth session
207 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionSeq
;
210 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
211 BufferPtr
+= SessionInfoSize
;
212 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
);
215 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
216 BufferPtr
+= sizeof(UINT16
);
218 CopyMem(BufferPtr
, &Buffer
->buffer
, Buffer
->size
);
219 BufferPtr
+= Buffer
->size
;
221 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
222 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
227 ResultBufSize
= sizeof(Res
);
228 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
,&ResultBufSize
, (UINT8
*)&Res
);
229 if (EFI_ERROR(Status
)) {
233 if (ResultBufSize
> sizeof(Res
)) {
234 DEBUG ((DEBUG_ERROR
, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));
235 return EFI_BUFFER_TOO_SMALL
;
239 // Validate response headers
241 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
242 if (RespSize
> sizeof(Res
)) {
243 DEBUG ((DEBUG_ERROR
, "SequenceUpdate: Response size too large! %d\r\n", RespSize
));
244 return EFI_BUFFER_TOO_SMALL
;
248 // Fail if command failed
250 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
251 DEBUG ((DEBUG_ERROR
, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
252 return EFI_DEVICE_ERROR
;
256 // Unmarshal the response
265 This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.
266 If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
267 the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each
268 bank extended with the associated digest value.
270 @param[in] PcrHandle PCR to be extended with the Event data
271 @param[in] SequenceHandle Authorization for the sequence
272 @param[in] Buffer Data to be added to the Event
273 @param[out] Results List of digests computed for the PCR
275 @retval EFI_SUCCESS Operation completed successfully.
276 @retval EFI_DEVICE_ERROR Unexpected device behavior.
280 Tpm2EventSequenceComplete (
281 IN TPMI_DH_PCR PcrHandle
,
282 IN TPMI_DH_OBJECT SequenceHandle
,
283 IN TPM2B_MAX_BUFFER
*Buffer
,
284 OUT TPML_DIGEST_VALUES
*Results
288 TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd
;
289 TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res
;
293 UINT32 SessionInfoSize
;
294 UINT32 SessionInfoSize2
;
296 UINT32 ResultBufSize
;
299 ZeroMem(&Cmd
, sizeof(Cmd
));
304 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
305 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_EventSequenceComplete
);
306 Cmd
.PcrHandle
= SwapBytes32(PcrHandle
);
307 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
310 // Add in pcrHandle Auth session
312 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionPcr
;
315 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
316 BufferPtr
+= SessionInfoSize
;
319 SessionInfoSize2
= CopyAuthSessionCommand (NULL
, BufferPtr
);
320 BufferPtr
+= SessionInfoSize2
;
321 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
+ SessionInfoSize2
);
324 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
325 BufferPtr
+= sizeof(UINT16
);
327 CopyMem(BufferPtr
, &Buffer
->buffer
[0], Buffer
->size
);
328 BufferPtr
+= Buffer
->size
;
330 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
331 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
336 ResultBufSize
= sizeof(Res
);
337 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
338 if (EFI_ERROR(Status
)) {
342 if (ResultBufSize
> sizeof(Res
)) {
343 DEBUG ((DEBUG_ERROR
, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
344 return EFI_BUFFER_TOO_SMALL
;
348 // Validate response headers
350 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
351 if (RespSize
> sizeof(Res
)) {
352 DEBUG ((DEBUG_ERROR
, "EventSequenceComplete: Response size too large! %d\r\n", RespSize
));
353 return EFI_BUFFER_TOO_SMALL
;
357 // Fail if command failed
359 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
360 DEBUG ((DEBUG_ERROR
, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
361 return EFI_DEVICE_ERROR
;
365 // Unmarshal the response
368 BufferPtr
= (UINT8
*)&Res
.Results
;
371 Results
->count
= SwapBytes32(ReadUnaligned32 ((UINT32
*)BufferPtr
));
372 if (Results
->count
> HASH_COUNT
) {
373 DEBUG ((DEBUG_ERROR
, "Tpm2EventSequenceComplete - Results->count error %x\n", Results
->count
));
374 return EFI_DEVICE_ERROR
;
377 BufferPtr
+= sizeof(UINT32
);
379 for (Index
= 0; Index
< Results
->count
; Index
++) {
380 Results
->digests
[Index
].hashAlg
= SwapBytes16(ReadUnaligned16 ((UINT16
*)BufferPtr
));
381 BufferPtr
+= sizeof(UINT16
);
383 DigestSize
= GetHashSizeFromAlgo (Results
->digests
[Index
].hashAlg
);
384 if (DigestSize
== 0) {
385 DEBUG ((DEBUG_ERROR
, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results
->digests
[Index
].hashAlg
));
386 return EFI_DEVICE_ERROR
;
389 &Results
->digests
[Index
].digest
,
393 BufferPtr
+= DigestSize
;
400 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
402 @param[in] SequenceHandle Authorization for the sequence
403 @param[in] Buffer Data to be added to the hash/HMAC
404 @param[out] Result The returned HMAC or digest in a sized buffer
406 @retval EFI_SUCCESS Operation completed successfully.
407 @retval EFI_DEVICE_ERROR Unexpected device behavior.
411 Tpm2SequenceComplete (
412 IN TPMI_DH_OBJECT SequenceHandle
,
413 IN TPM2B_MAX_BUFFER
*Buffer
,
414 OUT TPM2B_DIGEST
*Result
418 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd
;
419 TPM2_SEQUENCE_COMPLETE_RESPONSE Res
;
423 UINT32 SessionInfoSize
;
424 UINT32 ResultBufSize
;
426 ZeroMem(&Cmd
, sizeof(Cmd
));
431 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
432 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_SequenceComplete
);
433 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
436 // Add in Auth session
438 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionSeq
;
441 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
442 BufferPtr
+= SessionInfoSize
;
443 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
);
446 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
447 BufferPtr
+= sizeof(UINT16
);
449 CopyMem(BufferPtr
, &Buffer
->buffer
[0], Buffer
->size
);
450 BufferPtr
+= Buffer
->size
;
453 WriteUnaligned32 ((UINT32
*)BufferPtr
, SwapBytes32 (TPM_RH_NULL
));
454 BufferPtr
+= sizeof (UINT32
);
456 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
457 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
462 ResultBufSize
= sizeof(Res
);
463 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
464 if (EFI_ERROR(Status
)) {
468 if (ResultBufSize
> sizeof(Res
)) {
469 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
470 return EFI_BUFFER_TOO_SMALL
;
474 // Validate response headers
476 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
477 if (RespSize
> sizeof(Res
)) {
478 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Response size too large! %d\r\n", RespSize
));
479 return EFI_BUFFER_TOO_SMALL
;
483 // Fail if command failed
485 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
486 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
487 return EFI_DEVICE_ERROR
;
491 // Unmarshal the response
494 BufferPtr
= (UINT8
*)&Res
.Digest
;
497 Result
->size
= SwapBytes16(ReadUnaligned16 ((UINT16
*)BufferPtr
));
498 if (Result
->size
> sizeof(TPMU_HA
)){
499 DEBUG ((DEBUG_ERROR
, "Tpm2SequenceComplete - Result->size error %x\n", Result
->size
));
500 return EFI_DEVICE_ERROR
;
503 BufferPtr
+= sizeof(UINT16
);