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