Coverage Report

Created: 2026-04-11 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/edk2/SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c
Line
Count
Source
1
/** @file
2
  Implement TPM2 help.
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
typedef struct {
17
  TPMI_ALG_HASH    HashAlgo;
18
  UINT16           HashSize;
19
  UINT32           HashMask;
20
} INTERNAL_HASH_INFO;
21
22
STATIC INTERNAL_HASH_INFO  mHashInfo[] = {
23
  { TPM_ALG_SHA1,    SHA1_DIGEST_SIZE,    HASH_ALG_SHA1    },
24
  { TPM_ALG_SHA256,  SHA256_DIGEST_SIZE,  HASH_ALG_SHA256  },
25
  { TPM_ALG_SM3_256, SM3_256_DIGEST_SIZE, HASH_ALG_SM3_256 },
26
  { TPM_ALG_SHA384,  SHA384_DIGEST_SIZE,  HASH_ALG_SHA384  },
27
  { TPM_ALG_SHA512,  SHA512_DIGEST_SIZE,  HASH_ALG_SHA512  },
28
};
29
30
/**
31
  Return size of digest.
32
33
  @param[in] HashAlgo  Hash algorithm
34
35
  @return size of digest
36
**/
37
UINT16
38
EFIAPI
39
GetHashSizeFromAlgo (
40
  IN TPMI_ALG_HASH  HashAlgo
41
  )
42
60
{
43
60
  UINTN  Index;
44
45
227
  for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {
46
202
    if (mHashInfo[Index].HashAlgo == HashAlgo) {
47
35
      return mHashInfo[Index].HashSize;
48
35
    }
49
202
  }
50
51
25
  return 0;
52
60
}
53
54
/**
55
  Get hash mask from algorithm.
56
57
  @param[in] HashAlgo   Hash algorithm
58
59
  @return Hash mask
60
**/
61
UINT32
62
EFIAPI
63
GetHashMaskFromAlgo (
64
  IN TPMI_ALG_HASH  HashAlgo
65
  )
66
0
{
67
0
  UINTN  Index;
68
69
0
  for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {
70
0
    if (mHashInfo[Index].HashAlgo == HashAlgo) {
71
0
      return mHashInfo[Index].HashMask;
72
0
    }
73
0
  }
74
75
0
  return 0;
76
0
}
77
78
/**
79
  Copy AuthSessionIn to TPM2 command buffer.
80
81
  @param [in]  AuthSessionIn   Input AuthSession data
82
  @param [out] AuthSessionOut  Output AuthSession data in TPM2 command buffer
83
84
  @return AuthSession size
85
**/
86
UINT32
87
EFIAPI
88
CopyAuthSessionCommand (
89
  IN      TPMS_AUTH_COMMAND  *AuthSessionIn  OPTIONAL,
90
  OUT     UINT8              *AuthSessionOut
91
  )
92
150
{
93
150
  UINT8  *Buffer;
94
95
150
  Buffer = (UINT8 *)AuthSessionOut;
96
97
  //
98
  // Add in Auth session
99
  //
100
150
  if (AuthSessionIn != NULL) {
101
    //  sessionHandle
102
0
    WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (AuthSessionIn->sessionHandle));
103
0
    Buffer += sizeof (UINT32);
104
105
    // nonce
106
0
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size));
107
0
    Buffer += sizeof (UINT16);
108
109
0
    CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size);
110
0
    Buffer += AuthSessionIn->nonce.size;
111
112
    // sessionAttributes
113
0
    *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes;
114
0
    Buffer++;
115
116
    // hmac
117
0
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size));
118
0
    Buffer += sizeof (UINT16);
119
120
0
    CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size);
121
0
    Buffer += AuthSessionIn->hmac.size;
122
150
  } else {
123
    //  sessionHandle
124
150
    WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (TPM_RS_PW));
125
150
    Buffer += sizeof (UINT32);
126
127
    // nonce = nullNonce
128
150
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (0));
129
150
    Buffer += sizeof (UINT16);
130
131
    // sessionAttributes = 0
132
150
    *(UINT8 *)Buffer = 0x00;
133
150
    Buffer++;
134
135
    // hmac = nullAuth
136
150
    WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (0));
137
150
    Buffer += sizeof (UINT16);
138
150
  }
139
140
150
  return (UINT32)((UINTN)Buffer - (UINTN)AuthSessionOut);
141
150
}
142
143
/**
144
  Copy AuthSessionIn from TPM2 response buffer.
145
146
  @param [in]  AuthSessionIn   Input AuthSession data in TPM2 response buffer
147
  @param [out] AuthSessionOut  Output AuthSession data
148
149
  @return 0    copy failed
150
          else AuthSession size
151
**/
152
UINT32
153
EFIAPI
154
CopyAuthSessionResponse (
155
  IN      UINT8               *AuthSessionIn,
156
  OUT     TPMS_AUTH_RESPONSE  *AuthSessionOut OPTIONAL
157
  )
158
0
{
159
0
  UINT8               *Buffer;
160
0
  TPMS_AUTH_RESPONSE  LocalAuthSessionOut;
161
162
0
  if (AuthSessionOut == NULL) {
163
0
    AuthSessionOut = &LocalAuthSessionOut;
164
0
  }
165
166
0
  Buffer = (UINT8 *)AuthSessionIn;
167
168
  // nonce
169
0
  AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
170
0
  Buffer                    += sizeof (UINT16);
171
0
  if (AuthSessionOut->nonce.size > sizeof (TPMU_HA)) {
172
0
    DEBUG ((DEBUG_ERROR, "CopyAuthSessionResponse - nonce.size error %x\n", AuthSessionOut->nonce.size));
173
0
    return 0;
174
0
  }
175
176
0
  CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size);
177
0
  Buffer += AuthSessionOut->nonce.size;
178
179
  // sessionAttributes
180
0
  *(UINT8 *) &AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer;
181
0
  Buffer++;
182
183
  // hmac
184
0
  AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
185
0
  Buffer                   += sizeof (UINT16);
186
0
  if (AuthSessionOut->hmac.size > sizeof (TPMU_HA)) {
187
0
    DEBUG ((DEBUG_ERROR, "CopyAuthSessionResponse - hmac.size error %x\n", AuthSessionOut->hmac.size));
188
0
    return 0;
189
0
  }
190
191
0
  CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size);
192
0
  Buffer += AuthSessionOut->hmac.size;
193
194
0
  return (UINT32)((UINTN)Buffer - (UINTN)AuthSessionIn);
195
0
}
196
197
/**
198
  Return if hash alg is supported in HashAlgorithmMask.
199
200
  @param HashAlg            Hash algorithm to be checked.
201
  @param HashAlgorithmMask  Bitfield of allowed hash algorithms.
202
203
  @retval TRUE  Hash algorithm is supported.
204
  @retval FALSE Hash algorithm is not supported.
205
**/
206
BOOLEAN
207
EFIAPI
208
IsHashAlgSupportedInHashAlgorithmMask (
209
  IN TPMI_ALG_HASH  HashAlg,
210
  IN UINT32         HashAlgorithmMask
211
  )
212
0
{
213
0
  switch (HashAlg) {
214
0
    case TPM_ALG_SHA1:
215
0
      if ((HashAlgorithmMask & HASH_ALG_SHA1) != 0) {
216
0
        return TRUE;
217
0
      }
218
219
0
      break;
220
0
    case TPM_ALG_SHA256:
221
0
      if ((HashAlgorithmMask & HASH_ALG_SHA256) != 0) {
222
0
        return TRUE;
223
0
      }
224
225
0
      break;
226
0
    case TPM_ALG_SHA384:
227
0
      if ((HashAlgorithmMask & HASH_ALG_SHA384) != 0) {
228
0
        return TRUE;
229
0
      }
230
231
0
      break;
232
0
    case TPM_ALG_SHA512:
233
0
      if ((HashAlgorithmMask & HASH_ALG_SHA512) != 0) {
234
0
        return TRUE;
235
0
      }
236
237
0
      break;
238
0
    case TPM_ALG_SM3_256:
239
0
      if ((HashAlgorithmMask & HASH_ALG_SM3_256) != 0) {
240
0
        return TRUE;
241
0
      }
242
243
0
      break;
244
0
  }
245
246
0
  return FALSE;
247
0
}
248
249
/**
250
  Copy TPML_DIGEST_VALUES into a buffer
251
252
  @param[in,out] Buffer             Buffer to hold copied TPML_DIGEST_VALUES compact binary.
253
  @param[in]     DigestList         TPML_DIGEST_VALUES to be copied.
254
  @param[in]     HashAlgorithmMask  HASH bits corresponding to the desired digests to copy.
255
256
  @return The end of buffer to hold TPML_DIGEST_VALUES.
257
**/
258
VOID *
259
EFIAPI
260
CopyDigestListToBuffer (
261
  IN OUT VOID            *Buffer,
262
  IN TPML_DIGEST_VALUES  *DigestList,
263
  IN UINT32              HashAlgorithmMask
264
  )
265
0
{
266
0
  UINTN   Index;
267
0
  UINT16  DigestSize;
268
0
  UINT32  DigestListCount;
269
0
  UINT32  *DigestListCountPtr;
270
271
0
  DigestListCountPtr = (UINT32 *)Buffer;
272
0
  DigestListCount    = 0;
273
0
  Buffer             = (UINT8 *)Buffer + sizeof (DigestList->count);
274
0
  for (Index = 0; Index < DigestList->count; Index++) {
275
0
    if (!IsHashAlgSupportedInHashAlgorithmMask (DigestList->digests[Index].hashAlg, HashAlgorithmMask)) {
276
0
      DEBUG ((DEBUG_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg));
277
0
      continue;
278
0
    }
279
280
0
    CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof (DigestList->digests[Index].hashAlg));
281
0
    Buffer     = (UINT8 *)Buffer + sizeof (DigestList->digests[Index].hashAlg);
282
0
    DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
283
0
    CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);
284
0
    Buffer = (UINT8 *)Buffer + DigestSize;
285
0
    DigestListCount++;
286
0
  }
287
288
0
  WriteUnaligned32 (DigestListCountPtr, DigestListCount);
289
290
0
  return Buffer;
291
0
}
292
293
/**
294
  Copy a buffer into a TPML_DIGEST_VALUES structure.
295
296
  @param[in]     Buffer             Buffer to hold TPML_DIGEST_VALUES compact binary.
297
  @param[in]     BufferSize         Size of Buffer.
298
  @param[out]    DigestList         TPML_DIGEST_VALUES.
299
300
  @retval EFI_SUCCESS               Buffer was succesfully copied to DigestList.
301
  @retval EFI_BAD_BUFFER_SIZE       A bad buffer size passed to the function.
302
  @retval EFI_INVALID_PARAMETER     An invalid parameter passed to the function: NULL pointer or
303
                                    BufferSize bigger than TPML_DIGEST_VALUES.
304
**/
305
EFI_STATUS
306
EFIAPI
307
CopyBufferToDigestList (
308
  IN CONST  VOID                *Buffer,
309
  IN        UINTN               BufferSize,
310
  OUT       TPML_DIGEST_VALUES  *DigestList
311
  )
312
0
{
313
0
  EFI_STATUS   Status;
314
0
  UINTN        Index;
315
0
  UINT16       DigestSize;
316
0
  CONST UINT8  *BufferPtr;
317
318
0
  Status = EFI_INVALID_PARAMETER;
319
320
0
  if ((Buffer == NULL) || (DigestList == NULL) || (BufferSize > sizeof (TPML_DIGEST_VALUES))) {
321
0
    return EFI_INVALID_PARAMETER;
322
0
  }
323
324
0
  DigestList->count = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *)Buffer));
325
0
  if (DigestList->count > HASH_COUNT) {
326
0
    return EFI_INVALID_PARAMETER;
327
0
  }
328
329
0
  BufferPtr = (CONST UINT8 *)Buffer +  sizeof (UINT32);
330
0
  for (Index = 0; Index < DigestList->count; Index++) {
331
0
    if (BufferPtr - (CONST UINT8 *)Buffer + sizeof (UINT16) > BufferSize) {
332
0
      Status = EFI_BAD_BUFFER_SIZE;
333
0
      break;
334
0
    } else {
335
0
      DigestList->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((CONST UINT16 *)BufferPtr));
336
0
    }
337
338
0
    BufferPtr += sizeof (UINT16);
339
0
    DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
340
0
    if (BufferPtr - (CONST UINT8 *)Buffer + (UINTN)DigestSize > BufferSize) {
341
0
      Status = EFI_BAD_BUFFER_SIZE;
342
0
      break;
343
0
    } else {
344
0
      CopyMem (&DigestList->digests[Index].digest, BufferPtr, DigestSize);
345
0
    }
346
347
0
    BufferPtr += DigestSize;
348
0
    Status     = EFI_SUCCESS;
349
0
  }
350
351
0
  return Status;
352
0
}
353
354
/**
355
  Get TPML_DIGEST_VALUES data size.
356
357
  @param[in]     DigestList    TPML_DIGEST_VALUES data.
358
359
  @return TPML_DIGEST_VALUES data size.
360
**/
361
UINT32
362
EFIAPI
363
GetDigestListSize (
364
  IN TPML_DIGEST_VALUES  *DigestList
365
  )
366
0
{
367
0
  UINTN   Index;
368
0
  UINT16  DigestSize;
369
0
  UINT32  TotalSize;
370
371
0
  TotalSize = sizeof (DigestList->count);
372
0
  for (Index = 0; Index < DigestList->count; Index++) {
373
0
    DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
374
0
    TotalSize += sizeof (DigestList->digests[Index].hashAlg) + DigestSize;
375
0
  }
376
377
0
  return TotalSize;
378
0
}
379
380
/**
381
  Get the total digest size from a hash algorithm mask.
382
383
  @param[in]     HashAlgorithmMask.
384
385
  @return Digest size in bytes.
386
**/
387
UINT32
388
EFIAPI
389
GetDigestListSizeFromHashAlgorithmMask (
390
  IN UINT32  HashAlgorithmMask
391
  )
392
0
{
393
0
  UINTN   Index;
394
0
  UINT32  TotalSize;
395
396
0
  TotalSize = sizeof (UINT32);
397
0
  for (Index = 0; Index < ARRAY_SIZE (mHashInfo); Index++) {
398
0
    if ((mHashInfo[Index].HashMask & HashAlgorithmMask) != 0) {
399
0
      TotalSize += sizeof (TPMI_ALG_HASH) + mHashInfo[Index].HashSize;
400
0
    }
401
0
  }
402
403
0
  return TotalSize;
404
0
}
405
406
/**
407
  This function get digest from digest list.
408
409
  @param[in]  HashAlg       Digest algorithm
410
  @param[in]  DigestList    Digest list
411
  @param[out] Digest        Digest
412
413
  @retval EFI_SUCCESS       Digest is found and returned.
414
  @retval EFI_NOT_FOUND     Digest is not found.
415
**/
416
EFI_STATUS
417
EFIAPI
418
GetDigestFromDigestList (
419
  IN TPMI_ALG_HASH       HashAlg,
420
  IN TPML_DIGEST_VALUES  *DigestList,
421
  OUT VOID               *Digest
422
  )
423
0
{
424
0
  UINTN   Index;
425
0
  UINT16  DigestSize;
426
427
0
  DigestSize = GetHashSizeFromAlgo (HashAlg);
428
0
  for (Index = 0; Index < DigestList->count; Index++) {
429
0
    if (DigestList->digests[Index].hashAlg == HashAlg) {
430
0
      CopyMem (
431
0
        Digest,
432
0
        &DigestList->digests[Index].digest,
433
0
        DigestSize
434
0
        );
435
0
      return EFI_SUCCESS;
436
0
    }
437
0
  }
438
439
0
  return EFI_NOT_FOUND;
440
0
}