]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
3d99f0615c3554a2321d517b83ed7a76ff7cffcc
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2Sequences.c
1 /** @file
2 Implement TPM2 Sequences related command.
3
4 Copyright (c) 2013 - 2018, 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 TPM2B_AUTH Auth;
21 TPMI_ALG_HASH HashAlg;
22 } TPM2_HASH_SEQUENCE_START_COMMAND;
23
24 typedef struct {
25 TPM2_RESPONSE_HEADER Header;
26 TPMI_DH_OBJECT SequenceHandle;
27 } TPM2_HASH_SEQUENCE_START_RESPONSE;
28
29 typedef struct {
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;
36
37 typedef struct {
38 TPM2_RESPONSE_HEADER Header;
39 UINT32 ParameterSize;
40 TPMS_AUTH_RESPONSE AuthSessionSeq;
41 } TPM2_SEQUENCE_UPDATE_RESPONSE;
42
43 typedef struct {
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;
52
53 typedef struct {
54 TPM2_RESPONSE_HEADER Header;
55 UINT32 ParameterSize;
56 TPML_DIGEST_VALUES Results;
57 TPMS_AUTH_RESPONSE AuthSessionPcr;
58 TPMS_AUTH_RESPONSE AuthSessionSeq;
59 } TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE;
60
61 typedef struct {
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;
69
70 typedef struct {
71 TPM2_RESPONSE_HEADER Header;
72 UINT32 ParameterSize;
73 TPM2B_DIGEST Digest;
74 TPMS_AUTH_RESPONSE AuthSessionSeq;
75 } TPM2_SEQUENCE_COMPLETE_RESPONSE;
76
77 #pragma pack()
78
79 /**
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.
83
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
87
88 @retval EFI_SUCCESS Operation completed successfully.
89 @retval EFI_DEVICE_ERROR Unexpected device behavior.
90 **/
91 EFI_STATUS
92 EFIAPI
93 Tpm2HashSequenceStart (
94 IN TPMI_ALG_HASH HashAlg,
95 OUT TPMI_DH_OBJECT *SequenceHandle
96 )
97 {
98 EFI_STATUS Status;
99 TPM2_HASH_SEQUENCE_START_COMMAND Cmd;
100 TPM2_HASH_SEQUENCE_START_RESPONSE Res;
101 UINT32 CmdSize;
102 UINT32 RespSize;
103 UINT8 *Buffer;
104 UINT32 ResultBufSize;
105
106 ZeroMem(&Cmd, sizeof(Cmd));
107
108 //
109 // Construct command
110 //
111 Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
112 Cmd.Header.commandCode = SwapBytes32(TPM_CC_HashSequenceStart);
113
114 Buffer = (UINT8 *)&Cmd.Auth;
115
116 // auth = nullAuth
117 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
118 Buffer += sizeof(UINT16);
119
120 // hashAlg
121 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));
122 Buffer += sizeof(UINT16);
123
124 CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
125 Cmd.Header.paramSize = SwapBytes32(CmdSize);
126
127 //
128 // Call the TPM
129 //
130 ResultBufSize = sizeof(Res);
131 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
132 if (EFI_ERROR(Status)) {
133 return Status;
134 }
135
136 if (ResultBufSize > sizeof(Res)) {
137 DEBUG ((DEBUG_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));
138 return EFI_BUFFER_TOO_SMALL;
139 }
140
141 //
142 // Validate response headers
143 //
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;
148 }
149
150 //
151 // Fail if command failed
152 //
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;
156 }
157
158 //
159 // Unmarshal the response
160 //
161
162 // sequenceHandle
163 *SequenceHandle = SwapBytes32(Res.SequenceHandle);
164
165 return EFI_SUCCESS;
166 }
167
168 /**
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.
172
173 @param[in] SequenceHandle Handle for the sequence object
174 @param[in] Buffer Data to be added to hash
175
176 @retval EFI_SUCCESS Operation completed successfully.
177 @retval EFI_DEVICE_ERROR Unexpected device behavior.
178 **/
179 EFI_STATUS
180 EFIAPI
181 Tpm2SequenceUpdate (
182 IN TPMI_DH_OBJECT SequenceHandle,
183 IN TPM2B_MAX_BUFFER *Buffer
184 )
185 {
186 EFI_STATUS Status;
187 TPM2_SEQUENCE_UPDATE_COMMAND Cmd;
188 TPM2_SEQUENCE_UPDATE_RESPONSE Res;
189 UINT32 CmdSize;
190 UINT32 RespSize;
191 UINT8 *BufferPtr;
192 UINT32 SessionInfoSize;
193 UINT32 ResultBufSize;
194
195 ZeroMem(&Cmd, sizeof(Cmd));
196
197 //
198 // Construct command
199 //
200 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
201 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceUpdate);
202 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
203
204 //
205 // Add in Auth session
206 //
207 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
208
209 // sessionInfoSize
210 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
211 BufferPtr += SessionInfoSize;
212 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
213
214 // buffer.size
215 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
216 BufferPtr += sizeof(UINT16);
217
218 CopyMem(BufferPtr, &Buffer->buffer, Buffer->size);
219 BufferPtr += Buffer->size;
220
221 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
222 Cmd.Header.paramSize = SwapBytes32(CmdSize);
223
224 //
225 // Call the TPM
226 //
227 ResultBufSize = sizeof(Res);
228 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd,&ResultBufSize, (UINT8 *)&Res);
229 if (EFI_ERROR(Status)) {
230 return Status;
231 }
232
233 if (ResultBufSize > sizeof(Res)) {
234 DEBUG ((DEBUG_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));
235 return EFI_BUFFER_TOO_SMALL;
236 }
237
238 //
239 // Validate response headers
240 //
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;
245 }
246
247 //
248 // Fail if command failed
249 //
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;
253 }
254
255 //
256 // Unmarshal the response
257 //
258
259 // None
260
261 return EFI_SUCCESS;
262 }
263
264 /**
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.
269
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
274
275 @retval EFI_SUCCESS Operation completed successfully.
276 @retval EFI_DEVICE_ERROR Unexpected device behavior.
277 **/
278 EFI_STATUS
279 EFIAPI
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
285 )
286 {
287 EFI_STATUS Status;
288 TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd;
289 TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res;
290 UINT32 CmdSize;
291 UINT32 RespSize;
292 UINT8 *BufferPtr;
293 UINT32 SessionInfoSize;
294 UINT32 SessionInfoSize2;
295 UINT32 Index;
296 UINT32 ResultBufSize;
297 UINT16 DigestSize;
298
299 ZeroMem(&Cmd, sizeof(Cmd));
300
301 //
302 // Construct command
303 //
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);
308
309 //
310 // Add in pcrHandle Auth session
311 //
312 BufferPtr = (UINT8 *)&Cmd.AuthSessionPcr;
313
314 // sessionInfoSize
315 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
316 BufferPtr += SessionInfoSize;
317
318 // sessionInfoSize
319 SessionInfoSize2 = CopyAuthSessionCommand (NULL, BufferPtr);
320 BufferPtr += SessionInfoSize2;
321 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize + SessionInfoSize2);
322
323 // buffer.size
324 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
325 BufferPtr += sizeof(UINT16);
326
327 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
328 BufferPtr += Buffer->size;
329
330 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
331 Cmd.Header.paramSize = SwapBytes32(CmdSize);
332
333 //
334 // Call the TPM
335 //
336 ResultBufSize = sizeof(Res);
337 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
338 if (EFI_ERROR(Status)) {
339 return Status;
340 }
341
342 if (ResultBufSize > sizeof(Res)) {
343 DEBUG ((DEBUG_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
344 return EFI_BUFFER_TOO_SMALL;
345 }
346
347 //
348 // Validate response headers
349 //
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;
354 }
355
356 //
357 // Fail if command failed
358 //
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;
362 }
363
364 //
365 // Unmarshal the response
366 //
367
368 BufferPtr = (UINT8 *)&Res.Results;
369
370 // count
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;
375 }
376
377 BufferPtr += sizeof(UINT32);
378
379 for (Index = 0; Index < Results->count; Index++) {
380 Results->digests[Index].hashAlg = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));
381 BufferPtr += sizeof(UINT16);
382
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;
387 }
388 CopyMem(
389 &Results->digests[Index].digest,
390 BufferPtr,
391 DigestSize
392 );
393 BufferPtr += DigestSize;
394 }
395
396 return EFI_SUCCESS;
397 }
398
399 /**
400 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
401
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
405
406 @retval EFI_SUCCESS Operation completed successfully.
407 @retval EFI_DEVICE_ERROR Unexpected device behavior.
408 **/
409 EFI_STATUS
410 EFIAPI
411 Tpm2SequenceComplete (
412 IN TPMI_DH_OBJECT SequenceHandle,
413 IN TPM2B_MAX_BUFFER *Buffer,
414 OUT TPM2B_DIGEST *Result
415 )
416 {
417 EFI_STATUS Status;
418 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd;
419 TPM2_SEQUENCE_COMPLETE_RESPONSE Res;
420 UINT32 CmdSize;
421 UINT32 RespSize;
422 UINT8 *BufferPtr;
423 UINT32 SessionInfoSize;
424 UINT32 ResultBufSize;
425
426 ZeroMem(&Cmd, sizeof(Cmd));
427
428 //
429 // Construct command
430 //
431 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
432 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceComplete);
433 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
434
435 //
436 // Add in Auth session
437 //
438 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
439
440 // sessionInfoSize
441 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
442 BufferPtr += SessionInfoSize;
443 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
444
445 // buffer.size
446 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
447 BufferPtr += sizeof(UINT16);
448
449 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
450 BufferPtr += Buffer->size;
451
452 // Hierarchy
453 WriteUnaligned32 ((UINT32 *)BufferPtr, SwapBytes32 (TPM_RH_NULL));
454 BufferPtr += sizeof (UINT32);
455
456 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
457 Cmd.Header.paramSize = SwapBytes32(CmdSize);
458
459 //
460 // Call the TPM
461 //
462 ResultBufSize = sizeof(Res);
463 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
464 if (EFI_ERROR(Status)) {
465 return Status;
466 }
467
468 if (ResultBufSize > sizeof(Res)) {
469 DEBUG ((DEBUG_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
470 return EFI_BUFFER_TOO_SMALL;
471 }
472
473 //
474 // Validate response headers
475 //
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;
480 }
481
482 //
483 // Fail if command failed
484 //
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;
488 }
489
490 //
491 // Unmarshal the response
492 //
493
494 BufferPtr = (UINT8 *)&Res.Digest;
495
496 // digestSize
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;
501 }
502
503 BufferPtr += sizeof(UINT16);
504
505 CopyMem(
506 Result->buffer,
507 BufferPtr,
508 Result->size
509 );
510
511 return EFI_SUCCESS;
512 }