clear-pkgs-linux-iot-lts2018/0036-rpmb-mux-add-HKDF-for-...

228 lines
5.4 KiB
Diff
Raw Permalink Normal View History

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Qi Yadong <yadong.qi@intel.com>
Date: Thu, 18 Oct 2018 15:41:11 +0800
Subject: [PATCH] rpmb: mux: add HKDF for RPMB Mux module
Implement a HKDF (hash based key derivation function)
for RPMB key derivation.
Change-Id: Ic1a0d270c32d9ba101369ef10065b93f5c7ec479
Signed-off-by: Huang, Yang <yang.huang@intel.com>
Signed-off-by: Wei, Xinghai <xinghaix.wei@intel.com>
Signed-off-by: Qi Yadong <yadong.qi@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/char/rpmb/mux/Makefile | 4 +-
drivers/char/rpmb/mux/mux_hkdf.c | 166 +++++++++++++++++++++++++++++++
drivers/char/rpmb/mux/mux_hkdf.h | 14 +++
3 files changed, 183 insertions(+), 1 deletion(-)
create mode 100644 drivers/char/rpmb/mux/mux_hkdf.c
create mode 100644 drivers/char/rpmb/mux/mux_hkdf.h
diff --git a/drivers/char/rpmb/mux/Makefile b/drivers/char/rpmb/mux/Makefile
2020-10-27 02:14:06 +08:00
index 7afc458a0dd2..23234a88aa73 100644
--- a/drivers/char/rpmb/mux/Makefile
+++ b/drivers/char/rpmb/mux/Makefile
@@ -1,3 +1,5 @@
-obj-$(CONFIG_RPMB_MUX) += mux.o
+obj-$(CONFIG_RPMB_MUX) += rpmb_mux.o
+rpmb_mux-objs := mux.o
+rpmb_mux-objs += mux_hkdf.o
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/char/rpmb/mux/mux_hkdf.c b/drivers/char/rpmb/mux/mux_hkdf.c
new file mode 100644
2020-10-27 02:14:06 +08:00
index 000000000000..d4234924148e
--- /dev/null
+++ b/drivers/char/rpmb/mux/mux_hkdf.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * RPMB Mux HKDF
+ *
+ * Copyright (c) 2018 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/compat.h>
+#include <crypto/hash.h>
+#include "mux_hkdf.h"
+
+static int mux_sha256_extract(u8 *out_key, size_t out_len,
+ struct shash_desc *desc,
+ const u8 *secret, size_t secret_len,
+ const u8 *salt, size_t salt_len)
+{
+ int ret;
+ u8 salt0[SHA256_HASH_SIZE];
+
+ if (!salt || !salt_len) {
+ memset(salt0, 0, sizeof(salt0));
+ salt = salt0;
+ salt_len = sizeof(salt0);
+ }
+
+ ret = crypto_shash_setkey(desc->tfm, salt, salt_len);
+ if (ret) {
+ pr_err("set key failed = %d\n", ret);
+ goto out;
+ }
+
+ ret = crypto_shash_init(desc);
+ if (ret)
+ goto out;
+
+ ret = crypto_shash_update(desc, secret, secret_len);
+ if (ret)
+ goto out;
+
+ ret = crypto_shash_final(desc, out_key);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+static int mux_sha256_expand(u8 *out_key, size_t out_len,
+ struct shash_desc *desc,
+ const u8 *prk, size_t prk_len,
+ const u8 *info, size_t info_len)
+{
+ const size_t digest_len = SHA256_HASH_SIZE;
+ u8 previous[SHA256_HASH_SIZE];
+ size_t n, done = 0;
+ unsigned int i;
+ int ret = 0;
+
+ n = (out_len + digest_len - 1) / digest_len;
+
+ /* check for possible integer overflow */
+ if (out_len + digest_len < out_len)
+ return 0;
+
+ if (n > 255)
+ return 0;
+
+ for (i = 0; i < n; i++) {
+ u8 ctr = i + 1;
+ size_t todo;
+
+ ret = crypto_shash_setkey(desc->tfm, prk, prk_len);
+ if (ret)
+ goto out;
+
+ ret = crypto_shash_init(desc);
+ if (ret)
+ goto out;
+
+ if (i != 0 && crypto_shash_update(desc, previous, digest_len))
+ goto out;
+
+ if (crypto_shash_update(desc, info, info_len) ||
+ crypto_shash_update(desc, &ctr, 1) ||
+ crypto_shash_final(desc, previous)) {
+ ret = -EPERM;
+ goto out;
+ }
+
+ todo = digest_len;
+ /* Check if the length of left buffer is smaller than
+ * 32 to make sure no buffer overflow in below memcpy
+ */
+ if (done + todo > out_len)
+ todo = out_len - done;
+
+ memcpy(out_key + done, previous, todo);
+ done += todo;
+ }
+
+out:
+ memset(previous, 0, sizeof(previous));
+
+ return ret;
+}
+
+static struct shash_desc *mux_hkdf_init_hmac_sha256_desc(void)
+{
+ struct shash_desc *desc;
+ struct crypto_shash *tfm;
+
+ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+ if (IS_ERR(tfm))
+ return ERR_PTR(-EFAULT);
+
+ desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
+ if (!desc) {
+ crypto_free_shash(tfm);
+ return ERR_PTR(-ENOMEM);
+ }
+ desc->tfm = tfm;
+
+ return desc;
+}
+
+int mux_hkdf_sha256(u8 *out_key, size_t out_len,
+ const u8 *secret, size_t secret_len,
+ const u8 *salt, size_t salt_len,
+ const u8 *info, size_t info_len)
+{
+ u8 prk[SHA256_HASH_SIZE];
+ size_t prk_len = SHA256_HASH_SIZE;
+ int ret;
+ struct shash_desc *desc;
+
+ if (!out_key || !out_len)
+ return -EINVAL;
+
+ if (!secret || !secret_len)
+ return -EINVAL;
+
+ if (!info && info_len)
+ return -EINVAL;
+
+ desc = mux_hkdf_init_hmac_sha256_desc();
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ memset(prk, 0, sizeof(prk));
+
+ ret = mux_sha256_extract(prk, prk_len, desc,
+ secret, secret_len,
+ salt, salt_len);
+ if (ret)
+ goto err_free_shash;
+
+ ret = mux_sha256_expand(out_key, out_len, desc,
+ prk, prk_len,
+ info, info_len);
+
+err_free_shash:
+ crypto_free_shash(desc->tfm);
+ kfree(desc);
+
+ return ret;
+}
diff --git a/drivers/char/rpmb/mux/mux_hkdf.h b/drivers/char/rpmb/mux/mux_hkdf.h
new file mode 100644
2020-10-27 02:14:06 +08:00
index 000000000000..0055884054c2
--- /dev/null
+++ b/drivers/char/rpmb/mux/mux_hkdf.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/*
+ * Copyright (C) 2018 Intel Corp. All rights reserved
+ */
+#ifndef _MUX_HKDF_H
+#define _MUX_HKDF_H
+
+#define SHA256_HASH_SIZE 32
+
+int mux_hkdf_sha256(u8 *out_key, size_t out_len,
+ const u8 *secret, size_t secret_len,
+ const u8 *salt, size_t salt_len,
+ const u8 *info, size_t info_len);
+#endif /* !_MUX_HKDF_H */
--
https://clearlinux.org