Coverage Report

Created: 2024-10-17 06:29

/src/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Integrity.c
Line
Count
Source (jump to first uncovered line)
1
/** @file
2
  Implement TPM2 Integrity related command.
3
4
Copyright (c) 2013 - 2021, 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
  TPMI_DH_PCR            PcrHandle;
21
  UINT32                 AuthorizationSize;
22
  TPMS_AUTH_COMMAND      AuthSessionPcr;
23
  TPML_DIGEST_VALUES     DigestValues;
24
} TPM2_PCR_EXTEND_COMMAND;
25
26
typedef struct {
27
  TPM2_RESPONSE_HEADER    Header;
28
  UINT32                  ParameterSize;
29
  TPMS_AUTH_RESPONSE      AuthSessionPcr;
30
} TPM2_PCR_EXTEND_RESPONSE;
31
32
typedef struct {
33
  TPM2_COMMAND_HEADER    Header;
34
  TPMI_DH_PCR            PcrHandle;
35
  UINT32                 AuthorizationSize;
36
  TPMS_AUTH_COMMAND      AuthSessionPcr;
37
  TPM2B_EVENT            EventData;
38
} TPM2_PCR_EVENT_COMMAND;
39
40
typedef struct {
41
  TPM2_RESPONSE_HEADER    Header;
42
  UINT32                  ParameterSize;
43
  TPML_DIGEST_VALUES      Digests;
44
  TPMS_AUTH_RESPONSE      AuthSessionPcr;
45
} TPM2_PCR_EVENT_RESPONSE;
46
47
typedef struct {
48
  TPM2_COMMAND_HEADER    Header;
49
  TPML_PCR_SELECTION     PcrSelectionIn;
50
} TPM2_PCR_READ_COMMAND;
51
52
typedef struct {
53
  TPM2_RESPONSE_HEADER    Header;
54
  UINT32                  PcrUpdateCounter;
55
  TPML_PCR_SELECTION      PcrSelectionOut;
56
  TPML_DIGEST             PcrValues;
57
} TPM2_PCR_READ_RESPONSE;
58
59
typedef struct {
60
  TPM2_COMMAND_HEADER    Header;
61
  TPMI_RH_PLATFORM       AuthHandle;
62
  UINT32                 AuthSessionSize;
63
  TPMS_AUTH_COMMAND      AuthSession;
64
  TPML_PCR_SELECTION     PcrAllocation;
65
} TPM2_PCR_ALLOCATE_COMMAND;
66
67
typedef struct {
68
  TPM2_RESPONSE_HEADER    Header;
69
  UINT32                  AuthSessionSize;
70
  TPMI_YES_NO             AllocationSuccess;
71
  UINT32                  MaxPCR;
72
  UINT32                  SizeNeeded;
73
  UINT32                  SizeAvailable;
74
  TPMS_AUTH_RESPONSE      AuthSession;
75
} TPM2_PCR_ALLOCATE_RESPONSE;
76
77
#pragma pack()
78
79
/**
80
  This command is used to cause an update to the indicated PCR.
81
  The digests parameter contains one or more tagged digest value identified by an algorithm ID.
82
  For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
83
84
  @param[in] PcrHandle   Handle of the PCR
85
  @param[in] Digests     List of tagged digest values to be extended
86
87
  @retval EFI_SUCCESS      Operation completed successfully.
88
  @retval EFI_DEVICE_ERROR Unexpected device behavior.
89
**/
90
EFI_STATUS
91
EFIAPI
92
Tpm2PcrExtend (
93
  IN      TPMI_DH_PCR         PcrHandle,
94
  IN      TPML_DIGEST_VALUES  *Digests
95
  )
96
0
{
97
0
  EFI_STATUS                Status;
98
0
  TPM2_PCR_EXTEND_COMMAND   Cmd;
99
0
  TPM2_PCR_EXTEND_RESPONSE  Res;
100
0
  UINT32                    CmdSize;
101
0
  UINT32                    RespSize;
102
0
  UINT32                    ResultBufSize;
103
0
  UINT8                     *Buffer;
104
0
  UINTN                     Index;
105
0
  UINT32                    SessionInfoSize;
106
0
  UINT16                    DigestSize;
107
108
0
  Cmd.Header.tag         = SwapBytes16 (TPM_ST_SESSIONS);
109
0
  Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Extend);
110
0
  Cmd.PcrHandle          = SwapBytes32 (PcrHandle);
111
112
  //
113
  // Add in Auth session
114
  //
115
0
  Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
116
117
  // sessionInfoSize
118
0
  SessionInfoSize       = CopyAuthSessionCommand (NULL, Buffer);
119
0
  Buffer               += SessionInfoSize;
120
0
  Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
121
122
  // Digest Count
123
0
  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Digests->count));
124
0
  Buffer += sizeof (UINT32);
125
126
  // Digest
127
0
  for (Index = 0; Index < Digests->count; Index++) {
128
0
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Digests->digests[Index].hashAlg));
129
0
    Buffer    += sizeof (UINT16);
130
0
    DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
131
0
    if (DigestSize == 0) {
132
0
      DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
133
0
      return EFI_DEVICE_ERROR;
134
0
    }
135
136
0
    CopyMem (
137
0
      Buffer,
138
0
      &Digests->digests[Index].digest,
139
0
      DigestSize
140
0
      );
141
142
0
    DEBUG_CODE_BEGIN ();
143
0
    UINTN  Index2;
144
0
    DEBUG ((
145
0
      DEBUG_VERBOSE,
146
0
      "Tpm2PcrExtend - Hash = 0x%04x, Pcr[%02d], digest = ",
147
0
      Digests->digests[Index].hashAlg,
148
0
      (UINT8)PcrHandle
149
0
      ));
150
151
0
    for (Index2 = 0; Index2 < DigestSize; Index2++) {
152
0
      DEBUG ((DEBUG_VERBOSE, "%02x ", Buffer[Index2]));
153
0
    }
154
155
0
    DEBUG ((DEBUG_VERBOSE, "\n"));
156
0
    DEBUG_CODE_END ();
157
158
0
    Buffer += DigestSize;
159
0
  }
160
161
0
  CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
162
0
  Cmd.Header.paramSize = SwapBytes32 (CmdSize);
163
164
0
  ResultBufSize = sizeof (Res);
165
0
  Status        = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
166
0
  if (EFI_ERROR (Status)) {
167
0
    return Status;
168
0
  }
169
170
0
  if (ResultBufSize > sizeof (Res)) {
171
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
172
0
    return EFI_BUFFER_TOO_SMALL;
173
0
  }
174
175
  //
176
  // Validate response headers
177
  //
178
0
  RespSize = SwapBytes32 (Res.Header.paramSize);
179
0
  if (RespSize > sizeof (Res)) {
180
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
181
0
    return EFI_BUFFER_TOO_SMALL;
182
0
  }
183
184
  //
185
  // Fail if command failed
186
  //
187
0
  if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
188
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
189
0
    return EFI_DEVICE_ERROR;
190
0
  }
191
192
0
  DEBUG_CODE_BEGIN ();
193
0
  DEBUG ((DEBUG_VERBOSE, "Tpm2PcrExtend: PCR read after extend...\n"));
194
0
  Tpm2PcrReadForActiveBank (PcrHandle, NULL);
195
0
  DEBUG_CODE_END ();
196
197
  //
198
  // Unmarshal the response
199
  //
200
201
  // None
202
203
0
  return EFI_SUCCESS;
204
0
}
205
206
/**
207
  This command is used to cause an update to the indicated PCR.
208
  The data in eventData is hashed using the hash algorithm associated with each bank in which the
209
  indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
210
  references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
211
  TPM2_PCR_Extend().
212
  A TPM shall support an Event.size of zero through 1,024 inclusive.
213
214
  @param[in]  PcrHandle   Handle of the PCR
215
  @param[in]  EventData   Event data in sized buffer
216
  @param[out] Digests     List of digest
217
218
  @retval EFI_SUCCESS      Operation completed successfully.
219
  @retval EFI_DEVICE_ERROR Unexpected device behavior.
220
**/
221
EFI_STATUS
222
EFIAPI
223
Tpm2PcrEvent (
224
  IN      TPMI_DH_PCR      PcrHandle,
225
  IN      TPM2B_EVENT      *EventData,
226
  OUT  TPML_DIGEST_VALUES  *Digests
227
  )
228
143
{
229
143
  EFI_STATUS               Status;
230
143
  TPM2_PCR_EVENT_COMMAND   Cmd;
231
143
  TPM2_PCR_EVENT_RESPONSE  Res;
232
143
  UINT32                   CmdSize;
233
143
  UINT32                   RespSize;
234
143
  UINT32                   ResultBufSize;
235
143
  UINT8                    *Buffer;
236
143
  UINTN                    Index;
237
143
  UINT32                   SessionInfoSize;
238
143
  UINT16                   DigestSize;
239
240
143
  Cmd.Header.tag         = SwapBytes16 (TPM_ST_SESSIONS);
241
143
  Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Event);
242
143
  Cmd.PcrHandle          = SwapBytes32 (PcrHandle);
243
244
  //
245
  // Add in Auth session
246
  //
247
143
  Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
248
249
  // sessionInfoSize
250
143
  SessionInfoSize       = CopyAuthSessionCommand (NULL, Buffer);
251
143
  Buffer               += SessionInfoSize;
252
143
  Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
253
254
  // Event
255
143
  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (EventData->size));
256
143
  Buffer += sizeof (UINT16);
257
258
143
  CopyMem (Buffer, EventData->buffer, EventData->size);
259
143
  Buffer += EventData->size;
260
261
143
  CmdSize              = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
262
143
  Cmd.Header.paramSize = SwapBytes32 (CmdSize);
263
264
143
  ResultBufSize = sizeof (Res);
265
143
  Status        = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
266
143
  if (EFI_ERROR (Status)) {
267
0
    return Status;
268
0
  }
269
270
143
  if (ResultBufSize > sizeof (Res)) {
271
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
272
0
    return EFI_BUFFER_TOO_SMALL;
273
0
  }
274
275
  //
276
  // Validate response headers
277
  //
278
143
  RespSize = SwapBytes32 (Res.Header.paramSize);
279
143
  if (RespSize > sizeof (Res)) {
280
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
281
0
    return EFI_BUFFER_TOO_SMALL;
282
0
  }
283
284
  //
285
  // Fail if command failed
286
  //
287
143
  if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
288
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
289
0
    return EFI_DEVICE_ERROR;
290
0
  }
291
292
  //
293
  // Unmarshal the response
294
  //
295
143
  Buffer = (UINT8 *)&Res.Digests;
296
297
143
  Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
298
143
  if (Digests->count > HASH_COUNT) {
299
107
    DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent - Digests->count error %x\n", Digests->count));
300
107
    return EFI_DEVICE_ERROR;
301
107
  }
302
303
36
  Buffer += sizeof (UINT32);
304
68
  for (Index = 0; Index < Digests->count; Index++) {
305
56
    Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
306
56
    Buffer                         += sizeof (UINT16);
307
56
    DigestSize                      = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
308
56
    if (DigestSize == 0) {
309
24
      DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
310
24
      return EFI_DEVICE_ERROR;
311
24
    }
312
313
32
    CopyMem (
314
32
      &Digests->digests[Index].digest,
315
32
      Buffer,
316
32
      DigestSize
317
32
      );
318
32
    Buffer += DigestSize;
319
32
  }
320
321
12
  return EFI_SUCCESS;
322
36
}
323
324
/**
325
  This command returns the values of all PCR specified in pcrSelect.
326
327
  @param[in]  PcrSelectionIn     The selection of PCR to read.
328
  @param[out] PcrUpdateCounter   The current value of the PCR update counter.
329
  @param[out] PcrSelectionOut    The PCR in the returned list.
330
  @param[out] PcrValues          The contents of the PCR indicated in pcrSelect.
331
332
  @retval EFI_SUCCESS            Operation completed successfully.
333
  @retval EFI_DEVICE_ERROR       The command was unsuccessful.
334
**/
335
EFI_STATUS
336
EFIAPI
337
Tpm2PcrRead (
338
  IN      TPML_PCR_SELECTION  *PcrSelectionIn,
339
  OUT  UINT32                 *PcrUpdateCounter,
340
  OUT  TPML_PCR_SELECTION     *PcrSelectionOut,
341
  OUT  TPML_DIGEST            *PcrValues
342
  )
343
0
{
344
0
  EFI_STATUS              Status;
345
0
  TPM2_PCR_READ_COMMAND   SendBuffer;
346
0
  TPM2_PCR_READ_RESPONSE  RecvBuffer;
347
0
  UINT32                  SendBufferSize;
348
0
  UINT32                  RecvBufferSize;
349
0
  UINTN                   Index;
350
0
  TPML_DIGEST             *PcrValuesOut;
351
0
  TPM2B_DIGEST            *Digests;
352
353
  //
354
  // Construct command
355
  //
356
0
  SendBuffer.Header.tag         = SwapBytes16 (TPM_ST_NO_SESSIONS);
357
0
  SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Read);
358
359
0
  SendBuffer.PcrSelectionIn.count = SwapBytes32 (PcrSelectionIn->count);
360
0
  for (Index = 0; Index < PcrSelectionIn->count; Index++) {
361
0
    SendBuffer.PcrSelectionIn.pcrSelections[Index].hash         = SwapBytes16 (PcrSelectionIn->pcrSelections[Index].hash);
362
0
    SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
363
0
    CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
364
0
  }
365
366
0
  SendBufferSize              = sizeof (SendBuffer.Header) + sizeof (SendBuffer.PcrSelectionIn.count) + sizeof (SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
367
0
  SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
368
369
  //
370
  // send Tpm command
371
  //
372
0
  RecvBufferSize = sizeof (RecvBuffer);
373
0
  Status         = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
374
0
  if (EFI_ERROR (Status)) {
375
0
    return Status;
376
0
  }
377
378
0
  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
379
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
380
0
    return EFI_DEVICE_ERROR;
381
0
  }
382
383
0
  if (SwapBytes32 (RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
384
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
385
0
    return EFI_NOT_FOUND;
386
0
  }
387
388
  //
389
  // Return the response
390
  //
391
392
  //
393
  // PcrUpdateCounter
394
  //
395
0
  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter)) {
396
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
397
0
    return EFI_DEVICE_ERROR;
398
0
  }
399
400
0
  *PcrUpdateCounter = SwapBytes32 (RecvBuffer.PcrUpdateCounter);
401
402
  //
403
  // PcrSelectionOut
404
  //
405
0
  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count)) {
406
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
407
0
    return EFI_DEVICE_ERROR;
408
0
  }
409
410
0
  PcrSelectionOut->count = SwapBytes32 (RecvBuffer.PcrSelectionOut.count);
411
0
  if (PcrSelectionOut->count > HASH_COUNT) {
412
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrSelectionOut->count error %x\n", PcrSelectionOut->count));
413
0
    return EFI_DEVICE_ERROR;
414
0
  }
415
416
0
  if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
417
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
418
0
    return EFI_DEVICE_ERROR;
419
0
  }
420
421
0
  for (Index = 0; Index < PcrSelectionOut->count; Index++) {
422
0
    PcrSelectionOut->pcrSelections[Index].hash         = SwapBytes16 (RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
423
0
    PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
424
0
    if (PcrSelectionOut->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {
425
0
      return EFI_DEVICE_ERROR;
426
0
    }
427
428
0
    CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
429
0
  }
430
431
  //
432
  // PcrValues
433
  //
434
0
  PcrValuesOut     = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
435
0
  PcrValues->count = SwapBytes32 (PcrValuesOut->count);
436
  //
437
  // The number of digests in list is not greater than 8 per TPML_DIGEST definition
438
  //
439
0
  if (PcrValues->count > 8) {
440
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrValues->count error %x\n", PcrValues->count));
441
0
    return EFI_DEVICE_ERROR;
442
0
  }
443
444
0
  Digests = PcrValuesOut->digests;
445
0
  for (Index = 0; Index < PcrValues->count; Index++) {
446
0
    PcrValues->digests[Index].size = SwapBytes16 (Digests->size);
447
0
    if (PcrValues->digests[Index].size > sizeof (TPMU_HA)) {
448
0
      DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - Digest.size error %x\n", PcrValues->digests[Index].size));
449
0
      return EFI_DEVICE_ERROR;
450
0
    }
451
452
0
    CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
453
0
    Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof (Digests->size) + PcrValues->digests[Index].size);
454
0
  }
455
456
0
  return EFI_SUCCESS;
457
0
}
458
459
/**
460
  This command is used to set the desired PCR allocation of PCR and algorithms.
461
462
  @param[in]  AuthHandle         TPM_RH_PLATFORM+{PP}
463
  @param[in]  AuthSession        Auth Session context
464
  @param[in]  PcrAllocation      The requested allocation
465
  @param[out] AllocationSuccess  YES if the allocation succeeded
466
  @param[out] MaxPCR             maximum number of PCR that may be in a bank
467
  @param[out] SizeNeeded         number of octets required to satisfy the request
468
  @param[out] SizeAvailable      Number of octets available. Computed before the allocation
469
470
  @retval EFI_SUCCESS            Operation completed successfully.
471
  @retval EFI_DEVICE_ERROR       The command was unsuccessful.
472
**/
473
EFI_STATUS
474
EFIAPI
475
Tpm2PcrAllocate (
476
  IN  TPMI_RH_PLATFORM    AuthHandle,
477
  IN  TPMS_AUTH_COMMAND   *AuthSession,
478
  IN  TPML_PCR_SELECTION  *PcrAllocation,
479
  OUT TPMI_YES_NO         *AllocationSuccess,
480
  OUT UINT32              *MaxPCR,
481
  OUT UINT32              *SizeNeeded,
482
  OUT UINT32              *SizeAvailable
483
  )
484
0
{
485
0
  EFI_STATUS                  Status;
486
0
  TPM2_PCR_ALLOCATE_COMMAND   Cmd;
487
0
  TPM2_PCR_ALLOCATE_RESPONSE  Res;
488
0
  UINT32                      CmdSize;
489
0
  UINT32                      RespSize;
490
0
  UINT8                       *Buffer;
491
0
  UINT32                      SessionInfoSize;
492
0
  UINT8                       *ResultBuf;
493
0
  UINT32                      ResultBufSize;
494
0
  UINTN                       Index;
495
496
  //
497
  // Construct command
498
  //
499
0
  Cmd.Header.tag         = SwapBytes16 (TPM_ST_SESSIONS);
500
0
  Cmd.Header.paramSize   = SwapBytes32 (sizeof (Cmd));
501
0
  Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Allocate);
502
0
  Cmd.AuthHandle         = SwapBytes32 (AuthHandle);
503
504
  //
505
  // Add in Auth session
506
  //
507
0
  Buffer = (UINT8 *)&Cmd.AuthSession;
508
509
  // sessionInfoSize
510
0
  SessionInfoSize     = CopyAuthSessionCommand (AuthSession, Buffer);
511
0
  Buffer             += SessionInfoSize;
512
0
  Cmd.AuthSessionSize = SwapBytes32 (SessionInfoSize);
513
514
  // Count
515
0
  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (PcrAllocation->count));
516
0
  Buffer += sizeof (UINT32);
517
0
  for (Index = 0; Index < PcrAllocation->count; Index++) {
518
0
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (PcrAllocation->pcrSelections[Index].hash));
519
0
    Buffer          += sizeof (UINT16);
520
0
    *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
521
0
    Buffer++;
522
0
    CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
523
0
    Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
524
0
  }
525
526
0
  CmdSize              = (UINT32)(Buffer - (UINT8 *)&Cmd);
527
0
  Cmd.Header.paramSize = SwapBytes32 (CmdSize);
528
529
0
  ResultBuf     = (UINT8 *)&Res;
530
0
  ResultBufSize = sizeof (Res);
531
532
  //
533
  // Call the TPM
534
  //
535
0
  Status = Tpm2SubmitCommand (
536
0
             CmdSize,
537
0
             (UINT8 *)&Cmd,
538
0
             &ResultBufSize,
539
0
             ResultBuf
540
0
             );
541
0
  if (EFI_ERROR (Status)) {
542
0
    goto Done;
543
0
  }
544
545
0
  if (ResultBufSize > sizeof (Res)) {
546
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
547
0
    Status = EFI_BUFFER_TOO_SMALL;
548
0
    goto Done;
549
0
  }
550
551
  //
552
  // Validate response headers
553
  //
554
0
  RespSize = SwapBytes32 (Res.Header.paramSize);
555
0
  if (RespSize > sizeof (Res)) {
556
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
557
0
    Status = EFI_BUFFER_TOO_SMALL;
558
0
    goto Done;
559
0
  }
560
561
  //
562
  // Fail if command failed
563
  //
564
0
  if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
565
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
566
0
    Status = EFI_DEVICE_ERROR;
567
0
    goto Done;
568
0
  }
569
570
  //
571
  // Return the response
572
  //
573
0
  *AllocationSuccess = Res.AllocationSuccess;
574
0
  *MaxPCR            = SwapBytes32 (Res.MaxPCR);
575
0
  *SizeNeeded        = SwapBytes32 (Res.SizeNeeded);
576
0
  *SizeAvailable     = SwapBytes32 (Res.SizeAvailable);
577
578
0
Done:
579
  //
580
  // Clear AuthSession Content
581
  //
582
0
  ZeroMem (&Cmd, sizeof (Cmd));
583
0
  ZeroMem (&Res, sizeof (Res));
584
0
  return Status;
585
0
}
586
587
/**
588
  Alloc PCR data.
589
590
  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
591
  @param[in]  SupportedPCRBanks Supported PCR banks
592
  @param[in]  PCRBanks          PCR banks
593
594
  @retval EFI_SUCCESS Operation completed successfully.
595
**/
596
EFI_STATUS
597
EFIAPI
598
Tpm2PcrAllocateBanks (
599
  IN TPM2B_AUTH  *PlatformAuth   OPTIONAL,
600
  IN UINT32      SupportedPCRBanks,
601
  IN UINT32      PCRBanks
602
  )
603
0
{
604
0
  EFI_STATUS          Status;
605
0
  TPMS_AUTH_COMMAND   *AuthSession;
606
0
  TPMS_AUTH_COMMAND   LocalAuthSession;
607
0
  TPML_PCR_SELECTION  PcrAllocation;
608
0
  TPMI_YES_NO         AllocationSuccess;
609
0
  UINT32              MaxPCR;
610
0
  UINT32              SizeNeeded;
611
0
  UINT32              SizeAvailable;
612
613
0
  if (PlatformAuth == NULL) {
614
0
    AuthSession = NULL;
615
0
  } else {
616
0
    AuthSession = &LocalAuthSession;
617
0
    ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
618
0
    LocalAuthSession.sessionHandle = TPM_RS_PW;
619
0
    LocalAuthSession.hmac.size     = PlatformAuth->size;
620
0
    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
621
0
  }
622
623
  //
624
  // Fill input
625
  //
626
0
  ZeroMem (&PcrAllocation, sizeof (PcrAllocation));
627
0
  if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
628
0
    PcrAllocation.pcrSelections[PcrAllocation.count].hash         = TPM_ALG_SHA1;
629
0
    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
630
0
    if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
631
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
632
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
633
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
634
0
    } else {
635
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
636
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
637
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
638
0
    }
639
640
0
    PcrAllocation.count++;
641
0
  }
642
643
0
  if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
644
0
    PcrAllocation.pcrSelections[PcrAllocation.count].hash         = TPM_ALG_SHA256;
645
0
    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
646
0
    if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
647
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
648
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
649
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
650
0
    } else {
651
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
652
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
653
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
654
0
    }
655
656
0
    PcrAllocation.count++;
657
0
  }
658
659
0
  if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
660
0
    PcrAllocation.pcrSelections[PcrAllocation.count].hash         = TPM_ALG_SHA384;
661
0
    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
662
0
    if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
663
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
664
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
665
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
666
0
    } else {
667
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
668
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
669
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
670
0
    }
671
672
0
    PcrAllocation.count++;
673
0
  }
674
675
0
  if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
676
0
    PcrAllocation.pcrSelections[PcrAllocation.count].hash         = TPM_ALG_SHA512;
677
0
    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
678
0
    if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
679
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
680
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
681
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
682
0
    } else {
683
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
684
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
685
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
686
0
    }
687
688
0
    PcrAllocation.count++;
689
0
  }
690
691
0
  if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
692
0
    PcrAllocation.pcrSelections[PcrAllocation.count].hash         = TPM_ALG_SM3_256;
693
0
    PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
694
0
    if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
695
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
696
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
697
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
698
0
    } else {
699
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
700
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
701
0
      PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
702
0
    }
703
704
0
    PcrAllocation.count++;
705
0
  }
706
707
0
  Status = Tpm2PcrAllocate (
708
0
             TPM_RH_PLATFORM,
709
0
             AuthSession,
710
0
             &PcrAllocation,
711
0
             &AllocationSuccess,
712
0
             &MaxPCR,
713
0
             &SizeNeeded,
714
0
             &SizeAvailable
715
0
             );
716
0
  DEBUG ((DEBUG_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
717
0
  if (EFI_ERROR (Status)) {
718
0
    goto Done;
719
0
  }
720
721
0
  DEBUG ((DEBUG_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
722
0
  DEBUG ((DEBUG_INFO, "MaxPCR            - %08x\n", MaxPCR));
723
0
  DEBUG ((DEBUG_INFO, "SizeNeeded        - %08x\n", SizeNeeded));
724
0
  DEBUG ((DEBUG_INFO, "SizeAvailable     - %08x\n", SizeAvailable));
725
726
0
Done:
727
0
  ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
728
0
  return Status;
729
0
}
730
731
/**
732
   This function will query the TPM to determine which hashing algorithms and
733
   get the digests of all active and supported PCR banks of a specific PCR register.
734
735
   @param[in]     PcrHandle     The index of the PCR register to be read.
736
   @param[out]    HashList      List of digests from PCR register being read.
737
738
   @retval EFI_SUCCESS           The Pcr was read successfully.
739
   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
740
**/
741
EFI_STATUS
742
EFIAPI
743
Tpm2PcrReadForActiveBank (
744
  IN      TPMI_DH_PCR  PcrHandle,
745
  OUT     TPML_DIGEST  *HashList
746
  )
747
0
{
748
0
  EFI_STATUS          Status;
749
0
  TPML_PCR_SELECTION  Pcrs;
750
0
  TPML_PCR_SELECTION  PcrSelectionIn;
751
0
  TPML_PCR_SELECTION  PcrSelectionOut;
752
0
  TPML_DIGEST         PcrValues;
753
0
  UINT32              PcrUpdateCounter;
754
0
  UINT8               PcrIndex;
755
0
  UINT32              TpmHashAlgorithmBitmap;
756
0
  TPMI_ALG_HASH       CurrentPcrBankHash;
757
0
  UINT32              ActivePcrBanks;
758
0
  UINT32              TcgRegistryHashAlg;
759
0
  UINTN               Index;
760
0
  UINTN               Index2;
761
762
0
  PcrIndex = (UINT8)PcrHandle;
763
764
0
  if ((PcrIndex < 0) ||
765
0
      (PcrIndex >= IMPLEMENTATION_PCR))
766
0
  {
767
0
    return EFI_INVALID_PARAMETER;
768
0
  }
769
770
0
  ZeroMem (&PcrSelectionIn, sizeof (PcrSelectionIn));
771
0
  ZeroMem (&PcrUpdateCounter, sizeof (UINT32));
772
0
  ZeroMem (&PcrSelectionOut, sizeof (PcrSelectionOut));
773
0
  ZeroMem (&PcrValues, sizeof (PcrValues));
774
0
  ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
775
776
0
  DEBUG ((DEBUG_INFO, "ReadPcr - %02d\n", PcrIndex));
777
778
  //
779
  // Read TPM capabilities
780
  //
781
0
  Status = Tpm2GetCapabilityPcrs (&Pcrs);
782
783
0
  if (EFI_ERROR (Status)) {
784
0
    DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities\n"));
785
0
    return EFI_DEVICE_ERROR;
786
0
  }
787
788
  //
789
  // Get Active Pcrs
790
  //
791
0
  Status = Tpm2GetCapabilitySupportedAndActivePcrs (
792
0
             &TpmHashAlgorithmBitmap,
793
0
             &ActivePcrBanks
794
0
             );
795
796
0
  if (EFI_ERROR (Status)) {
797
0
    DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities and active PCRs\n"));
798
0
    return EFI_DEVICE_ERROR;
799
0
  }
800
801
  //
802
  // Select from Active PCRs
803
  //
804
0
  for (Index = 0; Index < Pcrs.count; Index++) {
805
0
    CurrentPcrBankHash = Pcrs.pcrSelections[Index].hash;
806
807
0
    switch (CurrentPcrBankHash) {
808
0
      case TPM_ALG_SHA1:
809
0
        DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA1 Present\n"));
810
0
        TcgRegistryHashAlg = HASH_ALG_SHA1;
811
0
        break;
812
0
      case TPM_ALG_SHA256:
813
0
        DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA256 Present\n"));
814
0
        TcgRegistryHashAlg = HASH_ALG_SHA256;
815
0
        break;
816
0
      case TPM_ALG_SHA384:
817
0
        DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA384 Present\n"));
818
0
        TcgRegistryHashAlg = HASH_ALG_SHA384;
819
0
        break;
820
0
      case TPM_ALG_SHA512:
821
0
        DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA512 Present\n"));
822
0
        TcgRegistryHashAlg = HASH_ALG_SHA512;
823
0
        break;
824
0
      case TPM_ALG_SM3_256:
825
0
        DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SM3 Present\n"));
826
0
        TcgRegistryHashAlg = HASH_ALG_SM3_256;
827
0
        break;
828
0
      default:
829
        //
830
        // Unsupported algorithm
831
        //
832
0
        DEBUG ((DEBUG_VERBOSE, "Unknown algorithm present\n"));
833
0
        TcgRegistryHashAlg = 0;
834
0
        break;
835
0
    }
836
837
    //
838
    // Skip unsupported and inactive PCR banks
839
    //
840
0
    if ((TcgRegistryHashAlg & ActivePcrBanks) == 0) {
841
0
      DEBUG ((DEBUG_VERBOSE, "Skipping unsupported or inactive bank: 0x%04x\n", CurrentPcrBankHash));
842
0
      continue;
843
0
    }
844
845
    //
846
    // Select PCR from current active bank
847
    //
848
0
    PcrSelectionIn.pcrSelections[PcrSelectionIn.count].hash         = Pcrs.pcrSelections[Index].hash;
849
0
    PcrSelectionIn.pcrSelections[PcrSelectionIn.count].sizeofSelect = PCR_SELECT_MAX;
850
0
    PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[0] = (PcrIndex < 8) ? 1 << PcrIndex : 0;
851
0
    PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[1] = (PcrIndex > 7) && (PcrIndex < 16) ? 1 << (PcrIndex - 8) : 0;
852
0
    PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[2] = (PcrIndex > 15) ? 1 << (PcrIndex - 16) : 0;
853
0
    PcrSelectionIn.count++;
854
0
  }
855
856
  //
857
  // Read PCRs
858
  //
859
0
  Status = Tpm2PcrRead (
860
0
             &PcrSelectionIn,
861
0
             &PcrUpdateCounter,
862
0
             &PcrSelectionOut,
863
0
             &PcrValues
864
0
             );
865
866
0
  if (EFI_ERROR (Status)) {
867
0
    DEBUG ((DEBUG_ERROR, "Tpm2PcrRead failed Status = %r \n", Status));
868
0
    return EFI_DEVICE_ERROR;
869
0
  }
870
871
0
  for (Index = 0; Index < PcrValues.count; Index++) {
872
0
    DEBUG ((
873
0
      DEBUG_INFO,
874
0
      "ReadPcr - HashAlg = 0x%04x, Pcr[%02d], digest = ",
875
0
      PcrSelectionOut.pcrSelections[Index].hash,
876
0
      PcrIndex
877
0
      ));
878
879
0
    for (Index2 = 0; Index2 < PcrValues.digests[Index].size; Index2++) {
880
0
      DEBUG ((DEBUG_INFO, "%02x ", PcrValues.digests[Index].buffer[Index2]));
881
0
    }
882
883
0
    DEBUG ((DEBUG_INFO, "\n"));
884
0
  }
885
886
0
  if (HashList != NULL) {
887
0
    CopyMem (
888
0
      HashList,
889
0
      &PcrValues,
890
0
      sizeof (TPML_DIGEST)
891
0
      );
892
0
  }
893
894
0
  return EFI_SUCCESS;
895
0
}