]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
SecurityPkg: Clean up source files
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2Sequences.c
CommitLineData
c1d93242
JY
1/** @file\r
2 Implement TPM2 Sequences related command.\r
3\r
dd577319 4Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>\r
c1d93242
JY
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <IndustryStandard/UefiTcgPlatform.h>\r
16#include <Library/Tpm2CommandLib.h>\r
17#include <Library/Tpm2DeviceLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21\r
22#pragma pack(1)\r
23\r
24typedef struct {\r
25 TPM2_COMMAND_HEADER Header;\r
26 TPM2B_AUTH Auth;\r
27 TPMI_ALG_HASH HashAlg;\r
28} TPM2_HASH_SEQUENCE_START_COMMAND;\r
29\r
30typedef struct {\r
31 TPM2_RESPONSE_HEADER Header;\r
32 TPMI_DH_OBJECT SequenceHandle;\r
33} TPM2_HASH_SEQUENCE_START_RESPONSE;\r
34\r
35typedef struct {\r
36 TPM2_COMMAND_HEADER Header;\r
37 TPMI_DH_OBJECT SequenceHandle;\r
38 UINT32 AuthorizationSize;\r
39 TPMS_AUTH_COMMAND AuthSessionSeq;\r
40 TPM2B_MAX_BUFFER Buffer;\r
41} TPM2_SEQUENCE_UPDATE_COMMAND;\r
42\r
43typedef struct {\r
44 TPM2_RESPONSE_HEADER Header;\r
45 UINT32 ParameterSize;\r
46 TPMS_AUTH_RESPONSE AuthSessionSeq;\r
47} TPM2_SEQUENCE_UPDATE_RESPONSE;\r
48\r
49typedef struct {\r
50 TPM2_COMMAND_HEADER Header;\r
51 TPMI_DH_PCR PcrHandle;\r
52 TPMI_DH_OBJECT SequenceHandle;\r
53 UINT32 AuthorizationSize;\r
54 TPMS_AUTH_COMMAND AuthSessionPcr;\r
55 TPMS_AUTH_COMMAND AuthSessionSeq;\r
56 TPM2B_MAX_BUFFER Buffer;\r
57} TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND;\r
58\r
59typedef struct {\r
60 TPM2_RESPONSE_HEADER Header;\r
61 UINT32 ParameterSize;\r
62 TPML_DIGEST_VALUES Results;\r
63 TPMS_AUTH_RESPONSE AuthSessionPcr;\r
64 TPMS_AUTH_RESPONSE AuthSessionSeq;\r
65} TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE;\r
66\r
67typedef struct {\r
68 TPM2_COMMAND_HEADER Header;\r
69 TPMI_DH_OBJECT SequenceHandle;\r
70 UINT32 AuthorizationSize;\r
71 TPMS_AUTH_COMMAND AuthSessionSeq;\r
72 TPM2B_MAX_BUFFER Buffer;\r
73 TPMI_RH_HIERARCHY Hierarchy;\r
74} TPM2_SEQUENCE_COMPLETE_COMMAND;\r
75\r
76typedef struct {\r
77 TPM2_RESPONSE_HEADER Header;\r
78 UINT32 ParameterSize;\r
79 TPM2B_DIGEST Digest;\r
80 TPMS_AUTH_RESPONSE AuthSessionSeq;\r
81} TPM2_SEQUENCE_COMPLETE_RESPONSE;\r
82\r
83#pragma pack()\r
84\r
85/**\r
86 This command starts a hash or an Event sequence.\r
87 If hashAlg is an implemented hash, then a hash sequence is started.\r
88 If hashAlg is TPM_ALG_NULL, then an Event sequence is started.\r
89\r
90 @param[in] HashAlg The hash algorithm to use for the hash sequence\r
91 An Event sequence starts if this is TPM_ALG_NULL.\r
92 @param[out] SequenceHandle A handle to reference the sequence\r
b3548d32 93\r
c1d93242
JY
94 @retval EFI_SUCCESS Operation completed successfully.\r
95 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
96**/\r
97EFI_STATUS\r
98EFIAPI\r
99Tpm2HashSequenceStart (\r
100 IN TPMI_ALG_HASH HashAlg,\r
101 OUT TPMI_DH_OBJECT *SequenceHandle\r
102 )\r
103{\r
104 EFI_STATUS Status;\r
105 TPM2_HASH_SEQUENCE_START_COMMAND Cmd;\r
106 TPM2_HASH_SEQUENCE_START_RESPONSE Res;\r
107 UINT32 CmdSize;\r
108 UINT32 RespSize;\r
109 UINT8 *Buffer;\r
110 UINT32 ResultBufSize;\r
111\r
112 ZeroMem(&Cmd, sizeof(Cmd));\r
113\r
114 //\r
115 // Construct command\r
116 //\r
117 Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);\r
118 Cmd.Header.commandCode = SwapBytes32(TPM_CC_HashSequenceStart);\r
119\r
120 Buffer = (UINT8 *)&Cmd.Auth;\r
121\r
122 // auth = nullAuth\r
123 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));\r
124 Buffer += sizeof(UINT16);\r
125\r
126 // hashAlg\r
127 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));\r
128 Buffer += sizeof(UINT16);\r
129\r
130 CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
131 Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
132\r
133 //\r
134 // Call the TPM\r
135 //\r
136 ResultBufSize = sizeof(Res);\r
137 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
138 if (EFI_ERROR(Status)) {\r
139 return Status;\r
140 }\r
141\r
142 if (ResultBufSize > sizeof(Res)) {\r
143 DEBUG ((EFI_D_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
144 return EFI_BUFFER_TOO_SMALL;\r
145 }\r
146\r
147 //\r
148 // Validate response headers\r
149 //\r
150 RespSize = SwapBytes32(Res.Header.paramSize);\r
151 if (RespSize > sizeof(Res)) {\r
152 DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response size too large! %d\r\n", RespSize));\r
153 return EFI_BUFFER_TOO_SMALL;\r
154 }\r
155\r
156 //\r
157 // Fail if command failed\r
158 //\r
159 if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
160 DEBUG ((EFI_D_ERROR, "HashSequenceStart: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
161 return EFI_DEVICE_ERROR;\r
162 }\r
163\r
164 //\r
165 // Unmarshal the response\r
166 //\r
167\r
168 // sequenceHandle\r
169 *SequenceHandle = SwapBytes32(Res.SequenceHandle);\r
170\r
171 return EFI_SUCCESS;\r
172}\r
173\r
174/**\r
175 This command is used to add data to a hash or HMAC sequence.\r
176 The amount of data in buffer may be any size up to the limits of the TPM.\r
177 NOTE: In all TPM, a buffer size of 1,024 octets is allowed.\r
178\r
179 @param[in] SequenceHandle Handle for the sequence object\r
180 @param[in] Buffer Data to be added to hash\r
b3548d32 181\r
c1d93242
JY
182 @retval EFI_SUCCESS Operation completed successfully.\r
183 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
184**/\r
185EFI_STATUS\r
186EFIAPI\r
187Tpm2SequenceUpdate (\r
188 IN TPMI_DH_OBJECT SequenceHandle,\r
189 IN TPM2B_MAX_BUFFER *Buffer\r
190 )\r
191{\r
192 EFI_STATUS Status;\r
193 TPM2_SEQUENCE_UPDATE_COMMAND Cmd;\r
194 TPM2_SEQUENCE_UPDATE_RESPONSE Res;\r
195 UINT32 CmdSize;\r
196 UINT32 RespSize;\r
197 UINT8 *BufferPtr;\r
198 UINT32 SessionInfoSize;\r
199 UINT32 ResultBufSize;\r
200\r
201 ZeroMem(&Cmd, sizeof(Cmd));\r
202\r
203 //\r
204 // Construct command\r
205 //\r
206 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
207 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceUpdate);\r
208 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
209\r
210 //\r
211 // Add in Auth session\r
212 //\r
213 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;\r
214\r
215 // sessionInfoSize\r
216 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
217 BufferPtr += SessionInfoSize;\r
218 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
219\r
220 // buffer.size\r
221 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
222 BufferPtr += sizeof(UINT16);\r
223\r
224 CopyMem(BufferPtr, &Buffer->buffer, Buffer->size);\r
225 BufferPtr += Buffer->size;\r
226\r
227 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
228 Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
229\r
230 //\r
231 // Call the TPM\r
232 //\r
233 ResultBufSize = sizeof(Res);\r
234 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd,&ResultBufSize, (UINT8 *)&Res);\r
235 if (EFI_ERROR(Status)) {\r
236 return Status;\r
237 }\r
238\r
239 if (ResultBufSize > sizeof(Res)) {\r
240 DEBUG ((EFI_D_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
241 return EFI_BUFFER_TOO_SMALL;\r
242 }\r
243\r
244 //\r
245 // Validate response headers\r
246 //\r
247 RespSize = SwapBytes32(Res.Header.paramSize);\r
248 if (RespSize > sizeof(Res)) {\r
249 DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response size too large! %d\r\n", RespSize));\r
250 return EFI_BUFFER_TOO_SMALL;\r
251 }\r
252\r
253 //\r
254 // Fail if command failed\r
255 //\r
256 if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
257 DEBUG ((EFI_D_ERROR, "SequenceUpdate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
258 return EFI_DEVICE_ERROR;\r
259 }\r
260\r
261 //\r
262 // Unmarshal the response\r
263 //\r
264\r
265 // None\r
266\r
267 return EFI_SUCCESS;\r
268}\r
269\r
270/**\r
271 This command adds the last part of data, if any, to an Event sequence and returns the result in a digest list.\r
272 If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in\r
273 the same manner as the digest list input parameter to TPM2_PCR_Extend() with the pcrHandle in each\r
274 bank extended with the associated digest value.\r
275\r
276 @param[in] PcrHandle PCR to be extended with the Event data\r
277 @param[in] SequenceHandle Authorization for the sequence\r
278 @param[in] Buffer Data to be added to the Event\r
279 @param[out] Results List of digests computed for the PCR\r
b3548d32 280\r
c1d93242
JY
281 @retval EFI_SUCCESS Operation completed successfully.\r
282 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
283**/\r
284EFI_STATUS\r
285EFIAPI\r
286Tpm2EventSequenceComplete (\r
287 IN TPMI_DH_PCR PcrHandle,\r
288 IN TPMI_DH_OBJECT SequenceHandle,\r
289 IN TPM2B_MAX_BUFFER *Buffer,\r
290 OUT TPML_DIGEST_VALUES *Results\r
291 )\r
292{\r
293 EFI_STATUS Status;\r
294 TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd;\r
295 TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res;\r
296 UINT32 CmdSize;\r
297 UINT32 RespSize;\r
298 UINT8 *BufferPtr;\r
299 UINT32 SessionInfoSize;\r
300 UINT32 SessionInfoSize2;\r
301 UINT32 Index;\r
302 UINT32 ResultBufSize;\r
303 UINT16 DigestSize;\r
304\r
305 ZeroMem(&Cmd, sizeof(Cmd));\r
306\r
307 //\r
308 // Construct command\r
309 //\r
310 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
311 Cmd.Header.commandCode = SwapBytes32(TPM_CC_EventSequenceComplete);\r
312 Cmd.PcrHandle = SwapBytes32(PcrHandle);\r
313 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
314\r
315 //\r
316 // Add in pcrHandle Auth session\r
317 //\r
318 BufferPtr = (UINT8 *)&Cmd.AuthSessionPcr;\r
319\r
320 // sessionInfoSize\r
321 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
322 BufferPtr += SessionInfoSize;\r
323\r
324 // sessionInfoSize\r
325 SessionInfoSize2 = CopyAuthSessionCommand (NULL, BufferPtr);\r
326 BufferPtr += SessionInfoSize2;\r
327 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize + SessionInfoSize2);\r
328\r
329 // buffer.size\r
330 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
331 BufferPtr += sizeof(UINT16);\r
332\r
333 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);\r
334 BufferPtr += Buffer->size;\r
335\r
336 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
337 Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
338\r
339 //\r
340 // Call the TPM\r
341 //\r
342 ResultBufSize = sizeof(Res);\r
343 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
344 if (EFI_ERROR(Status)) {\r
345 return Status;\r
346 }\r
347\r
348 if (ResultBufSize > sizeof(Res)) {\r
349 DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
350 return EFI_BUFFER_TOO_SMALL;\r
351 }\r
352\r
353 //\r
354 // Validate response headers\r
355 //\r
356 RespSize = SwapBytes32(Res.Header.paramSize);\r
357 if (RespSize > sizeof(Res)) {\r
358 DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response size too large! %d\r\n", RespSize));\r
359 return EFI_BUFFER_TOO_SMALL;\r
360 }\r
361\r
362 //\r
363 // Fail if command failed\r
364 //\r
365 if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
366 DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
367 return EFI_DEVICE_ERROR;\r
368 }\r
369\r
370 //\r
371 // Unmarshal the response\r
372 //\r
373\r
374 BufferPtr = (UINT8 *)&Res.Results;\r
375\r
376 // count\r
377 Results->count = SwapBytes32(ReadUnaligned32 ((UINT32 *)BufferPtr));\r
dd577319
ZC
378 if (Results->count > HASH_COUNT) {\r
379 DEBUG ((DEBUG_ERROR, "Tpm2EventSequenceComplete - Results->count error %x\n", Results->count));\r
380 return EFI_DEVICE_ERROR;\r
381 }\r
382\r
c1d93242
JY
383 BufferPtr += sizeof(UINT32);\r
384\r
385 for (Index = 0; Index < Results->count; Index++) {\r
386 Results->digests[Index].hashAlg = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));\r
387 BufferPtr += sizeof(UINT16);\r
388\r
389 DigestSize = GetHashSizeFromAlgo (Results->digests[Index].hashAlg);\r
390 if (DigestSize == 0) {\r
391 DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Unknown hash algorithm %d\r\n", Results->digests[Index].hashAlg));\r
392 return EFI_DEVICE_ERROR;\r
393 }\r
394 CopyMem(\r
395 &Results->digests[Index].digest,\r
396 BufferPtr,\r
397 DigestSize\r
398 );\r
399 BufferPtr += DigestSize;\r
400 }\r
401\r
402 return EFI_SUCCESS;\r
403}\r
404\r
405/**\r
406 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.\r
407\r
408 @param[in] SequenceHandle Authorization for the sequence\r
409 @param[in] Buffer Data to be added to the hash/HMAC\r
410 @param[out] Result The returned HMAC or digest in a sized buffer\r
b3548d32 411\r
c1d93242
JY
412 @retval EFI_SUCCESS Operation completed successfully.\r
413 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
414**/\r
415EFI_STATUS\r
416EFIAPI\r
417Tpm2SequenceComplete (\r
418 IN TPMI_DH_OBJECT SequenceHandle,\r
419 IN TPM2B_MAX_BUFFER *Buffer,\r
420 OUT TPM2B_DIGEST *Result\r
421 )\r
422{\r
423 EFI_STATUS Status;\r
424 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd;\r
425 TPM2_SEQUENCE_COMPLETE_RESPONSE Res;\r
426 UINT32 CmdSize;\r
427 UINT32 RespSize;\r
428 UINT8 *BufferPtr;\r
429 UINT32 SessionInfoSize;\r
430 UINT32 ResultBufSize;\r
431\r
432 ZeroMem(&Cmd, sizeof(Cmd));\r
433\r
434 //\r
435 // Construct command\r
436 //\r
437 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);\r
438 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceComplete);\r
439 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);\r
440\r
441 //\r
442 // Add in Auth session\r
443 //\r
444 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;\r
445\r
446 // sessionInfoSize\r
447 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);\r
448 BufferPtr += SessionInfoSize;\r
449 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
450\r
451 // buffer.size\r
452 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));\r
453 BufferPtr += sizeof(UINT16);\r
454\r
455 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);\r
456 BufferPtr += Buffer->size;\r
457\r
458 // Hierarchy\r
459 WriteUnaligned32 ((UINT32 *)BufferPtr, SwapBytes32 (TPM_RH_NULL));\r
460 BufferPtr += sizeof (UINT32);\r
461\r
462 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);\r
463 Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
464\r
465 //\r
466 // Call the TPM\r
467 //\r
468 ResultBufSize = sizeof(Res);\r
469 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
470 if (EFI_ERROR(Status)) {\r
471 return Status;\r
472 }\r
473\r
474 if (ResultBufSize > sizeof(Res)) {\r
475 DEBUG ((EFI_D_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
476 return EFI_BUFFER_TOO_SMALL;\r
477 }\r
478\r
479 //\r
480 // Validate response headers\r
481 //\r
482 RespSize = SwapBytes32(Res.Header.paramSize);\r
483 if (RespSize > sizeof(Res)) {\r
484 DEBUG ((EFI_D_ERROR, "SequenceComplete: Response size too large! %d\r\n", RespSize));\r
485 return EFI_BUFFER_TOO_SMALL;\r
486 }\r
487\r
488 //\r
489 // Fail if command failed\r
490 //\r
491 if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
492 DEBUG ((EFI_D_ERROR, "SequenceComplete: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
493 return EFI_DEVICE_ERROR;\r
494 }\r
495\r
496 //\r
497 // Unmarshal the response\r
498 //\r
499\r
500 BufferPtr = (UINT8 *)&Res.Digest;\r
501\r
502 // digestSize\r
503 Result->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));\r
dd577319
ZC
504 if (Result->size > sizeof(TPMU_HA)){\r
505 DEBUG ((DEBUG_ERROR, "Tpm2SequenceComplete - Result->size error %x\n", Result->size));\r
506 return EFI_DEVICE_ERROR;\r
507 }\r
508\r
c1d93242
JY
509 BufferPtr += sizeof(UINT16);\r
510\r
511 CopyMem(\r
512 Result->buffer,\r
513 BufferPtr,\r
514 Result->size\r
515 );\r
516\r
517 return EFI_SUCCESS;\r
518}\r