]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/Tpm2CommandLib/Tpm2Sequences.c
SecurityPkg: Clean up source files
[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 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
9
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.
12
13 **/
14
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>
21
22 #pragma pack(1)
23
24 typedef struct {
25 TPM2_COMMAND_HEADER Header;
26 TPM2B_AUTH Auth;
27 TPMI_ALG_HASH HashAlg;
28 } TPM2_HASH_SEQUENCE_START_COMMAND;
29
30 typedef struct {
31 TPM2_RESPONSE_HEADER Header;
32 TPMI_DH_OBJECT SequenceHandle;
33 } TPM2_HASH_SEQUENCE_START_RESPONSE;
34
35 typedef struct {
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;
42
43 typedef struct {
44 TPM2_RESPONSE_HEADER Header;
45 UINT32 ParameterSize;
46 TPMS_AUTH_RESPONSE AuthSessionSeq;
47 } TPM2_SEQUENCE_UPDATE_RESPONSE;
48
49 typedef struct {
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;
58
59 typedef struct {
60 TPM2_RESPONSE_HEADER Header;
61 UINT32 ParameterSize;
62 TPML_DIGEST_VALUES Results;
63 TPMS_AUTH_RESPONSE AuthSessionPcr;
64 TPMS_AUTH_RESPONSE AuthSessionSeq;
65 } TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE;
66
67 typedef struct {
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;
75
76 typedef struct {
77 TPM2_RESPONSE_HEADER Header;
78 UINT32 ParameterSize;
79 TPM2B_DIGEST Digest;
80 TPMS_AUTH_RESPONSE AuthSessionSeq;
81 } TPM2_SEQUENCE_COMPLETE_RESPONSE;
82
83 #pragma pack()
84
85 /**
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.
89
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
93
94 @retval EFI_SUCCESS Operation completed successfully.
95 @retval EFI_DEVICE_ERROR Unexpected device behavior.
96 **/
97 EFI_STATUS
98 EFIAPI
99 Tpm2HashSequenceStart (
100 IN TPMI_ALG_HASH HashAlg,
101 OUT TPMI_DH_OBJECT *SequenceHandle
102 )
103 {
104 EFI_STATUS Status;
105 TPM2_HASH_SEQUENCE_START_COMMAND Cmd;
106 TPM2_HASH_SEQUENCE_START_RESPONSE Res;
107 UINT32 CmdSize;
108 UINT32 RespSize;
109 UINT8 *Buffer;
110 UINT32 ResultBufSize;
111
112 ZeroMem(&Cmd, sizeof(Cmd));
113
114 //
115 // Construct command
116 //
117 Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
118 Cmd.Header.commandCode = SwapBytes32(TPM_CC_HashSequenceStart);
119
120 Buffer = (UINT8 *)&Cmd.Auth;
121
122 // auth = nullAuth
123 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
124 Buffer += sizeof(UINT16);
125
126 // hashAlg
127 WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg));
128 Buffer += sizeof(UINT16);
129
130 CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
131 Cmd.Header.paramSize = SwapBytes32(CmdSize);
132
133 //
134 // Call the TPM
135 //
136 ResultBufSize = sizeof(Res);
137 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
138 if (EFI_ERROR(Status)) {
139 return Status;
140 }
141
142 if (ResultBufSize > sizeof(Res)) {
143 DEBUG ((EFI_D_ERROR, "HashSequenceStart: Failed ExecuteCommand: Buffer Too Small\r\n"));
144 return EFI_BUFFER_TOO_SMALL;
145 }
146
147 //
148 // Validate response headers
149 //
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;
154 }
155
156 //
157 // Fail if command failed
158 //
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;
162 }
163
164 //
165 // Unmarshal the response
166 //
167
168 // sequenceHandle
169 *SequenceHandle = SwapBytes32(Res.SequenceHandle);
170
171 return EFI_SUCCESS;
172 }
173
174 /**
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.
178
179 @param[in] SequenceHandle Handle for the sequence object
180 @param[in] Buffer Data to be added to hash
181
182 @retval EFI_SUCCESS Operation completed successfully.
183 @retval EFI_DEVICE_ERROR Unexpected device behavior.
184 **/
185 EFI_STATUS
186 EFIAPI
187 Tpm2SequenceUpdate (
188 IN TPMI_DH_OBJECT SequenceHandle,
189 IN TPM2B_MAX_BUFFER *Buffer
190 )
191 {
192 EFI_STATUS Status;
193 TPM2_SEQUENCE_UPDATE_COMMAND Cmd;
194 TPM2_SEQUENCE_UPDATE_RESPONSE Res;
195 UINT32 CmdSize;
196 UINT32 RespSize;
197 UINT8 *BufferPtr;
198 UINT32 SessionInfoSize;
199 UINT32 ResultBufSize;
200
201 ZeroMem(&Cmd, sizeof(Cmd));
202
203 //
204 // Construct command
205 //
206 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
207 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceUpdate);
208 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
209
210 //
211 // Add in Auth session
212 //
213 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
214
215 // sessionInfoSize
216 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
217 BufferPtr += SessionInfoSize;
218 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
219
220 // buffer.size
221 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
222 BufferPtr += sizeof(UINT16);
223
224 CopyMem(BufferPtr, &Buffer->buffer, Buffer->size);
225 BufferPtr += Buffer->size;
226
227 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
228 Cmd.Header.paramSize = SwapBytes32(CmdSize);
229
230 //
231 // Call the TPM
232 //
233 ResultBufSize = sizeof(Res);
234 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd,&ResultBufSize, (UINT8 *)&Res);
235 if (EFI_ERROR(Status)) {
236 return Status;
237 }
238
239 if (ResultBufSize > sizeof(Res)) {
240 DEBUG ((EFI_D_ERROR, "SequenceUpdate: Failed ExecuteCommand: Buffer Too Small\r\n"));
241 return EFI_BUFFER_TOO_SMALL;
242 }
243
244 //
245 // Validate response headers
246 //
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;
251 }
252
253 //
254 // Fail if command failed
255 //
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;
259 }
260
261 //
262 // Unmarshal the response
263 //
264
265 // None
266
267 return EFI_SUCCESS;
268 }
269
270 /**
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.
275
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
280
281 @retval EFI_SUCCESS Operation completed successfully.
282 @retval EFI_DEVICE_ERROR Unexpected device behavior.
283 **/
284 EFI_STATUS
285 EFIAPI
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
291 )
292 {
293 EFI_STATUS Status;
294 TPM2_EVENT_SEQUENCE_COMPLETE_COMMAND Cmd;
295 TPM2_EVENT_SEQUENCE_COMPLETE_RESPONSE Res;
296 UINT32 CmdSize;
297 UINT32 RespSize;
298 UINT8 *BufferPtr;
299 UINT32 SessionInfoSize;
300 UINT32 SessionInfoSize2;
301 UINT32 Index;
302 UINT32 ResultBufSize;
303 UINT16 DigestSize;
304
305 ZeroMem(&Cmd, sizeof(Cmd));
306
307 //
308 // Construct command
309 //
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);
314
315 //
316 // Add in pcrHandle Auth session
317 //
318 BufferPtr = (UINT8 *)&Cmd.AuthSessionPcr;
319
320 // sessionInfoSize
321 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
322 BufferPtr += SessionInfoSize;
323
324 // sessionInfoSize
325 SessionInfoSize2 = CopyAuthSessionCommand (NULL, BufferPtr);
326 BufferPtr += SessionInfoSize2;
327 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize + SessionInfoSize2);
328
329 // buffer.size
330 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
331 BufferPtr += sizeof(UINT16);
332
333 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
334 BufferPtr += Buffer->size;
335
336 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
337 Cmd.Header.paramSize = SwapBytes32(CmdSize);
338
339 //
340 // Call the TPM
341 //
342 ResultBufSize = sizeof(Res);
343 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
344 if (EFI_ERROR(Status)) {
345 return Status;
346 }
347
348 if (ResultBufSize > sizeof(Res)) {
349 DEBUG ((EFI_D_ERROR, "EventSequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
350 return EFI_BUFFER_TOO_SMALL;
351 }
352
353 //
354 // Validate response headers
355 //
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;
360 }
361
362 //
363 // Fail if command failed
364 //
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;
368 }
369
370 //
371 // Unmarshal the response
372 //
373
374 BufferPtr = (UINT8 *)&Res.Results;
375
376 // count
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;
381 }
382
383 BufferPtr += sizeof(UINT32);
384
385 for (Index = 0; Index < Results->count; Index++) {
386 Results->digests[Index].hashAlg = SwapBytes16(ReadUnaligned16 ((UINT16 *)BufferPtr));
387 BufferPtr += sizeof(UINT16);
388
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;
393 }
394 CopyMem(
395 &Results->digests[Index].digest,
396 BufferPtr,
397 DigestSize
398 );
399 BufferPtr += DigestSize;
400 }
401
402 return EFI_SUCCESS;
403 }
404
405 /**
406 This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
407
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
411
412 @retval EFI_SUCCESS Operation completed successfully.
413 @retval EFI_DEVICE_ERROR Unexpected device behavior.
414 **/
415 EFI_STATUS
416 EFIAPI
417 Tpm2SequenceComplete (
418 IN TPMI_DH_OBJECT SequenceHandle,
419 IN TPM2B_MAX_BUFFER *Buffer,
420 OUT TPM2B_DIGEST *Result
421 )
422 {
423 EFI_STATUS Status;
424 TPM2_SEQUENCE_COMPLETE_COMMAND Cmd;
425 TPM2_SEQUENCE_COMPLETE_RESPONSE Res;
426 UINT32 CmdSize;
427 UINT32 RespSize;
428 UINT8 *BufferPtr;
429 UINT32 SessionInfoSize;
430 UINT32 ResultBufSize;
431
432 ZeroMem(&Cmd, sizeof(Cmd));
433
434 //
435 // Construct command
436 //
437 Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
438 Cmd.Header.commandCode = SwapBytes32(TPM_CC_SequenceComplete);
439 Cmd.SequenceHandle = SwapBytes32(SequenceHandle);
440
441 //
442 // Add in Auth session
443 //
444 BufferPtr = (UINT8 *)&Cmd.AuthSessionSeq;
445
446 // sessionInfoSize
447 SessionInfoSize = CopyAuthSessionCommand (NULL, BufferPtr);
448 BufferPtr += SessionInfoSize;
449 Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);
450
451 // buffer.size
452 WriteUnaligned16 ((UINT16 *)BufferPtr, SwapBytes16(Buffer->size));
453 BufferPtr += sizeof(UINT16);
454
455 CopyMem(BufferPtr, &Buffer->buffer[0], Buffer->size);
456 BufferPtr += Buffer->size;
457
458 // Hierarchy
459 WriteUnaligned32 ((UINT32 *)BufferPtr, SwapBytes32 (TPM_RH_NULL));
460 BufferPtr += sizeof (UINT32);
461
462 CmdSize = (UINT32)(BufferPtr - (UINT8 *)&Cmd);
463 Cmd.Header.paramSize = SwapBytes32(CmdSize);
464
465 //
466 // Call the TPM
467 //
468 ResultBufSize = sizeof(Res);
469 Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
470 if (EFI_ERROR(Status)) {
471 return Status;
472 }
473
474 if (ResultBufSize > sizeof(Res)) {
475 DEBUG ((EFI_D_ERROR, "SequenceComplete: Failed ExecuteCommand: Buffer Too Small\r\n"));
476 return EFI_BUFFER_TOO_SMALL;
477 }
478
479 //
480 // Validate response headers
481 //
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;
486 }
487
488 //
489 // Fail if command failed
490 //
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;
494 }
495
496 //
497 // Unmarshal the response
498 //
499
500 BufferPtr = (UINT8 *)&Res.Digest;
501
502 // digestSize
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;
507 }
508
509 BufferPtr += sizeof(UINT16);
510
511 CopyMem(
512 Result->buffer,
513 BufferPtr,
514 Result->size
515 );
516
517 return EFI_SUCCESS;
518 }