2 Implement TPM2 Sequences related command.
4 Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <IndustryStandard/UefiTcgPlatform.h>
16 #include <Library/Tpm2CommandLib.h>
17 #include <Library/Tpm2DeviceLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
25 TPM2_COMMAND_HEADER Header
;
27 TPMI_ALG_HASH HashAlg
;
28 } TPM2_HASH_SEQUENCE_START_COMMAND
;
31 TPM2_RESPONSE_HEADER Header
;
32 TPMI_DH_OBJECT SequenceHandle
;
33 } TPM2_HASH_SEQUENCE_START_RESPONSE
;
36 TPM2_COMMAND_HEADER Header
;
37 TPMI_DH_OBJECT SequenceHandle
;
38 UINT32 AuthorizationSize
;
39 TPMS_AUTH_COMMAND AuthSessionSeq
;
40 TPM2B_MAX_BUFFER Buffer
;
41 } TPM2_SEQUENCE_UPDATE_COMMAND
;
44 TPM2_RESPONSE_HEADER Header
;
46 TPMS_AUTH_RESPONSE AuthSessionSeq
;
47 } TPM2_SEQUENCE_UPDATE_RESPONSE
;
50 TPM2_COMMAND_HEADER Header
;
51 TPMI_DH_PCR PcrHandle
;
52 TPMI_DH_OBJECT SequenceHandle
;
53 UINT32 AuthorizationSize
;
54 TPMS_AUTH_COMMAND AuthSessionPcr
;
55 TPMS_AUTH_COMMAND AuthSessionSeq
;
56 TPM2B_MAX_BUFFER Buffer
;
57 } TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND
;
60 TPM2_RESPONSE_HEADER Header
;
62 TPML_DIGEST_VALUES Results
;
63 TPMS_AUTH_RESPONSE AuthSessionPcr
;
64 TPMS_AUTH_RESPONSE AuthSessionSeq
;
65 } TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE
;
68 TPM2_COMMAND_HEADER Header
;
69 TPMI_DH_OBJECT SequenceHandle
;
70 UINT32 AuthorizationSize
;
71 TPMS_AUTH_COMMAND AuthSessionSeq
;
72 TPM2B_MAX_BUFFER Buffer
;
73 TPMI_RH_HIERARCHY Hierarchy
;
74 } TPM2_SEQUENCE_COMPLETE_COMMAND
;
77 TPM2_RESPONSE_HEADER Header
;
80 TPMS_AUTH_RESPONSE AuthSessionSeq
;
81 } TPM2_SEQUENCE_COMPLETE_RESPONSE
;
86 This command starts a hash or an Event sequence.
87 If hashAlg is an implemented hash, then a hash sequence is started.
88 If hashAlg is TPM_ALG_NULL, then an Event sequence is started.
90 @param[in] HashAlg The hash algorithm to use for the hash sequence
91 An Event sequence starts if this is TPM_ALG_NULL.
92 @param[out] SequenceHandle A handle to reference the sequence
94 @retval EFI_SUCCESS Operation completed successfully.
95 @retval EFI_DEVICE_ERROR Unexpected device behavior.
99 Tpm2HashSequenceStart (
100 IN TPMI_ALG_HASH HashAlg
,
101 OUT TPMI_DH_OBJECT
*SequenceHandle
105 TPM2_HASH_SEQUENCE_START_COMMAND Cmd
;
106 TPM2_HASH_SEQUENCE_START_RESPONSE Res
;
110 UINT32 ResultBufSize
;
112 ZeroMem(&Cmd
, sizeof(Cmd
));
117 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_NO_SESSIONS
);
118 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_HashSequenceStart
);
120 Buffer
= (UINT8
*)&Cmd
.Auth
;
123 WriteUnaligned16 ((UINT16
*)Buffer
, SwapBytes16(0));
124 Buffer
+= sizeof(UINT16
);
127 WriteUnaligned16 ((UINT16
*)Buffer
, SwapBytes16(HashAlg
));
128 Buffer
+= sizeof(UINT16
);
130 CmdSize
= (UINT32
)(Buffer
- (UINT8
*)&Cmd
);
131 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
136 ResultBufSize
= sizeof(Res
);
137 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
138 if (EFI_ERROR(Status
)) {
142 if (ResultBufSize
> sizeof(Res
)) {
143 DEBUG ((EFI_D_ERROR
, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));
144 return EFI_BUFFER_TOO_SMALL
;
148 // Validate response headers
150 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
151 if (RespSize
> sizeof(Res
)) {
152 DEBUG ((EFI_D_ERROR
, "HashSequenceStart: Response size too large! %d\r\n", RespSize
));
153 return EFI_BUFFER_TOO_SMALL
;
157 // Fail if command failed
159 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
160 DEBUG ((EFI_D_ERROR
, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
161 return EFI_DEVICE_ERROR
;
165 // Unmarshal the response
169 *SequenceHandle
= SwapBytes32(Res
.SequenceHandle
);
175 This command is used to add data to a hash or HMAC sequence.
176 The amount of data in buffer may be any size up to the limits of the TPM.
177 NOTE: In all TPM, a buffer size of 1,024 octets is allowed.
179 @param[in] SequenceHandle Handle for the sequence object
180 @param[in] Buffer Data to be added to hash
182 @retval EFI_SUCCESS Operation completed successfully.
183 @retval EFI_DEVICE_ERROR Unexpected device behavior.
188 IN TPMI_DH_OBJECT SequenceHandle
,
189 IN TPM2B_MAX_BUFFER
*Buffer
193 TPM2_SEQUENCE_UPDATE_COMMAND Cmd
;
194 TPM2_SEQUENCE_UPDATE_RESPONSE Res
;
198 UINT32 SessionInfoSize
;
199 UINT32 ResultBufSize
;
201 ZeroMem(&Cmd
, sizeof(Cmd
));
206 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
207 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_SequenceUpdate
);
208 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
211 // Add in Auth session
213 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionSeq
;
216 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
217 BufferPtr
+= SessionInfoSize
;
218 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
);
221 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
222 BufferPtr
+= sizeof(UINT16
);
224 CopyMem(BufferPtr
, &Buffer
->buffer
, Buffer
->size
);
225 BufferPtr
+= Buffer
->size
;
227 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
228 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
233 ResultBufSize
= sizeof(Res
);
234 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
,&ResultBufSize
, (UINT8
*)&Res
);
235 if (EFI_ERROR(Status
)) {
239 if (ResultBufSize
> sizeof(Res
)) {
240 DEBUG ((EFI_D_ERROR
, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));
241 return EFI_BUFFER_TOO_SMALL
;
245 // Validate response headers
247 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
248 if (RespSize
> sizeof(Res
)) {
249 DEBUG ((EFI_D_ERROR
, "SequenceUpdate: Response size too large! %d\r\n", RespSize
));
250 return EFI_BUFFER_TOO_SMALL
;
254 // Fail if command failed
256 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
257 DEBUG ((EFI_D_ERROR
, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
258 return EFI_DEVICE_ERROR
;
262 // Unmarshal the response
271 This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.
272 If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
273 the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each
274 bank extended with the associated digest value.
276 @param[in] PcrHandle PCR to be extended with the Event data
277 @param[in] SequenceHandle Authorization for the sequence
278 @param[in] Buffer Data to be added to the Event
279 @param[out] Results List of digests computed for the PCR
281 @retval EFI_SUCCESS Operation completed successfully.
282 @retval EFI_DEVICE_ERROR Unexpected device behavior.
286 Tpm2EventSequenceComplete (
287 IN TPMI_DH_PCR PcrHandle
,
288 IN TPMI_DH_OBJECT SequenceHandle
,
289 IN TPM2B_MAX_BUFFER
*Buffer
,
290 OUT TPML_DIGEST_VALUES
*Results
294 TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd
;
295 TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res
;
299 UINT32 SessionInfoSize
;
300 UINT32 SessionInfoSize2
;
302 UINT32 ResultBufSize
;
305 ZeroMem(&Cmd
, sizeof(Cmd
));
310 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
311 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_EventSequenceComplete
);
312 Cmd
.PcrHandle
= SwapBytes32(PcrHandle
);
313 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
316 // Add in pcrHandle Auth session
318 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionPcr
;
321 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
322 BufferPtr
+= SessionInfoSize
;
325 SessionInfoSize2
= CopyAuthSessionCommand (NULL
, BufferPtr
);
326 BufferPtr
+= SessionInfoSize2
;
327 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
+ SessionInfoSize2
);
330 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
331 BufferPtr
+= sizeof(UINT16
);
333 CopyMem(BufferPtr
, &Buffer
->buffer
[0], Buffer
->size
);
334 BufferPtr
+= Buffer
->size
;
336 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
337 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
342 ResultBufSize
= sizeof(Res
);
343 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
344 if (EFI_ERROR(Status
)) {
348 if (ResultBufSize
> sizeof(Res
)) {
349 DEBUG ((EFI_D_ERROR
, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
350 return EFI_BUFFER_TOO_SMALL
;
354 // Validate response headers
356 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
357 if (RespSize
> sizeof(Res
)) {
358 DEBUG ((EFI_D_ERROR
, "EventSequenceComplete: Response size too large! %d\r\n", RespSize
));
359 return EFI_BUFFER_TOO_SMALL
;
363 // Fail if command failed
365 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
366 DEBUG ((EFI_D_ERROR
, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
367 return EFI_DEVICE_ERROR
;
371 // Unmarshal the response
374 BufferPtr
= (UINT8
*)&Res
.Results
;
377 Results
->count
= SwapBytes32(ReadUnaligned32 ((UINT32
*)BufferPtr
));
378 BufferPtr
+= sizeof(UINT32
);
380 for (Index
= 0; Index
< Results
->count
; Index
++) {
381 Results
->digests
[Index
].hashAlg
= SwapBytes16(ReadUnaligned16 ((UINT16
*)BufferPtr
));
382 BufferPtr
+= sizeof(UINT16
);
384 DigestSize
= GetHashSizeFromAlgo (Results
->digests
[Index
].hashAlg
);
385 if (DigestSize
== 0) {
386 DEBUG ((EFI_D_ERROR
, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results
->digests
[Index
].hashAlg
));
387 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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 BufferPtr
+= sizeof(UINT16
);