2 Implement TPM2 Sequences related command.
4 Copyright (c) 2013 - 2018, 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 if (Results
->count
> HASH_COUNT
) {
379 DEBUG ((DEBUG_ERROR
, "Tpm2EventSequenceComplete - Results->count error %x\n", Results
->count
));
380 return EFI_DEVICE_ERROR
;
383 BufferPtr
+= sizeof(UINT32
);
385 for (Index
= 0; Index
< Results
->count
; Index
++) {
386 Results
->digests
[Index
].hashAlg
= SwapBytes16(ReadUnaligned16 ((UINT16
*)BufferPtr
));
387 BufferPtr
+= sizeof(UINT16
);
389 DigestSize
= GetHashSizeFromAlgo (Results
->digests
[Index
].hashAlg
);
390 if (DigestSize
== 0) {
391 DEBUG ((EFI_D_ERROR
, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results
->digests
[Index
].hashAlg
));
392 return EFI_DEVICE_ERROR
;
395 &Results
->digests
[Index
].digest
,
399 BufferPtr
+= DigestSize
;
406 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
408 @param[in] SequenceHandle Authorization for the sequence
409 @param[in] Buffer Data to be added to the hash/HMAC
410 @param[out] Result The returned HMAC or digest in a sized buffer
412 @retval EFI_SUCCESS Operation completed successfully.
413 @retval EFI_DEVICE_ERROR Unexpected device behavior.
417 Tpm2SequenceComplete (
418 IN TPMI_DH_OBJECT SequenceHandle
,
419 IN TPM2B_MAX_BUFFER
*Buffer
,
420 OUT TPM2B_DIGEST
*Result
424 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd
;
425 TPM2_SEQUENCE_COMPLETE_RESPONSE Res
;
429 UINT32 SessionInfoSize
;
430 UINT32 ResultBufSize
;
432 ZeroMem(&Cmd
, sizeof(Cmd
));
437 Cmd
.Header
.tag
= SwapBytes16(TPM_ST_SESSIONS
);
438 Cmd
.Header
.commandCode
= SwapBytes32(TPM_CC_SequenceComplete
);
439 Cmd
.SequenceHandle
= SwapBytes32(SequenceHandle
);
442 // Add in Auth session
444 BufferPtr
= (UINT8
*)&Cmd
.AuthSessionSeq
;
447 SessionInfoSize
= CopyAuthSessionCommand (NULL
, BufferPtr
);
448 BufferPtr
+= SessionInfoSize
;
449 Cmd
.AuthorizationSize
= SwapBytes32(SessionInfoSize
);
452 WriteUnaligned16 ((UINT16
*)BufferPtr
, SwapBytes16(Buffer
->size
));
453 BufferPtr
+= sizeof(UINT16
);
455 CopyMem(BufferPtr
, &Buffer
->buffer
[0], Buffer
->size
);
456 BufferPtr
+= Buffer
->size
;
459 WriteUnaligned32 ((UINT32
*)BufferPtr
, SwapBytes32 (TPM_RH_NULL
));
460 BufferPtr
+= sizeof (UINT32
);
462 CmdSize
= (UINT32
)(BufferPtr
- (UINT8
*)&Cmd
);
463 Cmd
.Header
.paramSize
= SwapBytes32(CmdSize
);
468 ResultBufSize
= sizeof(Res
);
469 Status
= Tpm2SubmitCommand (CmdSize
, (UINT8
*)&Cmd
, &ResultBufSize
, (UINT8
*)&Res
);
470 if (EFI_ERROR(Status
)) {
474 if (ResultBufSize
> sizeof(Res
)) {
475 DEBUG ((EFI_D_ERROR
, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
476 return EFI_BUFFER_TOO_SMALL
;
480 // Validate response headers
482 RespSize
= SwapBytes32(Res
.Header
.paramSize
);
483 if (RespSize
> sizeof(Res
)) {
484 DEBUG ((EFI_D_ERROR
, "SequenceComplete: Response size too large! %d\r\n", RespSize
));
485 return EFI_BUFFER_TOO_SMALL
;
489 // Fail if command failed
491 if (SwapBytes32(Res
.Header
.responseCode
) != TPM_RC_SUCCESS
) {
492 DEBUG ((EFI_D_ERROR
, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res
.Header
.responseCode
)));
493 return EFI_DEVICE_ERROR
;
497 // Unmarshal the response
500 BufferPtr
= (UINT8
*)&Res
.Digest
;
503 Result
->size
= SwapBytes16(ReadUnaligned16 ((UINT16
*)BufferPtr
));
504 if (Result
->size
> sizeof(TPMU_HA
)){
505 DEBUG ((DEBUG_ERROR
, "Tpm2SequenceComplete - Result->size error %x\n", Result
->size
));
506 return EFI_DEVICE_ERROR
;
509 BufferPtr
+= sizeof(UINT16
);