/* all in one step */ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { unsigned long hashsize; int err; unsigned char *extracted; /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hashsize = hash_descriptor[hash_idx].hashsize; extracted = XMALLOC(hashsize); /* replace with static buffer? */ if (extracted == NULL) { return CRYPT_MEM; } if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { zeromem(extracted, hashsize); XFREE(extracted); return err; } err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); zeromem(extracted, hashsize); XFREE(extracted); return err; }
int hkdf_derive_secrets(unsigned char* out, enum hkdf_msg_ver_t offset, const unsigned char* in, const size_t inlen, const unsigned char* salt, const size_t saltlen, const unsigned char* info, const size_t infolen, const unsigned outlen) { unsigned char prk[crypto_auth_hmacsha256_BYTES]; hkdf_extract(prk, salt, saltlen, in, inlen); return hkdf_expand(out, offset, prk, sizeof prk, info, infolen, outlen); }
int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, const uint8_t *salt, size_t salt_len, const uint8_t *IKM, size_t IKM_len, const uint8_t *info, size_t info_len) { int result; uint8_t PRK[SHA256_DIGEST_SIZE]; if (!hkdf_extract(PRK, salt, salt_len, IKM, IKM_len)) return 0; result = hkdf_expand(OKM, OKM_len, PRK, info, info_len); memset(PRK, 0, sizeof(PRK)); return result; }
static void test_hkdf_sha1(const struct tstring *ikm, const struct tstring *salt, const struct tstring *info, const struct tstring *extract_output, const struct tstring *expand_output) { struct hmac_sha1_ctx ctx; uint8_t prk[SHA1_DIGEST_SIZE]; uint8_t *buffer = xalloc(expand_output->length); hmac_sha1_set_key(&ctx, salt->length, salt->data); hkdf_extract(&ctx, (nettle_hash_update_func*) hmac_sha1_update, (nettle_hash_digest_func*) hmac_sha1_digest, SHA1_DIGEST_SIZE, ikm->length, ikm->data, prk); if (MEMEQ(SHA1_DIGEST_SIZE, prk, extract_output->data) == 0) { fprintf(stdout, "\nGot:\n"); print_hex(SHA1_DIGEST_SIZE, prk); fprintf(stdout, "\nExpected:\n"); print_hex(extract_output->length, extract_output->data); abort(); } hmac_sha1_set_key(&ctx, SHA1_DIGEST_SIZE, prk); hkdf_expand(&ctx, (nettle_hash_update_func*) hmac_sha1_update, (nettle_hash_digest_func*) hmac_sha1_digest, SHA1_DIGEST_SIZE, info->length, info->data, expand_output->length, buffer); if (MEMEQ(expand_output->length, expand_output->data, buffer) == 0) { fprintf(stdout, "\nGot:\n"); print_hex(expand_output->length, buffer); fprintf(stdout, "\nExpected:\n"); print_hex(expand_output->length, expand_output->data); abort(); } free(buffer); }
bool hkdf(const uint8_t *salt, size_t salt_len, const uint8_t *key, size_t key_len, const uint8_t *info, size_t info_len, uint8_t *out, size_t out_len) { uint8_t prk[HASH_LEN]; HMAC_SHA256_CTX ctx; // Performs the extract phase. Notice that |salt| is used as the key and // |key| as the message. HMAC_SHA256_Init(&ctx, salt, salt_len); HMAC_SHA256_Update(&ctx, key, key_len); HMAC_SHA256_Final(prk, &ctx); // Performs the expand phase. if (!hkdf_expand(prk, HASH_LEN, info, info_len, out, out_len)) return false; explicit_bzero(prk, HASH_LEN); return true; }