Line | Count | Source (jump to first uncovered line) |
1 | | // This file was extracted from the TCG Published |
2 | | // Trusted Platform Module Library |
3 | | // Part 4: Supporting Routines |
4 | | // Family "2.0" |
5 | | // Level 00 Revision 01.16 |
6 | | // October 30, 2014 |
7 | | |
8 | | #include <string.h> |
9 | | |
10 | | #include "OsslCryptoEngine.h" |
11 | | #include "CpriHashData.c" |
12 | | #if OPENSSL_VERSION_NUMBER < 0x10100000L |
13 | | // |
14 | | // Temporary aliasing of SM3 to SHA256 until SM3 is available |
15 | | // |
16 | | #define EVP_sm3 EVP_sha256 |
17 | | |
18 | | static void *OPENSSL_zalloc(size_t num) |
19 | | { |
20 | | void *ret = OPENSSL_malloc(num); |
21 | | if (ret != NULL) |
22 | | memset(ret, 0, num); |
23 | | return ret; |
24 | | } |
25 | | |
26 | | static EVP_MD_CTX *EVP_MD_CTX_new(void) |
27 | | { |
28 | | return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); |
29 | | } |
30 | | |
31 | | static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) |
32 | | { |
33 | | EVP_MD_CTX_cleanup(ctx); |
34 | | OPENSSL_free(ctx); |
35 | | } |
36 | | #endif |
37 | | // |
38 | | // |
39 | | // Static Functions |
40 | | // |
41 | | // GetHashServer() |
42 | | // |
43 | | // This function returns the address of the hash server function |
44 | | // |
45 | | static EVP_MD * |
46 | | GetHashServer( |
47 | | TPM_ALG_ID hashAlg |
48 | | ) |
49 | 90 | { |
50 | 90 | switch (hashAlg) |
51 | 90 | { |
52 | 0 | #ifdef TPM_ALG_SHA1 |
53 | 9 | case TPM_ALG_SHA1: |
54 | 9 | return (EVP_MD *)EVP_sha1(); |
55 | 0 | break; |
56 | 0 | #endif |
57 | 0 | #ifdef TPM_ALG_SHA256 |
58 | 28 | case TPM_ALG_SHA256: |
59 | 28 | return (EVP_MD *)EVP_sha256(); |
60 | 0 | break; |
61 | 0 | #endif |
62 | 0 | #ifdef TPM_ALG_SHA384 |
63 | 38 | case TPM_ALG_SHA384: |
64 | 38 | return (EVP_MD *)EVP_sha384(); |
65 | 0 | break; |
66 | 0 | #endif |
67 | 0 | #ifdef TPM_ALG_SHA512 |
68 | 15 | case TPM_ALG_SHA512: |
69 | 15 | return (EVP_MD *)EVP_sha512(); |
70 | 0 | break; |
71 | 0 | #endif |
72 | | #ifdef TPM_ALG_SM3_256 |
73 | | case TPM_ALG_SM3_256: |
74 | | return (EVP_MD *)EVP_sm3(); // OpenSSL 1.1 introduced this function |
75 | | break; |
76 | | #endif |
77 | 0 | case TPM_ALG_NULL: |
78 | 0 | return NULL; |
79 | 0 | default: |
80 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
81 | 90 | } |
82 | 0 | return NULL; // Never reached. |
83 | 90 | } |
84 | | |
85 | | // |
86 | | // |
87 | | // GetHashInfoPointer() |
88 | | // |
89 | | // This function returns a pointer to the hash info for the algorithm. If the algorithm is not supported, function |
90 | | // returns a pointer to the data block associated with TPM_ALG_NULL. |
91 | | // |
92 | | static const HASH_INFO * |
93 | | GetHashInfoPointer( |
94 | | TPM_ALG_ID hashAlg |
95 | | ) |
96 | 22.2k | { |
97 | 22.2k | UINT32 i, tableSize; |
98 | | // Get the table size of g_hashData |
99 | 22.2k | tableSize = sizeof(g_hashData) / sizeof(g_hashData[0]); |
100 | 55.6k | for(i = 0; i < tableSize - 1; i++) |
101 | 55.6k | { |
102 | 55.6k | if(g_hashData[i].alg == hashAlg) |
103 | 22.2k | return &g_hashData[i]; |
104 | 55.6k | } |
105 | 1 | return &g_hashData[tableSize-1]; |
106 | 22.2k | } |
107 | | // |
108 | | // |
109 | | // Hash Functions |
110 | | // |
111 | | // _cpri__HashStartup() |
112 | | // |
113 | | // Function that is called to initialize the hash service. In this implementation, this function does nothing but |
114 | | // it is called by the CryptUtilStartup() function and must be present. |
115 | | // |
116 | | LIB_EXPORT BOOL |
117 | | _cpri__HashStartup( |
118 | | void |
119 | | ) |
120 | 693 | { |
121 | 693 | return TRUE; |
122 | 693 | } |
123 | | // |
124 | | // |
125 | | // _cpri__GetHashAlgByIndex() |
126 | | // |
127 | | // This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are |
128 | | // not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first |
129 | | // implemented hash and and index of 2 will return the last. All other index values will return |
130 | | // TPM_ALG_NULL. |
131 | | // |
132 | | // |
133 | | // |
134 | | // |
135 | | // Return Value Meaning |
136 | | // |
137 | | // TPM_ALG_xxx() a hash algorithm |
138 | | // TPM_ALG_NULL this can be used as a stop value |
139 | | // |
140 | | LIB_EXPORT TPM_ALG_ID |
141 | | _cpri__GetHashAlgByIndex( |
142 | | UINT32 index // IN: the index |
143 | | ) |
144 | 924 | { |
145 | 924 | if(index >= HASH_COUNT) |
146 | 0 | return TPM_ALG_NULL; |
147 | 924 | return g_hashData[index].alg; |
148 | 924 | } |
149 | | // |
150 | | // |
151 | | // _cpri__GetHashBlockSize() |
152 | | // |
153 | | // Returns the size of the block used for the hash |
154 | | // |
155 | | // Return Value Meaning |
156 | | // |
157 | | // <0 the algorithm is not a supported hash |
158 | | // >= the digest size (0 for TPM_ALG_NULL) |
159 | | // |
160 | | LIB_EXPORT UINT16 |
161 | | _cpri__GetHashBlockSize( |
162 | | TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
163 | | ) |
164 | 6 | { |
165 | 6 | return GetHashInfoPointer(hashAlg)->blockSize; |
166 | 6 | } |
167 | | // |
168 | | // |
169 | | // _cpri__GetHashDER |
170 | | // |
171 | | // This function returns a pointer to the DER string for the algorithm and indicates its size. |
172 | | // |
173 | | LIB_EXPORT UINT16 |
174 | | _cpri__GetHashDER( |
175 | | TPM_ALG_ID hashAlg, // IN: the algorithm to look up |
176 | | const BYTE **p |
177 | | ) |
178 | 0 | { |
179 | 0 | const HASH_INFO *q; |
180 | 0 | q = GetHashInfoPointer(hashAlg); |
181 | 0 | *p = &q->der[0]; |
182 | 0 | return q->derSize; |
183 | 0 | } |
184 | | // |
185 | | // |
186 | | // _cpri__GetDigestSize() |
187 | | // |
188 | | // Gets the digest size of the algorithm. The algorithm is required to be supported. |
189 | | // |
190 | | // Return Value Meaning |
191 | | // |
192 | | // =0 the digest size for TPM_ALG_NULL |
193 | | // >0 the digest size of a hash algorithm |
194 | | // |
195 | | LIB_EXPORT UINT16 |
196 | | _cpri__GetDigestSize( |
197 | | TPM_ALG_ID hashAlg // IN: hash algorithm to look up |
198 | | ) |
199 | 22.2k | { |
200 | 22.2k | return GetHashInfoPointer(hashAlg)->digestSize; |
201 | 22.2k | } |
202 | | // |
203 | | // |
204 | | // _cpri__GetContextAlg() |
205 | | // |
206 | | // This function returns the algorithm associated with a hash context |
207 | | // |
208 | | LIB_EXPORT TPM_ALG_ID |
209 | | _cpri__GetContextAlg( |
210 | | CPRI_HASH_STATE *hashState // IN: the hash context |
211 | | ) |
212 | 0 | { |
213 | 0 | return hashState->hashAlg; |
214 | 0 | } |
215 | | // |
216 | | // |
217 | | // _cpri__CopyHashState |
218 | | // |
219 | | // This function is used to clone a CPRI_HASH_STATE. The return value is the size of the state. |
220 | | // |
221 | | LIB_EXPORT UINT16 |
222 | | _cpri__CopyHashState ( |
223 | | CPRI_HASH_STATE *out, // OUT: destination of the state |
224 | | CPRI_HASH_STATE *in // IN: source of the state |
225 | | ) |
226 | 14.8k | { |
227 | 14.8k | EVP_MD_CTX *in_ctx = *(EVP_MD_CTX **)&in->state; |
228 | 14.8k | EVP_MD_CTX *out_ctx; |
229 | 14.8k | pAssert(sizeof(out->state) >= sizeof(EVP_MD_CTX *)); |
230 | 14.8k | if((out_ctx = EVP_MD_CTX_new()) == NULL) |
231 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
232 | 14.8k | if(!EVP_MD_CTX_copy_ex(out_ctx, in_ctx)) |
233 | 0 | { |
234 | 0 | EVP_MD_CTX_free(out_ctx); |
235 | 0 | return 0; |
236 | 0 | } |
237 | 14.8k | *(EVP_MD_CTX**)&out->state = out_ctx; |
238 | 14.8k | out->hashAlg = in->hashAlg; |
239 | 14.8k | return sizeof(EVP_MD_CTX *); |
240 | 14.8k | } |
241 | | |
242 | | // |
243 | | // |
244 | | // _cpri__StartHash() |
245 | | // |
246 | | // Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value of |
247 | | // stateSize in hashState is updated to indicate the number of bytes of state that were saved. This function |
248 | | // calls GetHashServer() and that function will put the TPM into failure mode if the hash algorithm is not |
249 | | // supported. |
250 | | // |
251 | | // Return Value Meaning |
252 | | // |
253 | | // 0 hash is TPM_ALG_NULL |
254 | | // >0 digest size |
255 | | LIB_EXPORT UINT16 |
256 | | _cpri__StartHash( |
257 | | TPM_ALG_ID hashAlg, // IN: hash algorithm |
258 | | BOOL sequence, // IN: TRUE if the state should be saved |
259 | | CPRI_HASH_STATE *hashState // OUT: the state of hash stack. |
260 | | ) |
261 | 90 | { |
262 | 90 | EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state; |
263 | 90 | EVP_MD *evpmdAlgorithm = NULL; |
264 | 90 | pAssert(sizeof(hashState->state) >= sizeof(EVP_MD_CTX *)); |
265 | 90 | evpmdAlgorithm = GetHashServer(hashAlg); |
266 | 90 | if(evpmdAlgorithm == NULL) |
267 | 0 | return 0; |
268 | 90 | if((context = EVP_MD_CTX_new()) == NULL) |
269 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
270 | 90 | *(EVP_MD_CTX**)&hashState->state = context; |
271 | 90 | hashState->hashAlg = hashAlg; |
272 | 90 | if(EVP_DigestInit_ex(context, evpmdAlgorithm, NULL) != 1) |
273 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
274 | 90 | return (CRYPT_RESULT)EVP_MD_CTX_size(context); |
275 | 90 | } |
276 | | // |
277 | | // |
278 | | // _cpri__UpdateHash() |
279 | | // |
280 | | // Add data to a hash or HMAC stack. |
281 | | // |
282 | | LIB_EXPORT void |
283 | | _cpri__UpdateHash( |
284 | | CPRI_HASH_STATE *hashState, // IN: the hash context information |
285 | | UINT32 dataSize, // IN: the size of data to be added to the |
286 | | // digest |
287 | | BYTE *data // IN: data to be hashed |
288 | | ) |
289 | 44.6k | { |
290 | 44.6k | EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state; |
291 | | // If there is no context, return |
292 | 44.6k | if(context == NULL) |
293 | 0 | return; |
294 | 44.6k | if(EVP_DigestUpdate(context, data, dataSize) != 1) |
295 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
296 | 44.6k | return; |
297 | 44.6k | } |
298 | | // |
299 | | // |
300 | | // _cpri__CompleteHash() |
301 | | // |
302 | | // Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size of |
303 | | // the digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, the |
304 | | // returned value is <= 0. |
305 | | // |
306 | | // Return Value Meaning |
307 | | // |
308 | | // 0 no data returned |
309 | | // >0 the number of bytes in the digest |
310 | | // |
311 | | LIB_EXPORT UINT16 |
312 | | _cpri__CompleteHash( |
313 | | CPRI_HASH_STATE *hashState, // IN: the state of hash stack |
314 | | UINT32 dOutSize, // IN: size of digest buffer |
315 | | BYTE *dOut // OUT: hash digest |
316 | | ) |
317 | 14.9k | { |
318 | 14.9k | EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state; |
319 | 14.9k | UINT16 retVal; |
320 | 14.9k | int hLen; |
321 | 14.9k | BYTE temp[EVP_MAX_MD_SIZE]; |
322 | 14.9k | BYTE *rBuffer = dOut; |
323 | 14.9k | if(context == NULL) |
324 | 0 | return 0; |
325 | 14.9k | hLen = EVP_MD_CTX_size(context); |
326 | 14.9k | if((unsigned)hLen > dOutSize) |
327 | 6 | rBuffer = temp; |
328 | 14.9k | if(EVP_DigestFinal_ex(context, rBuffer, NULL) == 1) |
329 | 14.9k | { |
330 | 14.9k | if(rBuffer != dOut) |
331 | 6 | { |
332 | 6 | if(dOut != NULL) |
333 | 0 | { |
334 | 0 | memcpy(dOut, temp, dOutSize); |
335 | 0 | } |
336 | 6 | retVal = (UINT16)dOutSize; |
337 | 6 | } |
338 | 14.9k | else |
339 | 14.9k | { |
340 | 14.9k | retVal = (UINT16)hLen; |
341 | 14.9k | } |
342 | 14.9k | } |
343 | 0 | else |
344 | 0 | { |
345 | 0 | retVal = 0; // Indicate that no data is returned |
346 | 0 | } |
347 | | |
348 | 14.9k | EVP_MD_CTX_free(context); |
349 | 14.9k | *(EVP_MD_CTX **)&hashState->state = NULL; |
350 | 14.9k | return retVal; |
351 | 14.9k | } |
352 | | // |
353 | | // |
354 | | // _cpri__ImportExportHashState() |
355 | | // |
356 | | // This function is used to import or export the hash state. This function would be called to export state when |
357 | | // a sequence object was being prepared for export |
358 | | // |
359 | | LIB_EXPORT void |
360 | | _cpri__ImportExportHashState( |
361 | | CPRI_HASH_STATE *osslFmt, // IN/OUT: the hash state formated for use |
362 | | // by openSSL |
363 | | EXPORT_HASH_STATE *externalFmt, // IN/OUT: the exported hash state |
364 | | IMPORT_EXPORT direction // |
365 | | ) |
366 | 0 | { |
367 | 0 | UNREFERENCED_PARAMETER(direction); |
368 | 0 | UNREFERENCED_PARAMETER(externalFmt); |
369 | 0 | UNREFERENCED_PARAMETER(osslFmt); |
370 | 0 | return; |
371 | | #if 0 |
372 | | if(direction == IMPORT_STATE) |
373 | | { |
374 | | // don't have the import export functions yet so just copy |
375 | | _cpri__CopyHashState(osslFmt, (CPRI_HASH_STATE *)externalFmt); |
376 | | } |
377 | | else |
378 | | { |
379 | | _cpri__CopyHashState((CPRI_HASH_STATE *)externalFmt, osslFmt); |
380 | | } |
381 | | #endif |
382 | 0 | } |
383 | | // |
384 | | // |
385 | | // |
386 | | // _cpri__HashBlock() |
387 | | // |
388 | | // Start a hash, hash a single block, update digest and return the size of the results. |
389 | | // The digestSize parameter can be smaller than the digest. If so, only the more significant bytes are |
390 | | // returned. |
391 | | // |
392 | | // Return Value Meaning |
393 | | // |
394 | | // >= 0 number of bytes in digest (may be zero) |
395 | | // |
396 | | LIB_EXPORT UINT16 |
397 | | _cpri__HashBlock( |
398 | | TPM_ALG_ID hashAlg, // IN: The hash algorithm |
399 | | UINT32 dataSize, // IN: size of buffer to hash |
400 | | BYTE *data, // IN: the buffer to hash |
401 | | UINT32 digestSize, // IN: size of the digest buffer |
402 | | BYTE *digest // OUT: hash digest |
403 | | ) |
404 | 0 | { |
405 | 0 | EVP_MD_CTX *hashContext; |
406 | 0 | EVP_MD *hashServer = NULL; |
407 | 0 | UINT16 retVal = 0; |
408 | 0 | BYTE b[EVP_MAX_MD_SIZE]; // temp buffer in case digestSize not |
409 | | // a full digest |
410 | 0 | unsigned int dSize = _cpri__GetDigestSize(hashAlg); |
411 | | // If there is no digest to compute return |
412 | 0 | if(dSize == 0) |
413 | 0 | return 0; |
414 | 0 | if ((hashContext = EVP_MD_CTX_new()) == NULL) |
415 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
416 | 0 | hashServer = GetHashServer(hashAlg); // Find the hash server |
417 | | // It is an error if the digest size is non-zero but there is no server |
418 | 0 | if( (hashServer == NULL) |
419 | 0 | || (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1) |
420 | 0 | || (EVP_DigestUpdate(hashContext, data, dataSize) != 1)) |
421 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
422 | 0 | else |
423 | 0 | { |
424 | | // If the size of the digest produced (dSize) is larger than the available |
425 | | // buffer (digestSize), then put the digest in a temp buffer and only copy |
426 | | // the most significant part into the available buffer. |
427 | 0 | if(dSize > digestSize) |
428 | 0 | { |
429 | 0 | if(EVP_DigestFinal_ex(hashContext, b, &dSize) != 1) |
430 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
431 | 0 | memcpy(digest, b, digestSize); |
432 | 0 | retVal = (UINT16)digestSize; |
433 | 0 | } |
434 | 0 | else |
435 | 0 | { |
436 | 0 | if((EVP_DigestFinal_ex(hashContext, digest, &dSize)) != 1) |
437 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
438 | 0 | retVal = (UINT16) dSize; |
439 | 0 | } |
440 | 0 | } |
441 | 0 | EVP_MD_CTX_free(hashContext); |
442 | 0 | return retVal; |
443 | 0 | } |
444 | | // |
445 | | // |
446 | | // |
447 | | // HMAC Functions |
448 | | // |
449 | | // _cpri__StartHMAC |
450 | | // |
451 | | // This function is used to start an HMAC using a temp hash context. The function does the initialization of |
452 | | // the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. |
453 | | // The function returns the number of bytes in a digest produced by hashAlg. |
454 | | // |
455 | | // Return Value Meaning |
456 | | // |
457 | | // >= 0 number of bytes in digest produced by hashAlg (may be zero) |
458 | | // |
459 | | LIB_EXPORT UINT16 |
460 | | _cpri__StartHMAC( |
461 | | TPM_ALG_ID hashAlg, // IN: the algorithm to use |
462 | | BOOL sequence, // IN: indicates if the state should be |
463 | | // saved |
464 | | CPRI_HASH_STATE *state, // IN/OUT: the state buffer |
465 | | UINT16 keySize, // IN: the size of the HMAC key |
466 | | BYTE *key, // IN: the HMAC key |
467 | | TPM2B *oPadKey // OUT: the key prepared for the oPad round |
468 | | ) |
469 | 6 | { |
470 | 6 | CPRI_HASH_STATE localState = {}; |
471 | 6 | UINT16 blockSize = _cpri__GetHashBlockSize(hashAlg); |
472 | 6 | UINT16 digestSize; |
473 | 6 | BYTE *pb; // temp pointer |
474 | 6 | UINT32 i; |
475 | | |
476 | | // If the key size is larger than the block size, then the hash of the key |
477 | | // is used as the key |
478 | 6 | if(keySize > blockSize) |
479 | 0 | { |
480 | | // large key so digest |
481 | 0 | if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0) |
482 | 0 | return 0; |
483 | 0 | _cpri__UpdateHash(&localState, keySize, key); |
484 | 0 | _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer); |
485 | 0 | oPadKey->size = digestSize; |
486 | 0 | } |
487 | 6 | else |
488 | 6 | { |
489 | | // key size is ok |
490 | 6 | memcpy(oPadKey->buffer, key, keySize); |
491 | 6 | oPadKey->size = keySize; |
492 | 6 | } |
493 | | // XOR the key with iPad (0x36) |
494 | 6 | pb = oPadKey->buffer; |
495 | 198 | for(i = oPadKey->size; i > 0; i--) |
496 | 192 | *pb++ ^= 0x36; |
497 | | // if the keySize is smaller than a block, fill the rest with 0x36 |
498 | 198 | for(i = blockSize - oPadKey->size; i > 0; i--) |
499 | 192 | *pb++ = 0x36; |
500 | | // Increase the oPadSize to a full block |
501 | 6 | oPadKey->size = blockSize; |
502 | | // Start a new hash with the HMAC key |
503 | | // This will go in the caller's state structure and may be a sequence or not |
504 | 6 | if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0) |
505 | 6 | { |
506 | 6 | _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer); |
507 | | // XOR the key block with 0x5c ^ 0x36 |
508 | 390 | for(pb = oPadKey->buffer, i = blockSize; i > 0; i--) |
509 | 384 | *pb++ ^= (0x5c ^ 0x36); |
510 | 6 | } |
511 | 6 | return digestSize; |
512 | 6 | } |
513 | | // |
514 | | // |
515 | | // _cpri_CompleteHMAC() |
516 | | // |
517 | | // This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will |
518 | | // then add the oPadKey and the completed digest and return the results in dOut. It will not return more than |
519 | | // dOutSize bytes. |
520 | | // |
521 | | // Return Value Meaning |
522 | | // |
523 | | // >= 0 number of bytes in dOut (may be zero) |
524 | | // |
525 | | LIB_EXPORT UINT16 |
526 | | _cpri__CompleteHMAC( |
527 | | CPRI_HASH_STATE *hashState, // IN: the state of hash stack |
528 | | TPM2B *oPadKey, // IN: the HMAC key in oPad format |
529 | | UINT32 dOutSize, // IN: size of digest buffer |
530 | | BYTE *dOut // OUT: hash digest |
531 | | ) |
532 | 3 | { |
533 | 3 | BYTE digest[MAX_DIGEST_SIZE]; |
534 | 3 | CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState; |
535 | 3 | CPRI_HASH_STATE localState = {}; |
536 | 3 | UINT16 digestSize = _cpri__GetDigestSize(state->hashAlg); |
537 | | |
538 | 3 | _cpri__CompleteHash(hashState, digestSize, digest); |
539 | | // Using the local hash state, do a hash with the oPad |
540 | 3 | if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize) |
541 | 0 | return 0; |
542 | 3 | _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer); |
543 | 3 | _cpri__UpdateHash(&localState, digestSize, digest); |
544 | 3 | return _cpri__CompleteHash(&localState, dOutSize, dOut); |
545 | 3 | } |
546 | | // |
547 | | // |
548 | | // Mask and Key Generation Functions |
549 | | // |
550 | | // _crypi_MGF1() |
551 | | // |
552 | | // This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || counter). This |
553 | | // function returns the length of the mask produced which could be zero if the digest algorithm is not |
554 | | // supported |
555 | | // |
556 | | // Return Value Meaning |
557 | | // |
558 | | // 0 hash algorithm not supported |
559 | | // >0 should be the same as mSize |
560 | | // |
561 | | LIB_EXPORT CRYPT_RESULT |
562 | | _cpri__MGF1( |
563 | | UINT32 mSize, // IN: length of the mask to be produced |
564 | | BYTE *mask, // OUT: buffer to receive the mask |
565 | | TPM_ALG_ID hashAlg, // IN: hash to use |
566 | | UINT32 sSize, // IN: size of the seed |
567 | | BYTE *seed // IN: seed size |
568 | | ) |
569 | 0 | { |
570 | 0 | EVP_MD_CTX *hashContext; |
571 | 0 | EVP_MD *hashServer = NULL; |
572 | 0 | CRYPT_RESULT retVal = 0; |
573 | 0 | BYTE b[MAX_DIGEST_SIZE]; // temp buffer in case mask is not an |
574 | | // even multiple of a full digest |
575 | 0 | CRYPT_RESULT dSize = _cpri__GetDigestSize(hashAlg); |
576 | 0 | unsigned int digestSize = (UINT32)dSize; |
577 | 0 | UINT32 remaining; |
578 | 0 | UINT32 counter; |
579 | 0 | BYTE swappedCounter[4]; |
580 | | // Parameter check |
581 | 0 | if(mSize > (1024*16)) // Semi-arbitrary maximum |
582 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
583 | | // If there is no digest to compute return |
584 | 0 | if(dSize <= 0) |
585 | 0 | return 0; |
586 | 0 | hashServer = GetHashServer(hashAlg); // Find the hash server |
587 | 0 | if(hashServer == NULL) |
588 | | // If there is no server, then there is no digest |
589 | 0 | return 0; |
590 | 0 | if ((hashContext = EVP_MD_CTX_new()) == NULL) |
591 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
592 | 0 | for(counter = 0, remaining = mSize; remaining > 0; counter++) |
593 | 0 | { |
594 | | // Because the system may be either Endian... |
595 | 0 | UINT32_TO_BYTE_ARRAY(counter, swappedCounter); |
596 | | // Start the hash and include the seed and counter |
597 | 0 | if( (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1) |
598 | 0 | || (EVP_DigestUpdate(hashContext, seed, sSize) != 1) |
599 | 0 | || (EVP_DigestUpdate(hashContext, swappedCounter, 4) != 1) |
600 | 0 | ) |
601 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
602 | | // Handling the completion depends on how much space remains in the mask |
603 | | // buffer. If it can hold the entire digest, put it there. If not |
604 | | // put the digest in a temp buffer and only copy the amount that |
605 | | // will fit into the mask buffer. |
606 | 0 | if(remaining < (unsigned)dSize) |
607 | 0 | { |
608 | 0 | if(EVP_DigestFinal_ex(hashContext, b, &digestSize) != 1) |
609 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
610 | 0 | memcpy(mask, b, remaining); |
611 | 0 | break; |
612 | 0 | } |
613 | 0 | else |
614 | 0 | { |
615 | 0 | if(EVP_DigestFinal_ex(hashContext, mask, &digestSize) != 1) |
616 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
617 | 0 | remaining -= dSize; |
618 | 0 | mask = &mask[dSize]; |
619 | 0 | } |
620 | 0 | retVal = (CRYPT_RESULT)mSize; |
621 | 0 | } |
622 | 0 | EVP_MD_CTX_free(hashContext); |
623 | 0 | return retVal; |
624 | 0 | } |
625 | | // |
626 | | // |
627 | | // _cpri_KDFa() |
628 | | // |
629 | | // This function performs the key generation according to Part 1 of the TPM specification. |
630 | | // This function returns the number of bytes generated which may be zero. |
631 | | // The key and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. |
632 | | // The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). |
633 | | // The once parameter is set to allow incremental generation of a large value. If this flag is TRUE, |
634 | | // sizeInBits will be used in the HMAC computation but only one iteration of the KDF is performed. This |
635 | | // would be used for XOR obfuscation so that the mask value can be generated in digest-sized chunks |
636 | | // rather than having to be generated all at once in an arbitrarily large buffer and then XORed() into the |
637 | | // result. If once is TRUE, then sizeInBits must be a multiple of 8. |
638 | | // Any error in the processing of this command is considered fatal. |
639 | | // |
640 | | // Return Value Meaning |
641 | | // |
642 | | // 0 hash algorithm is not supported or is TPM_ALG_NULL |
643 | | // >0 the number of bytes in the keyStream buffer |
644 | | // |
645 | | LIB_EXPORT UINT16 |
646 | | _cpri__KDFa( |
647 | | TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
648 | | TPM2B *key, // IN: HMAC key |
649 | | const char *label, // IN: a 0-byte terminated label used in KDF |
650 | | TPM2B *contextU, // IN: context U |
651 | | TPM2B *contextV, // IN: context V |
652 | | UINT32 sizeInBits, // IN: size of generated key in bit |
653 | | BYTE *keyStream, // OUT: key buffer |
654 | | UINT32 *counterInOut, // IN/OUT: caller may provide the iteration |
655 | | // counter for incremental operations to |
656 | | // avoid large intermediate buffers. |
657 | | BOOL once // IN: TRUE if only one iteration is performed |
658 | | // FALSE if iteration count determined by |
659 | | // "sizeInBits" |
660 | | ) |
661 | 0 | { |
662 | 0 | UINT32 counter = 0; // counter value |
663 | 0 | INT32 lLen = 0; // length of the label |
664 | 0 | INT16 hLen; // length of the hash |
665 | 0 | INT16 bytes; // number of bytes to produce |
666 | 0 | BYTE *stream = keyStream; |
667 | 0 | BYTE marshaledUint32[4]; |
668 | 0 | CPRI_HASH_STATE hashState = {}; |
669 | 0 | TPM2B_MAX_HASH_BLOCK hmacKey; |
670 | 0 | pAssert(key != NULL && keyStream != NULL); |
671 | 0 | pAssert(once == FALSE || (sizeInBits & 7) == 0); |
672 | 0 | if(counterInOut != NULL) |
673 | 0 | counter = *counterInOut; |
674 | | // Prepare label buffer. Calculate its size and keep the last 0 byte |
675 | 0 | if(label != NULL) |
676 | 0 | for(lLen = 0; label[lLen++] != 0; ); |
677 | | // Get the hash size. If it is less than or 0, either the |
678 | | // algorithm is not supported or the hash is TPM_ALG_NULL |
679 | | // |
680 | | // In either case the digest size is zero. This is the only return |
681 | | // other than the one at the end. All other exits from this function |
682 | | // are fatal errors. After we check that the algorithm is supported |
683 | | // anything else that goes wrong is an implementation flaw. |
684 | 0 | if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0) |
685 | 0 | return 0; |
686 | | // If the size of the request is larger than the numbers will handle, |
687 | | // it is a fatal error. |
688 | 0 | pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX); |
689 | 0 | bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8); |
690 | | // Generate required bytes |
691 | 0 | for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) |
692 | 0 | { |
693 | 0 | if(bytes < hLen) |
694 | 0 | hLen = bytes; |
695 | 0 | counter++; |
696 | | // Start HMAC |
697 | 0 | if(_cpri__StartHMAC(hashAlg, |
698 | 0 | FALSE, |
699 | 0 | &hashState, |
700 | 0 | key->size, |
701 | 0 | &key->buffer[0], |
702 | 0 | &hmacKey.b) <= 0) |
703 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
704 | | // Adding counter |
705 | 0 | UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); |
706 | 0 | _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
707 | | // Adding label |
708 | 0 | if(label != NULL) |
709 | 0 | _cpri__UpdateHash(&hashState, lLen, (BYTE *)label); |
710 | | // Adding contextU |
711 | 0 | if(contextU != NULL) |
712 | 0 | _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer); |
713 | | // Adding contextV |
714 | 0 | if(contextV != NULL) |
715 | 0 | _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer); |
716 | | // Adding size in bits |
717 | 0 | UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32); |
718 | 0 | _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
719 | | // Compute HMAC. At the start of each iteration, hLen is set |
720 | | // to the smaller of hLen and bytes. This causes bytes to decrement |
721 | | // exactly to zero to complete the loop |
722 | 0 | _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream); |
723 | 0 | } |
724 | | // Mask off bits if the required bits is not a multiple of byte size |
725 | 0 | if((sizeInBits % 8) != 0) |
726 | 0 | keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); |
727 | 0 | if(counterInOut != NULL) |
728 | 0 | *counterInOut = counter; |
729 | 0 | return (CRYPT_RESULT)((sizeInBits + 7)/8); |
730 | 0 | } |
731 | | // |
732 | | // |
733 | | // |
734 | | // _cpri__KDFe() |
735 | | // |
736 | | // KDFe() as defined in TPM specification part 1. |
737 | | // This function returns the number of bytes generated which may be zero. |
738 | | // The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The |
739 | | // value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any error in the processing |
740 | | // of this command is considered fatal. |
741 | | // |
742 | | // Return Value Meaning |
743 | | // |
744 | | // 0 hash algorithm is not supported or is TPM_ALG_NULL |
745 | | // >0 the number of bytes in the keyStream buffer |
746 | | // |
747 | | LIB_EXPORT UINT16 |
748 | | _cpri__KDFe( |
749 | | TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC |
750 | | TPM2B *Z, // IN: Z |
751 | | const char *label, // IN: a 0 terminated label using in KDF |
752 | | TPM2B *partyUInfo, // IN: PartyUInfo |
753 | | TPM2B *partyVInfo, // IN: PartyVInfo |
754 | | UINT32 sizeInBits, // IN: size of generated key in bit |
755 | | BYTE *keyStream // OUT: key buffer |
756 | | ) |
757 | 0 | { |
758 | 0 | UINT32 counter = 0; // counter value |
759 | 0 | UINT32 lSize = 0; |
760 | 0 | BYTE *stream = keyStream; |
761 | 0 | CPRI_HASH_STATE hashState = {}; |
762 | 0 | INT16 hLen = (INT16) _cpri__GetDigestSize(hashAlg); |
763 | 0 | INT16 bytes; // number of bytes to generate |
764 | 0 | BYTE marshaledUint32[4]; |
765 | 0 | pAssert( keyStream != NULL |
766 | 0 | && Z != NULL |
767 | 0 | && ((sizeInBits + 7) / 8) < INT16_MAX); |
768 | 0 | if(hLen == 0) |
769 | 0 | return 0; |
770 | 0 | bytes = (INT16)((sizeInBits + 7) / 8); |
771 | | // Prepare label buffer. Calculate its size and keep the last 0 byte |
772 | 0 | if(label != NULL) |
773 | 0 | for(lSize = 0; label[lSize++] != 0;); |
774 | | // Generate required bytes |
775 | | //The inner loop of that KDF uses: |
776 | | // Hashi := H(counter | Z | OtherInfo) (5) |
777 | | // Where: |
778 | | // Hashi the hash generated on the i-th iteration of the loop. |
779 | | // H() an approved hash function |
780 | | // counter a 32-bit counter that is initialized to 1 and incremented |
781 | | // on each iteration |
782 | | // Z the X coordinate of the product of a public ECC key and a |
783 | | // different private ECC key. |
784 | | // OtherInfo a collection of qualifying data for the KDF defined below. |
785 | | // In this specification, OtherInfo will be constructed by: |
786 | | // OtherInfo := Use | PartyUInfo | PartyVInfo |
787 | 0 | for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) |
788 | 0 | { |
789 | 0 | if(bytes < hLen) |
790 | 0 | hLen = bytes; |
791 | | // |
792 | 0 | counter++; |
793 | | // Start hash |
794 | 0 | if(_cpri__StartHash(hashAlg, FALSE, &hashState) == 0) |
795 | 0 | return 0; |
796 | | // Add counter |
797 | 0 | UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); |
798 | 0 | _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); |
799 | | // Add Z |
800 | 0 | if(Z != NULL) |
801 | 0 | _cpri__UpdateHash(&hashState, Z->size, Z->buffer); |
802 | | // Add label |
803 | 0 | if(label != NULL) |
804 | 0 | _cpri__UpdateHash(&hashState, lSize, (BYTE *)label); |
805 | 0 | else |
806 | | // The SP800-108 specification requires a zero between the label |
807 | | // and the context. |
808 | 0 | _cpri__UpdateHash(&hashState, 1, (BYTE *)""); |
809 | | // Add PartyUInfo |
810 | 0 | if(partyUInfo != NULL) |
811 | 0 | _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer); |
812 | | // Add PartyVInfo |
813 | 0 | if(partyVInfo != NULL) |
814 | 0 | _cpri__UpdateHash(&hashState, partyVInfo->size, partyVInfo->buffer); |
815 | | // Compute Hash. hLen was changed to be the smaller of bytes or hLen |
816 | | // at the start of each iteration. |
817 | 0 | _cpri__CompleteHash(&hashState, hLen, stream); |
818 | 0 | } |
819 | | // Mask off bits if the required bits is not a multiple of byte size |
820 | 0 | if((sizeInBits % 8) != 0) |
821 | 0 | keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); |
822 | 0 | return (CRYPT_RESULT)((sizeInBits + 7) / 8); |
823 | 0 | } |