int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { word32 i = 1; int hLen; int j, ret; Hmac hmac; byte buffer[MAX_DIGEST_SIZE]; if (hashType == MD5) { hLen = MD5_DIGEST_SIZE; } else if (hashType == SHA) { hLen = SHA_DIGEST_SIZE; } #ifndef NO_SHA256 else if (hashType == SHA256) { hLen = SHA256_DIGEST_SIZE; } #endif #ifdef CYASSL_SHA512 else if (hashType == SHA512) { hLen = SHA512_DIGEST_SIZE; } #endif else return BAD_FUNC_ARG; ret = HmacSetKey(&hmac, hashType, passwd, pLen); if (ret != 0) return ret; while (kLen) { int currentLen; HmacUpdate(&hmac, salt, sLen); /* encode i */ for (j = 0; j < 4; j++) { byte b = (byte)(i >> ((3-j) * 8)); HmacUpdate(&hmac, &b, 1); } HmacFinal(&hmac, buffer); currentLen = min(kLen, hLen); XMEMCPY(output, buffer, currentLen); for (j = 1; j < iterations; j++) { HmacUpdate(&hmac, buffer, hLen); HmacFinal(&hmac, buffer); xorbuf(output, buffer, currentLen); } output += currentLen; kLen -= currentLen; i++; } return 0; }
/* calc the hmac of data+sid+mtime */ static int session_client_hmac(HMAC_CTX *ctx, char *hmac, size_t hmac_sz, const char *data, const char *sid, const char *mtime, const char *hex_iv) { char mac[EVP_MAX_MD_SIZE]; int mac_len; dbg_err_if (ctx == NULL); dbg_err_if (hmac == NULL); dbg_err_if (data == NULL); dbg_err_if (sid == NULL); dbg_err_if (mtime == NULL); /* hex_iv may be NULL */ #if SSL_OPENSSL /* hmac must be at least 'EVP_MAX_MD_SIZE*2 + 1' (it will be hex encoded) */ dbg_err_if(hmac_sz < EVP_MAX_MD_SIZE*2 + 1); /* calc HMAC hash of the data buf + mtime (reuse stored key and md) */ HMAC_Init_ex(ctx, NULL, 0, NULL, NULL); HMAC_Update(ctx, data, strlen(data)); HMAC_Update(ctx, sid, strlen(sid)); HMAC_Update(ctx, mtime, strlen(mtime)); if(hex_iv) HMAC_Update(ctx, hex_iv, strlen(hex_iv)); HMAC_Final(ctx, mac, &mac_len); #endif #ifdef SSL_CYASSL HmacUpdate(ctx, (const byte*)data, strlen(data)); HmacUpdate(ctx, (const byte*)sid, strlen(sid)); HmacUpdate(ctx, (const byte*)mtime, strlen(mtime)); if(hex_iv) HmacUpdate(ctx, (const byte*)hex_iv, strlen(hex_iv)); HmacFinal(ctx, (byte*)mac); if (ctx->macType == MD5) mac_len = MD5_DIGEST_SIZE; else if (ctx->macType == SHA) mac_len = SHA_DIGEST_SIZE; else crit_err("unknown hash"); #endif /* encode the hash */ dbg_err_if(u_hexncpy(hmac, mac, mac_len, HEXCPY_ENCODE) <= 0); return 0; err: return -1; }
void HmacImpl<HASH,DRBGINFO>::HmacReseed(const byte* seed, size_t ssize) { ASSERT(DigestLength == m_v.size()); ASSERT(DigestLength == m_k.size()); ASSERT(seed && ssize); if(!seed || !ssize) throw IllegalArgumentException("Unable to reseed hmac drbg. The seed buffer or size is not valid"); try { // To reseed, we use {entropy || additional data}. // For this operation, we only need SeedLength (see Section 8.6.7). // Additional data optional, but should be present because the // setSeed interfaces require bits const size_t msize /*seed material size*/ = SeedLength; CryptoPP::SecByteBlock material(msize + ssize); RandomPool::GetSharedInstance().GenerateBlock(material.data(), msize); // Copy in the user provided "personalization" if(seed && ssize) ::memcpy(material.data()+msize, seed, ssize); HmacUpdate(material.data(), material.size()); } catch(CryptoPP::Exception& ex) { m_catastrophic = true; throw EncryptionException(NarrowString("Internal error: ") + ex.what()); } }
int hmac_sha256_test(void) { Hmac hmac; byte hash[SHA256_DIGEST_SIZE]; const char* keys[]= { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA" }; testVector a, b, c; testVector test_hmac[3]; int times = sizeof(test_hmac) / sizeof(testVector), i; a.input = "Hi There"; a.output = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1" "\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32" "\xcf\xf7"; a.inLen = strlen(a.input); a.outLen = strlen(a.output); b.input = "what do ya want for nothing?"; b.output = "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75" "\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec" "\x38\x43"; b.inLen = strlen(b.input); b.outLen = strlen(b.output); c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81" "\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5" "\x65\xfe"; c.inLen = strlen(c.input); c.outLen = strlen(c.output); test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { HmacSetKey(&hmac, SHA256, (byte*)keys[i], (word32)strlen(keys[i])); HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); HmacFinal(&hmac, hash); if (memcmp(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) return -20 - i; } return 0; }
int CRYPT_HMAC_DataAdd(CRYPT_HMAC_CTX* hmac, const unsigned char* input, unsigned int sz) { if (hmac == NULL || input == NULL) return BAD_FUNC_ARG; return HmacUpdate((Hmac*)hmac, input, sz); }
int hmac_sha_test(void) { Hmac hmac; byte hash[SHA_DIGEST_SIZE]; const char* keys[]= { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA" }; testVector a, b, c; testVector test_hmac[3]; int times = sizeof(test_hmac) / sizeof(testVector), i; a.input = "Hi There"; a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c" "\x8e\xf1\x46\xbe\x00"; a.inLen = strlen(a.input); a.outLen = strlen(a.output); b.input = "what do ya want for nothing?"; b.output = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf" "\x9c\x25\x9a\x7c\x79"; b.inLen = strlen(b.input); b.outLen = strlen(b.output); c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b" "\x4f\x63\xf1\x75\xd3"; c.inLen = strlen(c.input); c.outLen = strlen(c.output); test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)strlen(keys[i])); HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); HmacFinal(&hmac, hash); if (memcmp(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) return -20 - i; } return 0; }
int hmac_test() { Hmac hmac; byte hash[MD5_DIGEST_SIZE]; const char* keys[]= { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" }; testVector a, b, c; testVector test_hmac[3]; int times = sizeof(test_hmac) / sizeof(testVector), i; a.input = "Hi There"; a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" "\x9d"; a.inLen = strlen(a.input); a.outLen = strlen(a.output); b.input = "what do ya want for nothing?"; b.output = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7" "\x38"; b.inLen = strlen(b.input); b.outLen = strlen(b.output); c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3" "\xf6"; c.inLen = strlen(c.input); c.outLen = strlen(c.output); test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)strlen(keys[i])); HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); HmacFinal(&hmac, hash); if (memcmp(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) return -20 - i; } return 0; }
/* compute p_hash for MD5, SHA-1, or SHA-256 for TLSv1 PRF */ static void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) { word32 len = hash == md5_mac ? MD5_DIGEST_SIZE : hash == sha_mac ? SHA_DIGEST_SIZE : SHA256_DIGEST_SIZE; word32 times = resLen / len; word32 lastLen = resLen % len; word32 lastTime; word32 i; word32 idx = 0; byte previous[SHA256_DIGEST_SIZE]; /* max size */ byte current[SHA256_DIGEST_SIZE]; /* max size */ Hmac hmac; if (lastLen) times += 1; lastTime = times - 1; HmacSetKey(&hmac, hash == md5_mac ? MD5 : hash == sha_mac ? SHA : SHA256, secret, secLen); HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ HmacFinal(&hmac, previous); /* A1 */ for (i = 0; i < times; i++) { HmacUpdate(&hmac, previous, len); HmacUpdate(&hmac, seed, seedLen); HmacFinal(&hmac, current); if ( (i == lastTime) && lastLen) XMEMCPY(&result[idx], current, lastLen); else { XMEMCPY(&result[idx], current, len); idx += len; HmacUpdate(&hmac, previous, len); HmacFinal(&hmac, previous); } } }
void HmacImpl<HASH,DRBGINFO>::HmacInstantiate(const byte* seed, size_t ssize) { ASSERT(DigestLength == m_v.size()); ASSERT(DigestLength == m_k.size()); ASSERT(seed && ssize); if(!seed || !ssize) throw IllegalArgumentException("Unable to instatiate hmac drbg. The seed buffer or size is not valid"); try { ::memset(m_k.data(), 0x00, m_k.size()); ::memset(m_v.data(), 0x01, m_v.size()); m_hmac.SetKey(m_k.data(), m_k.size()); HmacUpdate(seed, ssize); } catch(CryptoPP::Exception& ex) { m_catastrophic = true; throw EncryptionException(NarrowString("Internal error: ") + ex.what()); } }
/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ static void p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) { word32 len = PHASH_MAX_DIGEST_SIZE; word32 times; word32 lastLen; word32 lastTime; word32 i; word32 idx = 0; byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */ byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */ Hmac hmac; switch (hash) { #ifndef NO_MD5 case md5_mac: { len = MD5_DIGEST_SIZE; hash = MD5; } break; #endif #ifndef NO_SHA256 case sha256_mac: { len = SHA256_DIGEST_SIZE; hash = SHA256; } break; #endif #ifdef CYASSL_SHA384 case sha384_mac: { len = SHA384_DIGEST_SIZE; hash = SHA384; } break; #endif #ifndef NO_SHA case sha_mac: default: { len = SHA_DIGEST_SIZE; hash = SHA; } break; #endif } times = resLen / len; lastLen = resLen % len; if (lastLen) times += 1; lastTime = times - 1; HmacSetKey(&hmac, hash, secret, secLen); HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ HmacFinal(&hmac, previous); /* A1 */ for (i = 0; i < times; i++) { HmacUpdate(&hmac, previous, len); HmacUpdate(&hmac, seed, seedLen); HmacFinal(&hmac, current); if ( (i == lastTime) && lastLen) XMEMCPY(&result[idx], current, min(lastLen, sizeof(current))); else { XMEMCPY(&result[idx], current, len); idx += len; HmacUpdate(&hmac, previous, len); HmacFinal(&hmac, previous); } } XMEMSET(previous, 0, sizeof previous); XMEMSET(current, 0, sizeof current); XMEMSET(&hmac, 0, sizeof hmac); }
/* check mcapi hmac against internal */ static int check_hmac(void) { CRYPT_HMAC_CTX mcHmac; Hmac defHmac; byte mcDigest[CRYPT_SHA512_DIGEST_SIZE]; byte defDigest[SHA512_DIGEST_SIZE]; strncpy((char*)key, "Jefe", 4); /* SHA1 */ CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA, key, 4); HmacSetKey(&defHmac, SHA, key, 4); CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); CRYPT_HMAC_Finalize(&mcHmac, mcDigest); HmacFinal(&defHmac, defDigest); if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { printf("hmac sha final memcmp fialed\n"); return -1; } printf("hmac sha mcapi test passed\n"); /* SHA-256 */ CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA256, key, 4); HmacSetKey(&defHmac, SHA256, key, 4); CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); CRYPT_HMAC_Finalize(&mcHmac, mcDigest); HmacFinal(&defHmac, defDigest); if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { printf("hmac sha256 final memcmp fialed\n"); return -1; } printf("hmac sha256 mcapi test passed\n"); /* SHA-384 */ CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA384, key, 4); HmacSetKey(&defHmac, SHA384, key, 4); CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); CRYPT_HMAC_Finalize(&mcHmac, mcDigest); HmacFinal(&defHmac, defDigest); if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { printf("hmac sha384 final memcmp fialed\n"); return -1; } printf("hmac sha384 mcapi test passed\n"); /* SHA-512 */ CRYPT_HMAC_SetKey(&mcHmac, CRYPT_HMAC_SHA512, key, 4); HmacSetKey(&defHmac, SHA512, key, 4); CRYPT_HMAC_DataAdd(&mcHmac, ourData, OUR_DATA_SIZE); HmacUpdate(&defHmac, ourData, OUR_DATA_SIZE); CRYPT_HMAC_Finalize(&mcHmac, mcDigest); HmacFinal(&defHmac, defDigest); if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { printf("hmac sha512 final memcmp fialed\n"); return -1; } printf("hmac sha512 mcapi test passed\n"); return 0; }
int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { word32 i = 1; int hLen; int j, ret; Hmac hmac; #ifdef CYASSL_SMALL_STACK byte* buffer; #else byte buffer[MAX_DIGEST_SIZE]; #endif if (hashType == MD5) { hLen = MD5_DIGEST_SIZE; } else if (hashType == SHA) { hLen = SHA_DIGEST_SIZE; } #ifndef NO_SHA256 else if (hashType == SHA256) { hLen = SHA256_DIGEST_SIZE; } #endif #ifdef CYASSL_SHA512 else if (hashType == SHA512) { hLen = SHA512_DIGEST_SIZE; } #endif else return BAD_FUNC_ARG; #ifdef CYASSL_SMALL_STACK buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (buffer == NULL) return MEMORY_E; #endif ret = HmacSetKey(&hmac, hashType, passwd, pLen); if (ret == 0) { while (kLen) { int currentLen; ret = HmacUpdate(&hmac, salt, sLen); if (ret != 0) break; /* encode i */ for (j = 0; j < 4; j++) { byte b = (byte)(i >> ((3-j) * 8)); ret = HmacUpdate(&hmac, &b, 1); if (ret != 0) break; } /* check ret from inside for loop */ if (ret != 0) break; ret = HmacFinal(&hmac, buffer); if (ret != 0) break; currentLen = min(kLen, hLen); XMEMCPY(output, buffer, currentLen); for (j = 1; j < iterations; j++) { ret = HmacUpdate(&hmac, buffer, hLen); if (ret != 0) break; ret = HmacFinal(&hmac, buffer); if (ret != 0) break; xorbuf(output, buffer, currentLen); } /* check ret from inside for loop */ if (ret != 0) break; output += currentLen; kLen -= currentLen; i++; } } #ifdef CYASSL_SMALL_STACK XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; }
int hmac_sha384_test(void) { Hmac hmac; byte hash[SHA384_DIGEST_SIZE]; const char* keys[]= { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "Jefe", "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" "\xAA\xAA\xAA" }; testVector a, b, c; testVector test_hmac[3]; int ret; int times = sizeof(test_hmac) / sizeof(testVector), i; a.input = "Hi There"; a.output = "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90" "\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb" "\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2" "\xfa\x9c\xb6"; a.inLen = strlen(a.input); a.outLen = strlen(a.output); b.input = "what do ya want for nothing?"; b.output = "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b" "\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22" "\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa" "\xb2\x16\x49"; b.inLen = strlen(b.input); b.outLen = strlen(b.output); c.input = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" "\xDD\xDD\xDD\xDD\xDD\xDD"; c.output = "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8" "\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66" "\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01" "\xa3\x4f\x27"; c.inLen = strlen(c.input); c.outLen = strlen(c.output); test_hmac[0] = a; test_hmac[1] = b; test_hmac[2] = c; for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) continue; /* fips not allowed */ #endif ret = HmacSetKey(&hmac,SHA384, (byte*)keys[i], (word32)strlen(keys[i])); if (ret != 0) return -4023; ret = HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) return -4024; ret = HmacFinal(&hmac, hash); if (ret != 0) return -4025; if (memcmp(hash, test_hmac[i].output, SHA384_DIGEST_SIZE) != 0) return -20 - i; } return 0; }
/* HMAC-KDF with hash type, optional salt and info, return 0 on success */ int HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, byte* out, word32 outSz) { Hmac myHmac; #ifdef CYASSL_SMALL_STACK byte* tmp; byte* prk; #else byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ byte prk[MAX_DIGEST_SIZE]; #endif const byte* localSalt; /* either points to user input or tmp */ int hashSz = GetHashSizeByType(type); word32 outIdx = 0; byte n = 0x1; int ret; if (hashSz < 0) return BAD_FUNC_ARG; #ifdef CYASSL_SMALL_STACK tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (prk == NULL) { XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #endif localSalt = salt; if (localSalt == NULL) { XMEMSET(tmp, 0, hashSz); localSalt = tmp; saltSz = hashSz; } do { ret = HmacSetKey(&myHmac, type, localSalt, saltSz); if (ret != 0) break; ret = HmacUpdate(&myHmac, inKey, inKeySz); if (ret != 0) break; ret = HmacFinal(&myHmac, prk); } while (0); if (ret == 0) { while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; ret = HmacSetKey(&myHmac, type, prk, hashSz); if (ret != 0) break; ret = HmacUpdate(&myHmac, tmp, tmpSz); if (ret != 0) break; ret = HmacUpdate(&myHmac, info, infoSz); if (ret != 0) break; ret = HmacUpdate(&myHmac, &n, 1); if (ret != 0) break; ret = HmacFinal(&myHmac, tmp); if (ret != 0) break; left = min(left, (word32)hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } } #ifdef CYASSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; }