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
;
390 &Results
->digests
[Index
].digest
,
394 BufferPtr
+= DigestSize
;
401 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
403 @param[in] SequenceHandle Authorization for the sequence
404 @param[in] Buffer Data to be added to the hash/HMAC
405 @param[out] Result The returned HMAC or digest in a sized buffer
407 @retval EFI_SUCCESS Operation completed successfully.
408 @retval EFI_DEVICE_ERROR Unexpected device behavior.
412 Tpm2SequenceComplete (
413 IN TPMI_DH_OBJECT SequenceHandle
,
414 IN TPM2B_MAX_BUFFER
*Buffer
,
415 OUT TPM2B_DIGEST
*Result
419 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd
;
420 TPM2_SEQUENCE_COMPLETE_RESPONSE Res
;
424 UINT32 SessionInfoSize
;
425 UINT32 ResultBufSize
;
427 ZeroMem (&Cmd
, sizeof (Cmd
));
432 Cmd
.Header
.tag
= SwapBytes16 (TPM_ST_SESSIONS
);
433 Cmd
.Header
.commandCode
= SwapBytes32 (TPM_CC_SequenceComplete
);
434 Cmd
.SequenceHandle
= SwapBytes32 (SequenceHandle
);
437 // Add in Auth session
439 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionSeq
;
442 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
443 BufferPtr
+= SessionInfoSize
;
444 Cmd
.AuthorizationSize
= SwapBytes32 (SessionInfoSize
);
447 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16 (Buffer
->size
));
448 BufferPtr
+= sizeof (UINT16
);
450 CopyMem (BufferPtr
, &Buffer
->buffer
[0], Buffer
->size
);
451 BufferPtr
+= Buffer
->size
;
454 WriteUnaligned32 ((UINT32
*)BufferPtr
, SwapBytes32 (TPM_RH_NULL
));
455 BufferPtr
+= sizeof (UINT32
);
457 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
458 Cmd
.Header
.paramSize
= SwapBytes32 (CmdSize
);
463 ResultBufSize
= sizeof (Res
);
464 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
465 if (EFI_ERROR (Status
)) {
469 if (ResultBufSize
> sizeof (Res
)) {
470 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
471 return EFI_BUFFER_TOO_SMALL
;
475 // Validate response headers
477 RespSize
= SwapBytes32 (Res
.Header
.paramSize
);
478 if (RespSize
> sizeof (Res
)) {
479 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Response size too large! %d\r\n", RespSize
));
480 return EFI_BUFFER_TOO_SMALL
;
484 // Fail if command failed
486 if (SwapBytes32 (Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
487 DEBUG ((DEBUG_ERROR
, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32 (Res
.Header
.responseCode
)));
488 return EFI_DEVICE_ERROR
;
492 // Unmarshal the response
495 BufferPtr
= (UINT8
*)&Res
.Digest
;
498 Result
->size
= SwapBytes16 (ReadUnaligned16 ((UINT16
*)BufferPtr
));
499 if (Result
->size
> sizeof (TPMU_HA
)) {
500 DEBUG ((DEBUG_ERROR
, "Tpm2SequenceComplete - Result->size error %x\n", Result
->size
));
501 return EFI_DEVICE_ERROR
;
504 BufferPtr
+= sizeof (UINT16
);