1 /** @file
2   Implement TPM2 help.
3 
4 Copyright (c) 2013 - 2016, 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 typedef struct {
23   TPMI_ALG_HASH              HashAlgo;
24   UINT16                     HashSize;
25   UINT32                     HashMask;
26 } INTERNAL_HASH_INFO;
27 
28 STATIC INTERNAL_HASH_INFO mHashInfo[] = {
29   {TPM_ALG_SHA1,          SHA1_DIGEST_SIZE,     HASH_ALG_SHA1},
30   {TPM_ALG_SHA256,        SHA256_DIGEST_SIZE,   HASH_ALG_SHA256},
31   {TPM_ALG_SM3_256,       SM3_256_DIGEST_SIZE,  HASH_ALG_SM3_256},
32   {TPM_ALG_SHA384,        SHA384_DIGEST_SIZE,   HASH_ALG_SHA384},
33   {TPM_ALG_SHA512,        SHA512_DIGEST_SIZE,   HASH_ALG_SHA512},
34 };
35 
36 /**
37   Return size of digest.
38 
39   @param[in] HashAlgo  Hash algorithm
40 
41   @return size of digest
42 **/
43 UINT16
44 EFIAPI
GetHashSizeFromAlgo(IN TPMI_ALG_HASH HashAlgo)45 GetHashSizeFromAlgo (
46   IN TPMI_ALG_HASH    HashAlgo
47   )
48 {
49   UINTN  Index;
50 
51   for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
52     if (mHashInfo[Index].HashAlgo == HashAlgo) {
53       return mHashInfo[Index].HashSize;
54     }
55   }
56   return 0;
57 }
58 
59 /**
60   Get hash mask from algorithm.
61 
62   @param[in] HashAlgo   Hash algorithm
63 
64   @return Hash mask
65 **/
66 UINT32
67 EFIAPI
GetHashMaskFromAlgo(IN TPMI_ALG_HASH HashAlgo)68 GetHashMaskFromAlgo (
69   IN TPMI_ALG_HASH     HashAlgo
70   )
71 {
72   UINTN  Index;
73 
74   for (Index = 0; Index < sizeof(mHashInfo)/sizeof(mHashInfo[0]); Index++) {
75     if (mHashInfo[Index].HashAlgo == HashAlgo) {
76       return mHashInfo[Index].HashMask;
77     }
78   }
79   return 0;
80 }
81 
82 /**
83   Copy AuthSessionIn to TPM2 command buffer.
84 
85   @param [in]  AuthSessionIn   Input AuthSession data
86   @param [out] AuthSessionOut  Output AuthSession data in TPM2 command buffer
87 
88   @return AuthSession size
89 **/
90 UINT32
91 EFIAPI
CopyAuthSessionCommand(IN TPMS_AUTH_COMMAND * AuthSessionIn,OPTIONAL OUT UINT8 * AuthSessionOut)92 CopyAuthSessionCommand (
93   IN      TPMS_AUTH_COMMAND         *AuthSessionIn, OPTIONAL
94   OUT     UINT8                     *AuthSessionOut
95   )
96 {
97   UINT8  *Buffer;
98 
99   Buffer = (UINT8 *)AuthSessionOut;
100 
101   //
102   // Add in Auth session
103   //
104   if (AuthSessionIn != NULL) {
105     //  sessionHandle
106     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle));
107     Buffer += sizeof(UINT32);
108 
109     // nonce
110     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size));
111     Buffer += sizeof(UINT16);
112 
113     CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size);
114     Buffer += AuthSessionIn->nonce.size;
115 
116     // sessionAttributes
117     *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes;
118     Buffer++;
119 
120     // hmac
121     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size));
122     Buffer += sizeof(UINT16);
123 
124     CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size);
125     Buffer += AuthSessionIn->hmac.size;
126   } else {
127     //  sessionHandle
128     WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW));
129     Buffer += sizeof(UINT32);
130 
131     // nonce = nullNonce
132     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
133     Buffer += sizeof(UINT16);
134 
135     // sessionAttributes = 0
136     *(UINT8 *)Buffer = 0x00;
137     Buffer++;
138 
139     // hmac = nullAuth
140     WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0));
141     Buffer += sizeof(UINT16);
142   }
143 
144   return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionOut);
145 }
146 
147 /**
148   Copy AuthSessionIn from TPM2 response buffer.
149 
150   @param [in]  AuthSessionIn   Input AuthSession data in TPM2 response buffer
151   @param [out] AuthSessionOut  Output AuthSession data
152 
153   @return AuthSession size
154 **/
155 UINT32
156 EFIAPI
CopyAuthSessionResponse(IN UINT8 * AuthSessionIn,OUT TPMS_AUTH_RESPONSE * AuthSessionOut OPTIONAL)157 CopyAuthSessionResponse (
158   IN      UINT8                      *AuthSessionIn,
159   OUT     TPMS_AUTH_RESPONSE         *AuthSessionOut OPTIONAL
160   )
161 {
162   UINT8                      *Buffer;
163   TPMS_AUTH_RESPONSE         LocalAuthSessionOut;
164 
165   if (AuthSessionOut == NULL) {
166     AuthSessionOut = &LocalAuthSessionOut;
167   }
168 
169   Buffer = (UINT8 *)AuthSessionIn;
170 
171   // nonce
172   AuthSessionOut->nonce.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
173   Buffer += sizeof(UINT16);
174 
175   CopyMem (AuthSessionOut->nonce.buffer, Buffer, AuthSessionOut->nonce.size);
176   Buffer += AuthSessionOut->nonce.size;
177 
178   // sessionAttributes
179   *(UINT8 *)&AuthSessionOut->sessionAttributes = *(UINT8 *)Buffer;
180   Buffer++;
181 
182   // hmac
183   AuthSessionOut->hmac.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
184   Buffer += sizeof(UINT16);
185 
186   CopyMem (AuthSessionOut->hmac.buffer, Buffer, AuthSessionOut->hmac.size);
187   Buffer += AuthSessionOut->hmac.size;
188 
189   return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionIn);
190 }
191 
192 /**
193   Return if hash alg is supported in HashAlgorithmMask.
194 
195   @param HashAlg            Hash algorithm to be checked.
196   @param HashAlgorithmMask  Bitfield of allowed hash algorithms.
197 
198   @retval TRUE  Hash algorithm is supported.
199   @retval FALSE Hash algorithm is not supported.
200 **/
201 BOOLEAN
202 EFIAPI
IsHashAlgSupportedInHashAlgorithmMask(IN TPMI_ALG_HASH HashAlg,IN UINT32 HashAlgorithmMask)203 IsHashAlgSupportedInHashAlgorithmMask(
204   IN TPMI_ALG_HASH  HashAlg,
205   IN UINT32         HashAlgorithmMask
206   )
207 {
208   switch (HashAlg) {
209   case TPM_ALG_SHA1:
210     if ((HashAlgorithmMask & HASH_ALG_SHA1) != 0) {
211       return TRUE;
212     }
213     break;
214   case TPM_ALG_SHA256:
215     if ((HashAlgorithmMask & HASH_ALG_SHA256) != 0) {
216       return TRUE;
217     }
218     break;
219   case TPM_ALG_SHA384:
220     if ((HashAlgorithmMask & HASH_ALG_SHA384) != 0) {
221       return TRUE;
222     }
223     break;
224   case TPM_ALG_SHA512:
225     if ((HashAlgorithmMask & HASH_ALG_SHA512) != 0) {
226       return TRUE;
227     }
228     break;
229   case TPM_ALG_SM3_256:
230     if ((HashAlgorithmMask & HASH_ALG_SM3_256) != 0) {
231       return TRUE;
232     }
233     break;
234   }
235 
236   return FALSE;
237 }
238 
239 /**
240   Copy TPML_DIGEST_VALUES into a buffer
241 
242   @param[in,out] Buffer             Buffer to hold copied TPML_DIGEST_VALUES compact binary.
243   @param[in]     DigestList         TPML_DIGEST_VALUES to be copied.
244   @param[in]     HashAlgorithmMask  HASH bits corresponding to the desired digests to copy.
245 
246   @return The end of buffer to hold TPML_DIGEST_VALUES.
247 **/
248 VOID *
249 EFIAPI
CopyDigestListToBuffer(IN OUT VOID * Buffer,IN TPML_DIGEST_VALUES * DigestList,IN UINT32 HashAlgorithmMask)250 CopyDigestListToBuffer (
251   IN OUT VOID                       *Buffer,
252   IN TPML_DIGEST_VALUES             *DigestList,
253   IN UINT32                         HashAlgorithmMask
254   )
255 {
256   UINTN  Index;
257   UINT16 DigestSize;
258   UINT32 DigestListCount;
259   UINT32 *DigestListCountPtr;
260 
261   DigestListCountPtr = (UINT32 *) Buffer;
262   DigestListCount = 0;
263   Buffer = (UINT8 *)Buffer + sizeof(DigestList->count);
264   for (Index = 0; Index < DigestList->count; Index++) {
265     if (!IsHashAlgSupportedInHashAlgorithmMask(DigestList->digests[Index].hashAlg, HashAlgorithmMask)) {
266       DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg));
267       continue;
268     }
269     CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg));
270     Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg);
271     DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
272     CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);
273     Buffer = (UINT8 *)Buffer + DigestSize;
274     DigestListCount++;
275   }
276   WriteUnaligned32 (DigestListCountPtr, DigestListCount);
277 
278   return Buffer;
279 }
280 
281 /**
282   Get TPML_DIGEST_VALUES data size.
283 
284   @param[in]     DigestList    TPML_DIGEST_VALUES data.
285 
286   @return TPML_DIGEST_VALUES data size.
287 **/
288 UINT32
289 EFIAPI
GetDigestListSize(IN TPML_DIGEST_VALUES * DigestList)290 GetDigestListSize (
291   IN TPML_DIGEST_VALUES             *DigestList
292   )
293 {
294   UINTN  Index;
295   UINT16 DigestSize;
296   UINT32 TotalSize;
297 
298   TotalSize = sizeof(DigestList->count);
299   for (Index = 0; Index < DigestList->count; Index++) {
300     DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);
301     TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize;
302   }
303 
304   return TotalSize;
305 }
306 
307 /**
308   This function get digest from digest list.
309 
310   @param[in]  HashAlg       Digest algorithm
311   @param[in]  DigestList    Digest list
312   @param[out] Digest        Digest
313 
314   @retval EFI_SUCCESS       Digest is found and returned.
315   @retval EFI_NOT_FOUND     Digest is not found.
316 **/
317 EFI_STATUS
318 EFIAPI
GetDigestFromDigestList(IN TPMI_ALG_HASH HashAlg,IN TPML_DIGEST_VALUES * DigestList,OUT VOID * Digest)319 GetDigestFromDigestList (
320   IN TPMI_ALG_HASH      HashAlg,
321   IN TPML_DIGEST_VALUES *DigestList,
322   OUT VOID              *Digest
323   )
324 {
325   UINTN  Index;
326   UINT16 DigestSize;
327 
328   DigestSize = GetHashSizeFromAlgo (HashAlg);
329   for (Index = 0; Index < DigestList->count; Index++) {
330     if (DigestList->digests[Index].hashAlg == HashAlg) {
331       CopyMem (
332         Digest,
333         &DigestList->digests[Index].digest,
334         DigestSize
335         );
336       return EFI_SUCCESS;
337     }
338   }
339 
340   return EFI_NOT_FOUND;
341 }
342