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