From 533a536140c13bb853e51a62af36bd56c6d85b0d Mon Sep 17 00:00:00 2001 From: nagendra modadugu Date: Tue, 29 Mar 2016 20:49:43 -0700 Subject: CR50: add support for HKDF (RFC 5869) Add support for SHA256 based HKDF key derivation as specified in RFC 5869. This change includes test vectors from the RFC. BRANCH=none BUG=chrome-os-partner:43025,chrome-os-partner:47524 TEST=tests under test/tpm2 pass Change-Id: I7d0e4e92775b74c41643f45587fc08f56d8916aa Signed-off-by: nagendra modadugu Reviewed-on: https://chromium-review.googlesource.com/336091 Commit-Ready: Nagendra Modadugu Tested-by: Nagendra Modadugu Reviewed-by: Marius Schilder --- chip/g/build.mk | 1 + chip/g/dcrypto/dcrypto.h | 8 +++++ chip/g/dcrypto/hkdf.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 chip/g/dcrypto/hkdf.c (limited to 'chip') diff --git a/chip/g/build.mk b/chip/g/build.mk index 6a279417a8..97589c7fd6 100644 --- a/chip/g/build.mk +++ b/chip/g/build.mk @@ -29,6 +29,7 @@ endif chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o chip-$(CONFIG_DCRYPTO)+= dcrypto/bn.o chip-$(CONFIG_DCRYPTO)+= dcrypto/hmac.o +chip-$(CONFIG_DCRYPTO)+= dcrypto/hkdf.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ec.o chip-$(CONFIG_DCRYPTO)+= dcrypto/p256_ecdsa.o diff --git a/chip/g/dcrypto/dcrypto.h b/chip/g/dcrypto/dcrypto.h index a412adee5a..c333d93fee 100644 --- a/chip/g/dcrypto/dcrypto.h +++ b/chip/g/dcrypto/dcrypto.h @@ -141,4 +141,12 @@ int DCRYPTO_p256_ecdsa_verify(const p256_int *key_x, const p256_int *key_y, const p256_int *digest, const p256_int *r, const p256_int *s); +/* + * HKDF. + */ +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); + #endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */ diff --git a/chip/g/dcrypto/hkdf.c b/chip/g/dcrypto/hkdf.c new file mode 100644 index 0000000000..db861ec318 --- /dev/null +++ b/chip/g/dcrypto/hkdf.c @@ -0,0 +1,79 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* An implementation of HKDF as per RFC 5869. */ + +#include "dcrypto.h" +#include "internal.h" + +static int hkdf_extract(uint8_t *PRK, const uint8_t *salt, size_t salt_len, + const uint8_t *IKM, size_t IKM_len) +{ + struct HMAC_CTX ctx; + + if (PRK == NULL) + return 0; + if (salt == NULL && salt_len > 0) + return 0; + if (IKM == NULL && IKM_len > 0) + return 0; + + dcrypto_HMAC_SHA256_init(&ctx, salt, salt_len); + dcrypto_HMAC_update(&ctx, IKM, IKM_len); + memcpy(PRK, dcrypto_HMAC_final(&ctx), SHA256_DIGEST_BYTES); + return 1; +} + +static int hkdf_expand(uint8_t *OKM, size_t OKM_len, const uint8_t *PRK, + const uint8_t *info, size_t info_len) +{ + uint8_t count = 1; + const uint8_t *T = OKM; + size_t T_len = 0; + uint32_t num_blocks = (OKM_len / SHA256_DIGEST_BYTES) + + (OKM_len % SHA256_DIGEST_BYTES ? 1 : 0); + + if (OKM == NULL || OKM_len == 0) + return 0; + if (PRK == NULL) + return 0; + if (info == NULL && info_len > 0) + return 0; + if (num_blocks > 255) + return 0; + + while (OKM_len > 0) { + struct HMAC_CTX ctx; + const size_t block_size = MIN(OKM_len, SHA256_DIGEST_BYTES); + + dcrypto_HMAC_SHA256_init(&ctx, PRK, SHA256_DIGEST_BYTES); + dcrypto_HMAC_update(&ctx, T, T_len); + dcrypto_HMAC_update(&ctx, info, info_len); + dcrypto_HMAC_update(&ctx, &count, sizeof(count)); + memcpy(OKM, dcrypto_HMAC_final(&ctx), block_size); + + T += T_len; + T_len = SHA256_DIGEST_BYTES; + count += 1; + OKM += block_size; + OKM_len -= block_size; + } + return 1; +} + +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_BYTES]; + + 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; +} -- cgit v1.2.1