1/* This file includes functions that were extracted from the TPM2 2 * source, but were present in files not included in compilation. 3 */ 4#include "Global.h" 5#include "CryptoEngine.h" 6 7#include <string.h> 8 9UINT16 _cpri__StartHMAC( 10 TPM_ALG_ID hashAlg, // IN: the algorithm to use 11 BOOL sequence, // IN: indicates if the state should be saved 12 CPRI_HASH_STATE * state, // IN/OUT: the state buffer 13 UINT16 keySize, // IN: the size of the HMAC key 14 BYTE * key, // IN: the HMAC key 15 TPM2B * oPadKey // OUT: the key prepared for the oPad round 16 ) 17{ 18 CPRI_HASH_STATE localState; 19 UINT16 blockSize = _cpri__GetHashBlockSize(hashAlg); 20 UINT16 digestSize; 21 BYTE *pb; // temp pointer 22 UINT32 i; 23 // If the key size is larger than the block size, then the hash of the key 24 // is used as the key 25 if(keySize > blockSize) 26 { 27 // large key so digest 28 if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0) 29 return 0; 30 _cpri__UpdateHash(&localState, keySize, key); 31 _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer); 32 oPadKey->size = digestSize; 33 } 34 else 35 { 36 // key size is ok 37 memcpy(oPadKey->buffer, key, keySize); 38 oPadKey->size = keySize; 39 } 40 // XOR the key with iPad (0x36) 41 pb = oPadKey->buffer; 42 for(i = oPadKey->size; i > 0; i--) 43 *pb++ ^= 0x36; 44 // if the keySize is smaller than a block, fill the rest with 0x36 45 for(i = blockSize - oPadKey->size; i > 0; i--) 46 *pb++ = 0x36; 47 // Increase the oPadSize to a full block 48 oPadKey->size = blockSize; 49 // Start a new hash with the HMAC key 50 // This will go in the caller's state structure and may be a sequence or not 51 if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0) 52 { 53 _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer); 54 // XOR the key block with 0x5c ^ 0x36 55 for(pb = oPadKey->buffer, i = blockSize; i > 0; i--) 56 *pb++ ^= (0x5c ^ 0x36); 57 } 58 return digestSize; 59} 60 61UINT16 _cpri__CompleteHMAC( 62 CPRI_HASH_STATE * hashState, // IN: the state of hash stack 63 TPM2B * oPadKey, // IN: the HMAC key in oPad format 64 UINT32 dOutSize, // IN: size of digest buffer 65 BYTE * dOut // OUT: hash digest 66 ) 67{ 68 BYTE digest[MAX_DIGEST_SIZE]; 69 CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState; 70 CPRI_HASH_STATE localState; 71 UINT16 digestSize = _cpri__GetDigestSize(state->hashAlg); 72 _cpri__CompleteHash(hashState, digestSize, digest); 73 // Using the local hash state, do a hash with the oPad 74 if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize) 75 return 0; 76 _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer); 77 _cpri__UpdateHash(&localState, digestSize, digest); 78 return _cpri__CompleteHash(&localState, dOutSize, dOut); 79} 80 81UINT16 _cpri__KDFa( 82 TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC 83 TPM2B * key, // IN: HMAC key 84 const char *label, // IN: a 0-byte terminated label used in KDF 85 TPM2B * contextU, // IN: context U 86 TPM2B * contextV, // IN: context V 87 UINT32 sizeInBits, // IN: size of generated key in bit 88 BYTE * keyStream, // OUT: key buffer 89 UINT32 * counterInOut, // IN/OUT: caller may provide the iteration 90 // counter for incremental operations to 91 // avoid large intermediate buffers. 92 BOOL once // IN: TRUE if only one iteration is 93 // performed FALSE if iteration count determined by "sizeInBits" 94 ) 95{ 96 UINT32 counter = 0; // counter value 97 INT32 lLen = 0; // length of the label 98 INT16 hLen; // length of the hash 99 INT16 bytes; // number of bytes to produce 100 BYTE *stream = keyStream; 101 BYTE marshaledUint32[4]; 102 CPRI_HASH_STATE hashState; 103 TPM2B_MAX_HASH_BLOCK hmacKey; 104 pAssert(key != NULL && keyStream != NULL); 105 pAssert(once == FALSE || (sizeInBits & 7) == 0); 106 if(counterInOut != NULL) 107 counter = *counterInOut; 108 // Prepare label buffer. Calculate its size and keep the last 0 byte 109 if(label != NULL) 110 for(lLen = 0; label[lLen++] != 0; ); 111 // Get the hash size. If it is less than or 0, either the 112 // algorithm is not supported or the hash is TPM_ALG_NULL 113// 114 // In either case the digest size is zero. This is the only return 115 // other than the one at the end. All other exits from this function 116 // are fatal errors. After we check that the algorithm is supported 117 // anything else that goes wrong is an implementation flaw. 118 if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0) 119 return 0; 120 // If the size of the request is larger than the numbers will handle, 121 // it is a fatal error. 122 pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX); 123 bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8); 124 // Generate required bytes 125 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) 126 { 127 if(bytes < hLen) 128 hLen = bytes; 129 counter++; 130 // Start HMAC 131 if(_cpri__StartHMAC(hashAlg, 132 FALSE, 133 &hashState, 134 key->size, 135 &key->buffer[0], 136 &hmacKey.b) <= 0) 137 FAIL(FATAL_ERROR_INTERNAL); 138 // Adding counter 139 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); 140 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); 141 // Adding label 142 if(label != NULL) 143 _cpri__UpdateHash(&hashState, lLen, (BYTE *)label); 144 // Adding contextU 145 if(contextU != NULL) 146 _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer); 147 // Adding contextV 148 if(contextV != NULL) 149 _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer); 150 // Adding size in bits 151 UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32); 152 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); 153 // Compute HMAC. At the start of each iteration, hLen is set 154 // to the smaller of hLen and bytes. This causes bytes to decrement 155 // exactly to zero to complete the loop 156 _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream); 157 } 158 // Mask off bits if the required bits is not a multiple of byte size 159 if((sizeInBits % 8) != 0) 160 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); 161 if(counterInOut != NULL) 162 *counterInOut = counter; 163 return (CRYPT_RESULT)((sizeInBits + 7)/8); 164} 165 166UINT16 _cpri__KDFe( 167 TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC 168 TPM2B * Z, // IN: Z 169 const char *label, // IN: a 0 terminated label using in KDF 170 TPM2B * partyUInfo, // IN: PartyUInfo 171 TPM2B * partyVInfo, // IN: PartyVInfo 172 UINT32 sizeInBits, // IN: size of generated key in bit 173 BYTE * keyStream // OUT: key buffer 174 ) 175{ 176 UINT32 counter = 0; // counter value 177 UINT32 lSize = 0; 178 BYTE *stream = keyStream; 179 CPRI_HASH_STATE hashState; 180 INT16 hLen = (INT16) _cpri__GetDigestSize(hashAlg); 181 INT16 bytes; // number of bytes to generate 182 BYTE marshaledUint32[4]; 183 pAssert( keyStream != NULL 184 && Z != NULL 185 && ((sizeInBits + 7) / 8) < INT16_MAX); 186 if(hLen == 0) 187 return 0; 188 bytes = (INT16)((sizeInBits + 7) / 8); 189 // Prepare label buffer. Calculate its size and keep the last 0 byte 190 if(label != NULL) 191 for(lSize = 0; label[lSize++] != 0;); 192 // Generate required bytes 193 //The inner loop of that KDF uses: 194 // Hashi := H(counter | Z | OtherInfo) (5) 195 // Where: 196 // Hashi the hash generated on the i-th iteration of the loop. 197 // H() an approved hash function 198 // counter a 32-bit counter that is initialized to 1 and incremented 199 // on each iteration 200 // Z the X coordinate of the product of a public ECC key and a 201 // different private ECC key. 202 // OtherInfo a collection of qualifying data for the KDF defined below. 203 // In this specification, OtherInfo will be constructed by: 204 // OtherInfo := Use | PartyUInfo | PartyVInfo 205 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) 206 { 207 if(bytes < hLen) 208 hLen = bytes; 209// 210 counter++; 211 // Start hash 212 if(_cpri__StartHash(hashAlg, FALSE, &hashState) == 0) 213 return 0; 214 // Add counter 215 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32); 216 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32); 217 // Add Z 218 if(Z != NULL) 219 _cpri__UpdateHash(&hashState, Z->size, Z->buffer); 220 // Add label 221 if(label != NULL) 222 _cpri__UpdateHash(&hashState, lSize, (BYTE *)label); 223 else 224 // The SP800-108 specification requires a zero between the label 225 // and the context. 226 _cpri__UpdateHash(&hashState, 1, (BYTE *)""); 227 // Add PartyUInfo 228 if(partyUInfo != NULL) 229 _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer); 230 // Add PartyVInfo 231 if(partyVInfo != NULL) 232 _cpri__UpdateHash(&hashState, partyVInfo->size, partyVInfo->buffer); 233 // Compute Hash. hLen was changed to be the smaller of bytes or hLen 234 // at the start of each iteration. 235 _cpri__CompleteHash(&hashState, hLen, stream); 236 } 237 // Mask off bits if the required bits is not a multiple of byte size 238 if((sizeInBits % 8) != 0) 239 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); 240 return (CRYPT_RESULT)((sizeInBits + 7) / 8); 241} 242 243UINT16 _cpri__GenerateSeededRandom( 244 INT32 randomSize, // IN: the size of the request 245 BYTE * random, // OUT: receives the data 246 TPM_ALG_ID hashAlg, // IN: used by KDF version but not here 247 TPM2B * seed, // IN: the seed value 248 const char *label, // IN: a label string (optional) 249 TPM2B * partyU, // IN: other data (oprtional) 250 TPM2B * partyV // IN: still more (optional) 251 ) 252{ 253 return (_cpri__KDFa(hashAlg, seed, label, partyU, partyV, 254 randomSize * 8, random, NULL, FALSE)); 255} 256