summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2016-03-29 20:49:43 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-04-14 17:28:21 -0700
commit533a536140c13bb853e51a62af36bd56c6d85b0d (patch)
tree1e6e4936caaf3f35259c7c0d7f99de6ddd1ea030 /chip
parent9ab5ffaef0b98e797ee6d1e09687c1fa7b4b79fe (diff)
downloadchrome-ec-533a536140c13bb853e51a62af36bd56c6d85b0d.tar.gz
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 <ngm@google.com> Reviewed-on: https://chromium-review.googlesource.com/336091 Commit-Ready: Nagendra Modadugu <ngm@google.com> Tested-by: Nagendra Modadugu <ngm@google.com> Reviewed-by: Marius Schilder <mschilder@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/g/build.mk1
-rw-r--r--chip/g/dcrypto/dcrypto.h8
-rw-r--r--chip/g/dcrypto/hkdf.c79
3 files changed, 88 insertions, 0 deletions
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;
+}