All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20  5:46 ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:46 UTC (permalink / raw)
  To: dhowells, zohar, jmorris, serge, linux-integrity, keyrings,
	linux-security-module, linux-kernel
  Cc: sahil.malhotra, Udit Agarwal

Secure keys are derieved using CAAM crypto block.

Secure keys derieved are the random number symmetric keys from CAAM.
Blobs corresponding to the key are formed using CAAM. User space
will only be able to view the blob of the key.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 Documentation/security/keys/secure-key.rst |  67 +++
 MAINTAINERS                                |  11 +
 include/keys/secure-type.h                 |  33 ++
 security/keys/Kconfig                      |  11 +
 security/keys/Makefile                     |   3 +
 security/keys/secure_key.c                 | 339 ++++++++++++
 security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
 security/keys/securekey_desc.h             | 141 +++++
 8 files changed, 1211 insertions(+)
 create mode 100644 Documentation/security/keys/secure-key.rst
 create mode 100644 include/keys/secure-type.h
 create mode 100644 security/keys/secure_key.c
 create mode 100644 security/keys/securekey_desc.c
 create mode 100644 security/keys/securekey_desc.h

diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
new file mode 100644
index 000000000000..0fc3367b00f8
--- /dev/null
+++ b/Documentation/security/keys/secure-key.rst
@@ -0,0 +1,67 @@
+==========
+Secure Key
+==========
+
+Secure key is the new type added to kernel key ring service.
+Secure key is a symmetric type key of minimum length 32 bytes
+and with maximum possible length to be 128 bytes. It is produced
+in kernel using the CAAM crypto engine. Userspace can only see
+the blob for the corresponding key. All the blobs are displayed
+or loaded in hex ascii.
+
+Secure key can only be created on platforms which supports CAAM
+hardware block. Secure key can also be used as a master key to
+create the encrypted keys along with the existing key types in
+kernel.
+
+Secure key uses CAAM hardware to generate the key and blobify its
+content for userspace. Generated blobs are tied up with the hardware
+secret key stored in CAAM, hence the same blob will not be able to
+de-blobify with the different secret key on another machine.
+
+Usage::
+
+	keyctl add secure <name> "new <keylen>" <ring>
+	keyctl load secure <name> "load <hex_blob>" <ring>
+	keyctl print <key_id>
+
+"keyctl add secure" option will create the random data of the
+specified key len using CAAM and store it as a key in kernel.
+Key contents will be displayed as blobs to the user in hex ascii.
+User can input key len from 32 bytes to 128 bytes.
+
+"keyctl load secure" option will load the blob contents. In kernel,
+key will be deirved using input blob and CAAM, along with the secret
+key stored in CAAM.
+
+"keyctl print" will return the hex string of the blob corresponding to
+key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
+the header bytes added by the CAAM.
+
+Example of secure key usage::
+
+1. Create the secure key with name kmk-master of length 32 bytes::
+
+	$ keyctl add secure kmk-master "new 32" @u
+	46001928
+
+	$keyctl show
+	Session Keyring
+	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
+	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
+	  46001928 --als-rv      0     0       \_ secure: kmk-master
+
+2. Print the blob contents for the kmk-master key::
+
+	$ keyctl print 46001928
+	d9743445b640f3d59c1670dddc0bc9c2
+	34fc9aab7dd05c965e6120025012f029b
+	07faa4776c4f6ed02899e35a135531e9a
+	6e5c2b51132f9d5aef28f68738e658296
+	3fe583177cfe50d2542b659a13039
+
+	$ keyctl pipe 46001928 > secure_key.blob
+
+3. Load the blob in the user key ring::
+
+	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
diff --git a/MAINTAINERS b/MAINTAINERS
index 9fd5e8808208..654be2ee4b0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
 F:	security/keys/trusted.c
 F:	security/keys/trusted.h
 
+KEYS-SECURE
+M:	Udit Agarwal <udit.agarwal@nxp.com>
+R:	Sahil Malhotra <sahil.malhotra@nxp.com>
+L:	linux-security-module@vger.kernel.org
+L:	keyrings@vger.kernel.org
+S:	Supported
+F:	include/keys/secure-type.h
+F:	security/keys/secure_key.c
+F:	security/keys/securekey_desc.c
+F:	security/keys/securekey_desc.h
+
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
 L:	keyrings@vger.kernel.org
diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
new file mode 100644
index 000000000000..5b7a5f144e41
--- /dev/null
+++ b/include/keys/secure-type.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#ifndef _KEYS_SECURE_TYPE_H
+#define _KEYS_SECURE_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+/* Minimum key size to be used is 32 bytes and maximum key size fixed
+ * is 128 bytes.
+ * Blob size to be kept is Maximum key size + blob header added by CAAM.
+ */
+
+#define MIN_KEY_SIZE                    32
+#define MAX_KEY_SIZE                    128
+#define BLOB_HEADER_SIZE		48
+
+#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
+
+struct secure_key_payload {
+	struct rcu_head rcu;
+	unsigned int key_len;
+	unsigned int blob_len;
+	unsigned char key[MAX_KEY_SIZE + 1];
+	unsigned char blob[MAX_BLOB_SIZE];
+};
+
+extern struct key_type key_type_secure;
+#endif
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 6462e6654ccf..7eb138b5a54f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -71,6 +71,17 @@ config TRUSTED_KEYS
 
 	  If you are unsure as to whether this is required, answer N.
 
+config SECURE_KEYS
+	tristate "SECURE_KEYS"
+	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	help
+	  This option provide support for creating secure-type key and blobs
+	  in kernel. Secure keys are random number symmetric keys generated
+	  from CAAM. The CAAM creates the blobs for the random key.
+	  Userspace will only be able to see the blob.
+
+	  If you are unsure as to whether this is required, answer N.
+
 config ENCRYPTED_KEYS
 	tristate "ENCRYPTED KEYS"
 	depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ef1581b337a3..606ba4efb9e6 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
 #
 obj-$(CONFIG_BIG_KEYS) += big_key.o
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
+obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
+obj-$(CONFIG_SECURE_KEYS) += secure_key.o
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
new file mode 100644
index 000000000000..ec8ad4394549
--- /dev/null
+++ b/security/keys/secure_key.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2018 NXP
+ * Secure key is generated using NXP CAAM hardware block. CAAM generates the
+ * random number (used as a key) and creates its blob for the user.
+ */
+
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <keys/secure-type.h>
+#include <linux/completion.h>
+
+#include "securekey_desc.h"
+
+static const char hmac_alg[] = "hmac(sha1)";
+static const char hash_alg[] = "sha1";
+
+static struct crypto_shash *hashalg;
+static struct crypto_shash *hmacalg;
+
+enum {
+	error = -1,
+	new_key,
+	load_blob,
+};
+
+static const match_table_t key_tokens = {
+	{new_key, "new"},
+	{load_blob, "load"},
+	{error, NULL}
+};
+
+static struct secure_key_payload *secure_payload_alloc(struct key *key)
+{
+	struct secure_key_payload *sec_key = NULL;
+	int ret = 0;
+
+	ret = key_payload_reserve(key, sizeof(*sec_key));
+	if (ret < 0)
+		goto out;
+
+	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
+	if (!sec_key)
+		goto out;
+
+out:
+	return sec_key;
+}
+
+/*
+ * parse_inputdata - parse the keyctl input data and fill in the
+ *		     payload structure for key or its blob.
+ * param[in]: data pointer to the data to be parsed for creating key.
+ * param[in]: p pointer to secure key payload structure to fill parsed data
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int parse_inputdata(char *data, struct secure_key_payload *p)
+{
+	substring_t args[MAX_OPT_ARGS];
+	long keylen = 0;
+	int ret = -EINVAL;
+	int key_cmd = -EINVAL;
+	char *c = NULL;
+
+	c = strsep(&data, " \t");
+	if (!c) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Get the keyctl command i.e. new_key or load_blob etc */
+	key_cmd = match_token(c, key_tokens, args);
+
+	switch (key_cmd) {
+	case new_key:
+		/* first argument is key size */
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = kstrtol(c, 10, &keylen);
+		if (ret < 0 || keylen < MIN_KEY_SIZE ||
+						keylen > MAX_KEY_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		p->key_len = keylen;
+		ret = new_key;
+
+		break;
+	case load_blob:
+		/* first argument is blob data for CAAM*/
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* Blob_len = No of characters in blob/2 */
+		p->blob_len = strlen(c) / 2;
+		if (p->blob_len > MAX_BLOB_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = hex2bin(p->blob, c, p->blob_len);
+		if (ret < 0) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = load_blob;
+
+		break;
+	case error:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+
+/*
+ * secure_instantiate - create a new secure type key.
+ * Supports the operation to generate a new key. A random number
+ * is generated from CAAM as key data and the corresponding red blob
+ * is formed and stored as key_blob.
+ * Also supports the operation to load the blob and key is derived using
+ * that blob from CAAM.
+ * On success, return 0. Otherwise return errno.
+ */
+static int secure_instantiate(struct key *key,
+		struct key_preparsed_payload *prep)
+{
+	struct secure_key_payload *payload = NULL;
+	size_t datalen = prep->datalen;
+	char *data = NULL;
+	int key_cmd = 0;
+	int ret = 0;
+	enum sk_req_type sk_op_type;
+	struct device *dev = NULL;
+
+	if (datalen <= 0 || datalen > 32767 || !prep->data) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(data, prep->data, datalen);
+	data[datalen] = '\0';
+
+	payload = secure_payload_alloc(key);
+	if (!payload) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Allocate caam job ring for operation to be performed from CAAM */
+	dev = caam_jr_alloc();
+	if (!dev) {
+		pr_info("caam_jr_alloc failed\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	key_cmd = parse_inputdata(data, payload);
+	if (key_cmd < 0) {
+		ret = key_cmd;
+		goto out;
+	}
+
+	switch (key_cmd) {
+	case load_blob:
+		/*
+		 * Red blob decryption to be done for load operation
+		 * to derive the key.
+		 */
+		sk_op_type = sk_red_blob_dec;
+		ret = key_deblob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	case new_key:
+		/* Get Random number from caam of the specified length */
+		sk_op_type = sk_get_random;
+		ret = caam_get_random(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: get_random fail (%d)\n", ret);
+			goto out;
+		}
+
+		/* Generate red blob of key random bytes with CAAM */
+		sk_op_type = sk_red_blob_enc;
+		ret = key_blob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	if (data)
+		kzfree(data);
+	if (dev)
+		caam_jr_free(dev);
+
+	if (!ret)
+		rcu_assign_keypointer(key, payload);
+	else
+		kzfree(payload);
+
+	return ret;
+}
+
+/*
+ * secure_read - copy the  blob data to userspace in hex.
+ * param[in]: key pointer to key struct
+ * param[in]: buffer pointer to user data for creating key
+ * param[in]: buflen is the length of the buffer
+ * On success, return to userspace the secure key data size.
+ */
+static long secure_read(const struct key *key, char __user *buffer,
+			 size_t buflen)
+{
+	const struct secure_key_payload *p = NULL;
+	char *ascii_buf;
+	char *bufp;
+	int i;
+
+	p = dereference_key_locked(key);
+	if (!p)
+		return -EINVAL;
+
+	if (buffer && buflen >= 2 * p->blob_len) {
+		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+		if (!ascii_buf)
+			return -ENOMEM;
+
+		bufp = ascii_buf;
+		for (i = 0; i < p->blob_len; i++)
+			bufp = hex_byte_pack(bufp, p->blob[i]);
+		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+			kzfree(ascii_buf);
+			return -EFAULT;
+		}
+		kzfree(ascii_buf);
+	}
+	return 2 * p->blob_len;
+}
+
+/*
+ * secure_destroy - clear and free the key's payload
+ */
+static void secure_destroy(struct key *key)
+{
+	kzfree(key->payload.data[0]);
+}
+
+struct key_type key_type_secure = {
+	.name = "secure",
+	.instantiate = secure_instantiate,
+	.destroy = secure_destroy,
+	.read = secure_read,
+};
+EXPORT_SYMBOL_GPL(key_type_secure);
+
+static void secure_shash_release(void)
+{
+	if (hashalg)
+		crypto_free_shash(hashalg);
+	if (hmacalg)
+		crypto_free_shash(hmacalg);
+}
+
+static int __init secure_shash_alloc(void)
+{
+	int ret;
+
+	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hmacalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hmac_alg);
+		return PTR_ERR(hmacalg);
+	}
+
+	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hashalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hash_alg);
+		ret = PTR_ERR(hashalg);
+		goto hashalg_fail;
+	}
+
+	return 0;
+
+hashalg_fail:
+	crypto_free_shash(hmacalg);
+	return ret;
+}
+
+static int __init init_secure_key(void)
+{
+	int ret;
+
+	ret = secure_shash_alloc();
+	if (ret < 0)
+		return ret;
+
+	ret = register_key_type(&key_type_secure);
+	if (ret < 0)
+		secure_shash_release();
+	return ret;
+}
+
+static void __exit cleanup_secure_key(void)
+{
+	secure_shash_release();
+	unregister_key_type(&key_type_secure);
+}
+
+late_initcall(init_secure_key);
+module_exit(cleanup_secure_key);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
new file mode 100644
index 000000000000..a4fa811a5753
--- /dev/null
+++ b/security/keys/securekey_desc.c
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP
+ *
+ */
+
+#include <keys/secure-type.h>
+#include "securekey_desc.h"
+
+/* key modifier for blob encapsulation & decapsulation descriptor */
+u8 key_modifier[] = "SECURE_KEY";
+u32 key_modifier_len = 10;
+
+void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct random_desc *rnd_desc = NULL;
+	size_t len = 0;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+	len = fetch_rnd_data->key_len;
+
+	/* command 0x82500000 */
+	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
+			OP_ALG_ALGSEL_RNG);
+	/* command 0x60340000 | len */
+	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
+	append_ptr(desc, rnd_desc->rnd_data);
+}
+
+void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_encap_desc *red_blob_desc =
+					&skdesc->dma_u.redblob_encapdesc;
+	struct sk_red_blob_encap *red_blob_req =
+					&skreq->req_u.sk_red_blob_encap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
+			  0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->redblob,
+			   red_blob_req->redblob_sz, 0);
+
+	/* RedBlob encapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+ * brief CAAM Descriptor creator from redblob to plaindata.
+ * param[in] skreq Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ */
+void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_decap_desc *red_blob_desc =
+					&skdesc->dma_u.redblob_decapdesc;
+	struct sk_red_blob_decap *red_blob_req =
+					&skreq->req_u.sk_red_blob_decap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->redblob,
+			  red_blob_req->redblob_sz, 0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->out_data,
+			   red_blob_req->data_sz, 0);
+
+	/* RedBlob decapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+ *			      struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+			   struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data;
+	struct random_desc *rnd_desc;
+
+	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+
+	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
+				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_random_map_fail;
+	}
+	return 0;
+
+sk_random_map_fail:
+	return -ENOMEM;
+}
+
+/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+ *					struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_encap *red_blob_encap;
+	struct redblob_encap_desc *red_blob_desc;
+
+	red_blob_encap = &req->req_u.sk_red_blob_encap;
+	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
+					red_blob_encap->data_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
+				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	return 0;
+
+sk_redblob_fail:
+	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
+			 DMA_TO_DEVICE);
+sk_data_fail:
+	return -ENOMEM;
+}
+
+/* static int caam_sk_redblob_decap_map(struct device *dev,
+ *					    struct sk_req *req,
+ *					    struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_decap *red_blob_decap;
+	struct redblob_decap_desc *red_blob_desc;
+
+	red_blob_decap = &req->req_u.sk_red_blob_decap;
+	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
+				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
+				red_blob_decap->data_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	return 0;
+
+sk_data_fail:
+	dma_unmap_single(dev, red_blob_desc->redblob,
+			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+sk_redblob_fail:
+	return -ENOMEM;
+}
+
+/* @fn void securekey_unmap(struct device *dev,
+ *			    struct sk_desc *skdesc, struct sk_req *req)
+ * @brief DMA unmap the buffer pointers.
+ * @param[in] dev Pointer to job ring device structure
+ * @param[in] skdesc Pointer to secure key descriptor structure
+ * @param[in] req Pointer to secure key request structure
+ */
+void securekey_unmap(struct device *dev,
+		     struct sk_desc *skdesc, struct sk_req *req)
+{
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			struct sk_fetch_rnd_data *fetch_rnd_data;
+			struct random_desc *rnd_desc;
+
+			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+			rnd_desc = &skdesc->dma_u.random_descp;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, rnd_desc->rnd_data,
+					 fetch_rnd_data->key_len,
+					 DMA_FROM_DEVICE);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			struct sk_red_blob_encap *red_blob_encap;
+			struct redblob_encap_desc *red_blob_desc;
+
+			red_blob_encap = &req->req_u.sk_red_blob_encap;
+			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->in_data,
+					 red_blob_encap->data_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_encap->redblob_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	case sk_red_blob_dec:
+		{
+			struct sk_red_blob_decap *red_blob_decap;
+			struct redblob_decap_desc *red_blob_desc;
+
+			red_blob_decap = &req->req_u.sk_red_blob_decap;
+			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_decap->redblob_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->out_data,
+					 red_blob_decap->data_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	default:
+		dev_err(dev, "Unable to find request type\n");
+		break;
+	}
+	kfree(skdesc);
+}
+
+/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+ *  brief CAAM Descriptor creator for secure key operations.
+ *  param[in] dev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+{
+	struct sk_desc *skdesc = NULL;
+	int ret = 0;
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			skdesc->req_type = req->type;
+
+			if (caam_sk_get_random_map(dev, req, skdesc)) {
+				dev_err(dev, "caam get_random map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+			caam_sk_rng_desc(req, skdesc);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_encap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to create redblob from data. */
+			caam_sk_redblob_encap_desc(req, skdesc);
+			break;
+		}
+
+	case sk_red_blob_dec:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_decap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to decap data from redblob. */
+			caam_sk_redblob_decap_desc(req, skdesc);
+			break;
+		}
+	default:
+		pr_debug("Unknown request type\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	req->desc_pointer = (void *)skdesc;
+
+out:
+	return ret;
+}
+
+/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
+ *			     void *context)
+ * brief callback function to be called when descriptor executed.
+ * param[in] dev Pointer to device structure
+ * param[in] desc descriptor pointer
+ * param[in] ret return status of Job submitted
+ * param[in] context void pointer
+ */
+static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
+			 void *context)
+{
+	struct sk_req *req = context;
+
+	if (ret) {
+		dev_err(dev, "caam op done err: %x\n", ret);
+		/* print the error source name. */
+		caam_jr_strstatus(dev, ret);
+	}
+	/* Call securekey_unmap function for unmapping the buffer pointers. */
+	securekey_unmap(dev, req->desc_pointer, req);
+
+	req->ret = ret;
+	complete(&req->comp);
+}
+
+
+/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+ *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
+ *  param[in] jrdev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+{
+	int ret;
+
+	init_completion(&req->comp);
+
+	/* caam_jr_enqueue function for Enqueue a job descriptor */
+	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
+	if (!ret)
+		wait_for_completion_interruptible(&req->comp);
+
+	ret = req->ret;
+	return ret;
+}
+
+/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+ *		   struct device *dev)
+ * Create the random number of the specified length using CAAM block
+ * param[in]: out pointer to place the random bytes
+ * param[in]: length for the random data bytes.
+ * param[in]: dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct sk_req *req = NULL;
+	int ret = 0;
+	void *temp = NULL;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->type = fetch_rnd;
+	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
+
+	/* initialise with key length */
+	fetch_rnd_data->key_len = p->key_len;
+
+	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	fetch_rnd_data->data = temp;
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		memcpy(p->key, fetch_rnd_data->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (req)
+		kfree(req);
+
+	if (temp)
+		kfree(temp);
+
+	return ret;
+}
+
+/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
+ *		struct device *dev)
+ * Deblobify the blob to get the key data and fill in secure key payload struct
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev)
+{
+	unsigned int blob_len;
+	struct sk_red_blob_decap *d_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	d_blob = &(req->req_u.sk_red_blob_decap);
+	blob_len = p->blob_len;
+	req->type = decap_type;
+
+	/*
+	 * Red blob size is the blob_len filled in payload struct
+	 * Data_sz i.e. key is the blob_len - blob header size
+	 */
+
+	d_blob->redblob_sz = blob_len;
+	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
+	total_sz = d_blob->data_sz + d_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	d_blob->redblob = temp;
+	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
+	memcpy(d_blob->redblob, p->blob, blob_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init: Failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->key_len = d_blob->data_sz;
+		memcpy(p->key, d_blob->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(temp);
+	if (req)
+		kfree(req);
+	return ret;
+}
+
+/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+ *		struct device *dev)
+ * To blobify the key data to get the blob. This blob can only be seen by
+ * userspace.
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev)
+{
+	unsigned int key_len;
+	struct sk_red_blob_encap *k_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	key_len = p->key_len;
+
+	req->type = encap_type;
+	k_blob = &(req->req_u.sk_red_blob_encap);
+
+	/*
+	 * Data_sz i.e. key len and the corresponding blob_len is
+	 * key_len + BLOB header size.
+	 */
+
+	k_blob->data_sz = key_len;
+	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
+	total_sz = k_blob->data_sz + k_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	k_blob->data = temp;
+
+	k_blob->redblob = k_blob->data + k_blob->data_sz;
+	memcpy(k_blob->data, p->key, key_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->blob_len = k_blob->redblob_sz;
+		memcpy(p->blob, k_blob->redblob, p->blob_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(req->mem_pointer);
+	if (req)
+		kfree(req);
+	return ret;
+
+}
+
diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
new file mode 100644
index 000000000000..0ee26e95b205
--- /dev/null
+++ b/security/keys/securekey_desc.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2018 NXP
+ *
+ */
+#ifndef _SECUREKEY_DESC_H_
+#define _SECUREKEY_DESC_H_
+
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+#include "pdb.h"
+
+#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
+#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
+
+/*
+ * brief defines different kinds of operations supported by this module.
+ */
+enum sk_req_type {
+	sk_get_random,
+	sk_red_blob_enc,
+	sk_red_blob_dec,
+};
+
+
+/*
+ * struct random_des
+ * param[out] rnd_data output buffer for random data.
+ */
+struct random_desc {
+	dma_addr_t rnd_data;
+};
+
+/* struct redblob_encap_desc
+ * details Structure containing dma address for redblob encapsulation.
+ * param[in] in_data input data to redblob encap descriptor.
+ * param[out] redblob output buffer for redblob.
+ */
+struct redblob_encap_desc {
+	dma_addr_t in_data;
+	dma_addr_t redblob;
+};
+
+/* struct redblob_decap_desc
+ * details Structure containing dma address for redblob decapsulation.
+ * param[in] redblob input buffer to redblob decap descriptor.
+ * param[out] out_data output data from redblob decap descriptor.
+ */
+struct redblob_decap_desc {
+	dma_addr_t redblob;
+	dma_addr_t out_data;
+};
+
+/* struct sk_desc
+ * details Structure for securekey descriptor creation.
+ * param[in] req_type operation supported.
+ * param[in] dma_u union of struct for supported operation.
+ */
+struct sk_desc {
+	u32 req_type;
+	union {
+		struct redblob_encap_desc redblob_encapdesc;
+		struct redblob_decap_desc redblob_decapdesc;
+		struct random_desc random_descp;
+	} dma_u;
+};
+
+/* struct sk_fetch_rnd_data
+ * decriptor structure containing key length.
+ */
+struct sk_fetch_rnd_data {
+	void *data;
+	size_t key_len;
+};
+
+/* struct sk_red_blob_encap
+ * details Structure containing buffer pointers for redblob encapsulation.
+ * param[in] data Input data.
+ * param[in] data_sz size of Input data.
+ * param[out] redblob output buffer for redblob.
+ * param[in] redblob_sz size of redblob.
+ */
+struct sk_red_blob_encap {
+	void *data;
+	uint32_t data_sz;
+	void *redblob;
+	uint32_t redblob_sz;
+};
+
+/* struct sk_red_blob_decap
+ * details Structure containing buffer pointers for redblob decapsulation.
+ * param[in] redblob Input redblob.
+ * param[in] redblob_sz size of redblob.
+ * param[out] data output buffer for data.
+ * param[in] data_sz size of output data.
+ */
+struct sk_red_blob_decap {
+	void *redblob;
+	uint32_t redblob_sz;
+	void *data;
+	uint32_t data_sz;
+};
+
+/* struct sk_req
+ * details Structure for securekey request creation.
+ * param[in] type operation supported.
+ * param[in] req_u union of struct for supported operation.
+ * param[out] ret return status of CAAM operation.
+ * param[in] mem_pointer memory pointer for allocated kernel memory.
+ * param[in] desc_pointer Pointer to securekey descriptor creation structure.
+ * param[in] comp struct completion object.
+ * param[in] hwdesc contains descriptor instructions.
+ */
+struct sk_req {
+	enum sk_req_type type;
+	void *arg;
+	union {
+		struct sk_red_blob_encap sk_red_blob_encap;
+		struct sk_red_blob_decap sk_red_blob_decap;
+		struct sk_fetch_rnd_data sk_fetch_rnd_data;
+	} req_u;
+	int ret;
+	void *mem_pointer;
+	void *desc_pointer;
+	struct completion comp;
+	u32 hwdesc[MAX_CAAM_DESCSIZE];
+};
+
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev);
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev);
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev);
+
+#endif /*_SECUREKEY_DESC_H_*/
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20  5:46 ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:46 UTC (permalink / raw)
  To: linux-security-module

Secure keys are derieved using CAAM crypto block.

Secure keys derieved are the random number symmetric keys from CAAM.
Blobs corresponding to the key are formed using CAAM. User space
will only be able to view the blob of the key.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 Documentation/security/keys/secure-key.rst |  67 +++
 MAINTAINERS                                |  11 +
 include/keys/secure-type.h                 |  33 ++
 security/keys/Kconfig                      |  11 +
 security/keys/Makefile                     |   3 +
 security/keys/secure_key.c                 | 339 ++++++++++++
 security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
 security/keys/securekey_desc.h             | 141 +++++
 8 files changed, 1211 insertions(+)
 create mode 100644 Documentation/security/keys/secure-key.rst
 create mode 100644 include/keys/secure-type.h
 create mode 100644 security/keys/secure_key.c
 create mode 100644 security/keys/securekey_desc.c
 create mode 100644 security/keys/securekey_desc.h

diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
new file mode 100644
index 000000000000..0fc3367b00f8
--- /dev/null
+++ b/Documentation/security/keys/secure-key.rst
@@ -0,0 +1,67 @@
+==========
+Secure Key
+==========
+
+Secure key is the new type added to kernel key ring service.
+Secure key is a symmetric type key of minimum length 32 bytes
+and with maximum possible length to be 128 bytes. It is produced
+in kernel using the CAAM crypto engine. Userspace can only see
+the blob for the corresponding key. All the blobs are displayed
+or loaded in hex ascii.
+
+Secure key can only be created on platforms which supports CAAM
+hardware block. Secure key can also be used as a master key to
+create the encrypted keys along with the existing key types in
+kernel.
+
+Secure key uses CAAM hardware to generate the key and blobify its
+content for userspace. Generated blobs are tied up with the hardware
+secret key stored in CAAM, hence the same blob will not be able to
+de-blobify with the different secret key on another machine.
+
+Usage::
+
+	keyctl add secure <name> "new <keylen>" <ring>
+	keyctl load secure <name> "load <hex_blob>" <ring>
+	keyctl print <key_id>
+
+"keyctl add secure" option will create the random data of the
+specified key len using CAAM and store it as a key in kernel.
+Key contents will be displayed as blobs to the user in hex ascii.
+User can input key len from 32 bytes to 128 bytes.
+
+"keyctl load secure" option will load the blob contents. In kernel,
+key will be deirved using input blob and CAAM, along with the secret
+key stored in CAAM.
+
+"keyctl print" will return the hex string of the blob corresponding to
+key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
+the header bytes added by the CAAM.
+
+Example of secure key usage::
+
+1. Create the secure key with name kmk-master of length 32 bytes::
+
+	$ keyctl add secure kmk-master "new 32" @u
+	46001928
+
+	$keyctl show
+	Session Keyring
+	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
+	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
+	  46001928 --als-rv      0     0       \_ secure: kmk-master
+
+2. Print the blob contents for the kmk-master key::
+
+	$ keyctl print 46001928
+	d9743445b640f3d59c1670dddc0bc9c2
+	34fc9aab7dd05c965e6120025012f029b
+	07faa4776c4f6ed02899e35a135531e9a
+	6e5c2b51132f9d5aef28f68738e658296
+	3fe583177cfe50d2542b659a13039
+
+	$ keyctl pipe 46001928 > secure_key.blob
+
+3. Load the blob in the user key ring::
+
+	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
diff --git a/MAINTAINERS b/MAINTAINERS
index 9fd5e8808208..654be2ee4b0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
 F:	security/keys/trusted.c
 F:	security/keys/trusted.h
 
+KEYS-SECURE
+M:	Udit Agarwal <udit.agarwal@nxp.com>
+R:	Sahil Malhotra <sahil.malhotra@nxp.com>
+L:	linux-security-module at vger.kernel.org
+L:	keyrings at vger.kernel.org
+S:	Supported
+F:	include/keys/secure-type.h
+F:	security/keys/secure_key.c
+F:	security/keys/securekey_desc.c
+F:	security/keys/securekey_desc.h
+
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
 L:	keyrings at vger.kernel.org
diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
new file mode 100644
index 000000000000..5b7a5f144e41
--- /dev/null
+++ b/include/keys/secure-type.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#ifndef _KEYS_SECURE_TYPE_H
+#define _KEYS_SECURE_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+/* Minimum key size to be used is 32 bytes and maximum key size fixed
+ * is 128 bytes.
+ * Blob size to be kept is Maximum key size + blob header added by CAAM.
+ */
+
+#define MIN_KEY_SIZE                    32
+#define MAX_KEY_SIZE                    128
+#define BLOB_HEADER_SIZE		48
+
+#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
+
+struct secure_key_payload {
+	struct rcu_head rcu;
+	unsigned int key_len;
+	unsigned int blob_len;
+	unsigned char key[MAX_KEY_SIZE + 1];
+	unsigned char blob[MAX_BLOB_SIZE];
+};
+
+extern struct key_type key_type_secure;
+#endif
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 6462e6654ccf..7eb138b5a54f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -71,6 +71,17 @@ config TRUSTED_KEYS
 
 	  If you are unsure as to whether this is required, answer N.
 
+config SECURE_KEYS
+	tristate "SECURE_KEYS"
+	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	help
+	  This option provide support for creating secure-type key and blobs
+	  in kernel. Secure keys are random number symmetric keys generated
+	  from CAAM. The CAAM creates the blobs for the random key.
+	  Userspace will only be able to see the blob.
+
+	  If you are unsure as to whether this is required, answer N.
+
 config ENCRYPTED_KEYS
 	tristate "ENCRYPTED KEYS"
 	depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ef1581b337a3..606ba4efb9e6 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
 #
 obj-$(CONFIG_BIG_KEYS) += big_key.o
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
+obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
+obj-$(CONFIG_SECURE_KEYS) += secure_key.o
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
new file mode 100644
index 000000000000..ec8ad4394549
--- /dev/null
+++ b/security/keys/secure_key.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2018 NXP
+ * Secure key is generated using NXP CAAM hardware block. CAAM generates the
+ * random number (used as a key) and creates its blob for the user.
+ */
+
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <keys/secure-type.h>
+#include <linux/completion.h>
+
+#include "securekey_desc.h"
+
+static const char hmac_alg[] = "hmac(sha1)";
+static const char hash_alg[] = "sha1";
+
+static struct crypto_shash *hashalg;
+static struct crypto_shash *hmacalg;
+
+enum {
+	error = -1,
+	new_key,
+	load_blob,
+};
+
+static const match_table_t key_tokens = {
+	{new_key, "new"},
+	{load_blob, "load"},
+	{error, NULL}
+};
+
+static struct secure_key_payload *secure_payload_alloc(struct key *key)
+{
+	struct secure_key_payload *sec_key = NULL;
+	int ret = 0;
+
+	ret = key_payload_reserve(key, sizeof(*sec_key));
+	if (ret < 0)
+		goto out;
+
+	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
+	if (!sec_key)
+		goto out;
+
+out:
+	return sec_key;
+}
+
+/*
+ * parse_inputdata - parse the keyctl input data and fill in the
+ *		     payload structure for key or its blob.
+ * param[in]: data pointer to the data to be parsed for creating key.
+ * param[in]: p pointer to secure key payload structure to fill parsed data
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int parse_inputdata(char *data, struct secure_key_payload *p)
+{
+	substring_t args[MAX_OPT_ARGS];
+	long keylen = 0;
+	int ret = -EINVAL;
+	int key_cmd = -EINVAL;
+	char *c = NULL;
+
+	c = strsep(&data, " \t");
+	if (!c) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Get the keyctl command i.e. new_key or load_blob etc */
+	key_cmd = match_token(c, key_tokens, args);
+
+	switch (key_cmd) {
+	case new_key:
+		/* first argument is key size */
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = kstrtol(c, 10, &keylen);
+		if (ret < 0 || keylen < MIN_KEY_SIZE ||
+						keylen > MAX_KEY_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		p->key_len = keylen;
+		ret = new_key;
+
+		break;
+	case load_blob:
+		/* first argument is blob data for CAAM*/
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* Blob_len = No of characters in blob/2 */
+		p->blob_len = strlen(c) / 2;
+		if (p->blob_len > MAX_BLOB_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = hex2bin(p->blob, c, p->blob_len);
+		if (ret < 0) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = load_blob;
+
+		break;
+	case error:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+
+/*
+ * secure_instantiate - create a new secure type key.
+ * Supports the operation to generate a new key. A random number
+ * is generated from CAAM as key data and the corresponding red blob
+ * is formed and stored as key_blob.
+ * Also supports the operation to load the blob and key is derived using
+ * that blob from CAAM.
+ * On success, return 0. Otherwise return errno.
+ */
+static int secure_instantiate(struct key *key,
+		struct key_preparsed_payload *prep)
+{
+	struct secure_key_payload *payload = NULL;
+	size_t datalen = prep->datalen;
+	char *data = NULL;
+	int key_cmd = 0;
+	int ret = 0;
+	enum sk_req_type sk_op_type;
+	struct device *dev = NULL;
+
+	if (datalen <= 0 || datalen > 32767 || !prep->data) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(data, prep->data, datalen);
+	data[datalen] = '\0';
+
+	payload = secure_payload_alloc(key);
+	if (!payload) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Allocate caam job ring for operation to be performed from CAAM */
+	dev = caam_jr_alloc();
+	if (!dev) {
+		pr_info("caam_jr_alloc failed\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	key_cmd = parse_inputdata(data, payload);
+	if (key_cmd < 0) {
+		ret = key_cmd;
+		goto out;
+	}
+
+	switch (key_cmd) {
+	case load_blob:
+		/*
+		 * Red blob decryption to be done for load operation
+		 * to derive the key.
+		 */
+		sk_op_type = sk_red_blob_dec;
+		ret = key_deblob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	case new_key:
+		/* Get Random number from caam of the specified length */
+		sk_op_type = sk_get_random;
+		ret = caam_get_random(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: get_random fail (%d)\n", ret);
+			goto out;
+		}
+
+		/* Generate red blob of key random bytes with CAAM */
+		sk_op_type = sk_red_blob_enc;
+		ret = key_blob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	if (data)
+		kzfree(data);
+	if (dev)
+		caam_jr_free(dev);
+
+	if (!ret)
+		rcu_assign_keypointer(key, payload);
+	else
+		kzfree(payload);
+
+	return ret;
+}
+
+/*
+ * secure_read - copy the  blob data to userspace in hex.
+ * param[in]: key pointer to key struct
+ * param[in]: buffer pointer to user data for creating key
+ * param[in]: buflen is the length of the buffer
+ * On success, return to userspace the secure key data size.
+ */
+static long secure_read(const struct key *key, char __user *buffer,
+			 size_t buflen)
+{
+	const struct secure_key_payload *p = NULL;
+	char *ascii_buf;
+	char *bufp;
+	int i;
+
+	p = dereference_key_locked(key);
+	if (!p)
+		return -EINVAL;
+
+	if (buffer && buflen >= 2 * p->blob_len) {
+		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+		if (!ascii_buf)
+			return -ENOMEM;
+
+		bufp = ascii_buf;
+		for (i = 0; i < p->blob_len; i++)
+			bufp = hex_byte_pack(bufp, p->blob[i]);
+		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+			kzfree(ascii_buf);
+			return -EFAULT;
+		}
+		kzfree(ascii_buf);
+	}
+	return 2 * p->blob_len;
+}
+
+/*
+ * secure_destroy - clear and free the key's payload
+ */
+static void secure_destroy(struct key *key)
+{
+	kzfree(key->payload.data[0]);
+}
+
+struct key_type key_type_secure = {
+	.name = "secure",
+	.instantiate = secure_instantiate,
+	.destroy = secure_destroy,
+	.read = secure_read,
+};
+EXPORT_SYMBOL_GPL(key_type_secure);
+
+static void secure_shash_release(void)
+{
+	if (hashalg)
+		crypto_free_shash(hashalg);
+	if (hmacalg)
+		crypto_free_shash(hmacalg);
+}
+
+static int __init secure_shash_alloc(void)
+{
+	int ret;
+
+	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hmacalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hmac_alg);
+		return PTR_ERR(hmacalg);
+	}
+
+	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hashalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hash_alg);
+		ret = PTR_ERR(hashalg);
+		goto hashalg_fail;
+	}
+
+	return 0;
+
+hashalg_fail:
+	crypto_free_shash(hmacalg);
+	return ret;
+}
+
+static int __init init_secure_key(void)
+{
+	int ret;
+
+	ret = secure_shash_alloc();
+	if (ret < 0)
+		return ret;
+
+	ret = register_key_type(&key_type_secure);
+	if (ret < 0)
+		secure_shash_release();
+	return ret;
+}
+
+static void __exit cleanup_secure_key(void)
+{
+	secure_shash_release();
+	unregister_key_type(&key_type_secure);
+}
+
+late_initcall(init_secure_key);
+module_exit(cleanup_secure_key);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
new file mode 100644
index 000000000000..a4fa811a5753
--- /dev/null
+++ b/security/keys/securekey_desc.c
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP
+ *
+ */
+
+#include <keys/secure-type.h>
+#include "securekey_desc.h"
+
+/* key modifier for blob encapsulation & decapsulation descriptor */
+u8 key_modifier[] = "SECURE_KEY";
+u32 key_modifier_len = 10;
+
+void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct random_desc *rnd_desc = NULL;
+	size_t len = 0;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+	len = fetch_rnd_data->key_len;
+
+	/* command 0x82500000 */
+	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
+			OP_ALG_ALGSEL_RNG);
+	/* command 0x60340000 | len */
+	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
+	append_ptr(desc, rnd_desc->rnd_data);
+}
+
+void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_encap_desc *red_blob_desc =
+					&skdesc->dma_u.redblob_encapdesc;
+	struct sk_red_blob_encap *red_blob_req =
+					&skreq->req_u.sk_red_blob_encap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
+			  0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->redblob,
+			   red_blob_req->redblob_sz, 0);
+
+	/* RedBlob encapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+ * brief CAAM Descriptor creator from redblob to plaindata.
+ * param[in] skreq Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ */
+void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_decap_desc *red_blob_desc =
+					&skdesc->dma_u.redblob_decapdesc;
+	struct sk_red_blob_decap *red_blob_req =
+					&skreq->req_u.sk_red_blob_decap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->redblob,
+			  red_blob_req->redblob_sz, 0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->out_data,
+			   red_blob_req->data_sz, 0);
+
+	/* RedBlob decapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+ *			      struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+			   struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data;
+	struct random_desc *rnd_desc;
+
+	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+
+	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
+				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_random_map_fail;
+	}
+	return 0;
+
+sk_random_map_fail:
+	return -ENOMEM;
+}
+
+/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+ *					struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_encap *red_blob_encap;
+	struct redblob_encap_desc *red_blob_desc;
+
+	red_blob_encap = &req->req_u.sk_red_blob_encap;
+	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
+					red_blob_encap->data_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
+				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	return 0;
+
+sk_redblob_fail:
+	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
+			 DMA_TO_DEVICE);
+sk_data_fail:
+	return -ENOMEM;
+}
+
+/* static int caam_sk_redblob_decap_map(struct device *dev,
+ *					    struct sk_req *req,
+ *					    struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_decap *red_blob_decap;
+	struct redblob_decap_desc *red_blob_desc;
+
+	red_blob_decap = &req->req_u.sk_red_blob_decap;
+	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
+				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
+				red_blob_decap->data_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	return 0;
+
+sk_data_fail:
+	dma_unmap_single(dev, red_blob_desc->redblob,
+			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+sk_redblob_fail:
+	return -ENOMEM;
+}
+
+/* @fn void securekey_unmap(struct device *dev,
+ *			    struct sk_desc *skdesc, struct sk_req *req)
+ * @brief DMA unmap the buffer pointers.
+ * @param[in] dev Pointer to job ring device structure
+ * @param[in] skdesc Pointer to secure key descriptor structure
+ * @param[in] req Pointer to secure key request structure
+ */
+void securekey_unmap(struct device *dev,
+		     struct sk_desc *skdesc, struct sk_req *req)
+{
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			struct sk_fetch_rnd_data *fetch_rnd_data;
+			struct random_desc *rnd_desc;
+
+			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+			rnd_desc = &skdesc->dma_u.random_descp;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, rnd_desc->rnd_data,
+					 fetch_rnd_data->key_len,
+					 DMA_FROM_DEVICE);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			struct sk_red_blob_encap *red_blob_encap;
+			struct redblob_encap_desc *red_blob_desc;
+
+			red_blob_encap = &req->req_u.sk_red_blob_encap;
+			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->in_data,
+					 red_blob_encap->data_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_encap->redblob_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	case sk_red_blob_dec:
+		{
+			struct sk_red_blob_decap *red_blob_decap;
+			struct redblob_decap_desc *red_blob_desc;
+
+			red_blob_decap = &req->req_u.sk_red_blob_decap;
+			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_decap->redblob_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->out_data,
+					 red_blob_decap->data_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	default:
+		dev_err(dev, "Unable to find request type\n");
+		break;
+	}
+	kfree(skdesc);
+}
+
+/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+ *  brief CAAM Descriptor creator for secure key operations.
+ *  param[in] dev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+{
+	struct sk_desc *skdesc = NULL;
+	int ret = 0;
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			skdesc->req_type = req->type;
+
+			if (caam_sk_get_random_map(dev, req, skdesc)) {
+				dev_err(dev, "caam get_random map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+			caam_sk_rng_desc(req, skdesc);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_encap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to create redblob from data. */
+			caam_sk_redblob_encap_desc(req, skdesc);
+			break;
+		}
+
+	case sk_red_blob_dec:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_decap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to decap data from redblob. */
+			caam_sk_redblob_decap_desc(req, skdesc);
+			break;
+		}
+	default:
+		pr_debug("Unknown request type\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	req->desc_pointer = (void *)skdesc;
+
+out:
+	return ret;
+}
+
+/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
+ *			     void *context)
+ * brief callback function to be called when descriptor executed.
+ * param[in] dev Pointer to device structure
+ * param[in] desc descriptor pointer
+ * param[in] ret return status of Job submitted
+ * param[in] context void pointer
+ */
+static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
+			 void *context)
+{
+	struct sk_req *req = context;
+
+	if (ret) {
+		dev_err(dev, "caam op done err: %x\n", ret);
+		/* print the error source name. */
+		caam_jr_strstatus(dev, ret);
+	}
+	/* Call securekey_unmap function for unmapping the buffer pointers. */
+	securekey_unmap(dev, req->desc_pointer, req);
+
+	req->ret = ret;
+	complete(&req->comp);
+}
+
+
+/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+ *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
+ *  param[in] jrdev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+{
+	int ret;
+
+	init_completion(&req->comp);
+
+	/* caam_jr_enqueue function for Enqueue a job descriptor */
+	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
+	if (!ret)
+		wait_for_completion_interruptible(&req->comp);
+
+	ret = req->ret;
+	return ret;
+}
+
+/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+ *		   struct device *dev)
+ * Create the random number of the specified length using CAAM block
+ * param[in]: out pointer to place the random bytes
+ * param[in]: length for the random data bytes.
+ * param[in]: dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct sk_req *req = NULL;
+	int ret = 0;
+	void *temp = NULL;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->type = fetch_rnd;
+	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
+
+	/* initialise with key length */
+	fetch_rnd_data->key_len = p->key_len;
+
+	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	fetch_rnd_data->data = temp;
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		memcpy(p->key, fetch_rnd_data->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (req)
+		kfree(req);
+
+	if (temp)
+		kfree(temp);
+
+	return ret;
+}
+
+/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
+ *		struct device *dev)
+ * Deblobify the blob to get the key data and fill in secure key payload struct
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev)
+{
+	unsigned int blob_len;
+	struct sk_red_blob_decap *d_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	d_blob = &(req->req_u.sk_red_blob_decap);
+	blob_len = p->blob_len;
+	req->type = decap_type;
+
+	/*
+	 * Red blob size is the blob_len filled in payload struct
+	 * Data_sz i.e. key is the blob_len - blob header size
+	 */
+
+	d_blob->redblob_sz = blob_len;
+	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
+	total_sz = d_blob->data_sz + d_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	d_blob->redblob = temp;
+	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
+	memcpy(d_blob->redblob, p->blob, blob_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init: Failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->key_len = d_blob->data_sz;
+		memcpy(p->key, d_blob->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(temp);
+	if (req)
+		kfree(req);
+	return ret;
+}
+
+/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+ *		struct device *dev)
+ * To blobify the key data to get the blob. This blob can only be seen by
+ * userspace.
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev)
+{
+	unsigned int key_len;
+	struct sk_red_blob_encap *k_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	key_len = p->key_len;
+
+	req->type = encap_type;
+	k_blob = &(req->req_u.sk_red_blob_encap);
+
+	/*
+	 * Data_sz i.e. key len and the corresponding blob_len is
+	 * key_len + BLOB header size.
+	 */
+
+	k_blob->data_sz = key_len;
+	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
+	total_sz = k_blob->data_sz + k_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	k_blob->data = temp;
+
+	k_blob->redblob = k_blob->data + k_blob->data_sz;
+	memcpy(k_blob->data, p->key, key_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->blob_len = k_blob->redblob_sz;
+		memcpy(p->blob, k_blob->redblob, p->blob_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(req->mem_pointer);
+	if (req)
+		kfree(req);
+	return ret;
+
+}
+
diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
new file mode 100644
index 000000000000..0ee26e95b205
--- /dev/null
+++ b/security/keys/securekey_desc.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2018 NXP
+ *
+ */
+#ifndef _SECUREKEY_DESC_H_
+#define _SECUREKEY_DESC_H_
+
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+#include "pdb.h"
+
+#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
+#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
+
+/*
+ * brief defines different kinds of operations supported by this module.
+ */
+enum sk_req_type {
+	sk_get_random,
+	sk_red_blob_enc,
+	sk_red_blob_dec,
+};
+
+
+/*
+ * struct random_des
+ * param[out] rnd_data output buffer for random data.
+ */
+struct random_desc {
+	dma_addr_t rnd_data;
+};
+
+/* struct redblob_encap_desc
+ * details Structure containing dma address for redblob encapsulation.
+ * param[in] in_data input data to redblob encap descriptor.
+ * param[out] redblob output buffer for redblob.
+ */
+struct redblob_encap_desc {
+	dma_addr_t in_data;
+	dma_addr_t redblob;
+};
+
+/* struct redblob_decap_desc
+ * details Structure containing dma address for redblob decapsulation.
+ * param[in] redblob input buffer to redblob decap descriptor.
+ * param[out] out_data output data from redblob decap descriptor.
+ */
+struct redblob_decap_desc {
+	dma_addr_t redblob;
+	dma_addr_t out_data;
+};
+
+/* struct sk_desc
+ * details Structure for securekey descriptor creation.
+ * param[in] req_type operation supported.
+ * param[in] dma_u union of struct for supported operation.
+ */
+struct sk_desc {
+	u32 req_type;
+	union {
+		struct redblob_encap_desc redblob_encapdesc;
+		struct redblob_decap_desc redblob_decapdesc;
+		struct random_desc random_descp;
+	} dma_u;
+};
+
+/* struct sk_fetch_rnd_data
+ * decriptor structure containing key length.
+ */
+struct sk_fetch_rnd_data {
+	void *data;
+	size_t key_len;
+};
+
+/* struct sk_red_blob_encap
+ * details Structure containing buffer pointers for redblob encapsulation.
+ * param[in] data Input data.
+ * param[in] data_sz size of Input data.
+ * param[out] redblob output buffer for redblob.
+ * param[in] redblob_sz size of redblob.
+ */
+struct sk_red_blob_encap {
+	void *data;
+	uint32_t data_sz;
+	void *redblob;
+	uint32_t redblob_sz;
+};
+
+/* struct sk_red_blob_decap
+ * details Structure containing buffer pointers for redblob decapsulation.
+ * param[in] redblob Input redblob.
+ * param[in] redblob_sz size of redblob.
+ * param[out] data output buffer for data.
+ * param[in] data_sz size of output data.
+ */
+struct sk_red_blob_decap {
+	void *redblob;
+	uint32_t redblob_sz;
+	void *data;
+	uint32_t data_sz;
+};
+
+/* struct sk_req
+ * details Structure for securekey request creation.
+ * param[in] type operation supported.
+ * param[in] req_u union of struct for supported operation.
+ * param[out] ret return status of CAAM operation.
+ * param[in] mem_pointer memory pointer for allocated kernel memory.
+ * param[in] desc_pointer Pointer to securekey descriptor creation structure.
+ * param[in] comp struct completion object.
+ * param[in] hwdesc contains descriptor instructions.
+ */
+struct sk_req {
+	enum sk_req_type type;
+	void *arg;
+	union {
+		struct sk_red_blob_encap sk_red_blob_encap;
+		struct sk_red_blob_decap sk_red_blob_decap;
+		struct sk_fetch_rnd_data sk_fetch_rnd_data;
+	} req_u;
+	int ret;
+	void *mem_pointer;
+	void *desc_pointer;
+	struct completion comp;
+	u32 hwdesc[MAX_CAAM_DESCSIZE];
+};
+
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev);
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev);
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev);
+
+#endif /*_SECUREKEY_DESC_H_*/
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/2] encrypted_keys: Adds support for secure key-type as master key.
  2018-07-20  5:46 ` Udit Agarwal
  (?)
@ 2018-07-20  5:46   ` Udit Agarwal
  -1 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:46 UTC (permalink / raw)
  To: dhowells, zohar, jmorris, serge, linux-integrity, keyrings,
	linux-security-module, linux-kernel
  Cc: sahil.malhotra, Udit Agarwal

Encrypted keys can use secure key-type as master key along with
trusted/user keys.

Secure key as master key uses, secure key type payload derieved
using CAAM hardware.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 MAINTAINERS                                   |  1 +
 security/keys/encrypted-keys/Makefile         |  2 +
 security/keys/encrypted-keys/encrypted.c      | 13 ++++++-
 security/keys/encrypted-keys/encrypted.h      | 13 +++++++
 .../keys/encrypted-keys/masterkey_secure.c    | 37 +++++++++++++++++++
 5 files changed, 64 insertions(+), 2 deletions(-)
 create mode 100644 security/keys/encrypted-keys/masterkey_secure.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 654be2ee4b0a..847254eec22a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7949,6 +7949,7 @@ F:	include/keys/secure-type.h
 F:	security/keys/secure_key.c
 F:	security/keys/securekey_desc.c
 F:	security/keys/securekey_desc.h
+F:	security/keys/encrypted-keys/masterkey_secure.c
 
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile
index 7a44dce6f69d..df2b906b7d24 100644
--- a/security/keys/encrypted-keys/Makefile
+++ b/security/keys/encrypted-keys/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o
 
 encrypted-keys-y := encrypted.o ecryptfs_format.o
 masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS) := masterkey_secure.o
 masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_secure.o
 encrypted-keys-y += $(masterkey-y) $(masterkey-m-m)
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index d92cbf9687c3..258b38094705 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -39,6 +39,7 @@
 #include "ecryptfs_format.h"
 
 static const char KEY_TRUSTED_PREFIX[] = "trusted:";
+static const char KEY_SECURE_PREFIX[] = "secure:";
 static const char KEY_USER_PREFIX[] = "user:";
 static const char hash_alg[] = "sha256";
 static const char hmac_alg[] = "hmac(sha256)";
@@ -49,6 +50,7 @@ static unsigned int ivsize;
 static int blksize;
 
 #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
+#define KEY_SECURE_PREFIX_LEN (sizeof(KEY_SECURE_PREFIX) - 1)
 #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
 #define KEY_ECRYPTFS_DESC_LEN 16
 #define HASH_SIZE SHA256_DIGEST_SIZE
@@ -125,7 +127,7 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)
 /*
  * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
  *
- * key-type:= "trusted:" | "user:"
+ * key-type:= "trusted:" | "user:" | "secure:"
  * desc:= master-key description
  *
  * Verify that 'key-type' is valid and that 'desc' exists. On key update,
@@ -140,6 +142,8 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
 
 	if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN))
 		prefix_len = KEY_TRUSTED_PREFIX_LEN;
+	else if (!strncmp(new_desc, KEY_SECURE_PREFIX, KEY_SECURE_PREFIX_LEN))
+		prefix_len = KEY_SECURE_PREFIX_LEN;
 	else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN))
 		prefix_len = KEY_USER_PREFIX_LEN;
 	else
@@ -358,7 +362,7 @@ static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
 
 enum derived_key_type { ENC_KEY, AUTH_KEY };
 
-/* Derive authentication/encryption key from trusted key */
+/* Derive authentication/encryption key from trusted/secure key */
 static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
 			   const u8 *master_key, size_t master_keylen)
 {
@@ -429,6 +433,11 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
 		mkey = request_trusted_key(epayload->master_desc +
 					   KEY_TRUSTED_PREFIX_LEN,
 					   master_key, master_keylen);
+	} else if (!strncmp(epayload->master_desc, KEY_SECURE_PREFIX,
+			    KEY_SECURE_PREFIX_LEN)) {
+		mkey = request_secure_key(epayload->master_desc +
+					  KEY_SECURE_PREFIX_LEN,
+					  master_key, master_keylen);
 	} else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX,
 			    KEY_USER_PREFIX_LEN)) {
 		mkey = request_user_key(epayload->master_desc +
diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h
index 1809995db452..f1cb73611e77 100644
--- a/security/keys/encrypted-keys/encrypted.h
+++ b/security/keys/encrypted-keys/encrypted.h
@@ -16,6 +16,19 @@ static inline struct key *request_trusted_key(const char *trusted_desc,
 }
 #endif
 
+#if defined(CONFIG_SECURE_KEYS)
+extern struct key *request_secure_key(const char *secure_desc,
+				      const u8 **master_key,
+				      size_t *master_keylen);
+#else
+static inline struct key *request_secure_key(const char *secure_desc,
+					     const u8 **master_key,
+					     size_t *master_keylen)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+#endif
+
 #if ENCRYPTED_DEBUG
 static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
 {
diff --git a/security/keys/encrypted-keys/masterkey_secure.c b/security/keys/encrypted-keys/masterkey_secure.c
new file mode 100644
index 000000000000..87068c966111
--- /dev/null
+++ b/security/keys/encrypted-keys/masterkey_secure.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <keys/secure-type.h>
+#include <keys/encrypted-type.h>
+#include "encrypted.h"
+
+/*
+ * request_secure_key - request the secure key
+ *
+ * Secure keys and their blobs are derived from CAAM hardware.
+ * Userspace manages secure  key-type data, but key data is not
+ * visible in plain form. It is presented as blobs.
+ */
+struct key *request_secure_key(const char *secure_desc,
+				const u8 **master_key, size_t *master_keylen)
+{
+	struct secure_key_payload *spayload;
+	struct key *skey;
+
+	skey = request_key(&key_type_secure, secure_desc, NULL);
+	if (IS_ERR(skey))
+		goto error;
+
+	down_read(&skey->sem);
+	spayload = skey->payload.data[0];
+	*master_key = spayload->key;
+	*master_keylen = spayload->key_len;
+error:
+	return skey;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/2] encrypted_keys: Adds support for secure key-type as master key.
@ 2018-07-20  5:46   ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:46 UTC (permalink / raw)
  To: linux-security-module

Encrypted keys can use secure key-type as master key along with
trusted/user keys.

Secure key as master key uses, secure key type payload derieved
using CAAM hardware.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 MAINTAINERS                                   |  1 +
 security/keys/encrypted-keys/Makefile         |  2 +
 security/keys/encrypted-keys/encrypted.c      | 13 ++++++-
 security/keys/encrypted-keys/encrypted.h      | 13 +++++++
 .../keys/encrypted-keys/masterkey_secure.c    | 37 +++++++++++++++++++
 5 files changed, 64 insertions(+), 2 deletions(-)
 create mode 100644 security/keys/encrypted-keys/masterkey_secure.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 654be2ee4b0a..847254eec22a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7949,6 +7949,7 @@ F:	include/keys/secure-type.h
 F:	security/keys/secure_key.c
 F:	security/keys/securekey_desc.c
 F:	security/keys/securekey_desc.h
+F:	security/keys/encrypted-keys/masterkey_secure.c
 
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile
index 7a44dce6f69d..df2b906b7d24 100644
--- a/security/keys/encrypted-keys/Makefile
+++ b/security/keys/encrypted-keys/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o
 
 encrypted-keys-y := encrypted.o ecryptfs_format.o
 masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS) := masterkey_secure.o
 masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_secure.o
 encrypted-keys-y += $(masterkey-y) $(masterkey-m-m)
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index d92cbf9687c3..258b38094705 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -39,6 +39,7 @@
 #include "ecryptfs_format.h"
 
 static const char KEY_TRUSTED_PREFIX[] = "trusted:";
+static const char KEY_SECURE_PREFIX[] = "secure:";
 static const char KEY_USER_PREFIX[] = "user:";
 static const char hash_alg[] = "sha256";
 static const char hmac_alg[] = "hmac(sha256)";
@@ -49,6 +50,7 @@ static unsigned int ivsize;
 static int blksize;
 
 #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
+#define KEY_SECURE_PREFIX_LEN (sizeof(KEY_SECURE_PREFIX) - 1)
 #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
 #define KEY_ECRYPTFS_DESC_LEN 16
 #define HASH_SIZE SHA256_DIGEST_SIZE
@@ -125,7 +127,7 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)
 /*
  * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
  *
- * key-type:= "trusted:" | "user:"
+ * key-type:= "trusted:" | "user:" | "secure:"
  * desc:= master-key description
  *
  * Verify that 'key-type' is valid and that 'desc' exists. On key update,
@@ -140,6 +142,8 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
 
 	if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN))
 		prefix_len = KEY_TRUSTED_PREFIX_LEN;
+	else if (!strncmp(new_desc, KEY_SECURE_PREFIX, KEY_SECURE_PREFIX_LEN))
+		prefix_len = KEY_SECURE_PREFIX_LEN;
 	else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN))
 		prefix_len = KEY_USER_PREFIX_LEN;
 	else
@@ -358,7 +362,7 @@ static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
 
 enum derived_key_type { ENC_KEY, AUTH_KEY };
 
-/* Derive authentication/encryption key from trusted key */
+/* Derive authentication/encryption key from trusted/secure key */
 static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
 			   const u8 *master_key, size_t master_keylen)
 {
@@ -429,6 +433,11 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
 		mkey = request_trusted_key(epayload->master_desc +
 					   KEY_TRUSTED_PREFIX_LEN,
 					   master_key, master_keylen);
+	} else if (!strncmp(epayload->master_desc, KEY_SECURE_PREFIX,
+			    KEY_SECURE_PREFIX_LEN)) {
+		mkey = request_secure_key(epayload->master_desc +
+					  KEY_SECURE_PREFIX_LEN,
+					  master_key, master_keylen);
 	} else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX,
 			    KEY_USER_PREFIX_LEN)) {
 		mkey = request_user_key(epayload->master_desc +
diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h
index 1809995db452..f1cb73611e77 100644
--- a/security/keys/encrypted-keys/encrypted.h
+++ b/security/keys/encrypted-keys/encrypted.h
@@ -16,6 +16,19 @@ static inline struct key *request_trusted_key(const char *trusted_desc,
 }
 #endif
 
+#if defined(CONFIG_SECURE_KEYS)
+extern struct key *request_secure_key(const char *secure_desc,
+				      const u8 **master_key,
+				      size_t *master_keylen);
+#else
+static inline struct key *request_secure_key(const char *secure_desc,
+					     const u8 **master_key,
+					     size_t *master_keylen)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+#endif
+
 #if ENCRYPTED_DEBUG
 static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
 {
diff --git a/security/keys/encrypted-keys/masterkey_secure.c b/security/keys/encrypted-keys/masterkey_secure.c
new file mode 100644
index 000000000000..87068c966111
--- /dev/null
+++ b/security/keys/encrypted-keys/masterkey_secure.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <keys/secure-type.h>
+#include <keys/encrypted-type.h>
+#include "encrypted.h"
+
+/*
+ * request_secure_key - request the secure key
+ *
+ * Secure keys and their blobs are derived from CAAM hardware.
+ * Userspace manages secure  key-type data, but key data is not
+ * visible in plain form. It is presented as blobs.
+ */
+struct key *request_secure_key(const char *secure_desc,
+				const u8 **master_key, size_t *master_keylen)
+{
+	struct secure_key_payload *spayload;
+	struct key *skey;
+
+	skey = request_key(&key_type_secure, secure_desc, NULL);
+	if (IS_ERR(skey))
+		goto error;
+
+	down_read(&skey->sem);
+	spayload = skey->payload.data[0];
+	*master_key = spayload->key;
+	*master_keylen = spayload->key_len;
+error:
+	return skey;
+}
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20  5:46 ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:58 UTC (permalink / raw)
  To: dhowells, zohar, jmorris, serge, linux-integrity, keyrings,
	linux-security-module, linux-kernel
  Cc: sahil.malhotra, Udit Agarwal

Secure keys are derieved using CAAM crypto block.

Secure keys derieved are the random number symmetric keys from CAAM.
Blobs corresponding to the key are formed using CAAM. User space
will only be able to view the blob of the key.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 Documentation/security/keys/secure-key.rst |  67 +++
 MAINTAINERS                                |  11 +
 include/keys/secure-type.h                 |  33 ++
 security/keys/Kconfig                      |  11 +
 security/keys/Makefile                     |   3 +
 security/keys/secure_key.c                 | 339 ++++++++++++
 security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
 security/keys/securekey_desc.h             | 141 +++++
 8 files changed, 1211 insertions(+)
 create mode 100644 Documentation/security/keys/secure-key.rst
 create mode 100644 include/keys/secure-type.h
 create mode 100644 security/keys/secure_key.c
 create mode 100644 security/keys/securekey_desc.c
 create mode 100644 security/keys/securekey_desc.h

diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
new file mode 100644
index 000000000000..0fc3367b00f8
--- /dev/null
+++ b/Documentation/security/keys/secure-key.rst
@@ -0,0 +1,67 @@
+=====
+Secure Key
+=====
+
+Secure key is the new type added to kernel key ring service.
+Secure key is a symmetric type key of minimum length 32 bytes
+and with maximum possible length to be 128 bytes. It is produced
+in kernel using the CAAM crypto engine. Userspace can only see
+the blob for the corresponding key. All the blobs are displayed
+or loaded in hex ascii.
+
+Secure key can only be created on platforms which supports CAAM
+hardware block. Secure key can also be used as a master key to
+create the encrypted keys along with the existing key types in
+kernel.
+
+Secure key uses CAAM hardware to generate the key and blobify its
+content for userspace. Generated blobs are tied up with the hardware
+secret key stored in CAAM, hence the same blob will not be able to
+de-blobify with the different secret key on another machine.
+
+Usage::
+
+	keyctl add secure <name> "new <keylen>" <ring>
+	keyctl load secure <name> "load <hex_blob>" <ring>
+	keyctl print <key_id>
+
+"keyctl add secure" option will create the random data of the
+specified key len using CAAM and store it as a key in kernel.
+Key contents will be displayed as blobs to the user in hex ascii.
+User can input key len from 32 bytes to 128 bytes.
+
+"keyctl load secure" option will load the blob contents. In kernel,
+key will be deirved using input blob and CAAM, along with the secret
+key stored in CAAM.
+
+"keyctl print" will return the hex string of the blob corresponding to
+key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
+the header bytes added by the CAAM.
+
+Example of secure key usage::
+
+1. Create the secure key with name kmk-master of length 32 bytes::
+
+	$ keyctl add secure kmk-master "new 32" @u
+	46001928
+
+	$keyctl show
+	Session Keyring
+	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
+	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
+	  46001928 --als-rv      0     0       \_ secure: kmk-master
+
+2. Print the blob contents for the kmk-master key::
+
+	$ keyctl print 46001928
+	d9743445b640f3d59c1670dddc0bc9c2
+	34fc9aab7dd05c965e6120025012f029b
+	07faa4776c4f6ed02899e35a135531e9a
+	6e5c2b51132f9d5aef28f68738e658296
+	3fe583177cfe50d2542b659a13039
+
+	$ keyctl pipe 46001928 > secure_key.blob
+
+3. Load the blob in the user key ring::
+
+	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
diff --git a/MAINTAINERS b/MAINTAINERS
index 9fd5e8808208..654be2ee4b0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
 F:	security/keys/trusted.c
 F:	security/keys/trusted.h
 
+KEYS-SECURE
+M:	Udit Agarwal <udit.agarwal@nxp.com>
+R:	Sahil Malhotra <sahil.malhotra@nxp.com>
+L:	linux-security-module@vger.kernel.org
+L:	keyrings@vger.kernel.org
+S:	Supported
+F:	include/keys/secure-type.h
+F:	security/keys/secure_key.c
+F:	security/keys/securekey_desc.c
+F:	security/keys/securekey_desc.h
+
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
 L:	keyrings@vger.kernel.org
diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
new file mode 100644
index 000000000000..5b7a5f144e41
--- /dev/null
+++ b/include/keys/secure-type.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#ifndef _KEYS_SECURE_TYPE_H
+#define _KEYS_SECURE_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+/* Minimum key size to be used is 32 bytes and maximum key size fixed
+ * is 128 bytes.
+ * Blob size to be kept is Maximum key size + blob header added by CAAM.
+ */
+
+#define MIN_KEY_SIZE                    32
+#define MAX_KEY_SIZE                    128
+#define BLOB_HEADER_SIZE		48
+
+#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
+
+struct secure_key_payload {
+	struct rcu_head rcu;
+	unsigned int key_len;
+	unsigned int blob_len;
+	unsigned char key[MAX_KEY_SIZE + 1];
+	unsigned char blob[MAX_BLOB_SIZE];
+};
+
+extern struct key_type key_type_secure;
+#endif
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 6462e6654ccf..7eb138b5a54f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -71,6 +71,17 @@ config TRUSTED_KEYS
 
 	  If you are unsure as to whether this is required, answer N.
 
+config SECURE_KEYS
+	tristate "SECURE_KEYS"
+	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	help
+	  This option provide support for creating secure-type key and blobs
+	  in kernel. Secure keys are random number symmetric keys generated
+	  from CAAM. The CAAM creates the blobs for the random key.
+	  Userspace will only be able to see the blob.
+
+	  If you are unsure as to whether this is required, answer N.
+
 config ENCRYPTED_KEYS
 	tristate "ENCRYPTED KEYS"
 	depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ef1581b337a3..606ba4efb9e6 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
 #
 obj-$(CONFIG_BIG_KEYS) += big_key.o
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
+obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
+obj-$(CONFIG_SECURE_KEYS) += secure_key.o
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
new file mode 100644
index 000000000000..ec8ad4394549
--- /dev/null
+++ b/security/keys/secure_key.c
@@ -0,0 +1,339 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2018 NXP
+ * Secure key is generated using NXP CAAM hardware block. CAAM generates the
+ * random number (used as a key) and creates its blob for the user.
+ */
+
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <keys/secure-type.h>
+#include <linux/completion.h>
+
+#include "securekey_desc.h"
+
+static const char hmac_alg[] = "hmac(sha1)";
+static const char hash_alg[] = "sha1";
+
+static struct crypto_shash *hashalg;
+static struct crypto_shash *hmacalg;
+
+enum {
+	error = -1,
+	new_key,
+	load_blob,
+};
+
+static const match_table_t key_tokens = {
+	{new_key, "new"},
+	{load_blob, "load"},
+	{error, NULL}
+};
+
+static struct secure_key_payload *secure_payload_alloc(struct key *key)
+{
+	struct secure_key_payload *sec_key = NULL;
+	int ret = 0;
+
+	ret = key_payload_reserve(key, sizeof(*sec_key));
+	if (ret < 0)
+		goto out;
+
+	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
+	if (!sec_key)
+		goto out;
+
+out:
+	return sec_key;
+}
+
+/*
+ * parse_inputdata - parse the keyctl input data and fill in the
+ *		     payload structure for key or its blob.
+ * param[in]: data pointer to the data to be parsed for creating key.
+ * param[in]: p pointer to secure key payload structure to fill parsed data
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int parse_inputdata(char *data, struct secure_key_payload *p)
+{
+	substring_t args[MAX_OPT_ARGS];
+	long keylen = 0;
+	int ret = -EINVAL;
+	int key_cmd = -EINVAL;
+	char *c = NULL;
+
+	c = strsep(&data, " \t");
+	if (!c) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Get the keyctl command i.e. new_key or load_blob etc */
+	key_cmd = match_token(c, key_tokens, args);
+
+	switch (key_cmd) {
+	case new_key:
+		/* first argument is key size */
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = kstrtol(c, 10, &keylen);
+		if (ret < 0 || keylen < MIN_KEY_SIZE ||
+						keylen > MAX_KEY_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		p->key_len = keylen;
+		ret = new_key;
+
+		break;
+	case load_blob:
+		/* first argument is blob data for CAAM*/
+		c = strsep(&data, " \t");
+		if (!c) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* Blob_len = No of characters in blob/2 */
+		p->blob_len = strlen(c) / 2;
+		if (p->blob_len > MAX_BLOB_SIZE) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = hex2bin(p->blob, c, p->blob_len);
+		if (ret < 0) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = load_blob;
+
+		break;
+	case error:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+
+/*
+ * secure_instantiate - create a new secure type key.
+ * Supports the operation to generate a new key. A random number
+ * is generated from CAAM as key data and the corresponding red blob
+ * is formed and stored as key_blob.
+ * Also supports the operation to load the blob and key is derived using
+ * that blob from CAAM.
+ * On success, return 0. Otherwise return errno.
+ */
+static int secure_instantiate(struct key *key,
+		struct key_preparsed_payload *prep)
+{
+	struct secure_key_payload *payload = NULL;
+	size_t datalen = prep->datalen;
+	char *data = NULL;
+	int key_cmd = 0;
+	int ret = 0;
+	enum sk_req_type sk_op_type;
+	struct device *dev = NULL;
+
+	if (datalen <= 0 || datalen > 32767 || !prep->data) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(data, prep->data, datalen);
+	data[datalen] = '\0';
+
+	payload = secure_payload_alloc(key);
+	if (!payload) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Allocate caam job ring for operation to be performed from CAAM */
+	dev = caam_jr_alloc();
+	if (!dev) {
+		pr_info("caam_jr_alloc failed\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	key_cmd = parse_inputdata(data, payload);
+	if (key_cmd < 0) {
+		ret = key_cmd;
+		goto out;
+	}
+
+	switch (key_cmd) {
+	case load_blob:
+		/*
+		 * Red blob decryption to be done for load operation
+		 * to derive the key.
+		 */
+		sk_op_type = sk_red_blob_dec;
+		ret = key_deblob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	case new_key:
+		/* Get Random number from caam of the specified length */
+		sk_op_type = sk_get_random;
+		ret = caam_get_random(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: get_random fail (%d)\n", ret);
+			goto out;
+		}
+
+		/* Generate red blob of key random bytes with CAAM */
+		sk_op_type = sk_red_blob_enc;
+		ret = key_blob(payload, sk_op_type, dev);
+		if (ret != 0) {
+			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
+			goto out;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	if (data)
+		kzfree(data);
+	if (dev)
+		caam_jr_free(dev);
+
+	if (!ret)
+		rcu_assign_keypointer(key, payload);
+	else
+		kzfree(payload);
+
+	return ret;
+}
+
+/*
+ * secure_read - copy the  blob data to userspace in hex.
+ * param[in]: key pointer to key struct
+ * param[in]: buffer pointer to user data for creating key
+ * param[in]: buflen is the length of the buffer
+ * On success, return to userspace the secure key data size.
+ */
+static long secure_read(const struct key *key, char __user *buffer,
+			 size_t buflen)
+{
+	const struct secure_key_payload *p = NULL;
+	char *ascii_buf;
+	char *bufp;
+	int i;
+
+	p = dereference_key_locked(key);
+	if (!p)
+		return -EINVAL;
+
+	if (buffer && buflen >= 2 * p->blob_len) {
+		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+		if (!ascii_buf)
+			return -ENOMEM;
+
+		bufp = ascii_buf;
+		for (i = 0; i < p->blob_len; i++)
+			bufp = hex_byte_pack(bufp, p->blob[i]);
+		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+			kzfree(ascii_buf);
+			return -EFAULT;
+		}
+		kzfree(ascii_buf);
+	}
+	return 2 * p->blob_len;
+}
+
+/*
+ * secure_destroy - clear and free the key's payload
+ */
+static void secure_destroy(struct key *key)
+{
+	kzfree(key->payload.data[0]);
+}
+
+struct key_type key_type_secure = {
+	.name = "secure",
+	.instantiate = secure_instantiate,
+	.destroy = secure_destroy,
+	.read = secure_read,
+};
+EXPORT_SYMBOL_GPL(key_type_secure);
+
+static void secure_shash_release(void)
+{
+	if (hashalg)
+		crypto_free_shash(hashalg);
+	if (hmacalg)
+		crypto_free_shash(hmacalg);
+}
+
+static int __init secure_shash_alloc(void)
+{
+	int ret;
+
+	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hmacalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hmac_alg);
+		return PTR_ERR(hmacalg);
+	}
+
+	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(hashalg)) {
+		pr_info("secure_key: could not allocate crypto %s\n",
+				hash_alg);
+		ret = PTR_ERR(hashalg);
+		goto hashalg_fail;
+	}
+
+	return 0;
+
+hashalg_fail:
+	crypto_free_shash(hmacalg);
+	return ret;
+}
+
+static int __init init_secure_key(void)
+{
+	int ret;
+
+	ret = secure_shash_alloc();
+	if (ret < 0)
+		return ret;
+
+	ret = register_key_type(&key_type_secure);
+	if (ret < 0)
+		secure_shash_release();
+	return ret;
+}
+
+static void __exit cleanup_secure_key(void)
+{
+	secure_shash_release();
+	unregister_key_type(&key_type_secure);
+}
+
+late_initcall(init_secure_key);
+module_exit(cleanup_secure_key);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
new file mode 100644
index 000000000000..a4fa811a5753
--- /dev/null
+++ b/security/keys/securekey_desc.c
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP
+ *
+ */
+
+#include <keys/secure-type.h>
+#include "securekey_desc.h"
+
+/* key modifier for blob encapsulation & decapsulation descriptor */
+u8 key_modifier[] = "SECURE_KEY";
+u32 key_modifier_len = 10;
+
+void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct random_desc *rnd_desc = NULL;
+	size_t len = 0;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+	len = fetch_rnd_data->key_len;
+
+	/* command 0x82500000 */
+	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
+			OP_ALG_ALGSEL_RNG);
+	/* command 0x60340000 | len */
+	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
+	append_ptr(desc, rnd_desc->rnd_data);
+}
+
+void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_encap_desc *red_blob_desc +					&skdesc->dma_u.redblob_encapdesc;
+	struct sk_red_blob_encap *red_blob_req +					&skreq->req_u.sk_red_blob_encap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
+			  0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->redblob,
+			   red_blob_req->redblob_sz, 0);
+
+	/* RedBlob encapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+ * brief CAAM Descriptor creator from redblob to plaindata.
+ * param[in] skreq Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ */
+void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
+{
+	struct redblob_decap_desc *red_blob_desc +					&skdesc->dma_u.redblob_decapdesc;
+	struct sk_red_blob_decap *red_blob_req +					&skreq->req_u.sk_red_blob_decap;
+	u32 *desc = skreq->hwdesc;
+
+	init_job_desc(desc, 0);
+
+	/* Load class 2 key with key modifier. */
+	append_key_as_imm(desc, key_modifier, key_modifier_len,
+			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
+
+	/* SEQ IN PTR Command. */
+	append_seq_in_ptr(desc, red_blob_desc->redblob,
+			  red_blob_req->redblob_sz, 0);
+
+	/* SEQ OUT PTR Command. */
+	append_seq_out_ptr(desc, red_blob_desc->out_data,
+			   red_blob_req->data_sz, 0);
+
+	/* RedBlob decapsulation PROTOCOL Command. */
+	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+}
+
+/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+ *			      struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
+			   struct sk_desc *skdesc)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data;
+	struct random_desc *rnd_desc;
+
+	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+	rnd_desc = &skdesc->dma_u.random_descp;
+
+	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
+				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_random_map_fail;
+	}
+	return 0;
+
+sk_random_map_fail:
+	return -ENOMEM;
+}
+
+/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+ *					struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_encap *red_blob_encap;
+	struct redblob_encap_desc *red_blob_desc;
+
+	red_blob_encap = &req->req_u.sk_red_blob_encap;
+	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
+					red_blob_encap->data_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
+				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	return 0;
+
+sk_redblob_fail:
+	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
+			 DMA_TO_DEVICE);
+sk_data_fail:
+	return -ENOMEM;
+}
+
+/* static int caam_sk_redblob_decap_map(struct device *dev,
+ *					    struct sk_req *req,
+ *					    struct sk_desc *skdesc)
+ * brief DMA map the buffer virtual pointers to physical address.
+ * param[in] dev Pointer to job ring device structure
+ * param[in] req Pointer to secure key request structure
+ * param[in] skdesc Pointer to secure key descriptor structure
+ * return 0 on success, error value otherwise.
+ */
+int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
+			      struct sk_desc *skdesc)
+{
+	struct sk_red_blob_decap *red_blob_decap;
+	struct redblob_decap_desc *red_blob_desc;
+
+	red_blob_decap = &req->req_u.sk_red_blob_decap;
+	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
+				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_redblob_fail;
+	}
+
+	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
+				red_blob_decap->data_sz, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
+		dev_err(dev, "Unable to map memory\n");
+		goto sk_data_fail;
+	}
+
+	return 0;
+
+sk_data_fail:
+	dma_unmap_single(dev, red_blob_desc->redblob,
+			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
+sk_redblob_fail:
+	return -ENOMEM;
+}
+
+/* @fn void securekey_unmap(struct device *dev,
+ *			    struct sk_desc *skdesc, struct sk_req *req)
+ * @brief DMA unmap the buffer pointers.
+ * @param[in] dev Pointer to job ring device structure
+ * @param[in] skdesc Pointer to secure key descriptor structure
+ * @param[in] req Pointer to secure key request structure
+ */
+void securekey_unmap(struct device *dev,
+		     struct sk_desc *skdesc, struct sk_req *req)
+{
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			struct sk_fetch_rnd_data *fetch_rnd_data;
+			struct random_desc *rnd_desc;
+
+			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
+			rnd_desc = &skdesc->dma_u.random_descp;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, rnd_desc->rnd_data,
+					 fetch_rnd_data->key_len,
+					 DMA_FROM_DEVICE);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			struct sk_red_blob_encap *red_blob_encap;
+			struct redblob_encap_desc *red_blob_desc;
+
+			red_blob_encap = &req->req_u.sk_red_blob_encap;
+			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->in_data,
+					 red_blob_encap->data_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_encap->redblob_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	case sk_red_blob_dec:
+		{
+			struct sk_red_blob_decap *red_blob_decap;
+			struct redblob_decap_desc *red_blob_desc;
+
+			red_blob_decap = &req->req_u.sk_red_blob_decap;
+			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
+
+			/* Unmap Descriptor buffer pointers. */
+			dma_unmap_single(dev, red_blob_desc->redblob,
+					 red_blob_decap->redblob_sz,
+					 DMA_TO_DEVICE);
+
+			dma_unmap_single(dev, red_blob_desc->out_data,
+					 red_blob_decap->data_sz,
+					 DMA_FROM_DEVICE);
+
+			break;
+		}
+	default:
+		dev_err(dev, "Unable to find request type\n");
+		break;
+	}
+	kfree(skdesc);
+}
+
+/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+ *  brief CAAM Descriptor creator for secure key operations.
+ *  param[in] dev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
+{
+	struct sk_desc *skdesc = NULL;
+	int ret = 0;
+
+	switch (req->type) {
+	case sk_get_random:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			skdesc->req_type = req->type;
+
+			if (caam_sk_get_random_map(dev, req, skdesc)) {
+				dev_err(dev, "caam get_random map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+			caam_sk_rng_desc(req, skdesc);
+			break;
+		}
+	case sk_red_blob_enc:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_encap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to create redblob from data. */
+			caam_sk_redblob_encap_desc(req, skdesc);
+			break;
+		}
+
+	case sk_red_blob_dec:
+		{
+			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
+			if (!skdesc) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			skdesc->req_type = req->type;
+
+			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
+				dev_err(dev, "caam redblob_decap map fail\n");
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			/* Descriptor function to decap data from redblob. */
+			caam_sk_redblob_decap_desc(req, skdesc);
+			break;
+		}
+	default:
+		pr_debug("Unknown request type\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	req->desc_pointer = (void *)skdesc;
+
+out:
+	return ret;
+}
+
+/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
+ *			     void *context)
+ * brief callback function to be called when descriptor executed.
+ * param[in] dev Pointer to device structure
+ * param[in] desc descriptor pointer
+ * param[in] ret return status of Job submitted
+ * param[in] context void pointer
+ */
+static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
+			 void *context)
+{
+	struct sk_req *req = context;
+
+	if (ret) {
+		dev_err(dev, "caam op done err: %x\n", ret);
+		/* print the error source name. */
+		caam_jr_strstatus(dev, ret);
+	}
+	/* Call securekey_unmap function for unmapping the buffer pointers. */
+	securekey_unmap(dev, req->desc_pointer, req);
+
+	req->ret = ret;
+	complete(&req->comp);
+}
+
+
+/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+ *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
+ *  param[in] jrdev Pointer to job ring device structure
+ *  param[in] req Pointer to secure key request structure
+ *  return 0 on success, error value otherwise.
+ */
+static int sk_job_submit(struct device *jrdev, struct sk_req *req)
+{
+	int ret;
+
+	init_completion(&req->comp);
+
+	/* caam_jr_enqueue function for Enqueue a job descriptor */
+	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
+	if (!ret)
+		wait_for_completion_interruptible(&req->comp);
+
+	ret = req->ret;
+	return ret;
+}
+
+/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+ *		   struct device *dev)
+ * Create the random number of the specified length using CAAM block
+ * param[in]: out pointer to place the random bytes
+ * param[in]: length for the random data bytes.
+ * param[in]: dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev)
+{
+	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
+	struct sk_req *req = NULL;
+	int ret = 0;
+	void *temp = NULL;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->type = fetch_rnd;
+	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
+
+	/* initialise with key length */
+	fetch_rnd_data->key_len = p->key_len;
+
+	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	fetch_rnd_data->data = temp;
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		memcpy(p->key, fetch_rnd_data->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (req)
+		kfree(req);
+
+	if (temp)
+		kfree(temp);
+
+	return ret;
+}
+
+/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
+ *		struct device *dev)
+ * Deblobify the blob to get the key data and fill in secure key payload struct
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev)
+{
+	unsigned int blob_len;
+	struct sk_red_blob_decap *d_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	d_blob = &(req->req_u.sk_red_blob_decap);
+	blob_len = p->blob_len;
+	req->type = decap_type;
+
+	/*
+	 * Red blob size is the blob_len filled in payload struct
+	 * Data_sz i.e. key is the blob_len - blob header size
+	 */
+
+	d_blob->redblob_sz = blob_len;
+	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
+	total_sz = d_blob->data_sz + d_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	d_blob->redblob = temp;
+	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
+	memcpy(d_blob->redblob, p->blob, blob_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init: Failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->key_len = d_blob->data_sz;
+		memcpy(p->key, d_blob->data, p->key_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(temp);
+	if (req)
+		kfree(req);
+	return ret;
+}
+
+/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+ *		struct device *dev)
+ * To blobify the key data to get the blob. This blob can only be seen by
+ * userspace.
+ * param[in] p pointer to the secure key payload
+ * param[in] decap_type operation to be done.
+ * param[in] dev dev Pointer to job ring device structure
+ * If operation is successful return 0, otherwise error.
+ */
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev)
+{
+	unsigned int key_len;
+	struct sk_red_blob_encap *k_blob;
+	struct sk_req *req = NULL;
+	int total_sz = 0, *temp = NULL, ret = 0;
+
+	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
+	if (!req) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	key_len = p->key_len;
+
+	req->type = encap_type;
+	k_blob = &(req->req_u.sk_red_blob_encap);
+
+	/*
+	 * Data_sz i.e. key len and the corresponding blob_len is
+	 * key_len + BLOB header size.
+	 */
+
+	k_blob->data_sz = key_len;
+	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
+	total_sz = k_blob->data_sz + k_blob->redblob_sz;
+
+	temp = kmalloc(total_sz, GFP_DMA);
+	if (!temp) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	req->mem_pointer = temp;
+	k_blob->data = temp;
+
+	k_blob->redblob = k_blob->data + k_blob->data_sz;
+	memcpy(k_blob->data, p->key, key_len);
+
+	ret = caam_securekey_desc_init(dev, req);
+
+	if (ret) {
+		pr_info("caam_securekey_desc_init failed\n");
+		goto out;
+	}
+
+	ret = sk_job_submit(dev, req);
+	if (!ret) {
+		/*Copy output to key buffer. */
+		p->blob_len = k_blob->redblob_sz;
+		memcpy(p->blob, k_blob->redblob, p->blob_len);
+	} else {
+		ret = -EINVAL;
+	}
+
+out:
+	if (temp)
+		kfree(req->mem_pointer);
+	if (req)
+		kfree(req);
+	return ret;
+
+}
+
diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
new file mode 100644
index 000000000000..0ee26e95b205
--- /dev/null
+++ b/security/keys/securekey_desc.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2018 NXP
+ *
+ */
+#ifndef _SECUREKEY_DESC_H_
+#define _SECUREKEY_DESC_H_
+
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+#include "pdb.h"
+
+#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
+#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
+
+/*
+ * brief defines different kinds of operations supported by this module.
+ */
+enum sk_req_type {
+	sk_get_random,
+	sk_red_blob_enc,
+	sk_red_blob_dec,
+};
+
+
+/*
+ * struct random_des
+ * param[out] rnd_data output buffer for random data.
+ */
+struct random_desc {
+	dma_addr_t rnd_data;
+};
+
+/* struct redblob_encap_desc
+ * details Structure containing dma address for redblob encapsulation.
+ * param[in] in_data input data to redblob encap descriptor.
+ * param[out] redblob output buffer for redblob.
+ */
+struct redblob_encap_desc {
+	dma_addr_t in_data;
+	dma_addr_t redblob;
+};
+
+/* struct redblob_decap_desc
+ * details Structure containing dma address for redblob decapsulation.
+ * param[in] redblob input buffer to redblob decap descriptor.
+ * param[out] out_data output data from redblob decap descriptor.
+ */
+struct redblob_decap_desc {
+	dma_addr_t redblob;
+	dma_addr_t out_data;
+};
+
+/* struct sk_desc
+ * details Structure for securekey descriptor creation.
+ * param[in] req_type operation supported.
+ * param[in] dma_u union of struct for supported operation.
+ */
+struct sk_desc {
+	u32 req_type;
+	union {
+		struct redblob_encap_desc redblob_encapdesc;
+		struct redblob_decap_desc redblob_decapdesc;
+		struct random_desc random_descp;
+	} dma_u;
+};
+
+/* struct sk_fetch_rnd_data
+ * decriptor structure containing key length.
+ */
+struct sk_fetch_rnd_data {
+	void *data;
+	size_t key_len;
+};
+
+/* struct sk_red_blob_encap
+ * details Structure containing buffer pointers for redblob encapsulation.
+ * param[in] data Input data.
+ * param[in] data_sz size of Input data.
+ * param[out] redblob output buffer for redblob.
+ * param[in] redblob_sz size of redblob.
+ */
+struct sk_red_blob_encap {
+	void *data;
+	uint32_t data_sz;
+	void *redblob;
+	uint32_t redblob_sz;
+};
+
+/* struct sk_red_blob_decap
+ * details Structure containing buffer pointers for redblob decapsulation.
+ * param[in] redblob Input redblob.
+ * param[in] redblob_sz size of redblob.
+ * param[out] data output buffer for data.
+ * param[in] data_sz size of output data.
+ */
+struct sk_red_blob_decap {
+	void *redblob;
+	uint32_t redblob_sz;
+	void *data;
+	uint32_t data_sz;
+};
+
+/* struct sk_req
+ * details Structure for securekey request creation.
+ * param[in] type operation supported.
+ * param[in] req_u union of struct for supported operation.
+ * param[out] ret return status of CAAM operation.
+ * param[in] mem_pointer memory pointer for allocated kernel memory.
+ * param[in] desc_pointer Pointer to securekey descriptor creation structure.
+ * param[in] comp struct completion object.
+ * param[in] hwdesc contains descriptor instructions.
+ */
+struct sk_req {
+	enum sk_req_type type;
+	void *arg;
+	union {
+		struct sk_red_blob_encap sk_red_blob_encap;
+		struct sk_red_blob_decap sk_red_blob_decap;
+		struct sk_fetch_rnd_data sk_fetch_rnd_data;
+	} req_u;
+	int ret;
+	void *mem_pointer;
+	void *desc_pointer;
+	struct completion comp;
+	u32 hwdesc[MAX_CAAM_DESCSIZE];
+};
+
+int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
+		    struct device *dev);
+int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
+	     struct device *dev);
+int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
+	       struct device *dev);
+
+#endif /*_SECUREKEY_DESC_H_*/
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/2] encrypted_keys: Adds support for secure key-type as master key.
@ 2018-07-20  5:46   ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-20  5:58 UTC (permalink / raw)
  To: dhowells, zohar, jmorris, serge, linux-integrity, keyrings,
	linux-security-module, linux-kernel
  Cc: sahil.malhotra, Udit Agarwal

Encrypted keys can use secure key-type as master key along with
trusted/user keys.

Secure key as master key uses, secure key type payload derieved
using CAAM hardware.

Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
---
 MAINTAINERS                                   |  1 +
 security/keys/encrypted-keys/Makefile         |  2 +
 security/keys/encrypted-keys/encrypted.c      | 13 ++++++-
 security/keys/encrypted-keys/encrypted.h      | 13 +++++++
 .../keys/encrypted-keys/masterkey_secure.c    | 37 +++++++++++++++++++
 5 files changed, 64 insertions(+), 2 deletions(-)
 create mode 100644 security/keys/encrypted-keys/masterkey_secure.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 654be2ee4b0a..847254eec22a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7949,6 +7949,7 @@ F:	include/keys/secure-type.h
 F:	security/keys/secure_key.c
 F:	security/keys/securekey_desc.c
 F:	security/keys/securekey_desc.h
+F:	security/keys/encrypted-keys/masterkey_secure.c
 
 KEYS/KEYRINGS:
 M:	David Howells <dhowells@redhat.com>
diff --git a/security/keys/encrypted-keys/Makefile b/security/keys/encrypted-keys/Makefile
index 7a44dce6f69d..df2b906b7d24 100644
--- a/security/keys/encrypted-keys/Makefile
+++ b/security/keys/encrypted-keys/Makefile
@@ -7,5 +7,7 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o
 
 encrypted-keys-y := encrypted.o ecryptfs_format.o
 masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS) := masterkey_secure.o
 masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_SECURE_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_secure.o
 encrypted-keys-y += $(masterkey-y) $(masterkey-m-m)
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index d92cbf9687c3..258b38094705 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -39,6 +39,7 @@
 #include "ecryptfs_format.h"
 
 static const char KEY_TRUSTED_PREFIX[] = "trusted:";
+static const char KEY_SECURE_PREFIX[] = "secure:";
 static const char KEY_USER_PREFIX[] = "user:";
 static const char hash_alg[] = "sha256";
 static const char hmac_alg[] = "hmac(sha256)";
@@ -49,6 +50,7 @@ static unsigned int ivsize;
 static int blksize;
 
 #define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
+#define KEY_SECURE_PREFIX_LEN (sizeof(KEY_SECURE_PREFIX) - 1)
 #define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
 #define KEY_ECRYPTFS_DESC_LEN 16
 #define HASH_SIZE SHA256_DIGEST_SIZE
@@ -125,7 +127,7 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)
 /*
  * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key
  *
- * key-type:= "trusted:" | "user:"
+ * key-type:= "trusted:" | "user:" | "secure:"
  * desc:= master-key description
  *
  * Verify that 'key-type' is valid and that 'desc' exists. On key update,
@@ -140,6 +142,8 @@ static int valid_master_desc(const char *new_desc, const char *orig_desc)
 
 	if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN))
 		prefix_len = KEY_TRUSTED_PREFIX_LEN;
+	else if (!strncmp(new_desc, KEY_SECURE_PREFIX, KEY_SECURE_PREFIX_LEN))
+		prefix_len = KEY_SECURE_PREFIX_LEN;
 	else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN))
 		prefix_len = KEY_USER_PREFIX_LEN;
 	else
@@ -358,7 +362,7 @@ static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
 
 enum derived_key_type { ENC_KEY, AUTH_KEY };
 
-/* Derive authentication/encryption key from trusted key */
+/* Derive authentication/encryption key from trusted/secure key */
 static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
 			   const u8 *master_key, size_t master_keylen)
 {
@@ -429,6 +433,11 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
 		mkey = request_trusted_key(epayload->master_desc +
 					   KEY_TRUSTED_PREFIX_LEN,
 					   master_key, master_keylen);
+	} else if (!strncmp(epayload->master_desc, KEY_SECURE_PREFIX,
+			    KEY_SECURE_PREFIX_LEN)) {
+		mkey = request_secure_key(epayload->master_desc +
+					  KEY_SECURE_PREFIX_LEN,
+					  master_key, master_keylen);
 	} else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX,
 			    KEY_USER_PREFIX_LEN)) {
 		mkey = request_user_key(epayload->master_desc +
diff --git a/security/keys/encrypted-keys/encrypted.h b/security/keys/encrypted-keys/encrypted.h
index 1809995db452..f1cb73611e77 100644
--- a/security/keys/encrypted-keys/encrypted.h
+++ b/security/keys/encrypted-keys/encrypted.h
@@ -16,6 +16,19 @@ static inline struct key *request_trusted_key(const char *trusted_desc,
 }
 #endif
 
+#if defined(CONFIG_SECURE_KEYS)
+extern struct key *request_secure_key(const char *secure_desc,
+				      const u8 **master_key,
+				      size_t *master_keylen);
+#else
+static inline struct key *request_secure_key(const char *secure_desc,
+					     const u8 **master_key,
+					     size_t *master_keylen)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+#endif
+
 #if ENCRYPTED_DEBUG
 static inline void dump_master_key(const u8 *master_key, size_t master_keylen)
 {
diff --git a/security/keys/encrypted-keys/masterkey_secure.c b/security/keys/encrypted-keys/masterkey_secure.c
new file mode 100644
index 000000000000..87068c966111
--- /dev/null
+++ b/security/keys/encrypted-keys/masterkey_secure.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 NXP.
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <keys/secure-type.h>
+#include <keys/encrypted-type.h>
+#include "encrypted.h"
+
+/*
+ * request_secure_key - request the secure key
+ *
+ * Secure keys and their blobs are derived from CAAM hardware.
+ * Userspace manages secure  key-type data, but key data is not
+ * visible in plain form. It is presented as blobs.
+ */
+struct key *request_secure_key(const char *secure_desc,
+				const u8 **master_key, size_t *master_keylen)
+{
+	struct secure_key_payload *spayload;
+	struct key *skey;
+
+	skey = request_key(&key_type_secure, secure_desc, NULL);
+	if (IS_ERR(skey))
+		goto error;
+
+	down_read(&skey->sem);
+	spayload = skey->payload.data[0];
+	*master_key = spayload->key;
+	*master_keylen = spayload->key_len;
+error:
+	return skey;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-20  5:46 ` Udit Agarwal
  (?)
@ 2018-07-20  8:40   ` Jan Lübbe
  -1 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-20  8:40 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: sahil.malhotra

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> +=====
> +Secure Key
> +=====
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.

Thanks for working on this, so far we've been using this functionality
via a custom sysfs interface. Proper integration into the keyring
framework would be very nice!

Some questions which might influence the userspace api design:

- If I remember correctly, CAAM key blobs contain flags which specify
if the key can be exported from the CAAM after unwrapping or not (then
it stays in one of the internal key registers). Which mode do you use?

- If that's not already supported by this series, do you intend to make
secure keys (in the non-exportable-mode) usable for encryption/
decryption, so they could be used for dm-crypt? If so, you'd probably
need some resource management in the CAAM driver, as the number of key
registers is limited.

- Secure keys could also be implemented using OP-TEE for example, so
the documentation shouldn't be CAAM-specific and only use it as an
example.

Are there corresponding changes to the CAAM driver needed to test this?

Best regards,
Jan
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20  8:40   ` Jan Lübbe
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-20  8:40 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: sahil.malhotra

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> +==========
> +Secure Key
> +==========
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.

Thanks for working on this, so far we've been using this functionality
via a custom sysfs interface. Proper integration into the keyring
framework would be very nice!

Some questions which might influence the userspace api design:

- If I remember correctly, CAAM key blobs contain flags which specify
if the key can be exported from the CAAM after unwrapping or not (then
it stays in one of the internal key registers). Which mode do you use?

- If that's not already supported by this series, do you intend to make
secure keys (in the non-exportable-mode) usable for encryption/
decryption, so they could be used for dm-crypt? If so, you'd probably
need some resource management in the CAAM driver, as the number of key
registers is limited.

- Secure keys could also be implemented using OP-TEE for example, so
the documentation shouldn't be CAAM-specific and only use it as an
example.

Are there corresponding changes to the CAAM driver needed to test this?

Best regards,
Jan
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20  8:40   ` Jan Lübbe
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-20  8:40 UTC (permalink / raw)
  To: linux-security-module

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> +==========
> +Secure Key
> +==========
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.

Thanks for working on this, so far we've been using this functionality
via a custom sysfs interface. Proper integration into the keyring
framework would be very nice!

Some questions which might influence the userspace api design:

- If I remember correctly, CAAM key blobs contain flags which specify
if the key can be exported from the CAAM after unwrapping or not (then
it stays in one of the internal key registers). Which mode do you use?

- If that's not already supported by this series, do you intend to make
secure keys (in the non-exportable-mode) usable for encryption/
decryption, so they could be used for dm-crypt? If so, you'd probably
need some resource management in the CAAM driver, as the number of key
registers is limited.

- Secure keys could also be implemented using OP-TEE for example, so
the documentation shouldn't be CAAM-specific and only use it as an
example.

Are there corresponding changes to the CAAM driver needed to test this?

Best regards,
Jan
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-20  5:46 ` Udit Agarwal
  (?)
@ 2018-07-20 18:37   ` kbuild test robot
  -1 siblings, 0 replies; 32+ messages in thread
From: kbuild test robot @ 2018-07-20 18:37 UTC (permalink / raw)
  To: keyrings

[-- Attachment #1: Type: text/plain, Size: 1529 bytes --]

Hi Udit,

I love your patch! Yet something to improve:

[auto build test ERROR on security/next]
[also build test ERROR on v4.18-rc5 next-20180720]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Udit-Agarwal/security-keys-secure_key-Adds-the-secure-key-support-based-on-CAAM/20180720-142144
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   In file included from security/keys/securekey_desc.c:8:0:
>> security/keys/securekey_desc.h:9:10: fatal error: compat.h: No such file or directory
    #include "compat.h"
             ^~~~~~~~~~
   compilation terminated.

vim +9 security/keys/securekey_desc.h

     8	
   > 9	#include "compat.h"
    10	#include "regs.h"
    11	#include "intern.h"
    12	#include "desc.h"
    13	#include "desc_constr.h"
    14	#include "jr.h"
    15	#include "error.h"
    16	#include "pdb.h"
    17	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 63424 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20 18:37   ` kbuild test robot
  0 siblings, 0 replies; 32+ messages in thread
From: kbuild test robot @ 2018-07-20 18:37 UTC (permalink / raw)
  To: Udit Agarwal
  Cc: kbuild-all, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel, sahil.malhotra,
	Udit Agarwal

[-- Attachment #1: Type: text/plain, Size: 1529 bytes --]

Hi Udit,

I love your patch! Yet something to improve:

[auto build test ERROR on security/next]
[also build test ERROR on v4.18-rc5 next-20180720]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Udit-Agarwal/security-keys-secure_key-Adds-the-secure-key-support-based-on-CAAM/20180720-142144
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   In file included from security/keys/securekey_desc.c:8:0:
>> security/keys/securekey_desc.h:9:10: fatal error: compat.h: No such file or directory
    #include "compat.h"
             ^~~~~~~~~~
   compilation terminated.

vim +9 security/keys/securekey_desc.h

     8	
   > 9	#include "compat.h"
    10	#include "regs.h"
    11	#include "intern.h"
    12	#include "desc.h"
    13	#include "desc_constr.h"
    14	#include "jr.h"
    15	#include "error.h"
    16	#include "pdb.h"
    17	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 63424 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-20 18:37   ` kbuild test robot
  0 siblings, 0 replies; 32+ messages in thread
From: kbuild test robot @ 2018-07-20 18:37 UTC (permalink / raw)
  To: Udit Agarwal
  Cc: kbuild-all, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel, sahil.malhotra,
	Udit Agarwal

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: multipart/mixed; boundary="/9DWx/yDrRhgMJTb", Size: 1606 bytes --]

Hi Udit,

I love your patch! Yet something to improve:

[auto build test ERROR on security/next]
[also build test ERROR on v4.18-rc5 next-20180720]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Udit-Agarwal/security-keys-secure_key-Adds-the-secure-key-support-based-on-CAAM/20180720-142144
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git next
config: arm-allmodconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   In file included from security/keys/securekey_desc.c:8:0:
>> security/keys/securekey_desc.h:9:10: fatal error: compat.h: No such file or directory
    #include "compat.h"
             ^~~~~~~~~~
   compilation terminated.

vim +9 security/keys/securekey_desc.h

     8	
   > 9	#include "compat.h"
    10	#include "regs.h"
    11	#include "intern.h"
    12	#include "desc.h"
    13	#include "desc_constr.h"
    14	#include "jr.h"
    15	#include "error.h"
    16	#include "pdb.h"
    17	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation


    [ Part 2, Application/GZIP 65 KB. ]
    [ Unable to print this part. ]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-20  8:40   ` Jan Lübbe
  (?)
  (?)
@ 2018-07-21 14:44     ` Udit Agarwal
  -1 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-21 14:44 UTC (permalink / raw)
  To: Jan Lübbe, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

SGksDQoNClRoYW5rcyBmb3Igc2hhcmluZyB0aGUgZG9jdW1lbnRhdGlvbiBjaGFuZ2VzIGFuZCBm
ZWVkYmFjay4NCg0KQmVsb3cgYXJlIHRoZSBhbnN3ZXJzIHRvIHRoZSBxdWVzdGlvbnM6DQoNCjEu
IEN1cnJlbnRseSB0aGUgc2VjdXJlIGtleSBwYXRjaCBzZXJpZXMgaGFzIGJlZW4gYWRkZWQgIHRv
IHN1cHBvcnQgb25seSBkYXRhIGJsb2JzLg0KSXQgaXMgbm90IHN1cHBvcnRpbmcga2V5IGJsb2Jz
IGFzIG9mIG5vdywgd2UgaGF2ZSB0aG91Z2h0IG9mIGFkZGluZyB0aGF0IHN1cHBvcnQgaW4gZnV0
dXJlLg0KDQoyLiBZZXMgc2VjdXJlIGtleXMgY291bGQgYWxzbyBiZSBpbXBsZW1lbnRlZCB1c2lu
ZyBPUFRFRS4gSSB3aWxsIGNoYW5nZSB0aGUgDQpkb2N1bWVudGF0aW9uIGluIG5leHQgcGF0Y2gg
dmVyc2lvbi4NCg0KQmVzdCByZWdhcmRzLA0KVWRpdCBBZ2Fyd2FsDQoNCg0KPiAtLS0tLU9yaWdp
bmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBKYW4gTMO8YmJlIFttYWlsdG86amx1QHBlbmd1dHJv
bml4LmRlXQ0KPiBTZW50OiBGcmlkYXksIEp1bHkgMjAsIDIwMTggMjoxMSBQTQ0KPiBUbzogVWRp
dCBBZ2Fyd2FsIDx1ZGl0LmFnYXJ3YWxAbnhwLmNvbT47IGRob3dlbGxzQHJlZGhhdC5jb207DQo+
IHpvaGFyQGxpbnV4LnZuZXQuaWJtLmNvbTsgam1vcnJpc0BuYW1laS5vcmc7IHNlcmdlQGhhbGx5
bi5jb207IGxpbnV4LQ0KPiBpbnRlZ3JpdHlAdmdlci5rZXJuZWwub3JnOyBrZXlyaW5nc0B2Z2Vy
Lmtlcm5lbC5vcmc7IGxpbnV4LXNlY3VyaXR5LQ0KPiBtb2R1bGVAdmdlci5rZXJuZWwub3JnOyBs
aW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnDQo+IENjOiBTYWhpbCBNYWxob3RyYSA8c2FoaWwu
bWFsaG90cmFAbnhwLmNvbT4NCj4gU3ViamVjdDogUmU6IFtQQVRDSCAxLzJdIHNlY3VyaXR5L2tl
eXMvc2VjdXJlX2tleTogQWRkcyB0aGUgc2VjdXJlIGtleSBzdXBwb3J0IGJhc2VkIG9uDQo+IENB
QU0uDQo+IA0KPiBPbiBGcmksIDIwMTgtMDctMjAgYXQgMTE6MTYgKzA1MzAsIFVkaXQgQWdhcndh
bCB3cm90ZToNCj4gPiArPT09PT09PT09PQ0KPiA+ICtTZWN1cmUgS2V5DQo+ID4gKz09PT09PT09
PT0NCj4gPiArDQo+ID4gK1NlY3VyZSBrZXkgaXMgdGhlIG5ldyB0eXBlIGFkZGVkIHRvIGtlcm5l
bCBrZXkgcmluZyBzZXJ2aWNlLg0KPiA+ICtTZWN1cmUga2V5IGlzIGEgc3ltbWV0cmljIHR5cGUg
a2V5IG9mIG1pbmltdW0gbGVuZ3RoIDMyIGJ5dGVzIGFuZA0KPiA+ICt3aXRoIG1heGltdW0gcG9z
c2libGUgbGVuZ3RoIHRvIGJlIDEyOCBieXRlcy4gSXQgaXMgcHJvZHVjZWQgaW4NCj4gPiAra2Vy
bmVsIHVzaW5nIHRoZSBDQUFNIGNyeXB0byBlbmdpbmUuIFVzZXJzcGFjZSBjYW4gb25seSBzZWUg
dGhlIGJsb2INCj4gPiArZm9yIHRoZSBjb3JyZXNwb25kaW5nIGtleS4gQWxsIHRoZSBibG9icyBh
cmUgZGlzcGxheWVkIG9yIGxvYWRlZCBpbg0KPiA+ICtoZXggYXNjaWkuDQo+ID4gKw0KPiA+ICtT
ZWN1cmUga2V5IGNhbiBvbmx5IGJlIGNyZWF0ZWQgb24gcGxhdGZvcm1zIHdoaWNoIHN1cHBvcnRz
IENBQU0NCj4gPiAraGFyZHdhcmUgYmxvY2suIFNlY3VyZSBrZXkgY2FuIGFsc28gYmUgdXNlZCBh
cyBhIG1hc3RlciBrZXkgdG8gY3JlYXRlDQo+ID4gK3RoZSBlbmNyeXB0ZWQga2V5cyBhbG9uZyB3
aXRoIHRoZSBleGlzdGluZyBrZXkgdHlwZXMgaW4ga2VybmVsLg0KPiA+ICsNCj4gPiArU2VjdXJl
IGtleSB1c2VzIENBQU0gaGFyZHdhcmUgdG8gZ2VuZXJhdGUgdGhlIGtleSBhbmQgYmxvYmlmeSBp
dHMNCj4gPiArY29udGVudCBmb3IgdXNlcnNwYWNlLiBHZW5lcmF0ZWQgYmxvYnMgYXJlIHRpZWQg
dXAgd2l0aCB0aGUgaGFyZHdhcmUNCj4gPiArc2VjcmV0IGtleSBzdG9yZWQgaW4gQ0FBTSwgaGVu
Y2UgdGhlIHNhbWUgYmxvYiB3aWxsIG5vdCBiZSBhYmxlIHRvDQo+ID4gK2RlLWJsb2JpZnkgd2l0
aCB0aGUgZGlmZmVyZW50IHNlY3JldCBrZXkgb24gYW5vdGhlciBtYWNoaW5lLg0KPiANCj4gVGhh
bmtzIGZvciB3b3JraW5nIG9uIHRoaXMsIHNvIGZhciB3ZSd2ZSBiZWVuIHVzaW5nIHRoaXMgZnVu
Y3Rpb25hbGl0eSB2aWEgYSBjdXN0b20gc3lzZnMNCj4gaW50ZXJmYWNlLiBQcm9wZXIgaW50ZWdy
YXRpb24gaW50byB0aGUga2V5cmluZyBmcmFtZXdvcmsgd291bGQgYmUgdmVyeSBuaWNlIQ0KPiAN
Cj4gU29tZSBxdWVzdGlvbnMgd2hpY2ggbWlnaHQgaW5mbHVlbmNlIHRoZSB1c2Vyc3BhY2UgYXBp
IGRlc2lnbjoNCj4gDQo+IC0gSWYgSSByZW1lbWJlciBjb3JyZWN0bHksIENBQU0ga2V5IGJsb2Jz
IGNvbnRhaW4gZmxhZ3Mgd2hpY2ggc3BlY2lmeSBpZiB0aGUga2V5IGNhbiBiZQ0KPiBleHBvcnRl
ZCBmcm9tIHRoZSBDQUFNIGFmdGVyIHVud3JhcHBpbmcgb3Igbm90ICh0aGVuIGl0IHN0YXlzIGlu
IG9uZSBvZiB0aGUgaW50ZXJuYWwga2V5DQo+IHJlZ2lzdGVycykuIFdoaWNoIG1vZGUgZG8geW91
IHVzZT8NCj4gDQo+IC0gSWYgdGhhdCdzIG5vdCBhbHJlYWR5IHN1cHBvcnRlZCBieSB0aGlzIHNl
cmllcywgZG8geW91IGludGVuZCB0byBtYWtlIHNlY3VyZSBrZXlzIChpbiB0aGUNCj4gbm9uLWV4
cG9ydGFibGUtbW9kZSkgdXNhYmxlIGZvciBlbmNyeXB0aW9uLyBkZWNyeXB0aW9uLCBzbyB0aGV5
IGNvdWxkIGJlIHVzZWQgZm9yIGRtLQ0KPiBjcnlwdD8gSWYgc28sIHlvdSdkIHByb2JhYmx5IG5l
ZWQgc29tZSByZXNvdXJjZSBtYW5hZ2VtZW50IGluIHRoZSBDQUFNIGRyaXZlciwgYXMgdGhlDQo+
IG51bWJlciBvZiBrZXkgcmVnaXN0ZXJzIGlzIGxpbWl0ZWQuDQo+IA0KPiAtIFNlY3VyZSBrZXlz
IGNvdWxkIGFsc28gYmUgaW1wbGVtZW50ZWQgdXNpbmcgT1AtVEVFIGZvciBleGFtcGxlLCBzbyB0
aGUNCj4gZG9jdW1lbnRhdGlvbiBzaG91bGRuJ3QgYmUgQ0FBTS1zcGVjaWZpYyBhbmQgb25seSB1
c2UgaXQgYXMgYW4gZXhhbXBsZS4NCj4gDQo+IEFyZSB0aGVyZSBjb3JyZXNwb25kaW5nIGNoYW5n
ZXMgdG8gdGhlIENBQU0gZHJpdmVyIG5lZWRlZCB0byB0ZXN0IHRoaXM/DQo+IA0KPiBCZXN0IHJl
Z2FyZHMsDQo+IEphbg0KPiAtLQ0KPiBQZW5ndXRyb25peCBlLksuICAgICAgICAgICAgICAgICAg
ICAgICAgICAgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KPiBJbmR1c3RyaWFsIExp
bnV4IFNvbHV0aW9ucyAgICAgICAgICAgICAgICAgfA0KPiBodHRwczovL2VtZWEwMS5zYWZlbGlu
a3MucHJvdGVjdGlvbi5vdXRsb29rLmNvbS8/dXJsPWh0dHAlM0ElMkYlMkZ3d3cucGVuZ3V0cm9u
aXgNCj4gLmRlJTJGJmFtcDtkYXRhPTAyJTdDMDElN0N1ZGl0LmFnYXJ3YWwlNDBueHAuY29tJTdD
MDFkMTIwODc0OGRhNGEyYWUzMjMwOA0KPiBkNWVlMWM4MTg5JTdDNjg2ZWExZDNiYzJiNGM2ZmE5
MmNkOTljNWMzMDE2MzUlN0MwJTdDMSU3QzYzNjY3NjcyODU2NzcxODQNCj4gOTMmYW1wO3NkYXRh
PXJSeFpUbGMlMkJicnZEOVZHTDZmV2x4UyUyQmNMV0l0MFJxRXYxVlQwekNMRXM0JTNEJmFtcDsN
Cj4gcmVzZXJ2ZWQ9MCAgfA0KPiBQZWluZXIgU3RyLiA2LTgsIDMxMTM3IEhpbGRlc2hlaW0sIEdl
cm1hbnkgfCBQaG9uZTogKzQ5LTUxMjEtMjA2OTE3LTAgICAgfA0KPiBBbXRzZ2VyaWNodCBIaWxk
ZXNoZWltLCBIUkEgMjY4NiAgICAgICAgICAgfCBGYXg6ICAgKzQ5LTUxMjEtMjA2OTE3LTU1NTUg
fA0K

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-21 14:44     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-21 14:44 UTC (permalink / raw)
  To: Jan Lübbe, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

Hi,

Thanks for sharing the documentation changes and feedback.

Below are the answers to the questions:

1. Currently the secure key patch series has been added  to support only data blobs.
It is not supporting key blobs as of now, we have thought of adding that support in future.

2. Yes secure keys could also be implemented using OPTEE. I will change the 
documentation in next patch version.

Best regards,
Udit Agarwal


> -----Original Message-----
> From: Jan Lübbe [mailto:jlu@pengutronix.de]
> Sent: Friday, July 20, 2018 2:11 PM
> To: Udit Agarwal <udit.agarwal@nxp.com>; dhowells@redhat.com;
> zohar@linux.vnet.ibm.com; jmorris@namei.org; serge@hallyn.com; linux-
> integrity@vger.kernel.org; keyrings@vger.kernel.org; linux-security-
> module@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Sahil Malhotra <sahil.malhotra@nxp.com>
> Subject: Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on
> CAAM.
> 
> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> 
> Thanks for working on this, so far we've been using this functionality via a custom sysfs
> interface. Proper integration into the keyring framework would be very nice!
> 
> Some questions which might influence the userspace api design:
> 
> - If I remember correctly, CAAM key blobs contain flags which specify if the key can be
> exported from the CAAM after unwrapping or not (then it stays in one of the internal key
> registers). Which mode do you use?
> 
> - If that's not already supported by this series, do you intend to make secure keys (in the
> non-exportable-mode) usable for encryption/ decryption, so they could be used for dm-
> crypt? If so, you'd probably need some resource management in the CAAM driver, as the
> number of key registers is limited.
> 
> - Secure keys could also be implemented using OP-TEE for example, so the
> documentation shouldn't be CAAM-specific and only use it as an example.
> 
> Are there corresponding changes to the CAAM driver needed to test this?
> 
> Best regards,
> Jan
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix
> .de%2F&amp;data=02%7C01%7Cudit.agarwal%40nxp.com%7C01d1208748da4a2ae32308
> d5ee1c8189%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C6366767285677184
> 93&amp;sdata=rRxZTlc%2BbrvD9VGL6fWlxS%2BcLWIt0RqEv1VT0zCLEs4%3D&amp;
> reserved=0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-21 14:44     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-21 14:44 UTC (permalink / raw)
  To: linux-security-module

Hi,

Thanks for sharing the documentation changes and feedback.

Below are the answers to the questions:

1. Currently the secure key patch series has been added  to support only data blobs.
It is not supporting key blobs as of now, we have thought of adding that support in future.

2. Yes secure keys could also be implemented using OPTEE. I will change the 
documentation in next patch version.

Best regards,
Udit Agarwal


> -----Original Message-----
> From: Jan L??bbe [mailto:jlu at pengutronix.de]
> Sent: Friday, July 20, 2018 2:11 PM
> To: Udit Agarwal <udit.agarwal@nxp.com>; dhowells at redhat.com;
> zohar at linux.vnet.ibm.com; jmorris at namei.org; serge at hallyn.com; linux-
> integrity at vger.kernel.org; keyrings at vger.kernel.org; linux-security-
> module at vger.kernel.org; linux-kernel at vger.kernel.org
> Cc: Sahil Malhotra <sahil.malhotra@nxp.com>
> Subject: Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on
> CAAM.
> 
> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> 
> Thanks for working on this, so far we've been using this functionality via a custom sysfs
> interface. Proper integration into the keyring framework would be very nice!
> 
> Some questions which might influence the userspace api design:
> 
> - If I remember correctly, CAAM key blobs contain flags which specify if the key can be
> exported from the CAAM after unwrapping or not (then it stays in one of the internal key
> registers). Which mode do you use?
> 
> - If that's not already supported by this series, do you intend to make secure keys (in the
> non-exportable-mode) usable for encryption/ decryption, so they could be used for dm-
> crypt? If so, you'd probably need some resource management in the CAAM driver, as the
> number of key registers is limited.
> 
> - Secure keys could also be implemented using OP-TEE for example, so the
> documentation shouldn't be CAAM-specific and only use it as an example.
> 
> Are there corresponding changes to the CAAM driver needed to test this?
> 
> Best regards,
> Jan
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix
> .de%2F&amp;data=02%7C01%7Cudit.agarwal%40nxp.com%7C01d1208748da4a2ae32308
> d5ee1c8189%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C6366767285677184
> 93&amp;sdata=rRxZTlc%2BbrvD9VGL6fWlxS%2BcLWIt0RqEv1VT0zCLEs4%3D&amp;
> reserved=0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
????{.n?+???????+%???????\x17??w??{.n?+????{??????????v?^?)????w*\x1fjg???\x1e???????j??\a??G??????\f???j:+v???w?j?m?????\x1e??\x1e?w?????f???h?????????

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-21 14:44     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-21 14:44 UTC (permalink / raw)
  To: Jan Lübbe, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

Hi,

Thanks for sharing the documentation changes and feedback.

Below are the answers to the questions:

1. Currently the secure key patch series has been added  to support only data blobs.
It is not supporting key blobs as of now, we have thought of adding that support in future.

2. Yes secure keys could also be implemented using OPTEE. I will change the 
documentation in next patch version.

Best regards,
Udit Agarwal


> -----Original Message-----
> From: Jan Lubbe [mailto:jlu@pengutronix.de]
> Sent: Friday, July 20, 2018 2:11 PM
> To: Udit Agarwal <udit.agarwal@nxp.com>; dhowells@redhat.com;
> zohar@linux.vnet.ibm.com; jmorris@namei.org; serge@hallyn.com; linux-
> integrity@vger.kernel.org; keyrings@vger.kernel.org; linux-security-
> module@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Sahil Malhotra <sahil.malhotra@nxp.com>
> Subject: Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on
> CAAM.
> 
> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> 
> Thanks for working on this, so far we've been using this functionality via a custom sysfs
> interface. Proper integration into the keyring framework would be very nice!
> 
> Some questions which might influence the userspace api design:
> 
> - If I remember correctly, CAAM key blobs contain flags which specify if the key can be
> exported from the CAAM after unwrapping or not (then it stays in one of the internal key
> registers). Which mode do you use?
> 
> - If that's not already supported by this series, do you intend to make secure keys (in the
> non-exportable-mode) usable for encryption/ decryption, so they could be used for dm-
> crypt? If so, you'd probably need some resource management in the CAAM driver, as the
> number of key registers is limited.
> 
> - Secure keys could also be implemented using OP-TEE for example, so the
> documentation shouldn't be CAAM-specific and only use it as an example.
> 
> Are there corresponding changes to the CAAM driver needed to test this?
> 
> Best regards,
> Jan
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix
> .de%2F&amp;data=02%7C01%7Cudit.agarwal%40nxp.com%7C01d1208748da4a2ae32308
> d5ee1c8189%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C6366767285677184
> 93&amp;sdata=rRxZTlc%2BbrvD9VGL6fWlxS%2BcLWIt0RqEv1VT0zCLEs4%3D&amp;
> reserved=0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-20  5:46 ` Udit Agarwal
  (?)
  (?)
@ 2018-07-22 23:34   ` Mimi Zohar
  -1 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-22 23:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: sahil.malhotra

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> Secure keys are derieved using CAAM crypto block.
> 
> Secure keys derieved are the random number symmetric keys from CAAM.
> Blobs corresponding to the key are formed using CAAM. User space
> will only be able to view the blob of the key.

The term "trusted keys" comes from the usage of the Trusted Platform
Module (TPM).  The term "trusted" now also refers to keyrings, which
has nothing to do with a TPM.

What is the correlation between the term "secure keys" and CAAM?  Are
"secure keys", as defined in this patch, limited to a specific HW
crypto device?

Mimi

> 
> Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> ---
>  Documentation/security/keys/secure-key.rst |  67 +++
>  MAINTAINERS                                |  11 +
>  include/keys/secure-type.h                 |  33 ++
>  security/keys/Kconfig                      |  11 +
>  security/keys/Makefile                     |   3 +
>  security/keys/secure_key.c                 | 339 ++++++++++++
>  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
>  security/keys/securekey_desc.h             | 141 +++++
>  8 files changed, 1211 insertions(+)
>  create mode 100644 Documentation/security/keys/secure-key.rst
>  create mode 100644 include/keys/secure-type.h
>  create mode 100644 security/keys/secure_key.c
>  create mode 100644 security/keys/securekey_desc.c
>  create mode 100644 security/keys/securekey_desc.h
> 
> diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
> new file mode 100644
> index 000000000000..0fc3367b00f8
> --- /dev/null
> +++ b/Documentation/security/keys/secure-key.rst
> @@ -0,0 +1,67 @@
> +=====
> +Secure Key
> +=====
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.
> +
> +Usage::
> +
> +	keyctl add secure <name> "new <keylen>" <ring>
> +	keyctl load secure <name> "load <hex_blob>" <ring>
> +	keyctl print <key_id>
> +
> +"keyctl add secure" option will create the random data of the
> +specified key len using CAAM and store it as a key in kernel.
> +Key contents will be displayed as blobs to the user in hex ascii.
> +User can input key len from 32 bytes to 128 bytes.
> +
> +"keyctl load secure" option will load the blob contents. In kernel,
> +key will be deirved using input blob and CAAM, along with the secret
> +key stored in CAAM.
> +
> +"keyctl print" will return the hex string of the blob corresponding to
> +key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
> +the header bytes added by the CAAM.
> +
> +Example of secure key usage::
> +
> +1. Create the secure key with name kmk-master of length 32 bytes::
> +
> +	$ keyctl add secure kmk-master "new 32" @u
> +	46001928
> +
> +	$keyctl show
> +	Session Keyring
> +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> +
> +2. Print the blob contents for the kmk-master key::
> +
> +	$ keyctl print 46001928
> +	d9743445b640f3d59c1670dddc0bc9c2
> +	34fc9aab7dd05c965e6120025012f029b
> +	07faa4776c4f6ed02899e35a135531e9a
> +	6e5c2b51132f9d5aef28f68738e658296
> +	3fe583177cfe50d2542b659a13039
> +
> +	$ keyctl pipe 46001928 > secure_key.blob
> +
> +3. Load the blob in the user key ring::
> +
> +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9fd5e8808208..654be2ee4b0a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
>  F:	security/keys/trusted.c
>  F:	security/keys/trusted.h
> 
> +KEYS-SECURE
> +M:	Udit Agarwal <udit.agarwal@nxp.com>
> +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> +L:	linux-security-module@vger.kernel.org
> +L:	keyrings@vger.kernel.org
> +S:	Supported
> +F:	include/keys/secure-type.h
> +F:	security/keys/secure_key.c
> +F:	security/keys/securekey_desc.c
> +F:	security/keys/securekey_desc.h
> +
>  KEYS/KEYRINGS:
>  M:	David Howells <dhowells@redhat.com>
>  L:	keyrings@vger.kernel.org
> diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> new file mode 100644
> index 000000000000..5b7a5f144e41
> --- /dev/null
> +++ b/include/keys/secure-type.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 NXP.
> + *
> + */
> +
> +#ifndef _KEYS_SECURE_TYPE_H
> +#define _KEYS_SECURE_TYPE_H
> +
> +#include <linux/key.h>
> +#include <linux/rcupdate.h>
> +
> +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> + * is 128 bytes.
> + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> + */
> +
> +#define MIN_KEY_SIZE                    32
> +#define MAX_KEY_SIZE                    128
> +#define BLOB_HEADER_SIZE		48
> +
> +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> +
> +struct secure_key_payload {
> +	struct rcu_head rcu;
> +	unsigned int key_len;
> +	unsigned int blob_len;
> +	unsigned char key[MAX_KEY_SIZE + 1];
> +	unsigned char blob[MAX_BLOB_SIZE];
> +};
> +
> +extern struct key_type key_type_secure;
> +#endif
> diff --git a/security/keys/Kconfig b/security/keys/Kconfig
> index 6462e6654ccf..7eb138b5a54f 100644
> --- a/security/keys/Kconfig
> +++ b/security/keys/Kconfig
> @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> 
>  	  If you are unsure as to whether this is required, answer N.
> 
> +config SECURE_KEYS
> +	tristate "SECURE_KEYS"
> +	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> +	help
> +	  This option provide support for creating secure-type key and blobs
> +	  in kernel. Secure keys are random number symmetric keys generated
> +	  from CAAM. The CAAM creates the blobs for the random key.
> +	  Userspace will only be able to see the blob.
> +
> +	  If you are unsure as to whether this is required, answer N.
> +
>  config ENCRYPTED_KEYS
>  	tristate "ENCRYPTED KEYS"
>  	depends on KEYS
> diff --git a/security/keys/Makefile b/security/keys/Makefile
> index ef1581b337a3..606ba4efb9e6 100644
> --- a/security/keys/Makefile
> +++ b/security/keys/Makefile
> @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
>  #
>  obj-$(CONFIG_BIG_KEYS) += big_key.o
>  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
>  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
> diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
> new file mode 100644
> index 000000000000..ec8ad4394549
> --- /dev/null
> +++ b/security/keys/secure_key.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2018 NXP
> + * Secure key is generated using NXP CAAM hardware block. CAAM generates the
> + * random number (used as a key) and creates its blob for the user.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/parser.h>
> +#include <linux/string.h>
> +#include <linux/key-type.h>
> +#include <linux/rcupdate.h>
> +#include <keys/secure-type.h>
> +#include <linux/completion.h>
> +
> +#include "securekey_desc.h"
> +
> +static const char hmac_alg[] = "hmac(sha1)";
> +static const char hash_alg[] = "sha1";
> +
> +static struct crypto_shash *hashalg;
> +static struct crypto_shash *hmacalg;
> +
> +enum {
> +	error = -1,
> +	new_key,
> +	load_blob,
> +};
> +
> +static const match_table_t key_tokens = {
> +	{new_key, "new"},
> +	{load_blob, "load"},
> +	{error, NULL}
> +};
> +
> +static struct secure_key_payload *secure_payload_alloc(struct key *key)
> +{
> +	struct secure_key_payload *sec_key = NULL;
> +	int ret = 0;
> +
> +	ret = key_payload_reserve(key, sizeof(*sec_key));
> +	if (ret < 0)
> +		goto out;
> +
> +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> +	if (!sec_key)
> +		goto out;
> +
> +out:
> +	return sec_key;
> +}
> +
> +/*
> + * parse_inputdata - parse the keyctl input data and fill in the
> + *		     payload structure for key or its blob.
> + * param[in]: data pointer to the data to be parsed for creating key.
> + * param[in]: p pointer to secure key payload structure to fill parsed data
> + * On success returns 0, otherwise -EINVAL.
> + */
> +static int parse_inputdata(char *data, struct secure_key_payload *p)
> +{
> +	substring_t args[MAX_OPT_ARGS];
> +	long keylen = 0;
> +	int ret = -EINVAL;
> +	int key_cmd = -EINVAL;
> +	char *c = NULL;
> +
> +	c = strsep(&data, " \t");
> +	if (!c) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Get the keyctl command i.e. new_key or load_blob etc */
> +	key_cmd = match_token(c, key_tokens, args);
> +
> +	switch (key_cmd) {
> +	case new_key:
> +		/* first argument is key size */
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = kstrtol(c, 10, &keylen);
> +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> +						keylen > MAX_KEY_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		p->key_len = keylen;
> +		ret = new_key;
> +
> +		break;
> +	case load_blob:
> +		/* first argument is blob data for CAAM*/
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		/* Blob_len = No of characters in blob/2 */
> +		p->blob_len = strlen(c) / 2;
> +		if (p->blob_len > MAX_BLOB_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = hex2bin(p->blob, c, p->blob_len);
> +		if (ret < 0) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		ret = load_blob;
> +
> +		break;
> +	case error:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	return ret;
> +}
> +
> +/*
> + * secure_instantiate - create a new secure type key.
> + * Supports the operation to generate a new key. A random number
> + * is generated from CAAM as key data and the corresponding red blob
> + * is formed and stored as key_blob.
> + * Also supports the operation to load the blob and key is derived using
> + * that blob from CAAM.
> + * On success, return 0. Otherwise return errno.
> + */
> +static int secure_instantiate(struct key *key,
> +		struct key_preparsed_payload *prep)
> +{
> +	struct secure_key_payload *payload = NULL;
> +	size_t datalen = prep->datalen;
> +	char *data = NULL;
> +	int key_cmd = 0;
> +	int ret = 0;
> +	enum sk_req_type sk_op_type;
> +	struct device *dev = NULL;
> +
> +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	data = kmalloc(datalen + 1, GFP_KERNEL);
> +	if (!data) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	memcpy(data, prep->data, datalen);
> +	data[datalen] = '\0';
> +
> +	payload = secure_payload_alloc(key);
> +	if (!payload) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Allocate caam job ring for operation to be performed from CAAM */
> +	dev = caam_jr_alloc();
> +	if (!dev) {
> +		pr_info("caam_jr_alloc failed\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	key_cmd = parse_inputdata(data, payload);
> +	if (key_cmd < 0) {
> +		ret = key_cmd;
> +		goto out;
> +	}
> +
> +	switch (key_cmd) {
> +	case load_blob:
> +		/*
> +		 * Red blob decryption to be done for load operation
> +		 * to derive the key.
> +		 */
> +		sk_op_type = sk_red_blob_dec;
> +		ret = key_deblob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	case new_key:
> +		/* Get Random number from caam of the specified length */
> +		sk_op_type = sk_get_random;
> +		ret = caam_get_random(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: get_random fail (%d)\n", ret);
> +			goto out;
> +		}
> +
> +		/* Generate red blob of key random bytes with CAAM */
> +		sk_op_type = sk_red_blob_enc;
> +		ret = key_blob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +out:
> +	if (data)
> +		kzfree(data);
> +	if (dev)
> +		caam_jr_free(dev);
> +
> +	if (!ret)
> +		rcu_assign_keypointer(key, payload);
> +	else
> +		kzfree(payload);
> +
> +	return ret;
> +}
> +
> +/*
> + * secure_read - copy the  blob data to userspace in hex.
> + * param[in]: key pointer to key struct
> + * param[in]: buffer pointer to user data for creating key
> + * param[in]: buflen is the length of the buffer
> + * On success, return to userspace the secure key data size.
> + */
> +static long secure_read(const struct key *key, char __user *buffer,
> +			 size_t buflen)
> +{
> +	const struct secure_key_payload *p = NULL;
> +	char *ascii_buf;
> +	char *bufp;
> +	int i;
> +
> +	p = dereference_key_locked(key);
> +	if (!p)
> +		return -EINVAL;
> +
> +	if (buffer && buflen >= 2 * p->blob_len) {
> +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> +		if (!ascii_buf)
> +			return -ENOMEM;
> +
> +		bufp = ascii_buf;
> +		for (i = 0; i < p->blob_len; i++)
> +			bufp = hex_byte_pack(bufp, p->blob[i]);
> +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> +			kzfree(ascii_buf);
> +			return -EFAULT;
> +		}
> +		kzfree(ascii_buf);
> +	}
> +	return 2 * p->blob_len;
> +}
> +
> +/*
> + * secure_destroy - clear and free the key's payload
> + */
> +static void secure_destroy(struct key *key)
> +{
> +	kzfree(key->payload.data[0]);
> +}
> +
> +struct key_type key_type_secure = {
> +	.name = "secure",
> +	.instantiate = secure_instantiate,
> +	.destroy = secure_destroy,
> +	.read = secure_read,
> +};
> +EXPORT_SYMBOL_GPL(key_type_secure);
> +
> +static void secure_shash_release(void)
> +{
> +	if (hashalg)
> +		crypto_free_shash(hashalg);
> +	if (hmacalg)
> +		crypto_free_shash(hmacalg);
> +}
> +
> +static int __init secure_shash_alloc(void)
> +{
> +	int ret;
> +
> +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hmacalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hmac_alg);
> +		return PTR_ERR(hmacalg);
> +	}
> +
> +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hashalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hash_alg);
> +		ret = PTR_ERR(hashalg);
> +		goto hashalg_fail;
> +	}
> +
> +	return 0;
> +
> +hashalg_fail:
> +	crypto_free_shash(hmacalg);
> +	return ret;
> +}
> +
> +static int __init init_secure_key(void)
> +{
> +	int ret;
> +
> +	ret = secure_shash_alloc();
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = register_key_type(&key_type_secure);
> +	if (ret < 0)
> +		secure_shash_release();
> +	return ret;
> +}
> +
> +static void __exit cleanup_secure_key(void)
> +{
> +	secure_shash_release();
> +	unregister_key_type(&key_type_secure);
> +}
> +
> +late_initcall(init_secure_key);
> +module_exit(cleanup_secure_key);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
> new file mode 100644
> index 000000000000..a4fa811a5753
> --- /dev/null
> +++ b/security/keys/securekey_desc.c
> @@ -0,0 +1,606 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 NXP
> + *
> + */
> +
> +#include <keys/secure-type.h>
> +#include "securekey_desc.h"
> +
> +/* key modifier for blob encapsulation & decapsulation descriptor */
> +u8 key_modifier[] = "SECURE_KEY";
> +u32 key_modifier_len = 10;
> +
> +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct random_desc *rnd_desc = NULL;
> +	size_t len = 0;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +	len = fetch_rnd_data->key_len;
> +
> +	/* command 0x82500000 */
> +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> +			OP_ALG_ALGSEL_RNG);
> +	/* command 0x60340000 | len */
> +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> +	append_ptr(desc, rnd_desc->rnd_data);
> +}
> +
> +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_encap_desc *red_blob_desc > +					&skdesc->dma_u.redblob_encapdesc;
> +	struct sk_red_blob_encap *red_blob_req > +					&skreq->req_u.sk_red_blob_encap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> +			  0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> +			   red_blob_req->redblob_sz, 0);
> +
> +	/* RedBlob encapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> + * brief CAAM Descriptor creator from redblob to plaindata.
> + * param[in] skreq Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + */
> +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_decap_desc *red_blob_desc > +					&skdesc->dma_u.redblob_decapdesc;
> +	struct sk_red_blob_decap *red_blob_req > +					&skreq->req_u.sk_red_blob_decap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> +			  red_blob_req->redblob_sz, 0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> +			   red_blob_req->data_sz, 0);
> +
> +	/* RedBlob decapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> + *			      struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> +			   struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data;
> +	struct random_desc *rnd_desc;
> +
> +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +
> +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_random_map_fail;
> +	}
> +	return 0;
> +
> +sk_random_map_fail:
> +	return -ENOMEM;
> +}
> +
> +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> + *					struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_encap *red_blob_encap;
> +	struct redblob_encap_desc *red_blob_desc;
> +
> +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	return 0;
> +
> +sk_redblob_fail:
> +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> +			 DMA_TO_DEVICE);
> +sk_data_fail:
> +	return -ENOMEM;
> +}
> +
> +/* static int caam_sk_redblob_decap_map(struct device *dev,
> + *					    struct sk_req *req,
> + *					    struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_decap *red_blob_decap;
> +	struct redblob_decap_desc *red_blob_desc;
> +
> +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	return 0;
> +
> +sk_data_fail:
> +	dma_unmap_single(dev, red_blob_desc->redblob,
> +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +sk_redblob_fail:
> +	return -ENOMEM;
> +}
> +
> +/* @fn void securekey_unmap(struct device *dev,
> + *			    struct sk_desc *skdesc, struct sk_req *req)
> + * @brief DMA unmap the buffer pointers.
> + * @param[in] dev Pointer to job ring device structure
> + * @param[in] skdesc Pointer to secure key descriptor structure
> + * @param[in] req Pointer to secure key request structure
> + */
> +void securekey_unmap(struct device *dev,
> +		     struct sk_desc *skdesc, struct sk_req *req)
> +{
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			struct sk_fetch_rnd_data *fetch_rnd_data;
> +			struct random_desc *rnd_desc;
> +
> +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +			rnd_desc = &skdesc->dma_u.random_descp;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, rnd_desc->rnd_data,
> +					 fetch_rnd_data->key_len,
> +					 DMA_FROM_DEVICE);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			struct sk_red_blob_encap *red_blob_encap;
> +			struct redblob_encap_desc *red_blob_desc;
> +
> +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->in_data,
> +					 red_blob_encap->data_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_encap->redblob_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	case sk_red_blob_dec:
> +		{
> +			struct sk_red_blob_decap *red_blob_decap;
> +			struct redblob_decap_desc *red_blob_desc;
> +
> +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_decap->redblob_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->out_data,
> +					 red_blob_decap->data_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	default:
> +		dev_err(dev, "Unable to find request type\n");
> +		break;
> +	}
> +	kfree(skdesc);
> +}
> +
> +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> + *  brief CAAM Descriptor creator for secure key operations.
> + *  param[in] dev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> +{
> +	struct sk_desc *skdesc = NULL;
> +	int ret = 0;
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam get_random map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			caam_sk_rng_desc(req, skdesc);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_encap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to create redblob from data. */
> +			caam_sk_redblob_encap_desc(req, skdesc);
> +			break;
> +		}
> +
> +	case sk_red_blob_dec:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_decap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to decap data from redblob. */
> +			caam_sk_redblob_decap_desc(req, skdesc);
> +			break;
> +		}
> +	default:
> +		pr_debug("Unknown request type\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	req->desc_pointer = (void *)skdesc;
> +
> +out:
> +	return ret;
> +}
> +
> +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> + *			     void *context)
> + * brief callback function to be called when descriptor executed.
> + * param[in] dev Pointer to device structure
> + * param[in] desc descriptor pointer
> + * param[in] ret return status of Job submitted
> + * param[in] context void pointer
> + */
> +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> +			 void *context)
> +{
> +	struct sk_req *req = context;
> +
> +	if (ret) {
> +		dev_err(dev, "caam op done err: %x\n", ret);
> +		/* print the error source name. */
> +		caam_jr_strstatus(dev, ret);
> +	}
> +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> +	securekey_unmap(dev, req->desc_pointer, req);
> +
> +	req->ret = ret;
> +	complete(&req->comp);
> +}
> +
> +
> +/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> + *  param[in] jrdev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> +{
> +	int ret;
> +
> +	init_completion(&req->comp);
> +
> +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> +	if (!ret)
> +		wait_for_completion_interruptible(&req->comp);
> +
> +	ret = req->ret;
> +	return ret;
> +}
> +
> +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> + *		   struct device *dev)
> + * Create the random number of the specified length using CAAM block
> + * param[in]: out pointer to place the random bytes
> + * param[in]: length for the random data bytes.
> + * param[in]: dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct sk_req *req = NULL;
> +	int ret = 0;
> +	void *temp = NULL;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->type = fetch_rnd;
> +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> +
> +	/* initialise with key length */
> +	fetch_rnd_data->key_len = p->key_len;
> +
> +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	fetch_rnd_data->data = temp;
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (req)
> +		kfree(req);
> +
> +	if (temp)
> +		kfree(temp);
> +
> +	return ret;
> +}
> +
> +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> + *		struct device *dev)
> + * Deblobify the blob to get the key data and fill in secure key payload struct
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev)
> +{
> +	unsigned int blob_len;
> +	struct sk_red_blob_decap *d_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	d_blob = &(req->req_u.sk_red_blob_decap);
> +	blob_len = p->blob_len;
> +	req->type = decap_type;
> +
> +	/*
> +	 * Red blob size is the blob_len filled in payload struct
> +	 * Data_sz i.e. key is the blob_len - blob header size
> +	 */
> +
> +	d_blob->redblob_sz = blob_len;
> +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	d_blob->redblob = temp;
> +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> +	memcpy(d_blob->redblob, p->blob, blob_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init: Failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->key_len = d_blob->data_sz;
> +		memcpy(p->key, d_blob->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(temp);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +}
> +
> +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> + *		struct device *dev)
> + * To blobify the key data to get the blob. This blob can only be seen by
> + * userspace.
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev)
> +{
> +	unsigned int key_len;
> +	struct sk_red_blob_encap *k_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	key_len = p->key_len;
> +
> +	req->type = encap_type;
> +	k_blob = &(req->req_u.sk_red_blob_encap);
> +
> +	/*
> +	 * Data_sz i.e. key len and the corresponding blob_len is
> +	 * key_len + BLOB header size.87ea58433208 
> +	 */
> +
> +	k_blob->data_sz = key_len;
> +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	k_blob->data = temp;
> +
> +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> +	memcpy(k_blob->data, p->key, key_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->blob_len = k_blob->redblob_sz;
> +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(req->mem_pointer);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +
> +}
> +
> diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
> new file mode 100644
> index 000000000000..0ee26e95b205
> --- /dev/null
> +++ b/security/keys/securekey_desc.h
> @@ -0,0 +1,141 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2018 NXP
> + *
> + */
> +#ifndef _SECUREKEY_DESC_H_
> +#define _SECUREKEY_DESC_H_
> +
> +#include "compat.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "desc.h"
> +#include "desc_constr.h"
> +#include "jr.h"
> +#include "error.h"
> +#include "pdb.h"
> +
> +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> +
> +/*
> + * brief defines different kinds of operations supported by this module.
> + */
> +enum sk_req_type {
> +	sk_get_random,
> +	sk_red_blob_enc,
> +	sk_red_blob_dec,
> +};
> +
> +
> +/*
> + * struct random_des
> + * param[out] rnd_data output buffer for random data.
> + */
> +struct random_desc {
> +	dma_addr_t rnd_data;
> +};
> +
> +/* struct redblob_encap_desc
> + * details Structure containing dma address for redblob encapsulation.
> + * param[in] in_data input data to redblob encap descriptor.
> + * param[out] redblob output buffer for redblob.
> + */
> +struct redblob_encap_desc {
> +	dma_addr_t in_data;
> +	dma_addr_t redblob;
> +};
> +
> +/* struct redblob_decap_desc
> + * details Structure containing dma address for redblob decapsulation.
> + * param[in] redblob input buffer to redblob decap descriptor.
> + * param[out] out_data output data from redblob decap descriptor.
> + */
> +struct redblob_decap_desc {
> +	dma_addr_t redblob;
> +	dma_addr_t out_data;
> +};
> +
> +/* struct sk_desc
> + * details Structure for securekey descriptor creation.
> + * param[in] req_type operation supported.
> + * param[in] dma_u union of struct for supported operation.
> + */
> +struct sk_desc {
> +	u32 req_type;
> +	union {
> +		struct redblob_encap_desc redblob_encapdesc;
> +		struct redblob_decap_desc redblob_decapdesc;
> +		struct random_desc random_descp;
> +	} dma_u;
> +};
> +
> +/* struct sk_fetch_rnd_data
> + * decriptor structure containing key length.
> + */
> +struct sk_fetch_rnd_data {
> +	void *data;
> +	size_t key_len;
> +};
> +
> +/* struct sk_red_blob_encap
> + * details Structure containing buffer pointers for redblob encapsulation.
> + * param[in] data Input data.
> + * param[in] data_sz size of Input data.
> + * param[out] redblob output buffer for redblob.
> + * param[in] redblob_sz size of redblob.
> + */
> +struct sk_red_blob_encap {
> +	void *data;
> +	uint32_t data_sz;
> +	void *redblob;
> +	uint32_t redblob_sz;
> +};
> +
> +/* struct sk_red_blob_decap
> + * details Structure containing buffer pointers for redblob decapsulation.
> + * param[in] redblob Input redblob.
> + * param[in] redblob_sz size of redblob.
> + * param[out] data output buffer for data.
> + * param[in] data_sz size of output data.
> + */
> +struct sk_red_blob_decap {
> +	void *redblob;
> +	uint32_t redblob_sz;
> +	void *data;
> +	uint32_t data_sz;
> +};
> +
> +/* struct sk_req
> + * details Structure for securekey request creation.
> + * param[in] type operation supported.
> + * param[in] req_u union of struct for supported operation.
> + * param[out] ret return status of CAAM operation.
> + * param[in] mem_pointer memory pointer for allocated kernel memory.
> + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> + * param[in] comp struct completion object.
> + * param[in] hwdesc contains descriptor instructions.
> + */
> +struct sk_req {
> +	enum sk_req_type type;
> +	void *arg;
> +	union {
> +		struct sk_red_blob_encap sk_red_blob_encap;
> +		struct sk_red_blob_decap sk_red_blob_decap;
> +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> +	} req_u;
> +	int ret;
> +	void *mem_pointer;
> +	void *desc_pointer;
> +	struct completion comp;
> +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> +};
> +
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev);
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev);
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev);
> +
> +#endif /*_SECUREKEY_DESC_H_*/


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-22 23:34   ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-22 23:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: sahil.malhotra

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> Secure keys are derieved using CAAM crypto block.
> 
> Secure keys derieved are the random number symmetric keys from CAAM.
> Blobs corresponding to the key are formed using CAAM. User space
> will only be able to view the blob of the key.

The term "trusted keys" comes from the usage of the Trusted Platform
Module (TPM).  The term "trusted" now also refers to keyrings, which
has nothing to do with a TPM.

What is the correlation between the term "secure keys" and CAAM?  Are
"secure keys", as defined in this patch, limited to a specific HW
crypto device?

Mimi

> 
> Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> ---
>  Documentation/security/keys/secure-key.rst |  67 +++
>  MAINTAINERS                                |  11 +
>  include/keys/secure-type.h                 |  33 ++
>  security/keys/Kconfig                      |  11 +
>  security/keys/Makefile                     |   3 +
>  security/keys/secure_key.c                 | 339 ++++++++++++
>  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
>  security/keys/securekey_desc.h             | 141 +++++
>  8 files changed, 1211 insertions(+)
>  create mode 100644 Documentation/security/keys/secure-key.rst
>  create mode 100644 include/keys/secure-type.h
>  create mode 100644 security/keys/secure_key.c
>  create mode 100644 security/keys/securekey_desc.c
>  create mode 100644 security/keys/securekey_desc.h
> 
> diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
> new file mode 100644
> index 000000000000..0fc3367b00f8
> --- /dev/null
> +++ b/Documentation/security/keys/secure-key.rst
> @@ -0,0 +1,67 @@
> +==========
> +Secure Key
> +==========
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.
> +
> +Usage::
> +
> +	keyctl add secure <name> "new <keylen>" <ring>
> +	keyctl load secure <name> "load <hex_blob>" <ring>
> +	keyctl print <key_id>
> +
> +"keyctl add secure" option will create the random data of the
> +specified key len using CAAM and store it as a key in kernel.
> +Key contents will be displayed as blobs to the user in hex ascii.
> +User can input key len from 32 bytes to 128 bytes.
> +
> +"keyctl load secure" option will load the blob contents. In kernel,
> +key will be deirved using input blob and CAAM, along with the secret
> +key stored in CAAM.
> +
> +"keyctl print" will return the hex string of the blob corresponding to
> +key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
> +the header bytes added by the CAAM.
> +
> +Example of secure key usage::
> +
> +1. Create the secure key with name kmk-master of length 32 bytes::
> +
> +	$ keyctl add secure kmk-master "new 32" @u
> +	46001928
> +
> +	$keyctl show
> +	Session Keyring
> +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> +
> +2. Print the blob contents for the kmk-master key::
> +
> +	$ keyctl print 46001928
> +	d9743445b640f3d59c1670dddc0bc9c2
> +	34fc9aab7dd05c965e6120025012f029b
> +	07faa4776c4f6ed02899e35a135531e9a
> +	6e5c2b51132f9d5aef28f68738e658296
> +	3fe583177cfe50d2542b659a13039
> +
> +	$ keyctl pipe 46001928 > secure_key.blob
> +
> +3. Load the blob in the user key ring::
> +
> +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9fd5e8808208..654be2ee4b0a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
>  F:	security/keys/trusted.c
>  F:	security/keys/trusted.h
> 
> +KEYS-SECURE
> +M:	Udit Agarwal <udit.agarwal@nxp.com>
> +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> +L:	linux-security-module@vger.kernel.org
> +L:	keyrings@vger.kernel.org
> +S:	Supported
> +F:	include/keys/secure-type.h
> +F:	security/keys/secure_key.c
> +F:	security/keys/securekey_desc.c
> +F:	security/keys/securekey_desc.h
> +
>  KEYS/KEYRINGS:
>  M:	David Howells <dhowells@redhat.com>
>  L:	keyrings@vger.kernel.org
> diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> new file mode 100644
> index 000000000000..5b7a5f144e41
> --- /dev/null
> +++ b/include/keys/secure-type.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 NXP.
> + *
> + */
> +
> +#ifndef _KEYS_SECURE_TYPE_H
> +#define _KEYS_SECURE_TYPE_H
> +
> +#include <linux/key.h>
> +#include <linux/rcupdate.h>
> +
> +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> + * is 128 bytes.
> + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> + */
> +
> +#define MIN_KEY_SIZE                    32
> +#define MAX_KEY_SIZE                    128
> +#define BLOB_HEADER_SIZE		48
> +
> +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> +
> +struct secure_key_payload {
> +	struct rcu_head rcu;
> +	unsigned int key_len;
> +	unsigned int blob_len;
> +	unsigned char key[MAX_KEY_SIZE + 1];
> +	unsigned char blob[MAX_BLOB_SIZE];
> +};
> +
> +extern struct key_type key_type_secure;
> +#endif
> diff --git a/security/keys/Kconfig b/security/keys/Kconfig
> index 6462e6654ccf..7eb138b5a54f 100644
> --- a/security/keys/Kconfig
> +++ b/security/keys/Kconfig
> @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> 
>  	  If you are unsure as to whether this is required, answer N.
> 
> +config SECURE_KEYS
> +	tristate "SECURE_KEYS"
> +	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> +	help
> +	  This option provide support for creating secure-type key and blobs
> +	  in kernel. Secure keys are random number symmetric keys generated
> +	  from CAAM. The CAAM creates the blobs for the random key.
> +	  Userspace will only be able to see the blob.
> +
> +	  If you are unsure as to whether this is required, answer N.
> +
>  config ENCRYPTED_KEYS
>  	tristate "ENCRYPTED KEYS"
>  	depends on KEYS
> diff --git a/security/keys/Makefile b/security/keys/Makefile
> index ef1581b337a3..606ba4efb9e6 100644
> --- a/security/keys/Makefile
> +++ b/security/keys/Makefile
> @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
>  #
>  obj-$(CONFIG_BIG_KEYS) += big_key.o
>  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
>  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
> diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
> new file mode 100644
> index 000000000000..ec8ad4394549
> --- /dev/null
> +++ b/security/keys/secure_key.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2018 NXP
> + * Secure key is generated using NXP CAAM hardware block. CAAM generates the
> + * random number (used as a key) and creates its blob for the user.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/parser.h>
> +#include <linux/string.h>
> +#include <linux/key-type.h>
> +#include <linux/rcupdate.h>
> +#include <keys/secure-type.h>
> +#include <linux/completion.h>
> +
> +#include "securekey_desc.h"
> +
> +static const char hmac_alg[] = "hmac(sha1)";
> +static const char hash_alg[] = "sha1";
> +
> +static struct crypto_shash *hashalg;
> +static struct crypto_shash *hmacalg;
> +
> +enum {
> +	error = -1,
> +	new_key,
> +	load_blob,
> +};
> +
> +static const match_table_t key_tokens = {
> +	{new_key, "new"},
> +	{load_blob, "load"},
> +	{error, NULL}
> +};
> +
> +static struct secure_key_payload *secure_payload_alloc(struct key *key)
> +{
> +	struct secure_key_payload *sec_key = NULL;
> +	int ret = 0;
> +
> +	ret = key_payload_reserve(key, sizeof(*sec_key));
> +	if (ret < 0)
> +		goto out;
> +
> +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> +	if (!sec_key)
> +		goto out;
> +
> +out:
> +	return sec_key;
> +}
> +
> +/*
> + * parse_inputdata - parse the keyctl input data and fill in the
> + *		     payload structure for key or its blob.
> + * param[in]: data pointer to the data to be parsed for creating key.
> + * param[in]: p pointer to secure key payload structure to fill parsed data
> + * On success returns 0, otherwise -EINVAL.
> + */
> +static int parse_inputdata(char *data, struct secure_key_payload *p)
> +{
> +	substring_t args[MAX_OPT_ARGS];
> +	long keylen = 0;
> +	int ret = -EINVAL;
> +	int key_cmd = -EINVAL;
> +	char *c = NULL;
> +
> +	c = strsep(&data, " \t");
> +	if (!c) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Get the keyctl command i.e. new_key or load_blob etc */
> +	key_cmd = match_token(c, key_tokens, args);
> +
> +	switch (key_cmd) {
> +	case new_key:
> +		/* first argument is key size */
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = kstrtol(c, 10, &keylen);
> +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> +						keylen > MAX_KEY_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		p->key_len = keylen;
> +		ret = new_key;
> +
> +		break;
> +	case load_blob:
> +		/* first argument is blob data for CAAM*/
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		/* Blob_len = No of characters in blob/2 */
> +		p->blob_len = strlen(c) / 2;
> +		if (p->blob_len > MAX_BLOB_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = hex2bin(p->blob, c, p->blob_len);
> +		if (ret < 0) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		ret = load_blob;
> +
> +		break;
> +	case error:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	return ret;
> +}
> +
> +/*
> + * secure_instantiate - create a new secure type key.
> + * Supports the operation to generate a new key. A random number
> + * is generated from CAAM as key data and the corresponding red blob
> + * is formed and stored as key_blob.
> + * Also supports the operation to load the blob and key is derived using
> + * that blob from CAAM.
> + * On success, return 0. Otherwise return errno.
> + */
> +static int secure_instantiate(struct key *key,
> +		struct key_preparsed_payload *prep)
> +{
> +	struct secure_key_payload *payload = NULL;
> +	size_t datalen = prep->datalen;
> +	char *data = NULL;
> +	int key_cmd = 0;
> +	int ret = 0;
> +	enum sk_req_type sk_op_type;
> +	struct device *dev = NULL;
> +
> +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	data = kmalloc(datalen + 1, GFP_KERNEL);
> +	if (!data) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	memcpy(data, prep->data, datalen);
> +	data[datalen] = '\0';
> +
> +	payload = secure_payload_alloc(key);
> +	if (!payload) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Allocate caam job ring for operation to be performed from CAAM */
> +	dev = caam_jr_alloc();
> +	if (!dev) {
> +		pr_info("caam_jr_alloc failed\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	key_cmd = parse_inputdata(data, payload);
> +	if (key_cmd < 0) {
> +		ret = key_cmd;
> +		goto out;
> +	}
> +
> +	switch (key_cmd) {
> +	case load_blob:
> +		/*
> +		 * Red blob decryption to be done for load operation
> +		 * to derive the key.
> +		 */
> +		sk_op_type = sk_red_blob_dec;
> +		ret = key_deblob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	case new_key:
> +		/* Get Random number from caam of the specified length */
> +		sk_op_type = sk_get_random;
> +		ret = caam_get_random(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: get_random fail (%d)\n", ret);
> +			goto out;
> +		}
> +
> +		/* Generate red blob of key random bytes with CAAM */
> +		sk_op_type = sk_red_blob_enc;
> +		ret = key_blob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +out:
> +	if (data)
> +		kzfree(data);
> +	if (dev)
> +		caam_jr_free(dev);
> +
> +	if (!ret)
> +		rcu_assign_keypointer(key, payload);
> +	else
> +		kzfree(payload);
> +
> +	return ret;
> +}
> +
> +/*
> + * secure_read - copy the  blob data to userspace in hex.
> + * param[in]: key pointer to key struct
> + * param[in]: buffer pointer to user data for creating key
> + * param[in]: buflen is the length of the buffer
> + * On success, return to userspace the secure key data size.
> + */
> +static long secure_read(const struct key *key, char __user *buffer,
> +			 size_t buflen)
> +{
> +	const struct secure_key_payload *p = NULL;
> +	char *ascii_buf;
> +	char *bufp;
> +	int i;
> +
> +	p = dereference_key_locked(key);
> +	if (!p)
> +		return -EINVAL;
> +
> +	if (buffer && buflen >= 2 * p->blob_len) {
> +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> +		if (!ascii_buf)
> +			return -ENOMEM;
> +
> +		bufp = ascii_buf;
> +		for (i = 0; i < p->blob_len; i++)
> +			bufp = hex_byte_pack(bufp, p->blob[i]);
> +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> +			kzfree(ascii_buf);
> +			return -EFAULT;
> +		}
> +		kzfree(ascii_buf);
> +	}
> +	return 2 * p->blob_len;
> +}
> +
> +/*
> + * secure_destroy - clear and free the key's payload
> + */
> +static void secure_destroy(struct key *key)
> +{
> +	kzfree(key->payload.data[0]);
> +}
> +
> +struct key_type key_type_secure = {
> +	.name = "secure",
> +	.instantiate = secure_instantiate,
> +	.destroy = secure_destroy,
> +	.read = secure_read,
> +};
> +EXPORT_SYMBOL_GPL(key_type_secure);
> +
> +static void secure_shash_release(void)
> +{
> +	if (hashalg)
> +		crypto_free_shash(hashalg);
> +	if (hmacalg)
> +		crypto_free_shash(hmacalg);
> +}
> +
> +static int __init secure_shash_alloc(void)
> +{
> +	int ret;
> +
> +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hmacalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hmac_alg);
> +		return PTR_ERR(hmacalg);
> +	}
> +
> +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hashalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hash_alg);
> +		ret = PTR_ERR(hashalg);
> +		goto hashalg_fail;
> +	}
> +
> +	return 0;
> +
> +hashalg_fail:
> +	crypto_free_shash(hmacalg);
> +	return ret;
> +}
> +
> +static int __init init_secure_key(void)
> +{
> +	int ret;
> +
> +	ret = secure_shash_alloc();
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = register_key_type(&key_type_secure);
> +	if (ret < 0)
> +		secure_shash_release();
> +	return ret;
> +}
> +
> +static void __exit cleanup_secure_key(void)
> +{
> +	secure_shash_release();
> +	unregister_key_type(&key_type_secure);
> +}
> +
> +late_initcall(init_secure_key);
> +module_exit(cleanup_secure_key);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
> new file mode 100644
> index 000000000000..a4fa811a5753
> --- /dev/null
> +++ b/security/keys/securekey_desc.c
> @@ -0,0 +1,606 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 NXP
> + *
> + */
> +
> +#include <keys/secure-type.h>
> +#include "securekey_desc.h"
> +
> +/* key modifier for blob encapsulation & decapsulation descriptor */
> +u8 key_modifier[] = "SECURE_KEY";
> +u32 key_modifier_len = 10;
> +
> +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct random_desc *rnd_desc = NULL;
> +	size_t len = 0;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +	len = fetch_rnd_data->key_len;
> +
> +	/* command 0x82500000 */
> +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> +			OP_ALG_ALGSEL_RNG);
> +	/* command 0x60340000 | len */
> +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> +	append_ptr(desc, rnd_desc->rnd_data);
> +}
> +
> +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_encap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_encapdesc;
> +	struct sk_red_blob_encap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_encap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> +			  0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> +			   red_blob_req->redblob_sz, 0);
> +
> +	/* RedBlob encapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> + * brief CAAM Descriptor creator from redblob to plaindata.
> + * param[in] skreq Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + */
> +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_decap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_decapdesc;
> +	struct sk_red_blob_decap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_decap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> +			  red_blob_req->redblob_sz, 0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> +			   red_blob_req->data_sz, 0);
> +
> +	/* RedBlob decapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> + *			      struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> +			   struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data;
> +	struct random_desc *rnd_desc;
> +
> +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +
> +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_random_map_fail;
> +	}
> +	return 0;
> +
> +sk_random_map_fail:
> +	return -ENOMEM;
> +}
> +
> +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> + *					struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_encap *red_blob_encap;
> +	struct redblob_encap_desc *red_blob_desc;
> +
> +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	return 0;
> +
> +sk_redblob_fail:
> +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> +			 DMA_TO_DEVICE);
> +sk_data_fail:
> +	return -ENOMEM;
> +}
> +
> +/* static int caam_sk_redblob_decap_map(struct device *dev,
> + *					    struct sk_req *req,
> + *					    struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_decap *red_blob_decap;
> +	struct redblob_decap_desc *red_blob_desc;
> +
> +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	return 0;
> +
> +sk_data_fail:
> +	dma_unmap_single(dev, red_blob_desc->redblob,
> +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +sk_redblob_fail:
> +	return -ENOMEM;
> +}
> +
> +/* @fn void securekey_unmap(struct device *dev,
> + *			    struct sk_desc *skdesc, struct sk_req *req)
> + * @brief DMA unmap the buffer pointers.
> + * @param[in] dev Pointer to job ring device structure
> + * @param[in] skdesc Pointer to secure key descriptor structure
> + * @param[in] req Pointer to secure key request structure
> + */
> +void securekey_unmap(struct device *dev,
> +		     struct sk_desc *skdesc, struct sk_req *req)
> +{
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			struct sk_fetch_rnd_data *fetch_rnd_data;
> +			struct random_desc *rnd_desc;
> +
> +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +			rnd_desc = &skdesc->dma_u.random_descp;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, rnd_desc->rnd_data,
> +					 fetch_rnd_data->key_len,
> +					 DMA_FROM_DEVICE);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			struct sk_red_blob_encap *red_blob_encap;
> +			struct redblob_encap_desc *red_blob_desc;
> +
> +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->in_data,
> +					 red_blob_encap->data_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_encap->redblob_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	case sk_red_blob_dec:
> +		{
> +			struct sk_red_blob_decap *red_blob_decap;
> +			struct redblob_decap_desc *red_blob_desc;
> +
> +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_decap->redblob_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->out_data,
> +					 red_blob_decap->data_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	default:
> +		dev_err(dev, "Unable to find request type\n");
> +		break;
> +	}
> +	kfree(skdesc);
> +}
> +
> +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> + *  brief CAAM Descriptor creator for secure key operations.
> + *  param[in] dev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> +{
> +	struct sk_desc *skdesc = NULL;
> +	int ret = 0;
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam get_random map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			caam_sk_rng_desc(req, skdesc);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_encap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to create redblob from data. */
> +			caam_sk_redblob_encap_desc(req, skdesc);
> +			break;
> +		}
> +
> +	case sk_red_blob_dec:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_decap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to decap data from redblob. */
> +			caam_sk_redblob_decap_desc(req, skdesc);
> +			break;
> +		}
> +	default:
> +		pr_debug("Unknown request type\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	req->desc_pointer = (void *)skdesc;
> +
> +out:
> +	return ret;
> +}
> +
> +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> + *			     void *context)
> + * brief callback function to be called when descriptor executed.
> + * param[in] dev Pointer to device structure
> + * param[in] desc descriptor pointer
> + * param[in] ret return status of Job submitted
> + * param[in] context void pointer
> + */
> +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> +			 void *context)
> +{
> +	struct sk_req *req = context;
> +
> +	if (ret) {
> +		dev_err(dev, "caam op done err: %x\n", ret);
> +		/* print the error source name. */
> +		caam_jr_strstatus(dev, ret);
> +	}
> +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> +	securekey_unmap(dev, req->desc_pointer, req);
> +
> +	req->ret = ret;
> +	complete(&req->comp);
> +}
> +
> +
> +/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> + *  param[in] jrdev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> +{
> +	int ret;
> +
> +	init_completion(&req->comp);
> +
> +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> +	if (!ret)
> +		wait_for_completion_interruptible(&req->comp);
> +
> +	ret = req->ret;
> +	return ret;
> +}
> +
> +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> + *		   struct device *dev)
> + * Create the random number of the specified length using CAAM block
> + * param[in]: out pointer to place the random bytes
> + * param[in]: length for the random data bytes.
> + * param[in]: dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct sk_req *req = NULL;
> +	int ret = 0;
> +	void *temp = NULL;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->type = fetch_rnd;
> +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> +
> +	/* initialise with key length */
> +	fetch_rnd_data->key_len = p->key_len;
> +
> +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	fetch_rnd_data->data = temp;
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (req)
> +		kfree(req);
> +
> +	if (temp)
> +		kfree(temp);
> +
> +	return ret;
> +}
> +
> +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> + *		struct device *dev)
> + * Deblobify the blob to get the key data and fill in secure key payload struct
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev)
> +{
> +	unsigned int blob_len;
> +	struct sk_red_blob_decap *d_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	d_blob = &(req->req_u.sk_red_blob_decap);
> +	blob_len = p->blob_len;
> +	req->type = decap_type;
> +
> +	/*
> +	 * Red blob size is the blob_len filled in payload struct
> +	 * Data_sz i.e. key is the blob_len - blob header size
> +	 */
> +
> +	d_blob->redblob_sz = blob_len;
> +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	d_blob->redblob = temp;
> +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> +	memcpy(d_blob->redblob, p->blob, blob_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init: Failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->key_len = d_blob->data_sz;
> +		memcpy(p->key, d_blob->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(temp);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +}
> +
> +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> + *		struct device *dev)
> + * To blobify the key data to get the blob. This blob can only be seen by
> + * userspace.
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev)
> +{
> +	unsigned int key_len;
> +	struct sk_red_blob_encap *k_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	key_len = p->key_len;
> +
> +	req->type = encap_type;
> +	k_blob = &(req->req_u.sk_red_blob_encap);
> +
> +	/*
> +	 * Data_sz i.e. key len and the corresponding blob_len is
> +	 * key_len + BLOB header size.87ea58433208 
> +	 */
> +
> +	k_blob->data_sz = key_len;
> +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	k_blob->data = temp;
> +
> +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> +	memcpy(k_blob->data, p->key, key_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->blob_len = k_blob->redblob_sz;
> +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(req->mem_pointer);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +
> +}
> +
> diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
> new file mode 100644
> index 000000000000..0ee26e95b205
> --- /dev/null
> +++ b/security/keys/securekey_desc.h
> @@ -0,0 +1,141 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2018 NXP
> + *
> + */
> +#ifndef _SECUREKEY_DESC_H_
> +#define _SECUREKEY_DESC_H_
> +
> +#include "compat.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "desc.h"
> +#include "desc_constr.h"
> +#include "jr.h"
> +#include "error.h"
> +#include "pdb.h"
> +
> +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> +
> +/*
> + * brief defines different kinds of operations supported by this module.
> + */
> +enum sk_req_type {
> +	sk_get_random,
> +	sk_red_blob_enc,
> +	sk_red_blob_dec,
> +};
> +
> +
> +/*
> + * struct random_des
> + * param[out] rnd_data output buffer for random data.
> + */
> +struct random_desc {
> +	dma_addr_t rnd_data;
> +};
> +
> +/* struct redblob_encap_desc
> + * details Structure containing dma address for redblob encapsulation.
> + * param[in] in_data input data to redblob encap descriptor.
> + * param[out] redblob output buffer for redblob.
> + */
> +struct redblob_encap_desc {
> +	dma_addr_t in_data;
> +	dma_addr_t redblob;
> +};
> +
> +/* struct redblob_decap_desc
> + * details Structure containing dma address for redblob decapsulation.
> + * param[in] redblob input buffer to redblob decap descriptor.
> + * param[out] out_data output data from redblob decap descriptor.
> + */
> +struct redblob_decap_desc {
> +	dma_addr_t redblob;
> +	dma_addr_t out_data;
> +};
> +
> +/* struct sk_desc
> + * details Structure for securekey descriptor creation.
> + * param[in] req_type operation supported.
> + * param[in] dma_u union of struct for supported operation.
> + */
> +struct sk_desc {
> +	u32 req_type;
> +	union {
> +		struct redblob_encap_desc redblob_encapdesc;
> +		struct redblob_decap_desc redblob_decapdesc;
> +		struct random_desc random_descp;
> +	} dma_u;
> +};
> +
> +/* struct sk_fetch_rnd_data
> + * decriptor structure containing key length.
> + */
> +struct sk_fetch_rnd_data {
> +	void *data;
> +	size_t key_len;
> +};
> +
> +/* struct sk_red_blob_encap
> + * details Structure containing buffer pointers for redblob encapsulation.
> + * param[in] data Input data.
> + * param[in] data_sz size of Input data.
> + * param[out] redblob output buffer for redblob.
> + * param[in] redblob_sz size of redblob.
> + */
> +struct sk_red_blob_encap {
> +	void *data;
> +	uint32_t data_sz;
> +	void *redblob;
> +	uint32_t redblob_sz;
> +};
> +
> +/* struct sk_red_blob_decap
> + * details Structure containing buffer pointers for redblob decapsulation.
> + * param[in] redblob Input redblob.
> + * param[in] redblob_sz size of redblob.
> + * param[out] data output buffer for data.
> + * param[in] data_sz size of output data.
> + */
> +struct sk_red_blob_decap {
> +	void *redblob;
> +	uint32_t redblob_sz;
> +	void *data;
> +	uint32_t data_sz;
> +};
> +
> +/* struct sk_req
> + * details Structure for securekey request creation.
> + * param[in] type operation supported.
> + * param[in] req_u union of struct for supported operation.
> + * param[out] ret return status of CAAM operation.
> + * param[in] mem_pointer memory pointer for allocated kernel memory.
> + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> + * param[in] comp struct completion object.
> + * param[in] hwdesc contains descriptor instructions.
> + */
> +struct sk_req {
> +	enum sk_req_type type;
> +	void *arg;
> +	union {
> +		struct sk_red_blob_encap sk_red_blob_encap;
> +		struct sk_red_blob_decap sk_red_blob_decap;
> +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> +	} req_u;
> +	int ret;
> +	void *mem_pointer;
> +	void *desc_pointer;
> +	struct completion comp;
> +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> +};
> +
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev);
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev);
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev);
> +
> +#endif /*_SECUREKEY_DESC_H_*/


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-22 23:34   ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-22 23:34 UTC (permalink / raw)
  To: linux-security-module

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> Secure keys are derieved using CAAM crypto block.
> 
> Secure keys derieved are the random number symmetric keys from CAAM.
> Blobs corresponding to the key are formed using CAAM. User space
> will only be able to view the blob of the key.

The term "trusted keys" comes from the usage of the Trusted Platform
Module (TPM). ?The term "trusted" now also refers to keyrings, which
has nothing to do with a TPM.

What is the correlation between the term "secure keys" and CAAM? ?Are
"secure keys", as defined in this patch, limited to a specific HW
crypto device?

Mimi

> 
> Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> ---
>  Documentation/security/keys/secure-key.rst |  67 +++
>  MAINTAINERS                                |  11 +
>  include/keys/secure-type.h                 |  33 ++
>  security/keys/Kconfig                      |  11 +
>  security/keys/Makefile                     |   3 +
>  security/keys/secure_key.c                 | 339 ++++++++++++
>  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
>  security/keys/securekey_desc.h             | 141 +++++
>  8 files changed, 1211 insertions(+)
>  create mode 100644 Documentation/security/keys/secure-key.rst
>  create mode 100644 include/keys/secure-type.h
>  create mode 100644 security/keys/secure_key.c
>  create mode 100644 security/keys/securekey_desc.c
>  create mode 100644 security/keys/securekey_desc.h
> 
> diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
> new file mode 100644
> index 000000000000..0fc3367b00f8
> --- /dev/null
> +++ b/Documentation/security/keys/secure-key.rst
> @@ -0,0 +1,67 @@
> +==========
> +Secure Key
> +==========
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.
> +
> +Usage::
> +
> +	keyctl add secure <name> "new <keylen>" <ring>
> +	keyctl load secure <name> "load <hex_blob>" <ring>
> +	keyctl print <key_id>
> +
> +"keyctl add secure" option will create the random data of the
> +specified key len using CAAM and store it as a key in kernel.
> +Key contents will be displayed as blobs to the user in hex ascii.
> +User can input key len from 32 bytes to 128 bytes.
> +
> +"keyctl load secure" option will load the blob contents. In kernel,
> +key will be deirved using input blob and CAAM, along with the secret
> +key stored in CAAM.
> +
> +"keyctl print" will return the hex string of the blob corresponding to
> +key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
> +the header bytes added by the CAAM.
> +
> +Example of secure key usage::
> +
> +1. Create the secure key with name kmk-master of length 32 bytes::
> +
> +	$ keyctl add secure kmk-master "new 32" @u
> +	46001928
> +
> +	$keyctl show
> +	Session Keyring
> +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> +
> +2. Print the blob contents for the kmk-master key::
> +
> +	$ keyctl print 46001928
> +	d9743445b640f3d59c1670dddc0bc9c2
> +	34fc9aab7dd05c965e6120025012f029b
> +	07faa4776c4f6ed02899e35a135531e9a
> +	6e5c2b51132f9d5aef28f68738e658296
> +	3fe583177cfe50d2542b659a13039
> +
> +	$ keyctl pipe 46001928 > secure_key.blob
> +
> +3. Load the blob in the user key ring::
> +
> +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9fd5e8808208..654be2ee4b0a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
>  F:	security/keys/trusted.c
>  F:	security/keys/trusted.h
> 
> +KEYS-SECURE
> +M:	Udit Agarwal <udit.agarwal@nxp.com>
> +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> +L:	linux-security-module at vger.kernel.org
> +L:	keyrings at vger.kernel.org
> +S:	Supported
> +F:	include/keys/secure-type.h
> +F:	security/keys/secure_key.c
> +F:	security/keys/securekey_desc.c
> +F:	security/keys/securekey_desc.h
> +
>  KEYS/KEYRINGS:
>  M:	David Howells <dhowells@redhat.com>
>  L:	keyrings at vger.kernel.org
> diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> new file mode 100644
> index 000000000000..5b7a5f144e41
> --- /dev/null
> +++ b/include/keys/secure-type.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 NXP.
> + *
> + */
> +
> +#ifndef _KEYS_SECURE_TYPE_H
> +#define _KEYS_SECURE_TYPE_H
> +
> +#include <linux/key.h>
> +#include <linux/rcupdate.h>
> +
> +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> + * is 128 bytes.
> + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> + */
> +
> +#define MIN_KEY_SIZE                    32
> +#define MAX_KEY_SIZE                    128
> +#define BLOB_HEADER_SIZE		48
> +
> +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> +
> +struct secure_key_payload {
> +	struct rcu_head rcu;
> +	unsigned int key_len;
> +	unsigned int blob_len;
> +	unsigned char key[MAX_KEY_SIZE + 1];
> +	unsigned char blob[MAX_BLOB_SIZE];
> +};
> +
> +extern struct key_type key_type_secure;
> +#endif
> diff --git a/security/keys/Kconfig b/security/keys/Kconfig
> index 6462e6654ccf..7eb138b5a54f 100644
> --- a/security/keys/Kconfig
> +++ b/security/keys/Kconfig
> @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> 
>  	  If you are unsure as to whether this is required, answer N.
> 
> +config SECURE_KEYS
> +	tristate "SECURE_KEYS"
> +	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> +	help
> +	  This option provide support for creating secure-type key and blobs
> +	  in kernel. Secure keys are random number symmetric keys generated
> +	  from CAAM. The CAAM creates the blobs for the random key.
> +	  Userspace will only be able to see the blob.
> +
> +	  If you are unsure as to whether this is required, answer N.
> +
>  config ENCRYPTED_KEYS
>  	tristate "ENCRYPTED KEYS"
>  	depends on KEYS
> diff --git a/security/keys/Makefile b/security/keys/Makefile
> index ef1581b337a3..606ba4efb9e6 100644
> --- a/security/keys/Makefile
> +++ b/security/keys/Makefile
> @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
>  #
>  obj-$(CONFIG_BIG_KEYS) += big_key.o
>  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
>  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
> diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
> new file mode 100644
> index 000000000000..ec8ad4394549
> --- /dev/null
> +++ b/security/keys/secure_key.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2018 NXP
> + * Secure key is generated using NXP CAAM hardware block. CAAM generates the
> + * random number (used as a key) and creates its blob for the user.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/parser.h>
> +#include <linux/string.h>
> +#include <linux/key-type.h>
> +#include <linux/rcupdate.h>
> +#include <keys/secure-type.h>
> +#include <linux/completion.h>
> +
> +#include "securekey_desc.h"
> +
> +static const char hmac_alg[] = "hmac(sha1)";
> +static const char hash_alg[] = "sha1";
> +
> +static struct crypto_shash *hashalg;
> +static struct crypto_shash *hmacalg;
> +
> +enum {
> +	error = -1,
> +	new_key,
> +	load_blob,
> +};
> +
> +static const match_table_t key_tokens = {
> +	{new_key, "new"},
> +	{load_blob, "load"},
> +	{error, NULL}
> +};
> +
> +static struct secure_key_payload *secure_payload_alloc(struct key *key)
> +{
> +	struct secure_key_payload *sec_key = NULL;
> +	int ret = 0;
> +
> +	ret = key_payload_reserve(key, sizeof(*sec_key));
> +	if (ret < 0)
> +		goto out;
> +
> +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> +	if (!sec_key)
> +		goto out;
> +
> +out:
> +	return sec_key;
> +}
> +
> +/*
> + * parse_inputdata - parse the keyctl input data and fill in the
> + *		     payload structure for key or its blob.
> + * param[in]: data pointer to the data to be parsed for creating key.
> + * param[in]: p pointer to secure key payload structure to fill parsed data
> + * On success returns 0, otherwise -EINVAL.
> + */
> +static int parse_inputdata(char *data, struct secure_key_payload *p)
> +{
> +	substring_t args[MAX_OPT_ARGS];
> +	long keylen = 0;
> +	int ret = -EINVAL;
> +	int key_cmd = -EINVAL;
> +	char *c = NULL;
> +
> +	c = strsep(&data, " \t");
> +	if (!c) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Get the keyctl command i.e. new_key or load_blob etc */
> +	key_cmd = match_token(c, key_tokens, args);
> +
> +	switch (key_cmd) {
> +	case new_key:
> +		/* first argument is key size */
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = kstrtol(c, 10, &keylen);
> +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> +						keylen > MAX_KEY_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		p->key_len = keylen;
> +		ret = new_key;
> +
> +		break;
> +	case load_blob:
> +		/* first argument is blob data for CAAM*/
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		/* Blob_len = No of characters in blob/2 */
> +		p->blob_len = strlen(c) / 2;
> +		if (p->blob_len > MAX_BLOB_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = hex2bin(p->blob, c, p->blob_len);
> +		if (ret < 0) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		ret = load_blob;
> +
> +		break;
> +	case error:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	return ret;
> +}
> +
> +/*
> + * secure_instantiate - create a new secure type key.
> + * Supports the operation to generate a new key. A random number
> + * is generated from CAAM as key data and the corresponding red blob
> + * is formed and stored as key_blob.
> + * Also supports the operation to load the blob and key is derived using
> + * that blob from CAAM.
> + * On success, return 0. Otherwise return errno.
> + */
> +static int secure_instantiate(struct key *key,
> +		struct key_preparsed_payload *prep)
> +{
> +	struct secure_key_payload *payload = NULL;
> +	size_t datalen = prep->datalen;
> +	char *data = NULL;
> +	int key_cmd = 0;
> +	int ret = 0;
> +	enum sk_req_type sk_op_type;
> +	struct device *dev = NULL;
> +
> +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	data = kmalloc(datalen + 1, GFP_KERNEL);
> +	if (!data) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	memcpy(data, prep->data, datalen);
> +	data[datalen] = '\0';
> +
> +	payload = secure_payload_alloc(key);
> +	if (!payload) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Allocate caam job ring for operation to be performed from CAAM */
> +	dev = caam_jr_alloc();
> +	if (!dev) {
> +		pr_info("caam_jr_alloc failed\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	key_cmd = parse_inputdata(data, payload);
> +	if (key_cmd < 0) {
> +		ret = key_cmd;
> +		goto out;
> +	}
> +
> +	switch (key_cmd) {
> +	case load_blob:
> +		/*
> +		 * Red blob decryption to be done for load operation
> +		 * to derive the key.
> +		 */
> +		sk_op_type = sk_red_blob_dec;
> +		ret = key_deblob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	case new_key:
> +		/* Get Random number from caam of the specified length */
> +		sk_op_type = sk_get_random;
> +		ret = caam_get_random(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: get_random fail (%d)\n", ret);
> +			goto out;
> +		}
> +
> +		/* Generate red blob of key random bytes with CAAM */
> +		sk_op_type = sk_red_blob_enc;
> +		ret = key_blob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +out:
> +	if (data)
> +		kzfree(data);
> +	if (dev)
> +		caam_jr_free(dev);
> +
> +	if (!ret)
> +		rcu_assign_keypointer(key, payload);
> +	else
> +		kzfree(payload);
> +
> +	return ret;
> +}
> +
> +/*
> + * secure_read - copy the  blob data to userspace in hex.
> + * param[in]: key pointer to key struct
> + * param[in]: buffer pointer to user data for creating key
> + * param[in]: buflen is the length of the buffer
> + * On success, return to userspace the secure key data size.
> + */
> +static long secure_read(const struct key *key, char __user *buffer,
> +			 size_t buflen)
> +{
> +	const struct secure_key_payload *p = NULL;
> +	char *ascii_buf;
> +	char *bufp;
> +	int i;
> +
> +	p = dereference_key_locked(key);
> +	if (!p)
> +		return -EINVAL;
> +
> +	if (buffer && buflen >= 2 * p->blob_len) {
> +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> +		if (!ascii_buf)
> +			return -ENOMEM;
> +
> +		bufp = ascii_buf;
> +		for (i = 0; i < p->blob_len; i++)
> +			bufp = hex_byte_pack(bufp, p->blob[i]);
> +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> +			kzfree(ascii_buf);
> +			return -EFAULT;
> +		}
> +		kzfree(ascii_buf);
> +	}
> +	return 2 * p->blob_len;
> +}
> +
> +/*
> + * secure_destroy - clear and free the key's payload
> + */
> +static void secure_destroy(struct key *key)
> +{
> +	kzfree(key->payload.data[0]);
> +}
> +
> +struct key_type key_type_secure = {
> +	.name = "secure",
> +	.instantiate = secure_instantiate,
> +	.destroy = secure_destroy,
> +	.read = secure_read,
> +};
> +EXPORT_SYMBOL_GPL(key_type_secure);
> +
> +static void secure_shash_release(void)
> +{
> +	if (hashalg)
> +		crypto_free_shash(hashalg);
> +	if (hmacalg)
> +		crypto_free_shash(hmacalg);
> +}
> +
> +static int __init secure_shash_alloc(void)
> +{
> +	int ret;
> +
> +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hmacalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hmac_alg);
> +		return PTR_ERR(hmacalg);
> +	}
> +
> +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hashalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hash_alg);
> +		ret = PTR_ERR(hashalg);
> +		goto hashalg_fail;
> +	}
> +
> +	return 0;
> +
> +hashalg_fail:
> +	crypto_free_shash(hmacalg);
> +	return ret;
> +}
> +
> +static int __init init_secure_key(void)
> +{
> +	int ret;
> +
> +	ret = secure_shash_alloc();
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = register_key_type(&key_type_secure);
> +	if (ret < 0)
> +		secure_shash_release();
> +	return ret;
> +}
> +
> +static void __exit cleanup_secure_key(void)
> +{
> +	secure_shash_release();
> +	unregister_key_type(&key_type_secure);
> +}
> +
> +late_initcall(init_secure_key);
> +module_exit(cleanup_secure_key);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
> new file mode 100644
> index 000000000000..a4fa811a5753
> --- /dev/null
> +++ b/security/keys/securekey_desc.c
> @@ -0,0 +1,606 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 NXP
> + *
> + */
> +
> +#include <keys/secure-type.h>
> +#include "securekey_desc.h"
> +
> +/* key modifier for blob encapsulation & decapsulation descriptor */
> +u8 key_modifier[] = "SECURE_KEY";
> +u32 key_modifier_len = 10;
> +
> +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct random_desc *rnd_desc = NULL;
> +	size_t len = 0;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +	len = fetch_rnd_data->key_len;
> +
> +	/* command 0x82500000 */
> +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> +			OP_ALG_ALGSEL_RNG);
> +	/* command 0x60340000 | len */
> +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> +	append_ptr(desc, rnd_desc->rnd_data);
> +}
> +
> +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_encap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_encapdesc;
> +	struct sk_red_blob_encap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_encap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> +			  0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> +			   red_blob_req->redblob_sz, 0);
> +
> +	/* RedBlob encapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> + * brief CAAM Descriptor creator from redblob to plaindata.
> + * param[in] skreq Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + */
> +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_decap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_decapdesc;
> +	struct sk_red_blob_decap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_decap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> +			  red_blob_req->redblob_sz, 0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> +			   red_blob_req->data_sz, 0);
> +
> +	/* RedBlob decapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> + *			      struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> +			   struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data;
> +	struct random_desc *rnd_desc;
> +
> +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +
> +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_random_map_fail;
> +	}
> +	return 0;
> +
> +sk_random_map_fail:
> +	return -ENOMEM;
> +}
> +
> +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> + *					struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_encap *red_blob_encap;
> +	struct redblob_encap_desc *red_blob_desc;
> +
> +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	return 0;
> +
> +sk_redblob_fail:
> +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> +			 DMA_TO_DEVICE);
> +sk_data_fail:
> +	return -ENOMEM;
> +}
> +
> +/* static int caam_sk_redblob_decap_map(struct device *dev,
> + *					    struct sk_req *req,
> + *					    struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_decap *red_blob_decap;
> +	struct redblob_decap_desc *red_blob_desc;
> +
> +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	return 0;
> +
> +sk_data_fail:
> +	dma_unmap_single(dev, red_blob_desc->redblob,
> +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +sk_redblob_fail:
> +	return -ENOMEM;
> +}
> +
> +/* @fn void securekey_unmap(struct device *dev,
> + *			    struct sk_desc *skdesc, struct sk_req *req)
> + * @brief DMA unmap the buffer pointers.
> + * @param[in] dev Pointer to job ring device structure
> + * @param[in] skdesc Pointer to secure key descriptor structure
> + * @param[in] req Pointer to secure key request structure
> + */
> +void securekey_unmap(struct device *dev,
> +		     struct sk_desc *skdesc, struct sk_req *req)
> +{
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			struct sk_fetch_rnd_data *fetch_rnd_data;
> +			struct random_desc *rnd_desc;
> +
> +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +			rnd_desc = &skdesc->dma_u.random_descp;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, rnd_desc->rnd_data,
> +					 fetch_rnd_data->key_len,
> +					 DMA_FROM_DEVICE);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			struct sk_red_blob_encap *red_blob_encap;
> +			struct redblob_encap_desc *red_blob_desc;
> +
> +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->in_data,
> +					 red_blob_encap->data_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_encap->redblob_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	case sk_red_blob_dec:
> +		{
> +			struct sk_red_blob_decap *red_blob_decap;
> +			struct redblob_decap_desc *red_blob_desc;
> +
> +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_decap->redblob_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->out_data,
> +					 red_blob_decap->data_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	default:
> +		dev_err(dev, "Unable to find request type\n");
> +		break;
> +	}
> +	kfree(skdesc);
> +}
> +
> +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> + *  brief CAAM Descriptor creator for secure key operations.
> + *  param[in] dev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> +{
> +	struct sk_desc *skdesc = NULL;
> +	int ret = 0;
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam get_random map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			caam_sk_rng_desc(req, skdesc);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_encap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to create redblob from data. */
> +			caam_sk_redblob_encap_desc(req, skdesc);
> +			break;
> +		}
> +
> +	case sk_red_blob_dec:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_decap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to decap data from redblob. */
> +			caam_sk_redblob_decap_desc(req, skdesc);
> +			break;
> +		}
> +	default:
> +		pr_debug("Unknown request type\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	req->desc_pointer = (void *)skdesc;
> +
> +out:
> +	return ret;
> +}
> +
> +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> + *			     void *context)
> + * brief callback function to be called when descriptor executed.
> + * param[in] dev Pointer to device structure
> + * param[in] desc descriptor pointer
> + * param[in] ret return status of Job submitted
> + * param[in] context void pointer
> + */
> +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> +			 void *context)
> +{
> +	struct sk_req *req = context;
> +
> +	if (ret) {
> +		dev_err(dev, "caam op done err: %x\n", ret);
> +		/* print the error source name. */
> +		caam_jr_strstatus(dev, ret);
> +	}
> +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> +	securekey_unmap(dev, req->desc_pointer, req);
> +
> +	req->ret = ret;
> +	complete(&req->comp);
> +}
> +
> +
> +/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> + *  param[in] jrdev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> +{
> +	int ret;
> +
> +	init_completion(&req->comp);
> +
> +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> +	if (!ret)
> +		wait_for_completion_interruptible(&req->comp);
> +
> +	ret = req->ret;
> +	return ret;
> +}
> +
> +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> + *		   struct device *dev)
> + * Create the random number of the specified length using CAAM block
> + * param[in]: out pointer to place the random bytes
> + * param[in]: length for the random data bytes.
> + * param[in]: dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct sk_req *req = NULL;
> +	int ret = 0;
> +	void *temp = NULL;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->type = fetch_rnd;
> +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> +
> +	/* initialise with key length */
> +	fetch_rnd_data->key_len = p->key_len;
> +
> +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	fetch_rnd_data->data = temp;
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (req)
> +		kfree(req);
> +
> +	if (temp)
> +		kfree(temp);
> +
> +	return ret;
> +}
> +
> +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> + *		struct device *dev)
> + * Deblobify the blob to get the key data and fill in secure key payload struct
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev)
> +{
> +	unsigned int blob_len;
> +	struct sk_red_blob_decap *d_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	d_blob = &(req->req_u.sk_red_blob_decap);
> +	blob_len = p->blob_len;
> +	req->type = decap_type;
> +
> +	/*
> +	 * Red blob size is the blob_len filled in payload struct
> +	 * Data_sz i.e. key is the blob_len - blob header size
> +	 */
> +
> +	d_blob->redblob_sz = blob_len;
> +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	d_blob->redblob = temp;
> +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> +	memcpy(d_blob->redblob, p->blob, blob_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init: Failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->key_len = d_blob->data_sz;
> +		memcpy(p->key, d_blob->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(temp);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +}
> +
> +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> + *		struct device *dev)
> + * To blobify the key data to get the blob. This blob can only be seen by
> + * userspace.
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev)
> +{
> +	unsigned int key_len;
> +	struct sk_red_blob_encap *k_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	key_len = p->key_len;
> +
> +	req->type = encap_type;
> +	k_blob = &(req->req_u.sk_red_blob_encap);
> +
> +	/*
> +	 * Data_sz i.e. key len and the corresponding blob_len is
> +	 * key_len + BLOB header size.87ea58433208 
> +	 */
> +
> +	k_blob->data_sz = key_len;
> +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	k_blob->data = temp;
> +
> +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> +	memcpy(k_blob->data, p->key, key_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->blob_len = k_blob->redblob_sz;
> +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(req->mem_pointer);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +
> +}
> +
> diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
> new file mode 100644
> index 000000000000..0ee26e95b205
> --- /dev/null
> +++ b/security/keys/securekey_desc.h
> @@ -0,0 +1,141 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2018 NXP
> + *
> + */
> +#ifndef _SECUREKEY_DESC_H_
> +#define _SECUREKEY_DESC_H_
> +
> +#include "compat.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "desc.h"
> +#include "desc_constr.h"
> +#include "jr.h"
> +#include "error.h"
> +#include "pdb.h"
> +
> +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> +
> +/*
> + * brief defines different kinds of operations supported by this module.
> + */
> +enum sk_req_type {
> +	sk_get_random,
> +	sk_red_blob_enc,
> +	sk_red_blob_dec,
> +};
> +
> +
> +/*
> + * struct random_des
> + * param[out] rnd_data output buffer for random data.
> + */
> +struct random_desc {
> +	dma_addr_t rnd_data;
> +};
> +
> +/* struct redblob_encap_desc
> + * details Structure containing dma address for redblob encapsulation.
> + * param[in] in_data input data to redblob encap descriptor.
> + * param[out] redblob output buffer for redblob.
> + */
> +struct redblob_encap_desc {
> +	dma_addr_t in_data;
> +	dma_addr_t redblob;
> +};
> +
> +/* struct redblob_decap_desc
> + * details Structure containing dma address for redblob decapsulation.
> + * param[in] redblob input buffer to redblob decap descriptor.
> + * param[out] out_data output data from redblob decap descriptor.
> + */
> +struct redblob_decap_desc {
> +	dma_addr_t redblob;
> +	dma_addr_t out_data;
> +};
> +
> +/* struct sk_desc
> + * details Structure for securekey descriptor creation.
> + * param[in] req_type operation supported.
> + * param[in] dma_u union of struct for supported operation.
> + */
> +struct sk_desc {
> +	u32 req_type;
> +	union {
> +		struct redblob_encap_desc redblob_encapdesc;
> +		struct redblob_decap_desc redblob_decapdesc;
> +		struct random_desc random_descp;
> +	} dma_u;
> +};
> +
> +/* struct sk_fetch_rnd_data
> + * decriptor structure containing key length.
> + */
> +struct sk_fetch_rnd_data {
> +	void *data;
> +	size_t key_len;
> +};
> +
> +/* struct sk_red_blob_encap
> + * details Structure containing buffer pointers for redblob encapsulation.
> + * param[in] data Input data.
> + * param[in] data_sz size of Input data.
> + * param[out] redblob output buffer for redblob.
> + * param[in] redblob_sz size of redblob.
> + */
> +struct sk_red_blob_encap {
> +	void *data;
> +	uint32_t data_sz;
> +	void *redblob;
> +	uint32_t redblob_sz;
> +};
> +
> +/* struct sk_red_blob_decap
> + * details Structure containing buffer pointers for redblob decapsulation.
> + * param[in] redblob Input redblob.
> + * param[in] redblob_sz size of redblob.
> + * param[out] data output buffer for data.
> + * param[in] data_sz size of output data.
> + */
> +struct sk_red_blob_decap {
> +	void *redblob;
> +	uint32_t redblob_sz;
> +	void *data;
> +	uint32_t data_sz;
> +};
> +
> +/* struct sk_req
> + * details Structure for securekey request creation.
> + * param[in] type operation supported.
> + * param[in] req_u union of struct for supported operation.
> + * param[out] ret return status of CAAM operation.
> + * param[in] mem_pointer memory pointer for allocated kernel memory.
> + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> + * param[in] comp struct completion object.
> + * param[in] hwdesc contains descriptor instructions.
> + */
> +struct sk_req {
> +	enum sk_req_type type;
> +	void *arg;
> +	union {
> +		struct sk_red_blob_encap sk_red_blob_encap;
> +		struct sk_red_blob_decap sk_red_blob_decap;
> +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> +	} req_u;
> +	int ret;
> +	void *mem_pointer;
> +	void *desc_pointer;
> +	struct completion comp;
> +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> +};
> +
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev);
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev);
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev);
> +
> +#endif /*_SECUREKEY_DESC_H_*/

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-22 23:34   ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-22 23:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: sahil.malhotra

On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> Secure keys are derieved using CAAM crypto block.
> 
> Secure keys derieved are the random number symmetric keys from CAAM.
> Blobs corresponding to the key are formed using CAAM. User space
> will only be able to view the blob of the key.

The term "trusted keys" comes from the usage of the Trusted Platform
Module (TPM).  The term "trusted" now also refers to keyrings, which
has nothing to do with a TPM.

What is the correlation between the term "secure keys" and CAAM?  Are
"secure keys", as defined in this patch, limited to a specific HW
crypto device?

Mimi

> 
> Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> ---
>  Documentation/security/keys/secure-key.rst |  67 +++
>  MAINTAINERS                                |  11 +
>  include/keys/secure-type.h                 |  33 ++
>  security/keys/Kconfig                      |  11 +
>  security/keys/Makefile                     |   3 +
>  security/keys/secure_key.c                 | 339 ++++++++++++
>  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
>  security/keys/securekey_desc.h             | 141 +++++
>  8 files changed, 1211 insertions(+)
>  create mode 100644 Documentation/security/keys/secure-key.rst
>  create mode 100644 include/keys/secure-type.h
>  create mode 100644 security/keys/secure_key.c
>  create mode 100644 security/keys/securekey_desc.c
>  create mode 100644 security/keys/securekey_desc.h
> 
> diff --git a/Documentation/security/keys/secure-key.rst b/Documentation/security/keys/secure-key.rst
> new file mode 100644
> index 000000000000..0fc3367b00f8
> --- /dev/null
> +++ b/Documentation/security/keys/secure-key.rst
> @@ -0,0 +1,67 @@
> +==========
> +Secure Key
> +==========
> +
> +Secure key is the new type added to kernel key ring service.
> +Secure key is a symmetric type key of minimum length 32 bytes
> +and with maximum possible length to be 128 bytes. It is produced
> +in kernel using the CAAM crypto engine. Userspace can only see
> +the blob for the corresponding key. All the blobs are displayed
> +or loaded in hex ascii.
> +
> +Secure key can only be created on platforms which supports CAAM
> +hardware block. Secure key can also be used as a master key to
> +create the encrypted keys along with the existing key types in
> +kernel.
> +
> +Secure key uses CAAM hardware to generate the key and blobify its
> +content for userspace. Generated blobs are tied up with the hardware
> +secret key stored in CAAM, hence the same blob will not be able to
> +de-blobify with the different secret key on another machine.
> +
> +Usage::
> +
> +	keyctl add secure <name> "new <keylen>" <ring>
> +	keyctl load secure <name> "load <hex_blob>" <ring>
> +	keyctl print <key_id>
> +
> +"keyctl add secure" option will create the random data of the
> +specified key len using CAAM and store it as a key in kernel.
> +Key contents will be displayed as blobs to the user in hex ascii.
> +User can input key len from 32 bytes to 128 bytes.
> +
> +"keyctl load secure" option will load the blob contents. In kernel,
> +key will be deirved using input blob and CAAM, along with the secret
> +key stored in CAAM.
> +
> +"keyctl print" will return the hex string of the blob corresponding to
> +key_id. Returned blob will be of key_len + 48 bytes. Extra 48 bytes are
> +the header bytes added by the CAAM.
> +
> +Example of secure key usage::
> +
> +1. Create the secure key with name kmk-master of length 32 bytes::
> +
> +	$ keyctl add secure kmk-master "new 32" @u
> +	46001928
> +
> +	$keyctl show
> +	Session Keyring
> +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> +
> +2. Print the blob contents for the kmk-master key::
> +
> +	$ keyctl print 46001928
> +	d9743445b640f3d59c1670dddc0bc9c2
> +	34fc9aab7dd05c965e6120025012f029b
> +	07faa4776c4f6ed02899e35a135531e9a
> +	6e5c2b51132f9d5aef28f68738e658296
> +	3fe583177cfe50d2542b659a13039
> +
> +	$ keyctl pipe 46001928 > secure_key.blob
> +
> +3. Load the blob in the user key ring::
> +
> +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9fd5e8808208..654be2ee4b0a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
>  F:	security/keys/trusted.c
>  F:	security/keys/trusted.h
> 
> +KEYS-SECURE
> +M:	Udit Agarwal <udit.agarwal@nxp.com>
> +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> +L:	linux-security-module@vger.kernel.org
> +L:	keyrings@vger.kernel.org
> +S:	Supported
> +F:	include/keys/secure-type.h
> +F:	security/keys/secure_key.c
> +F:	security/keys/securekey_desc.c
> +F:	security/keys/securekey_desc.h
> +
>  KEYS/KEYRINGS:
>  M:	David Howells <dhowells@redhat.com>
>  L:	keyrings@vger.kernel.org
> diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> new file mode 100644
> index 000000000000..5b7a5f144e41
> --- /dev/null
> +++ b/include/keys/secure-type.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2018 NXP.
> + *
> + */
> +
> +#ifndef _KEYS_SECURE_TYPE_H
> +#define _KEYS_SECURE_TYPE_H
> +
> +#include <linux/key.h>
> +#include <linux/rcupdate.h>
> +
> +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> + * is 128 bytes.
> + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> + */
> +
> +#define MIN_KEY_SIZE                    32
> +#define MAX_KEY_SIZE                    128
> +#define BLOB_HEADER_SIZE		48
> +
> +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> +
> +struct secure_key_payload {
> +	struct rcu_head rcu;
> +	unsigned int key_len;
> +	unsigned int blob_len;
> +	unsigned char key[MAX_KEY_SIZE + 1];
> +	unsigned char blob[MAX_BLOB_SIZE];
> +};
> +
> +extern struct key_type key_type_secure;
> +#endif
> diff --git a/security/keys/Kconfig b/security/keys/Kconfig
> index 6462e6654ccf..7eb138b5a54f 100644
> --- a/security/keys/Kconfig
> +++ b/security/keys/Kconfig
> @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> 
>  	  If you are unsure as to whether this is required, answer N.
> 
> +config SECURE_KEYS
> +	tristate "SECURE_KEYS"
> +	depends on KEYS && CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> +	help
> +	  This option provide support for creating secure-type key and blobs
> +	  in kernel. Secure keys are random number symmetric keys generated
> +	  from CAAM. The CAAM creates the blobs for the random key.
> +	  Userspace will only be able to see the blob.
> +
> +	  If you are unsure as to whether this is required, answer N.
> +
>  config ENCRYPTED_KEYS
>  	tristate "ENCRYPTED KEYS"
>  	depends on KEYS
> diff --git a/security/keys/Makefile b/security/keys/Makefile
> index ef1581b337a3..606ba4efb9e6 100644
> --- a/security/keys/Makefile
> +++ b/security/keys/Makefile
> @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
>  #
>  obj-$(CONFIG_BIG_KEYS) += big_key.o
>  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
>  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
> diff --git a/security/keys/secure_key.c b/security/keys/secure_key.c
> new file mode 100644
> index 000000000000..ec8ad4394549
> --- /dev/null
> +++ b/security/keys/secure_key.c
> @@ -0,0 +1,339 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2018 NXP
> + * Secure key is generated using NXP CAAM hardware block. CAAM generates the
> + * random number (used as a key) and creates its blob for the user.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/parser.h>
> +#include <linux/string.h>
> +#include <linux/key-type.h>
> +#include <linux/rcupdate.h>
> +#include <keys/secure-type.h>
> +#include <linux/completion.h>
> +
> +#include "securekey_desc.h"
> +
> +static const char hmac_alg[] = "hmac(sha1)";
> +static const char hash_alg[] = "sha1";
> +
> +static struct crypto_shash *hashalg;
> +static struct crypto_shash *hmacalg;
> +
> +enum {
> +	error = -1,
> +	new_key,
> +	load_blob,
> +};
> +
> +static const match_table_t key_tokens = {
> +	{new_key, "new"},
> +	{load_blob, "load"},
> +	{error, NULL}
> +};
> +
> +static struct secure_key_payload *secure_payload_alloc(struct key *key)
> +{
> +	struct secure_key_payload *sec_key = NULL;
> +	int ret = 0;
> +
> +	ret = key_payload_reserve(key, sizeof(*sec_key));
> +	if (ret < 0)
> +		goto out;
> +
> +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> +	if (!sec_key)
> +		goto out;
> +
> +out:
> +	return sec_key;
> +}
> +
> +/*
> + * parse_inputdata - parse the keyctl input data and fill in the
> + *		     payload structure for key or its blob.
> + * param[in]: data pointer to the data to be parsed for creating key.
> + * param[in]: p pointer to secure key payload structure to fill parsed data
> + * On success returns 0, otherwise -EINVAL.
> + */
> +static int parse_inputdata(char *data, struct secure_key_payload *p)
> +{
> +	substring_t args[MAX_OPT_ARGS];
> +	long keylen = 0;
> +	int ret = -EINVAL;
> +	int key_cmd = -EINVAL;
> +	char *c = NULL;
> +
> +	c = strsep(&data, " \t");
> +	if (!c) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Get the keyctl command i.e. new_key or load_blob etc */
> +	key_cmd = match_token(c, key_tokens, args);
> +
> +	switch (key_cmd) {
> +	case new_key:
> +		/* first argument is key size */
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = kstrtol(c, 10, &keylen);
> +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> +						keylen > MAX_KEY_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		p->key_len = keylen;
> +		ret = new_key;
> +
> +		break;
> +	case load_blob:
> +		/* first argument is blob data for CAAM*/
> +		c = strsep(&data, " \t");
> +		if (!c) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		/* Blob_len = No of characters in blob/2 */
> +		p->blob_len = strlen(c) / 2;
> +		if (p->blob_len > MAX_BLOB_SIZE) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = hex2bin(p->blob, c, p->blob_len);
> +		if (ret < 0) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +		ret = load_blob;
> +
> +		break;
> +	case error:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	return ret;
> +}
> +
> +/*
> + * secure_instantiate - create a new secure type key.
> + * Supports the operation to generate a new key. A random number
> + * is generated from CAAM as key data and the corresponding red blob
> + * is formed and stored as key_blob.
> + * Also supports the operation to load the blob and key is derived using
> + * that blob from CAAM.
> + * On success, return 0. Otherwise return errno.
> + */
> +static int secure_instantiate(struct key *key,
> +		struct key_preparsed_payload *prep)
> +{
> +	struct secure_key_payload *payload = NULL;
> +	size_t datalen = prep->datalen;
> +	char *data = NULL;
> +	int key_cmd = 0;
> +	int ret = 0;
> +	enum sk_req_type sk_op_type;
> +	struct device *dev = NULL;
> +
> +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	data = kmalloc(datalen + 1, GFP_KERNEL);
> +	if (!data) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	memcpy(data, prep->data, datalen);
> +	data[datalen] = '\0';
> +
> +	payload = secure_payload_alloc(key);
> +	if (!payload) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Allocate caam job ring for operation to be performed from CAAM */
> +	dev = caam_jr_alloc();
> +	if (!dev) {
> +		pr_info("caam_jr_alloc failed\n");
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	key_cmd = parse_inputdata(data, payload);
> +	if (key_cmd < 0) {
> +		ret = key_cmd;
> +		goto out;
> +	}
> +
> +	switch (key_cmd) {
> +	case load_blob:
> +		/*
> +		 * Red blob decryption to be done for load operation
> +		 * to derive the key.
> +		 */
> +		sk_op_type = sk_red_blob_dec;
> +		ret = key_deblob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	case new_key:
> +		/* Get Random number from caam of the specified length */
> +		sk_op_type = sk_get_random;
> +		ret = caam_get_random(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: get_random fail (%d)\n", ret);
> +			goto out;
> +		}
> +
> +		/* Generate red blob of key random bytes with CAAM */
> +		sk_op_type = sk_red_blob_enc;
> +		ret = key_blob(payload, sk_op_type, dev);
> +		if (ret != 0) {
> +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> +			goto out;
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +out:
> +	if (data)
> +		kzfree(data);
> +	if (dev)
> +		caam_jr_free(dev);
> +
> +	if (!ret)
> +		rcu_assign_keypointer(key, payload);
> +	else
> +		kzfree(payload);
> +
> +	return ret;
> +}
> +
> +/*
> + * secure_read - copy the  blob data to userspace in hex.
> + * param[in]: key pointer to key struct
> + * param[in]: buffer pointer to user data for creating key
> + * param[in]: buflen is the length of the buffer
> + * On success, return to userspace the secure key data size.
> + */
> +static long secure_read(const struct key *key, char __user *buffer,
> +			 size_t buflen)
> +{
> +	const struct secure_key_payload *p = NULL;
> +	char *ascii_buf;
> +	char *bufp;
> +	int i;
> +
> +	p = dereference_key_locked(key);
> +	if (!p)
> +		return -EINVAL;
> +
> +	if (buffer && buflen >= 2 * p->blob_len) {
> +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> +		if (!ascii_buf)
> +			return -ENOMEM;
> +
> +		bufp = ascii_buf;
> +		for (i = 0; i < p->blob_len; i++)
> +			bufp = hex_byte_pack(bufp, p->blob[i]);
> +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> +			kzfree(ascii_buf);
> +			return -EFAULT;
> +		}
> +		kzfree(ascii_buf);
> +	}
> +	return 2 * p->blob_len;
> +}
> +
> +/*
> + * secure_destroy - clear and free the key's payload
> + */
> +static void secure_destroy(struct key *key)
> +{
> +	kzfree(key->payload.data[0]);
> +}
> +
> +struct key_type key_type_secure = {
> +	.name = "secure",
> +	.instantiate = secure_instantiate,
> +	.destroy = secure_destroy,
> +	.read = secure_read,
> +};
> +EXPORT_SYMBOL_GPL(key_type_secure);
> +
> +static void secure_shash_release(void)
> +{
> +	if (hashalg)
> +		crypto_free_shash(hashalg);
> +	if (hmacalg)
> +		crypto_free_shash(hmacalg);
> +}
> +
> +static int __init secure_shash_alloc(void)
> +{
> +	int ret;
> +
> +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hmacalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hmac_alg);
> +		return PTR_ERR(hmacalg);
> +	}
> +
> +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hashalg)) {
> +		pr_info("secure_key: could not allocate crypto %s\n",
> +				hash_alg);
> +		ret = PTR_ERR(hashalg);
> +		goto hashalg_fail;
> +	}
> +
> +	return 0;
> +
> +hashalg_fail:
> +	crypto_free_shash(hmacalg);
> +	return ret;
> +}
> +
> +static int __init init_secure_key(void)
> +{
> +	int ret;
> +
> +	ret = secure_shash_alloc();
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = register_key_type(&key_type_secure);
> +	if (ret < 0)
> +		secure_shash_release();
> +	return ret;
> +}
> +
> +static void __exit cleanup_secure_key(void)
> +{
> +	secure_shash_release();
> +	unregister_key_type(&key_type_secure);
> +}
> +
> +late_initcall(init_secure_key);
> +module_exit(cleanup_secure_key);
> +
> +MODULE_LICENSE("GPL");
> diff --git a/security/keys/securekey_desc.c b/security/keys/securekey_desc.c
> new file mode 100644
> index 000000000000..a4fa811a5753
> --- /dev/null
> +++ b/security/keys/securekey_desc.c
> @@ -0,0 +1,606 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 NXP
> + *
> + */
> +
> +#include <keys/secure-type.h>
> +#include "securekey_desc.h"
> +
> +/* key modifier for blob encapsulation & decapsulation descriptor */
> +u8 key_modifier[] = "SECURE_KEY";
> +u32 key_modifier_len = 10;
> +
> +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct random_desc *rnd_desc = NULL;
> +	size_t len = 0;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +	len = fetch_rnd_data->key_len;
> +
> +	/* command 0x82500000 */
> +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> +			OP_ALG_ALGSEL_RNG);
> +	/* command 0x60340000 | len */
> +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> +	append_ptr(desc, rnd_desc->rnd_data);
> +}
> +
> +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_encap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_encapdesc;
> +	struct sk_red_blob_encap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_encap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> +			  0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> +			   red_blob_req->redblob_sz, 0);
> +
> +	/* RedBlob encapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> + * brief CAAM Descriptor creator from redblob to plaindata.
> + * param[in] skreq Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + */
> +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc *skdesc)
> +{
> +	struct redblob_decap_desc *red_blob_desc =
> +					&skdesc->dma_u.redblob_decapdesc;
> +	struct sk_red_blob_decap *red_blob_req =
> +					&skreq->req_u.sk_red_blob_decap;
> +	u32 *desc = skreq->hwdesc;
> +
> +	init_job_desc(desc, 0);
> +
> +	/* Load class 2 key with key modifier. */
> +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> +
> +	/* SEQ IN PTR Command. */
> +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> +			  red_blob_req->redblob_sz, 0);
> +
> +	/* SEQ OUT PTR Command. */
> +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> +			   red_blob_req->data_sz, 0);
> +
> +	/* RedBlob decapsulation PROTOCOL Command. */
> +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
> +}
> +
> +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> + *			      struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> +			   struct sk_desc *skdesc)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data;
> +	struct random_desc *rnd_desc;
> +
> +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +	rnd_desc = &skdesc->dma_u.random_descp;
> +
> +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_random_map_fail;
> +	}
> +	return 0;
> +
> +sk_random_map_fail:
> +	return -ENOMEM;
> +}
> +
> +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> + *					struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_encap *red_blob_encap;
> +	struct redblob_encap_desc *red_blob_desc;
> +
> +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	return 0;
> +
> +sk_redblob_fail:
> +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> +			 DMA_TO_DEVICE);
> +sk_data_fail:
> +	return -ENOMEM;
> +}
> +
> +/* static int caam_sk_redblob_decap_map(struct device *dev,
> + *					    struct sk_req *req,
> + *					    struct sk_desc *skdesc)
> + * brief DMA map the buffer virtual pointers to physical address.
> + * param[in] dev Pointer to job ring device structure
> + * param[in] req Pointer to secure key request structure
> + * param[in] skdesc Pointer to secure key descriptor structure
> + * return 0 on success, error value otherwise.
> + */
> +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> +			      struct sk_desc *skdesc)
> +{
> +	struct sk_red_blob_decap *red_blob_decap;
> +	struct redblob_decap_desc *red_blob_desc;
> +
> +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_redblob_fail;
> +	}
> +
> +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> +		dev_err(dev, "Unable to map memory\n");
> +		goto sk_data_fail;
> +	}
> +
> +	return 0;
> +
> +sk_data_fail:
> +	dma_unmap_single(dev, red_blob_desc->redblob,
> +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> +sk_redblob_fail:
> +	return -ENOMEM;
> +}
> +
> +/* @fn void securekey_unmap(struct device *dev,
> + *			    struct sk_desc *skdesc, struct sk_req *req)
> + * @brief DMA unmap the buffer pointers.
> + * @param[in] dev Pointer to job ring device structure
> + * @param[in] skdesc Pointer to secure key descriptor structure
> + * @param[in] req Pointer to secure key request structure
> + */
> +void securekey_unmap(struct device *dev,
> +		     struct sk_desc *skdesc, struct sk_req *req)
> +{
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			struct sk_fetch_rnd_data *fetch_rnd_data;
> +			struct random_desc *rnd_desc;
> +
> +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> +			rnd_desc = &skdesc->dma_u.random_descp;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, rnd_desc->rnd_data,
> +					 fetch_rnd_data->key_len,
> +					 DMA_FROM_DEVICE);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			struct sk_red_blob_encap *red_blob_encap;
> +			struct redblob_encap_desc *red_blob_desc;
> +
> +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->in_data,
> +					 red_blob_encap->data_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_encap->redblob_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	case sk_red_blob_dec:
> +		{
> +			struct sk_red_blob_decap *red_blob_decap;
> +			struct redblob_decap_desc *red_blob_desc;
> +
> +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> +
> +			/* Unmap Descriptor buffer pointers. */
> +			dma_unmap_single(dev, red_blob_desc->redblob,
> +					 red_blob_decap->redblob_sz,
> +					 DMA_TO_DEVICE);
> +
> +			dma_unmap_single(dev, red_blob_desc->out_data,
> +					 red_blob_decap->data_sz,
> +					 DMA_FROM_DEVICE);
> +
> +			break;
> +		}
> +	default:
> +		dev_err(dev, "Unable to find request type\n");
> +		break;
> +	}
> +	kfree(skdesc);
> +}
> +
> +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> + *  brief CAAM Descriptor creator for secure key operations.
> + *  param[in] dev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> +{
> +	struct sk_desc *skdesc = NULL;
> +	int ret = 0;
> +
> +	switch (req->type) {
> +	case sk_get_random:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam get_random map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +			caam_sk_rng_desc(req, skdesc);
> +			break;
> +		}
> +	case sk_red_blob_enc:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_encap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to create redblob from data. */
> +			caam_sk_redblob_encap_desc(req, skdesc);
> +			break;
> +		}
> +
> +	case sk_red_blob_dec:
> +		{
> +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> +			if (!skdesc) {
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			skdesc->req_type = req->type;
> +
> +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> +				dev_err(dev, "caam redblob_decap map fail\n");
> +				ret = -ENOMEM;
> +				goto out;
> +			}
> +
> +			/* Descriptor function to decap data from redblob. */
> +			caam_sk_redblob_decap_desc(req, skdesc);
> +			break;
> +		}
> +	default:
> +		pr_debug("Unknown request type\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	req->desc_pointer = (void *)skdesc;
> +
> +out:
> +	return ret;
> +}
> +
> +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> + *			     void *context)
> + * brief callback function to be called when descriptor executed.
> + * param[in] dev Pointer to device structure
> + * param[in] desc descriptor pointer
> + * param[in] ret return status of Job submitted
> + * param[in] context void pointer
> + */
> +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> +			 void *context)
> +{
> +	struct sk_req *req = context;
> +
> +	if (ret) {
> +		dev_err(dev, "caam op done err: %x\n", ret);
> +		/* print the error source name. */
> +		caam_jr_strstatus(dev, ret);
> +	}
> +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> +	securekey_unmap(dev, req->desc_pointer, req);
> +
> +	req->ret = ret;
> +	complete(&req->comp);
> +}
> +
> +
> +/*  static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> + *  param[in] jrdev Pointer to job ring device structure
> + *  param[in] req Pointer to secure key request structure
> + *  return 0 on success, error value otherwise.
> + */
> +static int sk_job_submit(struct device *jrdev, struct sk_req *req)
> +{
> +	int ret;
> +
> +	init_completion(&req->comp);
> +
> +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> +	if (!ret)
> +		wait_for_completion_interruptible(&req->comp);
> +
> +	ret = req->ret;
> +	return ret;
> +}
> +
> +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> + *		   struct device *dev)
> + * Create the random number of the specified length using CAAM block
> + * param[in]: out pointer to place the random bytes
> + * param[in]: length for the random data bytes.
> + * param[in]: dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev)
> +{
> +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> +	struct sk_req *req = NULL;
> +	int ret = 0;
> +	void *temp = NULL;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->type = fetch_rnd;
> +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> +
> +	/* initialise with key length */
> +	fetch_rnd_data->key_len = p->key_len;
> +
> +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +	fetch_rnd_data->data = temp;
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (req)
> +		kfree(req);
> +
> +	if (temp)
> +		kfree(temp);
> +
> +	return ret;
> +}
> +
> +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> + *		struct device *dev)
> + * Deblobify the blob to get the key data and fill in secure key payload struct
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev)
> +{
> +	unsigned int blob_len;
> +	struct sk_red_blob_decap *d_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	d_blob = &(req->req_u.sk_red_blob_decap);
> +	blob_len = p->blob_len;
> +	req->type = decap_type;
> +
> +	/*
> +	 * Red blob size is the blob_len filled in payload struct
> +	 * Data_sz i.e. key is the blob_len - blob header size
> +	 */
> +
> +	d_blob->redblob_sz = blob_len;
> +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	d_blob->redblob = temp;
> +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> +	memcpy(d_blob->redblob, p->blob, blob_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init: Failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->key_len = d_blob->data_sz;
> +		memcpy(p->key, d_blob->data, p->key_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(temp);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +}
> +
> +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> + *		struct device *dev)
> + * To blobify the key data to get the blob. This blob can only be seen by
> + * userspace.
> + * param[in] p pointer to the secure key payload
> + * param[in] decap_type operation to be done.
> + * param[in] dev dev Pointer to job ring device structure
> + * If operation is successful return 0, otherwise error.
> + */
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev)
> +{
> +	unsigned int key_len;
> +	struct sk_red_blob_encap *k_blob;
> +	struct sk_req *req = NULL;
> +	int total_sz = 0, *temp = NULL, ret = 0;
> +
> +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> +	if (!req) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	key_len = p->key_len;
> +
> +	req->type = encap_type;
> +	k_blob = &(req->req_u.sk_red_blob_encap);
> +
> +	/*
> +	 * Data_sz i.e. key len and the corresponding blob_len is
> +	 * key_len + BLOB header size.87ea58433208 
> +	 */
> +
> +	k_blob->data_sz = key_len;
> +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> +
> +	temp = kmalloc(total_sz, GFP_DMA);
> +	if (!temp) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	req->mem_pointer = temp;
> +	k_blob->data = temp;
> +
> +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> +	memcpy(k_blob->data, p->key, key_len);
> +
> +	ret = caam_securekey_desc_init(dev, req);
> +
> +	if (ret) {
> +		pr_info("caam_securekey_desc_init failed\n");
> +		goto out;
> +	}
> +
> +	ret = sk_job_submit(dev, req);
> +	if (!ret) {
> +		/*Copy output to key buffer. */
> +		p->blob_len = k_blob->redblob_sz;
> +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> +	} else {
> +		ret = -EINVAL;
> +	}
> +
> +out:
> +	if (temp)
> +		kfree(req->mem_pointer);
> +	if (req)
> +		kfree(req);
> +	return ret;
> +
> +}
> +
> diff --git a/security/keys/securekey_desc.h b/security/keys/securekey_desc.h
> new file mode 100644
> index 000000000000..0ee26e95b205
> --- /dev/null
> +++ b/security/keys/securekey_desc.h
> @@ -0,0 +1,141 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2018 NXP
> + *
> + */
> +#ifndef _SECUREKEY_DESC_H_
> +#define _SECUREKEY_DESC_H_
> +
> +#include "compat.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "desc.h"
> +#include "desc_constr.h"
> +#include "jr.h"
> +#include "error.h"
> +#include "pdb.h"
> +
> +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> +
> +/*
> + * brief defines different kinds of operations supported by this module.
> + */
> +enum sk_req_type {
> +	sk_get_random,
> +	sk_red_blob_enc,
> +	sk_red_blob_dec,
> +};
> +
> +
> +/*
> + * struct random_des
> + * param[out] rnd_data output buffer for random data.
> + */
> +struct random_desc {
> +	dma_addr_t rnd_data;
> +};
> +
> +/* struct redblob_encap_desc
> + * details Structure containing dma address for redblob encapsulation.
> + * param[in] in_data input data to redblob encap descriptor.
> + * param[out] redblob output buffer for redblob.
> + */
> +struct redblob_encap_desc {
> +	dma_addr_t in_data;
> +	dma_addr_t redblob;
> +};
> +
> +/* struct redblob_decap_desc
> + * details Structure containing dma address for redblob decapsulation.
> + * param[in] redblob input buffer to redblob decap descriptor.
> + * param[out] out_data output data from redblob decap descriptor.
> + */
> +struct redblob_decap_desc {
> +	dma_addr_t redblob;
> +	dma_addr_t out_data;
> +};
> +
> +/* struct sk_desc
> + * details Structure for securekey descriptor creation.
> + * param[in] req_type operation supported.
> + * param[in] dma_u union of struct for supported operation.
> + */
> +struct sk_desc {
> +	u32 req_type;
> +	union {
> +		struct redblob_encap_desc redblob_encapdesc;
> +		struct redblob_decap_desc redblob_decapdesc;
> +		struct random_desc random_descp;
> +	} dma_u;
> +};
> +
> +/* struct sk_fetch_rnd_data
> + * decriptor structure containing key length.
> + */
> +struct sk_fetch_rnd_data {
> +	void *data;
> +	size_t key_len;
> +};
> +
> +/* struct sk_red_blob_encap
> + * details Structure containing buffer pointers for redblob encapsulation.
> + * param[in] data Input data.
> + * param[in] data_sz size of Input data.
> + * param[out] redblob output buffer for redblob.
> + * param[in] redblob_sz size of redblob.
> + */
> +struct sk_red_blob_encap {
> +	void *data;
> +	uint32_t data_sz;
> +	void *redblob;
> +	uint32_t redblob_sz;
> +};
> +
> +/* struct sk_red_blob_decap
> + * details Structure containing buffer pointers for redblob decapsulation.
> + * param[in] redblob Input redblob.
> + * param[in] redblob_sz size of redblob.
> + * param[out] data output buffer for data.
> + * param[in] data_sz size of output data.
> + */
> +struct sk_red_blob_decap {
> +	void *redblob;
> +	uint32_t redblob_sz;
> +	void *data;
> +	uint32_t data_sz;
> +};
> +
> +/* struct sk_req
> + * details Structure for securekey request creation.
> + * param[in] type operation supported.
> + * param[in] req_u union of struct for supported operation.
> + * param[out] ret return status of CAAM operation.
> + * param[in] mem_pointer memory pointer for allocated kernel memory.
> + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> + * param[in] comp struct completion object.
> + * param[in] hwdesc contains descriptor instructions.
> + */
> +struct sk_req {
> +	enum sk_req_type type;
> +	void *arg;
> +	union {
> +		struct sk_red_blob_encap sk_red_blob_encap;
> +		struct sk_red_blob_decap sk_red_blob_decap;
> +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> +	} req_u;
> +	int ret;
> +	void *mem_pointer;
> +	void *desc_pointer;
> +	struct completion comp;
> +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> +};
> +
> +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> +		    struct device *dev);
> +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> +	     struct device *dev);
> +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> +	       struct device *dev);
> +
> +#endif /*_SECUREKEY_DESC_H_*/

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-21 14:44     ` Udit Agarwal
  (?)
  (?)
@ 2018-07-23 12:42       ` Jan Lübbe
  -1 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-23 12:42 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

Hi,

On Sat, 2018-07-21 at 14:44 +0000, Udit Agarwal wrote:
> Thanks for sharing the documentation changes and feedback.
> 
> Below are the answers to the questions:
> 
> 1. Currently the secure key patch series has been added  to support
> only data blobs.
> It is not supporting key blobs as of now, we have thought of adding
> that support in future.

OK. Do have a plan how the key blobs would be represented in the
keyring? It seems it would need to be some sort of handle instead of
the key data. Would it need a different userspace API?

> 2. Yes secure keys could also be implemented using OPTEE. I will
> change the documentation in next patch version.

Thanks!

Jan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-23 12:42       ` Jan Lübbe
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-23 12:42 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

Hi,

On Sat, 2018-07-21 at 14:44 +0000, Udit Agarwal wrote:
> Thanks for sharing the documentation changes and feedback.
> 
> Below are the answers to the questions:
> 
> 1. Currently the secure key patch series has been added  to support
> only data blobs.
> It is not supporting key blobs as of now, we have thought of adding
> that support in future.

OK. Do have a plan how the key blobs would be represented in the
keyring? It seems it would need to be some sort of handle instead of
the key data. Would it need a different userspace API?

> 2. Yes secure keys could also be implemented using OPTEE. I will
> change the documentation in next patch version.

Thanks!

Jan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-23 12:42       ` Jan Lübbe
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-23 12:42 UTC (permalink / raw)
  To: linux-security-module

Hi,

On Sat, 2018-07-21 at 14:44 +0000, Udit Agarwal wrote:
> Thanks for sharing the documentation changes and feedback.
> 
> Below are the answers to the questions:
> 
> 1. Currently the secure key patch series has been added  to support
> only data blobs.
> It is not supporting key blobs as of now, we have thought of adding
> that support in future.

OK. Do have a plan how the key blobs would be represented in the
keyring? It seems it would need to be some sort of handle instead of
the key data. Would it need a different userspace API?

> 2. Yes secure keys could also be implemented using OPTEE. I will
> change the documentation in next patch version.

Thanks!

Jan
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-23 12:42       ` Jan Lübbe
  0 siblings, 0 replies; 32+ messages in thread
From: Jan Lübbe @ 2018-07-23 12:42 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

Hi,

On Sat, 2018-07-21 at 14:44 +0000, Udit Agarwal wrote:
> Thanks for sharing the documentation changes and feedback.
> 
> Below are the answers to the questions:
> 
> 1. Currently the secure key patch series has been added  to support
> only data blobs.
> It is not supporting key blobs as of now, we have thought of adding
> that support in future.

OK. Do have a plan how the key blobs would be represented in the
keyring? It seems it would need to be some sort of handle instead of
the key data. Would it need a different userspace API?

> 2. Yes secure keys could also be implemented using OPTEE. I will
> change the documentation in next patch version.

Thanks!

Jan

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-22 23:34   ` Mimi Zohar
  (?)
  (?)
@ 2018-07-24 12:31     ` Udit Agarwal
  -1 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-24 12:31 UTC (permalink / raw)
  To: Mimi Zohar, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

PiBPbiBGcmksIDIwMTgtMDctMjAgYXQgMTE6MTYgKzA1MzAsIFVkaXQgQWdhcndhbCB3cm90ZToN
Cj4gPiBTZWN1cmUga2V5cyBhcmUgZGVyaWV2ZWQgdXNpbmcgQ0FBTSBjcnlwdG8gYmxvY2suDQo+
ID4NCj4gPiBTZWN1cmUga2V5cyBkZXJpZXZlZCBhcmUgdGhlIHJhbmRvbSBudW1iZXIgc3ltbWV0
cmljIGtleXMgZnJvbSBDQUFNLg0KPiA+IEJsb2JzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGtleSBh
cmUgZm9ybWVkIHVzaW5nIENBQU0uIFVzZXIgc3BhY2Ugd2lsbA0KPiA+IG9ubHkgYmUgYWJsZSB0
byB2aWV3IHRoZSBibG9iIG9mIHRoZSBrZXkuDQo+IA0KPiBUaGUgdGVybSAidHJ1c3RlZCBrZXlz
IiBjb21lcyBmcm9tIHRoZSB1c2FnZSBvZiB0aGUgVHJ1c3RlZCBQbGF0Zm9ybSBNb2R1bGUNCj4g
KFRQTSkuIMKgVGhlIHRlcm0gInRydXN0ZWQiIG5vdyBhbHNvIHJlZmVycyB0byBrZXlyaW5ncywg
d2hpY2ggaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCBhDQo+IFRQTS4NCj4gDQo+IFdoYXQgaXMgdGhl
IGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHRlcm0gInNlY3VyZSBrZXlzIiBhbmQgQ0FBTT8gwqBB
cmUgInNlY3VyZSBrZXlzIiwgYXMNCj4gZGVmaW5lZCBpbiB0aGlzIHBhdGNoLCBsaW1pdGVkIHRv
IGEgc3BlY2lmaWMgSFcgY3J5cHRvIGRldmljZT8NCj4gDQo+IE1pbWkNCj4gDQoNClllcyB0aGUg
c2VjdXJlIGtleXMgYW5kIENBQU0gYXJlIGNvcnJlbGF0ZWQuIFNlY3VyZSBrZXlzIGRlcGVuZHMg
b24gTlhQIENBQU0gY3J5cHRvIEhXDQphY2NlbGVyYXRvci4gU2VjdXJlIGtleSBpcyBhIHJhbmRv
bSBkYXRhIG9mIGxlbmd0aCBYIChwYXNzZWQgdXNpbmcga2V5Y3RsIGNvbW1hbmQpICYgZGVyaXZl
ZA0KdXNpbmcgQ0FBTS4gQmxvYiBvZiB0aGlzIGRhdGEgaXMgYWxzbyBjcmVhdGVkIHVzaW5nIENB
QU0uIE9ubHkgYmxvYiBpcyB2aXNpYmxlIHRvIHVzZXIgc3BhY2UuDQoNClJlZ2FyZHMsDQpVZGl0
IA0KDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBVZGl0IEFnYXJ3YWwgPHVkaXQuYWdhcndhbEBu
eHAuY29tPg0KPiA+IFJldmlld2VkLWJ5OiBTYWhpbCBNYWxob3RyYSA8c2FoaWwubWFsaG90cmFA
bnhwLmNvbT4NCj4gPiAtLS0NCj4gPiAgRG9jdW1lbnRhdGlvbi9zZWN1cml0eS9rZXlzL3NlY3Vy
ZS1rZXkucnN0IHwgIDY3ICsrKw0KPiA+ICBNQUlOVEFJTkVSUyAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgfCAgMTEgKw0KPiA+ICBpbmNsdWRlL2tleXMvc2VjdXJlLXR5cGUuaCAgICAg
ICAgICAgICAgICAgfCAgMzMgKysNCj4gPiAgc2VjdXJpdHkva2V5cy9LY29uZmlnICAgICAgICAg
ICAgICAgICAgICAgIHwgIDExICsNCj4gPiAgc2VjdXJpdHkva2V5cy9NYWtlZmlsZSAgICAgICAg
ICAgICAgICAgICAgIHwgICAzICsNCj4gPiAgc2VjdXJpdHkva2V5cy9zZWN1cmVfa2V5LmMgICAg
ICAgICAgICAgICAgIHwgMzM5ICsrKysrKysrKysrKw0KPiA+ICBzZWN1cml0eS9rZXlzL3NlY3Vy
ZWtleV9kZXNjLmMgICAgICAgICAgICAgfCA2MDYgKysrKysrKysrKysrKysrKysrKysrDQo+ID4g
IHNlY3VyaXR5L2tleXMvc2VjdXJla2V5X2Rlc2MuaCAgICAgICAgICAgICB8IDE0MSArKysrKw0K
PiA+ICA4IGZpbGVzIGNoYW5nZWQsIDEyMTEgaW5zZXJ0aW9ucygrKQ0KPiA+ICBjcmVhdGUgbW9k
ZSAxMDA2NDQgRG9jdW1lbnRhdGlvbi9zZWN1cml0eS9rZXlzL3NlY3VyZS1rZXkucnN0DQo+ID4g
IGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL2tleXMvc2VjdXJlLXR5cGUuaCAgY3JlYXRlIG1v
ZGUgMTAwNjQ0DQo+ID4gc2VjdXJpdHkva2V5cy9zZWN1cmVfa2V5LmMgIGNyZWF0ZSBtb2RlIDEw
MDY0NA0KPiA+IHNlY3VyaXR5L2tleXMvc2VjdXJla2V5X2Rlc2MuYyAgY3JlYXRlIG1vZGUgMTAw
NjQ0DQo+ID4gc2VjdXJpdHkva2V5cy9zZWN1cmVrZXlfZGVzYy5oDQo+ID4NCj4gPiBkaWZmIC0t
Z2l0IGEvRG9jdW1lbnRhdGlvbi9zZWN1cml0eS9rZXlzL3NlY3VyZS1rZXkucnN0DQo+ID4gYi9E
b2N1bWVudGF0aW9uL3NlY3VyaXR5L2tleXMvc2VjdXJlLWtleS5yc3QNCj4gPiBuZXcgZmlsZSBt
b2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAwMDAwMC4uMGZjMzM2N2IwMGY4DQo+ID4gLS0t
IC9kZXYvbnVsbA0KPiA+ICsrKyBiL0RvY3VtZW50YXRpb24vc2VjdXJpdHkva2V5cy9zZWN1cmUt
a2V5LnJzdA0KPiA+IEBAIC0wLDAgKzEsNjcgQEANCj4gPiArPT09PT09PT09PQ0KPiA+ICtTZWN1
cmUgS2V5DQo+ID4gKz09PT09PT09PT0NCj4gPiArDQo+ID4gK1NlY3VyZSBrZXkgaXMgdGhlIG5l
dyB0eXBlIGFkZGVkIHRvIGtlcm5lbCBrZXkgcmluZyBzZXJ2aWNlLg0KPiA+ICtTZWN1cmUga2V5
IGlzIGEgc3ltbWV0cmljIHR5cGUga2V5IG9mIG1pbmltdW0gbGVuZ3RoIDMyIGJ5dGVzIGFuZA0K
PiA+ICt3aXRoIG1heGltdW0gcG9zc2libGUgbGVuZ3RoIHRvIGJlIDEyOCBieXRlcy4gSXQgaXMg
cHJvZHVjZWQgaW4NCj4gPiAra2VybmVsIHVzaW5nIHRoZSBDQUFNIGNyeXB0byBlbmdpbmUuIFVz
ZXJzcGFjZSBjYW4gb25seSBzZWUgdGhlIGJsb2INCj4gPiArZm9yIHRoZSBjb3JyZXNwb25kaW5n
IGtleS4gQWxsIHRoZSBibG9icyBhcmUgZGlzcGxheWVkIG9yIGxvYWRlZCBpbg0KPiA+ICtoZXgg
YXNjaWkuDQo+ID4gKw0KPiA+ICtTZWN1cmUga2V5IGNhbiBvbmx5IGJlIGNyZWF0ZWQgb24gcGxh
dGZvcm1zIHdoaWNoIHN1cHBvcnRzIENBQU0NCj4gPiAraGFyZHdhcmUgYmxvY2suIFNlY3VyZSBr
ZXkgY2FuIGFsc28gYmUgdXNlZCBhcyBhIG1hc3RlciBrZXkgdG8gY3JlYXRlDQo+ID4gK3RoZSBl
bmNyeXB0ZWQga2V5cyBhbG9uZyB3aXRoIHRoZSBleGlzdGluZyBrZXkgdHlwZXMgaW4ga2VybmVs
Lg0KPiA+ICsNCj4gPiArU2VjdXJlIGtleSB1c2VzIENBQU0gaGFyZHdhcmUgdG8gZ2VuZXJhdGUg
dGhlIGtleSBhbmQgYmxvYmlmeSBpdHMNCj4gPiArY29udGVudCBmb3IgdXNlcnNwYWNlLiBHZW5l
cmF0ZWQgYmxvYnMgYXJlIHRpZWQgdXAgd2l0aCB0aGUgaGFyZHdhcmUNCj4gPiArc2VjcmV0IGtl
eSBzdG9yZWQgaW4gQ0FBTSwgaGVuY2UgdGhlIHNhbWUgYmxvYiB3aWxsIG5vdCBiZSBhYmxlIHRv
DQo+ID4gK2RlLWJsb2JpZnkgd2l0aCB0aGUgZGlmZmVyZW50IHNlY3JldCBrZXkgb24gYW5vdGhl
ciBtYWNoaW5lLg0KPiA+ICsNCj4gPiArVXNhZ2U6Og0KPiA+ICsNCj4gPiArCWtleWN0bCBhZGQg
c2VjdXJlIDxuYW1lPiAibmV3IDxrZXlsZW4+IiA8cmluZz4NCj4gPiArCWtleWN0bCBsb2FkIHNl
Y3VyZSA8bmFtZT4gImxvYWQgPGhleF9ibG9iPiIgPHJpbmc+DQo+ID4gKwlrZXljdGwgcHJpbnQg
PGtleV9pZD4NCj4gPiArDQo+ID4gKyJrZXljdGwgYWRkIHNlY3VyZSIgb3B0aW9uIHdpbGwgY3Jl
YXRlIHRoZSByYW5kb20gZGF0YSBvZiB0aGUNCj4gPiArc3BlY2lmaWVkIGtleSBsZW4gdXNpbmcg
Q0FBTSBhbmQgc3RvcmUgaXQgYXMgYSBrZXkgaW4ga2VybmVsLg0KPiA+ICtLZXkgY29udGVudHMg
d2lsbCBiZSBkaXNwbGF5ZWQgYXMgYmxvYnMgdG8gdGhlIHVzZXIgaW4gaGV4IGFzY2lpLg0KPiA+
ICtVc2VyIGNhbiBpbnB1dCBrZXkgbGVuIGZyb20gMzIgYnl0ZXMgdG8gMTI4IGJ5dGVzLg0KPiA+
ICsNCj4gPiArImtleWN0bCBsb2FkIHNlY3VyZSIgb3B0aW9uIHdpbGwgbG9hZCB0aGUgYmxvYiBj
b250ZW50cy4gSW4ga2VybmVsLA0KPiA+ICtrZXkgd2lsbCBiZSBkZWlydmVkIHVzaW5nIGlucHV0
IGJsb2IgYW5kIENBQU0sIGFsb25nIHdpdGggdGhlIHNlY3JldA0KPiA+ICtrZXkgc3RvcmVkIGlu
IENBQU0uDQo+ID4gKw0KPiA+ICsia2V5Y3RsIHByaW50IiB3aWxsIHJldHVybiB0aGUgaGV4IHN0
cmluZyBvZiB0aGUgYmxvYiBjb3JyZXNwb25kaW5nDQo+ID4gK3RvIGtleV9pZC4gUmV0dXJuZWQg
YmxvYiB3aWxsIGJlIG9mIGtleV9sZW4gKyA0OCBieXRlcy4gRXh0cmEgNDgNCj4gPiArYnl0ZXMg
YXJlIHRoZSBoZWFkZXIgYnl0ZXMgYWRkZWQgYnkgdGhlIENBQU0uDQo+ID4gKw0KPiA+ICtFeGFt
cGxlIG9mIHNlY3VyZSBrZXkgdXNhZ2U6Og0KPiA+ICsNCj4gPiArMS4gQ3JlYXRlIHRoZSBzZWN1
cmUga2V5IHdpdGggbmFtZSBrbWstbWFzdGVyIG9mIGxlbmd0aCAzMiBieXRlczo6DQo+ID4gKw0K
PiA+ICsJJCBrZXljdGwgYWRkIHNlY3VyZSBrbWstbWFzdGVyICJuZXcgMzIiIEB1DQo+ID4gKwk0
NjAwMTkyOA0KPiA+ICsNCj4gPiArCSRrZXljdGwgc2hvdw0KPiA+ICsJU2Vzc2lvbiBLZXlyaW5n
DQo+ID4gKwkxMDMwNzgzNjI2IC0tYWxzd3J2ICAgICAgMCA2NTUzNCAga2V5cmluZzogX3VpZF9z
ZXMuMA0KPiA+ICsJIDY5NTkyNzc0NSAtLWFsc3dydiAgICAgIDAgNjU1MzQgICBcXyBrZXlyaW5n
OiBfdWlkLjANCj4gPiArCSAgNDYwMDE5MjggLS1hbHMtcnYgICAgICAwICAgICAwICAgICAgIFxf
IHNlY3VyZToga21rLW1hc3Rlcg0KPiA+ICsNCj4gPiArMi4gUHJpbnQgdGhlIGJsb2IgY29udGVu
dHMgZm9yIHRoZSBrbWstbWFzdGVyIGtleTo6DQo+ID4gKw0KPiA+ICsJJCBrZXljdGwgcHJpbnQg
NDYwMDE5MjgNCj4gPiArCWQ5NzQzNDQ1YjY0MGYzZDU5YzE2NzBkZGRjMGJjOWMyDQo+ID4gKwkz
NGZjOWFhYjdkZDA1Yzk2NWU2MTIwMDI1MDEyZjAyOWINCj4gPiArCTA3ZmFhNDc3NmM0ZjZlZDAy
ODk5ZTM1YTEzNTUzMWU5YQ0KPiA+ICsJNmU1YzJiNTExMzJmOWQ1YWVmMjhmNjg3MzhlNjU4Mjk2
DQo+ID4gKwkzZmU1ODMxNzdjZmU1MGQyNTQyYjY1OWExMzAzOQ0KPiA+ICsNCj4gPiArCSQga2V5
Y3RsIHBpcGUgNDYwMDE5MjggPiBzZWN1cmVfa2V5LmJsb2INCj4gPiArDQo+ID4gKzMuIExvYWQg
dGhlIGJsb2IgaW4gdGhlIHVzZXIga2V5IHJpbmc6Og0KPiA+ICsNCj4gPiArCSQga2V5Y3RsIGxv
YWQgc2VjdXJlIGttay1tYXN0ZXIgImxvYWQgJ2NhdCBzZWN1cmVfa2V5LmJsb2InIiBAdQ0KPiA+
IGRpZmYgLS1naXQgYS9NQUlOVEFJTkVSUyBiL01BSU5UQUlORVJTIGluZGV4DQo+ID4gOWZkNWU4
ODA4MjA4Li42NTRiZTJlZTRiMGEgMTAwNjQ0DQo+ID4gLS0tIGEvTUFJTlRBSU5FUlMNCj4gPiAr
KysgYi9NQUlOVEFJTkVSUw0KPiA+IEBAIC03OTM5LDYgKzc5MzksMTcgQEAgRjoJaW5jbHVkZS9r
ZXlzL3RydXN0ZWQtdHlwZS5oDQo+ID4gIEY6CXNlY3VyaXR5L2tleXMvdHJ1c3RlZC5jDQo+ID4g
IEY6CXNlY3VyaXR5L2tleXMvdHJ1c3RlZC5oDQo+ID4NCj4gPiArS0VZUy1TRUNVUkUNCj4gPiAr
TToJVWRpdCBBZ2Fyd2FsIDx1ZGl0LmFnYXJ3YWxAbnhwLmNvbT4NCj4gPiArUjoJU2FoaWwgTWFs
aG90cmEgPHNhaGlsLm1hbGhvdHJhQG54cC5jb20+DQo+ID4gK0w6CWxpbnV4LXNlY3VyaXR5LW1v
ZHVsZUB2Z2VyLmtlcm5lbC5vcmcNCj4gPiArTDoJa2V5cmluZ3NAdmdlci5rZXJuZWwub3JnDQo+
ID4gK1M6CVN1cHBvcnRlZA0KPiA+ICtGOglpbmNsdWRlL2tleXMvc2VjdXJlLXR5cGUuaA0KPiA+
ICtGOglzZWN1cml0eS9rZXlzL3NlY3VyZV9rZXkuYw0KPiA+ICtGOglzZWN1cml0eS9rZXlzL3Nl
Y3VyZWtleV9kZXNjLmMNCj4gPiArRjoJc2VjdXJpdHkva2V5cy9zZWN1cmVrZXlfZGVzYy5oDQo+
ID4gKw0KPiA+ICBLRVlTL0tFWVJJTkdTOg0KPiA+ICBNOglEYXZpZCBIb3dlbGxzIDxkaG93ZWxs
c0ByZWRoYXQuY29tPg0KPiA+ICBMOglrZXlyaW5nc0B2Z2VyLmtlcm5lbC5vcmcNCj4gPiBkaWZm
IC0tZ2l0IGEvaW5jbHVkZS9rZXlzL3NlY3VyZS10eXBlLmggYi9pbmNsdWRlL2tleXMvc2VjdXJl
LXR5cGUuaA0KPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0IGluZGV4IDAwMDAwMDAwMDAwMC4uNWI3
YTVmMTQ0ZTQxDQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL2luY2x1ZGUva2V5cy9zZWN1
cmUtdHlwZS5oDQo+ID4gQEAgLTAsMCArMSwzMyBAQA0KPiA+ICsvKiBTUERYLUxpY2Vuc2UtSWRl
bnRpZmllcjogR1BMLTIuMCAqLw0KPiA+ICsvKg0KPiA+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTgg
TlhQLg0KPiA+ICsgKg0KPiA+ICsgKi8NCj4gPiArDQo+ID4gKyNpZm5kZWYgX0tFWVNfU0VDVVJF
X1RZUEVfSA0KPiA+ICsjZGVmaW5lIF9LRVlTX1NFQ1VSRV9UWVBFX0gNCj4gPiArDQo+ID4gKyNp
bmNsdWRlIDxsaW51eC9rZXkuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3JjdXBkYXRlLmg+DQo+
ID4gKw0KPiA+ICsvKiBNaW5pbXVtIGtleSBzaXplIHRvIGJlIHVzZWQgaXMgMzIgYnl0ZXMgYW5k
IG1heGltdW0ga2V5IHNpemUgZml4ZWQNCj4gPiArICogaXMgMTI4IGJ5dGVzLg0KPiA+ICsgKiBC
bG9iIHNpemUgdG8gYmUga2VwdCBpcyBNYXhpbXVtIGtleSBzaXplICsgYmxvYiBoZWFkZXIgYWRk
ZWQgYnkgQ0FBTS4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsjZGVmaW5lIE1JTl9LRVlfU0laRSAg
ICAgICAgICAgICAgICAgICAgMzINCj4gPiArI2RlZmluZSBNQVhfS0VZX1NJWkUgICAgICAgICAg
ICAgICAgICAgIDEyOA0KPiA+ICsjZGVmaW5lIEJMT0JfSEVBREVSX1NJWkUJCTQ4DQo+ID4gKw0K
PiA+ICsjZGVmaW5lIE1BWF9CTE9CX1NJWkUgICAgICAgICAgICAgICAgICAgKE1BWF9LRVlfU0la
RSArIEJMT0JfSEVBREVSX1NJWkUpDQo+ID4gKw0KPiA+ICtzdHJ1Y3Qgc2VjdXJlX2tleV9wYXls
b2FkIHsNCj4gPiArCXN0cnVjdCByY3VfaGVhZCByY3U7DQo+ID4gKwl1bnNpZ25lZCBpbnQga2V5
X2xlbjsNCj4gPiArCXVuc2lnbmVkIGludCBibG9iX2xlbjsNCj4gPiArCXVuc2lnbmVkIGNoYXIg
a2V5W01BWF9LRVlfU0laRSArIDFdOw0KPiA+ICsJdW5zaWduZWQgY2hhciBibG9iW01BWF9CTE9C
X1NJWkVdOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArZXh0ZXJuIHN0cnVjdCBrZXlfdHlwZSBrZXlf
dHlwZV9zZWN1cmU7ICNlbmRpZg0KPiA+IGRpZmYgLS1naXQgYS9zZWN1cml0eS9rZXlzL0tjb25m
aWcgYi9zZWN1cml0eS9rZXlzL0tjb25maWcgaW5kZXgNCj4gPiA2NDYyZTY2NTRjY2YuLjdlYjEz
OGI1YTU0ZiAxMDA2NDQNCj4gPiAtLS0gYS9zZWN1cml0eS9rZXlzL0tjb25maWcNCj4gPiArKysg
Yi9zZWN1cml0eS9rZXlzL0tjb25maWcNCj4gPiBAQCAtNzEsNiArNzEsMTcgQEAgY29uZmlnIFRS
VVNURURfS0VZUw0KPiA+DQo+ID4gIAkgIElmIHlvdSBhcmUgdW5zdXJlIGFzIHRvIHdoZXRoZXIg
dGhpcyBpcyByZXF1aXJlZCwgYW5zd2VyIE4uDQo+ID4NCj4gPiArY29uZmlnIFNFQ1VSRV9LRVlT
DQo+ID4gKwl0cmlzdGF0ZSAiU0VDVVJFX0tFWVMiDQo+ID4gKwlkZXBlbmRzIG9uIEtFWVMgJiYg
Q1JZUFRPX0RFVl9GU0xfQ0FBTSAmJg0KPiBDUllQVE9fREVWX0ZTTF9DQUFNX0pSDQo+ID4gKwlo
ZWxwDQo+ID4gKwkgIFRoaXMgb3B0aW9uIHByb3ZpZGUgc3VwcG9ydCBmb3IgY3JlYXRpbmcgc2Vj
dXJlLXR5cGUga2V5IGFuZCBibG9icw0KPiA+ICsJICBpbiBrZXJuZWwuIFNlY3VyZSBrZXlzIGFy
ZSByYW5kb20gbnVtYmVyIHN5bW1ldHJpYyBrZXlzIGdlbmVyYXRlZA0KPiA+ICsJICBmcm9tIENB
QU0uIFRoZSBDQUFNIGNyZWF0ZXMgdGhlIGJsb2JzIGZvciB0aGUgcmFuZG9tIGtleS4NCj4gPiAr
CSAgVXNlcnNwYWNlIHdpbGwgb25seSBiZSBhYmxlIHRvIHNlZSB0aGUgYmxvYi4NCj4gPiArDQo+
ID4gKwkgIElmIHlvdSBhcmUgdW5zdXJlIGFzIHRvIHdoZXRoZXIgdGhpcyBpcyByZXF1aXJlZCwg
YW5zd2VyIE4uDQo+ID4gKw0KPiA+ICBjb25maWcgRU5DUllQVEVEX0tFWVMNCj4gPiAgCXRyaXN0
YXRlICJFTkNSWVBURUQgS0VZUyINCj4gPiAgCWRlcGVuZHMgb24gS0VZUw0KPiA+IGRpZmYgLS1n
aXQgYS9zZWN1cml0eS9rZXlzL01ha2VmaWxlIGIvc2VjdXJpdHkva2V5cy9NYWtlZmlsZSBpbmRl
eA0KPiA+IGVmMTU4MWIzMzdhMy4uNjA2YmE0ZWZiOWU2IDEwMDY0NA0KPiA+IC0tLSBhL3NlY3Vy
aXR5L2tleXMvTWFrZWZpbGUNCj4gPiArKysgYi9zZWN1cml0eS9rZXlzL01ha2VmaWxlDQo+ID4g
QEAgLTI4LDQgKzI4LDcgQEAgb2JqLSQoQ09ORklHX0tFWV9ESF9PUEVSQVRJT05TKSArPSBkaC5v
ICAjDQo+ID4gIG9iai0kKENPTkZJR19CSUdfS0VZUykgKz0gYmlnX2tleS5vDQo+ID4gIG9iai0k
KENPTkZJR19UUlVTVEVEX0tFWVMpICs9IHRydXN0ZWQubw0KPiA+ICtjY2ZsYWdzLSQoQ09ORklH
X1NFQ1VSRV9LRVlTKSArPSAtSSQob2JqKS8uLi8uLi9kcml2ZXJzL2NyeXB0by9jYWFtLw0KPiA+
ICtvYmotJChDT05GSUdfU0VDVVJFX0tFWVMpICs9IHNlY3VyZWtleV9kZXNjLm8NCj4gPiArb2Jq
LSQoQ09ORklHX1NFQ1VSRV9LRVlTKSArPSBzZWN1cmVfa2V5Lm8NCj4gPiAgb2JqLSQoQ09ORklH
X0VOQ1JZUFRFRF9LRVlTKSArPSBlbmNyeXB0ZWQta2V5cy8gZGlmZiAtLWdpdA0KPiA+IGEvc2Vj
dXJpdHkva2V5cy9zZWN1cmVfa2V5LmMgYi9zZWN1cml0eS9rZXlzL3NlY3VyZV9rZXkuYyBuZXcg
ZmlsZQ0KPiA+IG1vZGUgMTAwNjQ0IGluZGV4IDAwMDAwMDAwMDAwMC4uZWM4YWQ0Mzk0NTQ5DQo+
ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL3NlY3VyaXR5L2tleXMvc2VjdXJlX2tleS5jDQo+
ID4gQEAgLTAsMCArMSwzMzkgQEANCj4gPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ
TC0yLjANCj4gPiArLyogQ29weXJpZ2h0IChDKSAyMDE4IE5YUA0KPiA+ICsgKiBTZWN1cmUga2V5
IGlzIGdlbmVyYXRlZCB1c2luZyBOWFAgQ0FBTSBoYXJkd2FyZSBibG9jay4gQ0FBTQ0KPiA+ICtn
ZW5lcmF0ZXMgdGhlDQo+ID4gKyAqIHJhbmRvbSBudW1iZXIgKHVzZWQgYXMgYSBrZXkpIGFuZCBj
cmVhdGVzIGl0cyBibG9iIGZvciB0aGUgdXNlci4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsjaW5j
bHVkZSA8bGludXgvc2xhYi5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcGFyc2VyLmg+DQo+ID4g
KyNpbmNsdWRlIDxsaW51eC9zdHJpbmcuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L2tleS10eXBl
Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9yY3VwZGF0ZS5oPg0KPiA+ICsjaW5jbHVkZSA8a2V5
cy9zZWN1cmUtdHlwZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvY29tcGxldGlvbi5oPg0KPiA+
ICsNCj4gPiArI2luY2x1ZGUgInNlY3VyZWtleV9kZXNjLmgiDQo+ID4gKw0KPiA+ICtzdGF0aWMg
Y29uc3QgY2hhciBobWFjX2FsZ1tdID0gImhtYWMoc2hhMSkiOyBzdGF0aWMgY29uc3QgY2hhcg0K
PiA+ICtoYXNoX2FsZ1tdID0gInNoYTEiOw0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBjcnlw
dG9fc2hhc2ggKmhhc2hhbGc7DQo+ID4gK3N0YXRpYyBzdHJ1Y3QgY3J5cHRvX3NoYXNoICpobWFj
YWxnOw0KPiA+ICsNCj4gPiArZW51bSB7DQo+ID4gKwllcnJvciA9IC0xLA0KPiA+ICsJbmV3X2tl
eSwNCj4gPiArCWxvYWRfYmxvYiwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBt
YXRjaF90YWJsZV90IGtleV90b2tlbnMgPSB7DQo+ID4gKwl7bmV3X2tleSwgIm5ldyJ9LA0KPiA+
ICsJe2xvYWRfYmxvYiwgImxvYWQifSwNCj4gPiArCXtlcnJvciwgTlVMTH0NCj4gPiArfTsNCj4g
PiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3Qgc2VjdXJlX2tleV9wYXlsb2FkICpzZWN1cmVfcGF5bG9h
ZF9hbGxvYyhzdHJ1Y3Qga2V5DQo+ID4gKyprZXkpIHsNCj4gPiArCXN0cnVjdCBzZWN1cmVfa2V5
X3BheWxvYWQgKnNlY19rZXkgPSBOVUxMOw0KPiA+ICsJaW50IHJldCA9IDA7DQo+ID4gKw0KPiA+
ICsJcmV0ID0ga2V5X3BheWxvYWRfcmVzZXJ2ZShrZXksIHNpemVvZigqc2VjX2tleSkpOw0KPiA+
ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKw0KPiA+ICsJc2VjX2tleSA9
IGt6YWxsb2Moc2l6ZW9mKCpzZWNfa2V5KSwgR0ZQX0tFUk5FTCk7DQo+ID4gKwlpZiAoIXNlY19r
ZXkpDQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKw0KPiA+ICtvdXQ6DQo+ID4gKwlyZXR1cm4gc2Vj
X2tleTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogcGFyc2VfaW5wdXRkYXRhIC0g
cGFyc2UgdGhlIGtleWN0bCBpbnB1dCBkYXRhIGFuZCBmaWxsIGluIHRoZQ0KPiA+ICsgKgkJICAg
ICBwYXlsb2FkIHN0cnVjdHVyZSBmb3Iga2V5IG9yIGl0cyBibG9iLg0KPiA+ICsgKiBwYXJhbVtp
bl06IGRhdGEgcG9pbnRlciB0byB0aGUgZGF0YSB0byBiZSBwYXJzZWQgZm9yIGNyZWF0aW5nIGtl
eS4NCj4gPiArICogcGFyYW1baW5dOiBwIHBvaW50ZXIgdG8gc2VjdXJlIGtleSBwYXlsb2FkIHN0
cnVjdHVyZSB0byBmaWxsDQo+ID4gK3BhcnNlZCBkYXRhDQo+ID4gKyAqIE9uIHN1Y2Nlc3MgcmV0
dXJucyAwLCBvdGhlcndpc2UgLUVJTlZBTC4NCj4gPiArICovDQo+ID4gK3N0YXRpYyBpbnQgcGFy
c2VfaW5wdXRkYXRhKGNoYXIgKmRhdGEsIHN0cnVjdCBzZWN1cmVfa2V5X3BheWxvYWQgKnApDQo+
ID4gK3sNCj4gPiArCXN1YnN0cmluZ190IGFyZ3NbTUFYX09QVF9BUkdTXTsNCj4gPiArCWxvbmcg
a2V5bGVuID0gMDsNCj4gPiArCWludCByZXQgPSAtRUlOVkFMOw0KPiA+ICsJaW50IGtleV9jbWQg
PSAtRUlOVkFMOw0KPiA+ICsJY2hhciAqYyA9IE5VTEw7DQo+ID4gKw0KPiA+ICsJYyA9IHN0cnNl
cCgmZGF0YSwgIiBcdCIpOw0KPiA+ICsJaWYgKCFjKSB7DQo+ID4gKwkJcmV0ID0gLUVJTlZBTDsN
Cj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkvKiBHZXQgdGhlIGtleWN0
bCBjb21tYW5kIGkuZS4gbmV3X2tleSBvciBsb2FkX2Jsb2IgZXRjICovDQo+ID4gKwlrZXlfY21k
ID0gbWF0Y2hfdG9rZW4oYywga2V5X3Rva2VucywgYXJncyk7DQo+ID4gKw0KPiA+ICsJc3dpdGNo
IChrZXlfY21kKSB7DQo+ID4gKwljYXNlIG5ld19rZXk6DQo+ID4gKwkJLyogZmlyc3QgYXJndW1l
bnQgaXMga2V5IHNpemUgKi8NCj4gPiArCQljID0gc3Ryc2VwKCZkYXRhLCAiIFx0Iik7DQo+ID4g
KwkJaWYgKCFjKSB7DQo+ID4gKwkJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwkJCWdvdG8gb3V0Ow0K
PiA+ICsJCX0NCj4gPiArDQo+ID4gKwkJcmV0ID0ga3N0cnRvbChjLCAxMCwgJmtleWxlbik7DQo+
ID4gKwkJaWYgKHJldCA8IDAgfHwga2V5bGVuIDwgTUlOX0tFWV9TSVpFIHx8DQo+ID4gKwkJCQkJ
CWtleWxlbiA+IE1BWF9LRVlfU0laRSkgew0KPiA+ICsJCQlyZXQgPSAtRUlOVkFMOw0KPiA+ICsJ
CQlnb3RvIG91dDsNCj4gPiArCQl9DQo+ID4gKw0KPiA+ICsJCXAtPmtleV9sZW4gPSBrZXlsZW47
DQo+ID4gKwkJcmV0ID0gbmV3X2tleTsNCj4gPiArDQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNl
IGxvYWRfYmxvYjoNCj4gPiArCQkvKiBmaXJzdCBhcmd1bWVudCBpcyBibG9iIGRhdGEgZm9yIENB
QU0qLw0KPiA+ICsJCWMgPSBzdHJzZXAoJmRhdGEsICIgXHQiKTsNCj4gPiArCQlpZiAoIWMpIHsN
Cj4gPiArCQkJcmV0ID0gLUVJTlZBTDsNCj4gPiArCQkJZ290byBvdXQ7DQo+ID4gKwkJfQ0KPiA+
ICsNCj4gPiArCQkvKiBCbG9iX2xlbiA9IE5vIG9mIGNoYXJhY3RlcnMgaW4gYmxvYi8yICovDQo+
ID4gKwkJcC0+YmxvYl9sZW4gPSBzdHJsZW4oYykgLyAyOw0KPiA+ICsJCWlmIChwLT5ibG9iX2xl
biA+IE1BWF9CTE9CX1NJWkUpIHsNCj4gPiArCQkJcmV0ID0gLUVJTlZBTDsNCj4gPiArCQkJZ290
byBvdXQ7DQo+ID4gKwkJfQ0KPiA+ICsNCj4gPiArCQlyZXQgPSBoZXgyYmluKHAtPmJsb2IsIGMs
IHAtPmJsb2JfbGVuKTsNCj4gPiArCQlpZiAocmV0IDwgMCkgew0KPiA+ICsJCQlyZXQgPSAtRUlO
VkFMOw0KPiA+ICsJCQlnb3RvIG91dDsNCj4gPiArCQl9DQo+ID4gKwkJcmV0ID0gbG9hZF9ibG9i
Ow0KPiA+ICsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgZXJyb3I6DQo+ID4gKwkJcmV0ID0g
LUVJTlZBTDsNCj4gPiArCQlicmVhazsNCj4gPiArCX0NCj4gPiArDQo+ID4gK291dDoNCj4gPiAr
CXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIHNlY3VyZV9pbnN0
YW50aWF0ZSAtIGNyZWF0ZSBhIG5ldyBzZWN1cmUgdHlwZSBrZXkuDQo+ID4gKyAqIFN1cHBvcnRz
IHRoZSBvcGVyYXRpb24gdG8gZ2VuZXJhdGUgYSBuZXcga2V5LiBBIHJhbmRvbSBudW1iZXINCj4g
PiArICogaXMgZ2VuZXJhdGVkIGZyb20gQ0FBTSBhcyBrZXkgZGF0YSBhbmQgdGhlIGNvcnJlc3Bv
bmRpbmcgcmVkIGJsb2INCj4gPiArICogaXMgZm9ybWVkIGFuZCBzdG9yZWQgYXMga2V5X2Jsb2Iu
DQo+ID4gKyAqIEFsc28gc3VwcG9ydHMgdGhlIG9wZXJhdGlvbiB0byBsb2FkIHRoZSBibG9iIGFu
ZCBrZXkgaXMgZGVyaXZlZA0KPiA+ICt1c2luZw0KPiA+ICsgKiB0aGF0IGJsb2IgZnJvbSBDQUFN
Lg0KPiA+ICsgKiBPbiBzdWNjZXNzLCByZXR1cm4gMC4gT3RoZXJ3aXNlIHJldHVybiBlcnJuby4N
Cj4gPiArICovDQo+ID4gK3N0YXRpYyBpbnQgc2VjdXJlX2luc3RhbnRpYXRlKHN0cnVjdCBrZXkg
KmtleSwNCj4gPiArCQlzdHJ1Y3Qga2V5X3ByZXBhcnNlZF9wYXlsb2FkICpwcmVwKSB7DQo+ID4g
KwlzdHJ1Y3Qgc2VjdXJlX2tleV9wYXlsb2FkICpwYXlsb2FkID0gTlVMTDsNCj4gPiArCXNpemVf
dCBkYXRhbGVuID0gcHJlcC0+ZGF0YWxlbjsNCj4gPiArCWNoYXIgKmRhdGEgPSBOVUxMOw0KPiA+
ICsJaW50IGtleV9jbWQgPSAwOw0KPiA+ICsJaW50IHJldCA9IDA7DQo+ID4gKwllbnVtIHNrX3Jl
cV90eXBlIHNrX29wX3R5cGU7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBOVUxMOw0KPiA+
ICsNCj4gPiArCWlmIChkYXRhbGVuIDw9IDAgfHwgZGF0YWxlbiA+IDMyNzY3IHx8ICFwcmVwLT5k
YXRhKSB7DQo+ID4gKwkJcmV0ID0gLUVJTlZBTDsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0N
Cj4gPiArDQo+ID4gKwlkYXRhID0ga21hbGxvYyhkYXRhbGVuICsgMSwgR0ZQX0tFUk5FTCk7DQo+
ID4gKwlpZiAoIWRhdGEpIHsNCj4gPiArCQlyZXQgPSAtRU5PTUVNOw0KPiA+ICsJCWdvdG8gb3V0
Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCW1lbWNweShkYXRhLCBwcmVwLT5kYXRhLCBkYXRhbGVu
KTsNCj4gPiArCWRhdGFbZGF0YWxlbl0gPSAnXDAnOw0KPiA+ICsNCj4gPiArCXBheWxvYWQgPSBz
ZWN1cmVfcGF5bG9hZF9hbGxvYyhrZXkpOw0KPiA+ICsJaWYgKCFwYXlsb2FkKSB7DQo+ID4gKwkJ
cmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkv
KiBBbGxvY2F0ZSBjYWFtIGpvYiByaW5nIGZvciBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkIGZy
b20gQ0FBTSAqLw0KPiA+ICsJZGV2ID0gY2FhbV9qcl9hbGxvYygpOw0KPiA+ICsJaWYgKCFkZXYp
IHsNCj4gPiArCQlwcl9pbmZvKCJjYWFtX2pyX2FsbG9jIGZhaWxlZFxuIik7DQo+ID4gKwkJcmV0
ID0gLUVOT0RFVjsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlrZXlf
Y21kID0gcGFyc2VfaW5wdXRkYXRhKGRhdGEsIHBheWxvYWQpOw0KPiA+ICsJaWYgKGtleV9jbWQg
PCAwKSB7DQo+ID4gKwkJcmV0ID0ga2V5X2NtZDsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0N
Cj4gPiArDQo+ID4gKwlzd2l0Y2ggKGtleV9jbWQpIHsNCj4gPiArCWNhc2UgbG9hZF9ibG9iOg0K
PiA+ICsJCS8qDQo+ID4gKwkJICogUmVkIGJsb2IgZGVjcnlwdGlvbiB0byBiZSBkb25lIGZvciBs
b2FkIG9wZXJhdGlvbg0KPiA+ICsJCSAqIHRvIGRlcml2ZSB0aGUga2V5Lg0KPiA+ICsJCSAqLw0K
PiA+ICsJCXNrX29wX3R5cGUgPSBza19yZWRfYmxvYl9kZWM7DQo+ID4gKwkJcmV0ID0ga2V5X2Rl
YmxvYihwYXlsb2FkLCBza19vcF90eXBlLCBkZXYpOw0KPiA+ICsJCWlmIChyZXQgIT0gMCkgew0K
PiA+ICsJCQlwcl9pbmZvKCJzZWN1cmVfa2V5OiBrZXlfYmxvYiBkZWNhcCBmYWlsICglZClcbiIs
IHJldCk7DQo+ID4gKwkJCWdvdG8gb3V0Ow0KPiA+ICsJCX0NCj4gPiArCQlicmVhazsNCj4gPiAr
CWNhc2UgbmV3X2tleToNCj4gPiArCQkvKiBHZXQgUmFuZG9tIG51bWJlciBmcm9tIGNhYW0gb2Yg
dGhlIHNwZWNpZmllZCBsZW5ndGggKi8NCj4gPiArCQlza19vcF90eXBlID0gc2tfZ2V0X3JhbmRv
bTsNCj4gPiArCQlyZXQgPSBjYWFtX2dldF9yYW5kb20ocGF5bG9hZCwgc2tfb3BfdHlwZSwgZGV2
KTsNCj4gPiArCQlpZiAocmV0ICE9IDApIHsNCj4gPiArCQkJcHJfaW5mbygic2VjdXJlX2tleTog
Z2V0X3JhbmRvbSBmYWlsICglZClcbiIsIHJldCk7DQo+ID4gKwkJCWdvdG8gb3V0Ow0KPiA+ICsJ
CX0NCj4gPiArDQo+ID4gKwkJLyogR2VuZXJhdGUgcmVkIGJsb2Igb2Yga2V5IHJhbmRvbSBieXRl
cyB3aXRoIENBQU0gKi8NCj4gPiArCQlza19vcF90eXBlID0gc2tfcmVkX2Jsb2JfZW5jOw0KPiA+
ICsJCXJldCA9IGtleV9ibG9iKHBheWxvYWQsIHNrX29wX3R5cGUsIGRldik7DQo+ID4gKwkJaWYg
KHJldCAhPSAwKSB7DQo+ID4gKwkJCXByX2luZm8oInNlY3VyZV9rZXk6IGtleV9ibG9iIGVuY2Fw
IGZhaWwgKCVkKVxuIiwgcmV0KTsNCj4gPiArCQkJZ290byBvdXQ7DQo+ID4gKwkJfQ0KPiA+ICsJ
CWJyZWFrOw0KPiA+ICsJZGVmYXVsdDoNCj4gPiArCQlyZXQgPSAtRUlOVkFMOw0KPiA+ICsJCWdv
dG8gb3V0Ow0KPiA+ICsJfQ0KPiA+ICtvdXQ6DQo+ID4gKwlpZiAoZGF0YSkNCj4gPiArCQlremZy
ZWUoZGF0YSk7DQo+ID4gKwlpZiAoZGV2KQ0KPiA+ICsJCWNhYW1fanJfZnJlZShkZXYpOw0KPiA+
ICsNCj4gPiArCWlmICghcmV0KQ0KPiA+ICsJCXJjdV9hc3NpZ25fa2V5cG9pbnRlcihrZXksIHBh
eWxvYWQpOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCWt6ZnJlZShwYXlsb2FkKTsNCj4gPiArDQo+ID4g
KwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzZWN1cmVfcmVh
ZCAtIGNvcHkgdGhlICBibG9iIGRhdGEgdG8gdXNlcnNwYWNlIGluIGhleC4NCj4gPiArICogcGFy
YW1baW5dOiBrZXkgcG9pbnRlciB0byBrZXkgc3RydWN0DQo+ID4gKyAqIHBhcmFtW2luXTogYnVm
ZmVyIHBvaW50ZXIgdG8gdXNlciBkYXRhIGZvciBjcmVhdGluZyBrZXkNCj4gPiArICogcGFyYW1b
aW5dOiBidWZsZW4gaXMgdGhlIGxlbmd0aCBvZiB0aGUgYnVmZmVyDQo+ID4gKyAqIE9uIHN1Y2Nl
c3MsIHJldHVybiB0byB1c2Vyc3BhY2UgdGhlIHNlY3VyZSBrZXkgZGF0YSBzaXplLg0KPiA+ICsg
Ki8NCj4gPiArc3RhdGljIGxvbmcgc2VjdXJlX3JlYWQoY29uc3Qgc3RydWN0IGtleSAqa2V5LCBj
aGFyIF9fdXNlciAqYnVmZmVyLA0KPiA+ICsJCQkgc2l6ZV90IGJ1ZmxlbikNCj4gPiArew0KPiA+
ICsJY29uc3Qgc3RydWN0IHNlY3VyZV9rZXlfcGF5bG9hZCAqcCA9IE5VTEw7DQo+ID4gKwljaGFy
ICphc2NpaV9idWY7DQo+ID4gKwljaGFyICpidWZwOw0KPiA+ICsJaW50IGk7DQo+ID4gKw0KPiA+
ICsJcCA9IGRlcmVmZXJlbmNlX2tleV9sb2NrZWQoa2V5KTsNCj4gPiArCWlmICghcCkNCj4gPiAr
CQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArDQo+ID4gKwlpZiAoYnVmZmVyICYmIGJ1ZmxlbiA+PSAy
ICogcC0+YmxvYl9sZW4pIHsNCj4gPiArCQlhc2NpaV9idWYgPSBrbWFsbG9jKDIgKiBwLT5ibG9i
X2xlbiwgR0ZQX0tFUk5FTCk7DQo+ID4gKwkJaWYgKCFhc2NpaV9idWYpDQo+ID4gKwkJCXJldHVy
biAtRU5PTUVNOw0KPiA+ICsNCj4gPiArCQlidWZwID0gYXNjaWlfYnVmOw0KPiA+ICsJCWZvciAo
aSA9IDA7IGkgPCBwLT5ibG9iX2xlbjsgaSsrKQ0KPiA+ICsJCQlidWZwID0gaGV4X2J5dGVfcGFj
ayhidWZwLCBwLT5ibG9iW2ldKTsNCj4gPiArCQlpZiAoY29weV90b191c2VyKGJ1ZmZlciwgYXNj
aWlfYnVmLCAyICogcC0+YmxvYl9sZW4pICE9IDApIHsNCj4gPiArCQkJa3pmcmVlKGFzY2lpX2J1
Zik7DQo+ID4gKwkJCXJldHVybiAtRUZBVUxUOw0KPiA+ICsJCX0NCj4gPiArCQlremZyZWUoYXNj
aWlfYnVmKTsNCj4gPiArCX0NCj4gPiArCXJldHVybiAyICogcC0+YmxvYl9sZW47DQo+ID4gK30N
Cj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIHNlY3VyZV9kZXN0cm95IC0gY2xlYXIgYW5kIGZyZWUg
dGhlIGtleSdzIHBheWxvYWQgICovIHN0YXRpYyB2b2lkDQo+ID4gK3NlY3VyZV9kZXN0cm95KHN0
cnVjdCBrZXkgKmtleSkgew0KPiA+ICsJa3pmcmVlKGtleS0+cGF5bG9hZC5kYXRhWzBdKTsNCj4g
PiArfQ0KPiA+ICsNCj4gPiArc3RydWN0IGtleV90eXBlIGtleV90eXBlX3NlY3VyZSA9IHsNCj4g
PiArCS5uYW1lID0gInNlY3VyZSIsDQo+ID4gKwkuaW5zdGFudGlhdGUgPSBzZWN1cmVfaW5zdGFu
dGlhdGUsDQo+ID4gKwkuZGVzdHJveSA9IHNlY3VyZV9kZXN0cm95LA0KPiA+ICsJLnJlYWQgPSBz
ZWN1cmVfcmVhZCwNCj4gPiArfTsNCj4gPiArRVhQT1JUX1NZTUJPTF9HUEwoa2V5X3R5cGVfc2Vj
dXJlKTsNCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIHNlY3VyZV9zaGFzaF9yZWxlYXNlKHZvaWQp
IHsNCj4gPiArCWlmIChoYXNoYWxnKQ0KPiA+ICsJCWNyeXB0b19mcmVlX3NoYXNoKGhhc2hhbGcp
Ow0KPiA+ICsJaWYgKGhtYWNhbGcpDQo+ID4gKwkJY3J5cHRvX2ZyZWVfc2hhc2goaG1hY2FsZyk7
DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgX19pbml0IHNlY3VyZV9zaGFzaF9hbGxv
Yyh2b2lkKSB7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWhtYWNhbGcgPSBjcnlwdG9f
YWxsb2Nfc2hhc2goaG1hY19hbGcsIDAsIENSWVBUT19BTEdfQVNZTkMpOw0KPiA+ICsJaWYgKElT
X0VSUihobWFjYWxnKSkgew0KPiA+ICsJCXByX2luZm8oInNlY3VyZV9rZXk6IGNvdWxkIG5vdCBh
bGxvY2F0ZSBjcnlwdG8gJXNcbiIsDQo+ID4gKwkJCQlobWFjX2FsZyk7DQo+ID4gKwkJcmV0dXJu
IFBUUl9FUlIoaG1hY2FsZyk7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJaGFzaGFsZyA9IGNyeXB0
b19hbGxvY19zaGFzaChoYXNoX2FsZywgMCwgQ1JZUFRPX0FMR19BU1lOQyk7DQo+ID4gKwlpZiAo
SVNfRVJSKGhhc2hhbGcpKSB7DQo+ID4gKwkJcHJfaW5mbygic2VjdXJlX2tleTogY291bGQgbm90
IGFsbG9jYXRlIGNyeXB0byAlc1xuIiwNCj4gPiArCQkJCWhhc2hfYWxnKTsNCj4gPiArCQlyZXQg
PSBQVFJfRVJSKGhhc2hhbGcpOw0KPiA+ICsJCWdvdG8gaGFzaGFsZ19mYWlsOw0KPiA+ICsJfQ0K
PiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiAraGFzaGFsZ19mYWlsOg0KPiA+ICsJ
Y3J5cHRvX2ZyZWVfc2hhc2goaG1hY2FsZyk7DQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+
ID4gKw0KPiA+ICtzdGF0aWMgaW50IF9faW5pdCBpbml0X3NlY3VyZV9rZXkodm9pZCkgew0KPiA+
ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlyZXQgPSBzZWN1cmVfc2hhc2hfYWxsb2MoKTsNCj4g
PiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0g
cmVnaXN0ZXJfa2V5X3R5cGUoJmtleV90eXBlX3NlY3VyZSk7DQo+ID4gKwlpZiAocmV0IDwgMCkN
Cj4gPiArCQlzZWN1cmVfc2hhc2hfcmVsZWFzZSgpOw0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiAr
fQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgX19leGl0IGNsZWFudXBfc2VjdXJlX2tleSh2b2lk
KSB7DQo+ID4gKwlzZWN1cmVfc2hhc2hfcmVsZWFzZSgpOw0KPiA+ICsJdW5yZWdpc3Rlcl9rZXlf
dHlwZSgma2V5X3R5cGVfc2VjdXJlKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArbGF0ZV9pbml0Y2Fs
bChpbml0X3NlY3VyZV9rZXkpOw0KPiA+ICttb2R1bGVfZXhpdChjbGVhbnVwX3NlY3VyZV9rZXkp
Ow0KPiA+ICsNCj4gPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOw0KPiA+IGRpZmYgLS1naXQgYS9z
ZWN1cml0eS9rZXlzL3NlY3VyZWtleV9kZXNjLmMNCj4gPiBiL3NlY3VyaXR5L2tleXMvc2VjdXJl
a2V5X2Rlc2MuYyBuZXcgZmlsZSBtb2RlIDEwMDY0NCBpbmRleA0KPiA+IDAwMDAwMDAwMDAwMC4u
YTRmYTgxMWE1NzUzDQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL3NlY3VyaXR5L2tleXMv
c2VjdXJla2V5X2Rlc2MuYw0KPiA+IEBAIC0wLDAgKzEsNjA2IEBADQo+ID4gKy8vIFNQRFgtTGlj
ZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wDQo+ID4gKy8qDQo+ID4gKyAqIENvcHlyaWdodCAoQykg
MjAxOCBOWFANCj4gPiArICoNCj4gPiArICovDQo+ID4gKw0KPiA+ICsjaW5jbHVkZSA8a2V5cy9z
ZWN1cmUtdHlwZS5oPg0KPiA+ICsjaW5jbHVkZSAic2VjdXJla2V5X2Rlc2MuaCINCj4gPiArDQo+
ID4gKy8qIGtleSBtb2RpZmllciBmb3IgYmxvYiBlbmNhcHN1bGF0aW9uICYgZGVjYXBzdWxhdGlv
biBkZXNjcmlwdG9yICovDQo+ID4gK3U4IGtleV9tb2RpZmllcltdID0gIlNFQ1VSRV9LRVkiOw0K
PiA+ICt1MzIga2V5X21vZGlmaWVyX2xlbiA9IDEwOw0KPiA+ICsNCj4gPiArdm9pZCBjYWFtX3Nr
X3JuZ19kZXNjKHN0cnVjdCBza19yZXEgKnNrcmVxLCBzdHJ1Y3Qgc2tfZGVzYyAqc2tkZXNjKSB7
DQo+ID4gKwlzdHJ1Y3Qgc2tfZmV0Y2hfcm5kX2RhdGEgKmZldGNoX3JuZF9kYXRhID0gTlVMTDsN
Cj4gPiArCXN0cnVjdCByYW5kb21fZGVzYyAqcm5kX2Rlc2MgPSBOVUxMOw0KPiA+ICsJc2l6ZV90
IGxlbiA9IDA7DQo+ID4gKwl1MzIgKmRlc2MgPSBza3JlcS0+aHdkZXNjOw0KPiA+ICsNCj4gPiAr
CWluaXRfam9iX2Rlc2MoZGVzYywgMCk7DQo+ID4gKw0KPiA+ICsJZmV0Y2hfcm5kX2RhdGEgPSAm
c2tyZXEtPnJlcV91LnNrX2ZldGNoX3JuZF9kYXRhOw0KPiA+ICsJcm5kX2Rlc2MgPSAmc2tkZXNj
LT5kbWFfdS5yYW5kb21fZGVzY3A7DQo+ID4gKwlsZW4gPSBmZXRjaF9ybmRfZGF0YS0+a2V5X2xl
bjsNCj4gPiArDQo+ID4gKwkvKiBjb21tYW5kIDB4ODI1MDAwMDAgKi8NCj4gPiArCWFwcGVuZF9j
bWQoZGVzYywgQ01EX09QRVJBVElPTiB8IE9QX1RZUEVfQ0xBU1MxX0FMRyB8DQo+ID4gKwkJCU9Q
X0FMR19BTEdTRUxfUk5HKTsNCj4gPiArCS8qIGNvbW1hbmQgMHg2MDM0MDAwMCB8IGxlbiAqLw0K
PiA+ICsJYXBwZW5kX2NtZChkZXNjLCBDTURfRklGT19TVE9SRSB8IEZJRk9TVF9UWVBFX1JOR1NU
T1JFIHwgbGVuKTsNCj4gPiArCWFwcGVuZF9wdHIoZGVzYywgcm5kX2Rlc2MtPnJuZF9kYXRhKTsg
fQ0KPiA+ICsNCj4gPiArdm9pZCBjYWFtX3NrX3JlZGJsb2JfZW5jYXBfZGVzYyhzdHJ1Y3Qgc2tf
cmVxICpza3JlcSwgc3RydWN0IHNrX2Rlc2MNCj4gPiArKnNrZGVzYykgew0KPiA+ICsJc3RydWN0
IHJlZGJsb2JfZW5jYXBfZGVzYyAqcmVkX2Jsb2JfZGVzYyA9DQo+ID4gKwkJCQkJJnNrZGVzYy0+
ZG1hX3UucmVkYmxvYl9lbmNhcGRlc2M7DQo+ID4gKwlzdHJ1Y3Qgc2tfcmVkX2Jsb2JfZW5jYXAg
KnJlZF9ibG9iX3JlcSA9DQo+ID4gKwkJCQkJJnNrcmVxLT5yZXFfdS5za19yZWRfYmxvYl9lbmNh
cDsNCj4gPiArCXUzMiAqZGVzYyA9IHNrcmVxLT5od2Rlc2M7DQo+ID4gKw0KPiA+ICsJaW5pdF9q
b2JfZGVzYyhkZXNjLCAwKTsNCj4gPiArDQo+ID4gKwkvKiBMb2FkIGNsYXNzIDIga2V5IHdpdGgg
a2V5IG1vZGlmaWVyLiAqLw0KPiA+ICsJYXBwZW5kX2tleV9hc19pbW0oZGVzYywga2V5X21vZGlm
aWVyLCBrZXlfbW9kaWZpZXJfbGVuLA0KPiA+ICsJCQkgIGtleV9tb2RpZmllcl9sZW4sIENMQVNT
XzIgfCBLRVlfREVTVF9DTEFTU19SRUcpOw0KPiA+ICsNCj4gPiArCS8qIFNFUSBJTiBQVFIgQ29t
bWFuZC4gKi8NCj4gPiArCWFwcGVuZF9zZXFfaW5fcHRyKGRlc2MsIHJlZF9ibG9iX2Rlc2MtPmlu
X2RhdGEsIHJlZF9ibG9iX3JlcS0+ZGF0YV9zeiwNCj4gPiArCQkJICAwKTsNCj4gPiArDQo+ID4g
KwkvKiBTRVEgT1VUIFBUUiBDb21tYW5kLiAqLw0KPiA+ICsJYXBwZW5kX3NlcV9vdXRfcHRyKGRl
c2MsIHJlZF9ibG9iX2Rlc2MtPnJlZGJsb2IsDQo+ID4gKwkJCSAgIHJlZF9ibG9iX3JlcS0+cmVk
YmxvYl9zeiwgMCk7DQo+ID4gKw0KPiA+ICsJLyogUmVkQmxvYiBlbmNhcHN1bGF0aW9uIFBST1RP
Q09MIENvbW1hbmQuICovDQo+ID4gKwlhcHBlbmRfb3BlcmF0aW9uKGRlc2MsIE9QX1RZUEVfRU5D
QVBfUFJPVE9DT0wgfCBPUF9QQ0xJRF9CTE9CKTsgfQ0KPiA+ICsNCj4gPiArLyogdm9pZCBjYWFt
X3NrX3JlZGJsb2JfZGVjYXBfZGVzYyhzdHJ1Y3Qgc2tfcmVxICpza3JlcSwgc3RydWN0DQo+ID4g
K3NrX2Rlc2MgKnNrZGVzYykNCj4gPiArICogYnJpZWYgQ0FBTSBEZXNjcmlwdG9yIGNyZWF0b3Ig
ZnJvbSByZWRibG9iIHRvIHBsYWluZGF0YS4NCj4gPiArICogcGFyYW1baW5dIHNrcmVxIFBvaW50
ZXIgdG8gc2VjdXJlIGtleSByZXF1ZXN0IHN0cnVjdHVyZQ0KPiA+ICsgKiBwYXJhbVtpbl0gc2tk
ZXNjIFBvaW50ZXIgdG8gc2VjdXJlIGtleSBkZXNjcmlwdG9yIHN0cnVjdHVyZSAgKi8NCj4gPiAr
dm9pZCBjYWFtX3NrX3JlZGJsb2JfZGVjYXBfZGVzYyhzdHJ1Y3Qgc2tfcmVxICpza3JlcSwgc3Ry
dWN0IHNrX2Rlc2MNCj4gPiArKnNrZGVzYykgew0KPiA+ICsJc3RydWN0IHJlZGJsb2JfZGVjYXBf
ZGVzYyAqcmVkX2Jsb2JfZGVzYyA9DQo+ID4gKwkJCQkJJnNrZGVzYy0+ZG1hX3UucmVkYmxvYl9k
ZWNhcGRlc2M7DQo+ID4gKwlzdHJ1Y3Qgc2tfcmVkX2Jsb2JfZGVjYXAgKnJlZF9ibG9iX3JlcSA9
DQo+ID4gKwkJCQkJJnNrcmVxLT5yZXFfdS5za19yZWRfYmxvYl9kZWNhcDsNCj4gPiArCXUzMiAq
ZGVzYyA9IHNrcmVxLT5od2Rlc2M7DQo+ID4gKw0KPiA+ICsJaW5pdF9qb2JfZGVzYyhkZXNjLCAw
KTsNCj4gPiArDQo+ID4gKwkvKiBMb2FkIGNsYXNzIDIga2V5IHdpdGgga2V5IG1vZGlmaWVyLiAq
Lw0KPiA+ICsJYXBwZW5kX2tleV9hc19pbW0oZGVzYywga2V5X21vZGlmaWVyLCBrZXlfbW9kaWZp
ZXJfbGVuLA0KPiA+ICsJCQkgIGtleV9tb2RpZmllcl9sZW4sIENMQVNTXzIgfCBLRVlfREVTVF9D
TEFTU19SRUcpOw0KPiA+ICsNCj4gPiArCS8qIFNFUSBJTiBQVFIgQ29tbWFuZC4gKi8NCj4gPiAr
CWFwcGVuZF9zZXFfaW5fcHRyKGRlc2MsIHJlZF9ibG9iX2Rlc2MtPnJlZGJsb2IsDQo+ID4gKwkJ
CSAgcmVkX2Jsb2JfcmVxLT5yZWRibG9iX3N6LCAwKTsNCj4gPiArDQo+ID4gKwkvKiBTRVEgT1VU
IFBUUiBDb21tYW5kLiAqLw0KPiA+ICsJYXBwZW5kX3NlcV9vdXRfcHRyKGRlc2MsIHJlZF9ibG9i
X2Rlc2MtPm91dF9kYXRhLA0KPiA+ICsJCQkgICByZWRfYmxvYl9yZXEtPmRhdGFfc3osIDApOw0K
PiA+ICsNCj4gPiArCS8qIFJlZEJsb2IgZGVjYXBzdWxhdGlvbiBQUk9UT0NPTCBDb21tYW5kLiAq
Lw0KPiA+ICsJYXBwZW5kX29wZXJhdGlvbihkZXNjLCBPUF9UWVBFX0RFQ0FQX1BST1RPQ09MIHwg
T1BfUENMSURfQkxPQik7IH0NCj4gPiArDQo+ID4gKy8qIGludCBjYWFtX3NrX2dldF9yYW5kb21f
bWFwKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHNrX3JlcSAqcmVxLA0KPiA+ICsgKgkJCSAg
ICAgIHN0cnVjdCBza19kZXNjICpza2Rlc2MpDQo+ID4gKyAqIGJyaWVmIERNQSBtYXAgdGhlIGJ1
ZmZlciB2aXJ0dWFsIHBvaW50ZXJzIHRvIHBoeXNpY2FsIGFkZHJlc3MuDQo+ID4gKyAqIHBhcmFt
W2luXSBkZXYgUG9pbnRlciB0byBqb2IgcmluZyBkZXZpY2Ugc3RydWN0dXJlDQo+ID4gKyAqIHBh
cmFtW2luXSByZXEgUG9pbnRlciB0byBzZWN1cmUga2V5IHJlcXVlc3Qgc3RydWN0dXJlDQo+ID4g
KyAqIHBhcmFtW2luXSBza2Rlc2MgUG9pbnRlciB0byBzZWN1cmUga2V5IGRlc2NyaXB0b3Igc3Ry
dWN0dXJlDQo+ID4gKyAqIHJldHVybiAwIG9uIHN1Y2Nlc3MsIGVycm9yIHZhbHVlIG90aGVyd2lz
ZS4NCj4gPiArICovDQo+ID4gK2ludCBjYWFtX3NrX2dldF9yYW5kb21fbWFwKHN0cnVjdCBkZXZp
Y2UgKmRldiwgc3RydWN0IHNrX3JlcSAqcmVxLA0KPiA+ICsJCQkgICBzdHJ1Y3Qgc2tfZGVzYyAq
c2tkZXNjKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3Qgc2tfZmV0Y2hfcm5kX2RhdGEgKmZldGNoX3Ju
ZF9kYXRhOw0KPiA+ICsJc3RydWN0IHJhbmRvbV9kZXNjICpybmRfZGVzYzsNCj4gPiArDQo+ID4g
KwlmZXRjaF9ybmRfZGF0YSA9ICZyZXEtPnJlcV91LnNrX2ZldGNoX3JuZF9kYXRhOw0KPiA+ICsJ
cm5kX2Rlc2MgPSAmc2tkZXNjLT5kbWFfdS5yYW5kb21fZGVzY3A7DQo+ID4gKw0KPiA+ICsJcm5k
X2Rlc2MtPnJuZF9kYXRhID0gZG1hX21hcF9zaW5nbGUoZGV2LCBmZXRjaF9ybmRfZGF0YS0+ZGF0
YSwNCj4gPiArCQkJCWZldGNoX3JuZF9kYXRhLT5rZXlfbGVuLCBETUFfRlJPTV9ERVZJQ0UpOw0K
PiA+ICsNCj4gPiArCWlmIChkbWFfbWFwcGluZ19lcnJvcihkZXYsIHJuZF9kZXNjLT5ybmRfZGF0
YSkpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIlVuYWJsZSB0byBtYXAgbWVtb3J5XG4iKTsNCj4g
PiArCQlnb3RvIHNrX3JhbmRvbV9tYXBfZmFpbDsNCj4gPiArCX0NCj4gPiArCXJldHVybiAwOw0K
PiA+ICsNCj4gPiArc2tfcmFuZG9tX21hcF9mYWlsOg0KPiA+ICsJcmV0dXJuIC1FTk9NRU07DQo+
ID4gK30NCj4gPiArDQo+ID4gKy8qIGludCBjYWFtX3NrX3JlZGJsb2JfZW5jYXBfbWFwKHN0cnVj
dCBkZXZpY2UgKmRldiwgc3RydWN0IHNrX3JlcSAqcmVxLA0KPiA+ICsgKgkJCQkJc3RydWN0IHNr
X2Rlc2MgKnNrZGVzYykNCj4gPiArICogYnJpZWYgRE1BIG1hcCB0aGUgYnVmZmVyIHZpcnR1YWwg
cG9pbnRlcnMgdG8gcGh5c2ljYWwgYWRkcmVzcy4NCj4gPiArICogcGFyYW1baW5dIGRldiBQb2lu
dGVyIHRvIGpvYiByaW5nIGRldmljZSBzdHJ1Y3R1cmUNCj4gPiArICogcGFyYW1baW5dIHJlcSBQ
b2ludGVyIHRvIHNlY3VyZSBrZXkgcmVxdWVzdCBzdHJ1Y3R1cmUNCj4gPiArICogcGFyYW1baW5d
IHNrZGVzYyBQb2ludGVyIHRvIHNlY3VyZSBrZXkgZGVzY3JpcHRvciBzdHJ1Y3R1cmUNCj4gPiAr
ICogcmV0dXJuIDAgb24gc3VjY2VzcywgZXJyb3IgdmFsdWUgb3RoZXJ3aXNlLg0KPiA+ICsgKi8N
Cj4gPiAraW50IGNhYW1fc2tfcmVkYmxvYl9lbmNhcF9tYXAoc3RydWN0IGRldmljZSAqZGV2LCBz
dHJ1Y3Qgc2tfcmVxICpyZXEsDQo+ID4gKwkJCSAgICAgIHN0cnVjdCBza19kZXNjICpza2Rlc2Mp
DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBza19yZWRfYmxvYl9lbmNhcCAqcmVkX2Jsb2JfZW5jYXA7
DQo+ID4gKwlzdHJ1Y3QgcmVkYmxvYl9lbmNhcF9kZXNjICpyZWRfYmxvYl9kZXNjOw0KPiA+ICsN
Cj4gPiArCXJlZF9ibG9iX2VuY2FwID0gJnJlcS0+cmVxX3Uuc2tfcmVkX2Jsb2JfZW5jYXA7DQo+
ID4gKwlyZWRfYmxvYl9kZXNjID0gJnNrZGVzYy0+ZG1hX3UucmVkYmxvYl9lbmNhcGRlc2M7DQo+
ID4gKw0KPiA+ICsJcmVkX2Jsb2JfZGVzYy0+aW5fZGF0YSA9IGRtYV9tYXBfc2luZ2xlKGRldiwg
cmVkX2Jsb2JfZW5jYXAtPmRhdGEsDQo+ID4gKwkJCQkJcmVkX2Jsb2JfZW5jYXAtPmRhdGFfc3os
IERNQV9UT19ERVZJQ0UpOw0KPiA+ICsJaWYgKGRtYV9tYXBwaW5nX2Vycm9yKGRldiwgcmVkX2Js
b2JfZGVzYy0+aW5fZGF0YSkpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIlVuYWJsZSB0byBtYXAg
bWVtb3J5XG4iKTsNCj4gPiArCQlnb3RvIHNrX2RhdGFfZmFpbDsNCj4gPiArCX0NCj4gPiArDQo+
ID4gKwlyZWRfYmxvYl9kZXNjLT5yZWRibG9iID0gZG1hX21hcF9zaW5nbGUoZGV2LCByZWRfYmxv
Yl9lbmNhcC0+cmVkYmxvYiwNCj4gPiArCQkJCXJlZF9ibG9iX2VuY2FwLT5yZWRibG9iX3N6LCBE
TUFfRlJPTV9ERVZJQ0UpOw0KPiA+ICsJaWYgKGRtYV9tYXBwaW5nX2Vycm9yKGRldiwgcmVkX2Js
b2JfZGVzYy0+cmVkYmxvYikpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIlVuYWJsZSB0byBtYXAg
bWVtb3J5XG4iKTsNCj4gPiArCQlnb3RvIHNrX3JlZGJsb2JfZmFpbDsNCj4gPiArCX0NCj4gPiAr
DQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArDQo+ID4gK3NrX3JlZGJsb2JfZmFpbDoNCj4gPiArCWRt
YV91bm1hcF9zaW5nbGUoZGV2LCByZWRfYmxvYl9kZXNjLT5pbl9kYXRhLCByZWRfYmxvYl9lbmNh
cC0+ZGF0YV9zeiwNCj4gPiArCQkJIERNQV9UT19ERVZJQ0UpOw0KPiA+ICtza19kYXRhX2ZhaWw6
DQo+ID4gKwlyZXR1cm4gLUVOT01FTTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyogc3RhdGljIGlu
dCBjYWFtX3NrX3JlZGJsb2JfZGVjYXBfbWFwKHN0cnVjdCBkZXZpY2UgKmRldiwNCj4gPiArICoJ
CQkJCSAgICBzdHJ1Y3Qgc2tfcmVxICpyZXEsDQo+ID4gKyAqCQkJCQkgICAgc3RydWN0IHNrX2Rl
c2MgKnNrZGVzYykNCj4gPiArICogYnJpZWYgRE1BIG1hcCB0aGUgYnVmZmVyIHZpcnR1YWwgcG9p
bnRlcnMgdG8gcGh5c2ljYWwgYWRkcmVzcy4NCj4gPiArICogcGFyYW1baW5dIGRldiBQb2ludGVy
IHRvIGpvYiByaW5nIGRldmljZSBzdHJ1Y3R1cmUNCj4gPiArICogcGFyYW1baW5dIHJlcSBQb2lu
dGVyIHRvIHNlY3VyZSBrZXkgcmVxdWVzdCBzdHJ1Y3R1cmUNCj4gPiArICogcGFyYW1baW5dIHNr
ZGVzYyBQb2ludGVyIHRvIHNlY3VyZSBrZXkgZGVzY3JpcHRvciBzdHJ1Y3R1cmUNCj4gPiArICog
cmV0dXJuIDAgb24gc3VjY2VzcywgZXJyb3IgdmFsdWUgb3RoZXJ3aXNlLg0KPiA+ICsgKi8NCj4g
PiAraW50IGNhYW1fc2tfcmVkYmxvYl9kZWNhcF9tYXAoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1
Y3Qgc2tfcmVxICpyZXEsDQo+ID4gKwkJCSAgICAgIHN0cnVjdCBza19kZXNjICpza2Rlc2MpDQo+
ID4gK3sNCj4gPiArCXN0cnVjdCBza19yZWRfYmxvYl9kZWNhcCAqcmVkX2Jsb2JfZGVjYXA7DQo+
ID4gKwlzdHJ1Y3QgcmVkYmxvYl9kZWNhcF9kZXNjICpyZWRfYmxvYl9kZXNjOw0KPiA+ICsNCj4g
PiArCXJlZF9ibG9iX2RlY2FwID0gJnJlcS0+cmVxX3Uuc2tfcmVkX2Jsb2JfZGVjYXA7DQo+ID4g
KwlyZWRfYmxvYl9kZXNjID0gJnNrZGVzYy0+ZG1hX3UucmVkYmxvYl9kZWNhcGRlc2M7DQo+ID4g
Kw0KPiA+ICsJcmVkX2Jsb2JfZGVzYy0+cmVkYmxvYiA9IGRtYV9tYXBfc2luZ2xlKGRldiwgcmVk
X2Jsb2JfZGVjYXAtPnJlZGJsb2IsDQo+ID4gKwkJCQlyZWRfYmxvYl9kZWNhcC0+cmVkYmxvYl9z
eiwgRE1BX1RPX0RFVklDRSk7DQo+ID4gKwlpZiAoZG1hX21hcHBpbmdfZXJyb3IoZGV2LCByZWRf
YmxvYl9kZXNjLT5yZWRibG9iKSkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiVW5hYmxlIHRvIG1h
cCBtZW1vcnlcbiIpOw0KPiA+ICsJCWdvdG8gc2tfcmVkYmxvYl9mYWlsOw0KPiA+ICsJfQ0KPiA+
ICsNCj4gPiArCXJlZF9ibG9iX2Rlc2MtPm91dF9kYXRhID0gZG1hX21hcF9zaW5nbGUoZGV2LCBy
ZWRfYmxvYl9kZWNhcC0+ZGF0YSwNCj4gPiArCQkJCXJlZF9ibG9iX2RlY2FwLT5kYXRhX3N6LCBE
TUFfRlJPTV9ERVZJQ0UpOw0KPiA+ICsJaWYgKGRtYV9tYXBwaW5nX2Vycm9yKGRldiwgcmVkX2Js
b2JfZGVzYy0+b3V0X2RhdGEpKSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJVbmFibGUgdG8gbWFw
IG1lbW9yeVxuIik7DQo+ID4gKwkJZ290byBza19kYXRhX2ZhaWw7DQo+ID4gKwl9DQo+ID4gKw0K
PiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtza19kYXRhX2ZhaWw6DQo+ID4gKwlkbWFfdW5t
YXBfc2luZ2xlKGRldiwgcmVkX2Jsb2JfZGVzYy0+cmVkYmxvYiwNCj4gPiArCQkJIHJlZF9ibG9i
X2RlY2FwLT5yZWRibG9iX3N6LCBETUFfVE9fREVWSUNFKTsNCj4gPiArc2tfcmVkYmxvYl9mYWls
Og0KPiA+ICsJcmV0dXJuIC1FTk9NRU07DQo+ID4gK30NCj4gPiArDQo+ID4gKy8qIEBmbiB2b2lk
IHNlY3VyZWtleV91bm1hcChzdHJ1Y3QgZGV2aWNlICpkZXYsDQo+ID4gKyAqCQkJICAgIHN0cnVj
dCBza19kZXNjICpza2Rlc2MsIHN0cnVjdCBza19yZXEgKnJlcSkNCj4gPiArICogQGJyaWVmIERN
QSB1bm1hcCB0aGUgYnVmZmVyIHBvaW50ZXJzLg0KPiA+ICsgKiBAcGFyYW1baW5dIGRldiBQb2lu
dGVyIHRvIGpvYiByaW5nIGRldmljZSBzdHJ1Y3R1cmUNCj4gPiArICogQHBhcmFtW2luXSBza2Rl
c2MgUG9pbnRlciB0byBzZWN1cmUga2V5IGRlc2NyaXB0b3Igc3RydWN0dXJlDQo+ID4gKyAqIEBw
YXJhbVtpbl0gcmVxIFBvaW50ZXIgdG8gc2VjdXJlIGtleSByZXF1ZXN0IHN0cnVjdHVyZSAgKi8g
dm9pZA0KPiA+ICtzZWN1cmVrZXlfdW5tYXAoc3RydWN0IGRldmljZSAqZGV2LA0KPiA+ICsJCSAg
ICAgc3RydWN0IHNrX2Rlc2MgKnNrZGVzYywgc3RydWN0IHNrX3JlcSAqcmVxKSB7DQo+ID4gKw0K
PiA+ICsJc3dpdGNoIChyZXEtPnR5cGUpIHsNCj4gPiArCWNhc2Ugc2tfZ2V0X3JhbmRvbToNCj4g
PiArCQl7DQo+ID4gKwkJCXN0cnVjdCBza19mZXRjaF9ybmRfZGF0YSAqZmV0Y2hfcm5kX2RhdGE7
DQo+ID4gKwkJCXN0cnVjdCByYW5kb21fZGVzYyAqcm5kX2Rlc2M7DQo+ID4gKw0KPiA+ICsJCQlm
ZXRjaF9ybmRfZGF0YSA9ICZyZXEtPnJlcV91LnNrX2ZldGNoX3JuZF9kYXRhOw0KPiA+ICsJCQly
bmRfZGVzYyA9ICZza2Rlc2MtPmRtYV91LnJhbmRvbV9kZXNjcDsNCj4gPiArDQo+ID4gKwkJCS8q
IFVubWFwIERlc2NyaXB0b3IgYnVmZmVyIHBvaW50ZXJzLiAqLw0KPiA+ICsJCQlkbWFfdW5tYXBf
c2luZ2xlKGRldiwgcm5kX2Rlc2MtPnJuZF9kYXRhLA0KPiA+ICsJCQkJCSBmZXRjaF9ybmRfZGF0
YS0+a2V5X2xlbiwNCj4gPiArCQkJCQkgRE1BX0ZST01fREVWSUNFKTsNCj4gPiArCQkJYnJlYWs7
DQo+ID4gKwkJfQ0KPiA+ICsJY2FzZSBza19yZWRfYmxvYl9lbmM6DQo+ID4gKwkJew0KPiA+ICsJ
CQlzdHJ1Y3Qgc2tfcmVkX2Jsb2JfZW5jYXAgKnJlZF9ibG9iX2VuY2FwOw0KPiA+ICsJCQlzdHJ1
Y3QgcmVkYmxvYl9lbmNhcF9kZXNjICpyZWRfYmxvYl9kZXNjOw0KPiA+ICsNCj4gPiArCQkJcmVk
X2Jsb2JfZW5jYXAgPSAmcmVxLT5yZXFfdS5za19yZWRfYmxvYl9lbmNhcDsNCj4gPiArCQkJcmVk
X2Jsb2JfZGVzYyA9ICZza2Rlc2MtPmRtYV91LnJlZGJsb2JfZW5jYXBkZXNjOw0KPiA+ICsNCj4g
PiArCQkJLyogVW5tYXAgRGVzY3JpcHRvciBidWZmZXIgcG9pbnRlcnMuICovDQo+ID4gKwkJCWRt
YV91bm1hcF9zaW5nbGUoZGV2LCByZWRfYmxvYl9kZXNjLT5pbl9kYXRhLA0KPiA+ICsJCQkJCSBy
ZWRfYmxvYl9lbmNhcC0+ZGF0YV9zeiwNCj4gPiArCQkJCQkgRE1BX1RPX0RFVklDRSk7DQo+ID4g
Kw0KPiA+ICsJCQlkbWFfdW5tYXBfc2luZ2xlKGRldiwgcmVkX2Jsb2JfZGVzYy0+cmVkYmxvYiwN
Cj4gPiArCQkJCQkgcmVkX2Jsb2JfZW5jYXAtPnJlZGJsb2Jfc3osDQo+ID4gKwkJCQkJIERNQV9G
Uk9NX0RFVklDRSk7DQo+ID4gKw0KPiA+ICsJCQlicmVhazsNCj4gPiArCQl9DQo+ID4gKwljYXNl
IHNrX3JlZF9ibG9iX2RlYzoNCj4gPiArCQl7DQo+ID4gKwkJCXN0cnVjdCBza19yZWRfYmxvYl9k
ZWNhcCAqcmVkX2Jsb2JfZGVjYXA7DQo+ID4gKwkJCXN0cnVjdCByZWRibG9iX2RlY2FwX2Rlc2Mg
KnJlZF9ibG9iX2Rlc2M7DQo+ID4gKw0KPiA+ICsJCQlyZWRfYmxvYl9kZWNhcCA9ICZyZXEtPnJl
cV91LnNrX3JlZF9ibG9iX2RlY2FwOw0KPiA+ICsJCQlyZWRfYmxvYl9kZXNjID0gJnNrZGVzYy0+
ZG1hX3UucmVkYmxvYl9kZWNhcGRlc2M7DQo+ID4gKw0KPiA+ICsJCQkvKiBVbm1hcCBEZXNjcmlw
dG9yIGJ1ZmZlciBwb2ludGVycy4gKi8NCj4gPiArCQkJZG1hX3VubWFwX3NpbmdsZShkZXYsIHJl
ZF9ibG9iX2Rlc2MtPnJlZGJsb2IsDQo+ID4gKwkJCQkJIHJlZF9ibG9iX2RlY2FwLT5yZWRibG9i
X3N6LA0KPiA+ICsJCQkJCSBETUFfVE9fREVWSUNFKTsNCj4gPiArDQo+ID4gKwkJCWRtYV91bm1h
cF9zaW5nbGUoZGV2LCByZWRfYmxvYl9kZXNjLT5vdXRfZGF0YSwNCj4gPiArCQkJCQkgcmVkX2Js
b2JfZGVjYXAtPmRhdGFfc3osDQo+ID4gKwkJCQkJIERNQV9GUk9NX0RFVklDRSk7DQo+ID4gKw0K
PiA+ICsJCQlicmVhazsNCj4gPiArCQl9DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCWRldl9lcnIo
ZGV2LCAiVW5hYmxlIHRvIGZpbmQgcmVxdWVzdCB0eXBlXG4iKTsNCj4gPiArCQlicmVhazsNCj4g
PiArCX0NCj4gPiArCWtmcmVlKHNrZGVzYyk7DQo+ID4gK30NCj4gPiArDQo+ID4gKy8qICBpbnQg
Y2FhbV9zZWN1cmVrZXlfZGVzY19pbml0KHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHNrX3Jl
cQ0KPiA+ICsqcmVxKQ0KPiA+ICsgKiAgYnJpZWYgQ0FBTSBEZXNjcmlwdG9yIGNyZWF0b3IgZm9y
IHNlY3VyZSBrZXkgb3BlcmF0aW9ucy4NCj4gPiArICogIHBhcmFtW2luXSBkZXYgUG9pbnRlciB0
byBqb2IgcmluZyBkZXZpY2Ugc3RydWN0dXJlDQo+ID4gKyAqICBwYXJhbVtpbl0gcmVxIFBvaW50
ZXIgdG8gc2VjdXJlIGtleSByZXF1ZXN0IHN0cnVjdHVyZQ0KPiA+ICsgKiAgcmV0dXJuIDAgb24g
c3VjY2VzcywgZXJyb3IgdmFsdWUgb3RoZXJ3aXNlLg0KPiA+ICsgKi8NCj4gPiAraW50IGNhYW1f
c2VjdXJla2V5X2Rlc2NfaW5pdChzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBza19yZXEgKnJl
cSkNCj4gPiArew0KPiA+ICsJc3RydWN0IHNrX2Rlc2MgKnNrZGVzYyA9IE5VTEw7DQo+ID4gKwlp
bnQgcmV0ID0gMDsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKHJlcS0+dHlwZSkgew0KPiA+ICsJY2Fz
ZSBza19nZXRfcmFuZG9tOg0KPiA+ICsJCXsNCj4gPiArCQkJc2tkZXNjID0ga21hbGxvYyhzaXpl
b2YoKnNrZGVzYyksIEdGUF9ETUEpOw0KPiA+ICsJCQlpZiAoIXNrZGVzYykgew0KPiA+ICsJCQkJ
cmV0ID0gLUVOT01FTTsNCj4gPiArCQkJCWdvdG8gb3V0Ow0KPiA+ICsJCQl9DQo+ID4gKwkJCXNr
ZGVzYy0+cmVxX3R5cGUgPSByZXEtPnR5cGU7DQo+ID4gKw0KPiA+ICsJCQlpZiAoY2FhbV9za19n
ZXRfcmFuZG9tX21hcChkZXYsIHJlcSwgc2tkZXNjKSkgew0KPiA+ICsJCQkJZGV2X2VycihkZXYs
ICJjYWFtIGdldF9yYW5kb20gbWFwIGZhaWxcbiIpOw0KPiA+ICsJCQkJcmV0ID0gLUVOT01FTTsN
Cj4gPiArCQkJCWdvdG8gb3V0Ow0KPiA+ICsJCQl9DQo+ID4gKwkJCWNhYW1fc2tfcm5nX2Rlc2Mo
cmVxLCBza2Rlc2MpOw0KPiA+ICsJCQlicmVhazsNCj4gPiArCQl9DQo+ID4gKwljYXNlIHNrX3Jl
ZF9ibG9iX2VuYzoNCj4gPiArCQl7DQo+ID4gKwkJCXNrZGVzYyA9IGttYWxsb2Moc2l6ZW9mKCpz
a2Rlc2MpLCBHRlBfRE1BKTsNCj4gPiArCQkJaWYgKCFza2Rlc2MpIHsNCj4gPiArCQkJCXJldCA9
IC1FTk9NRU07DQo+ID4gKwkJCQlnb3RvIG91dDsNCj4gPiArCQkJfQ0KPiA+ICsNCj4gPiArCQkJ
c2tkZXNjLT5yZXFfdHlwZSA9IHJlcS0+dHlwZTsNCj4gPiArDQo+ID4gKwkJCWlmIChjYWFtX3Nr
X3JlZGJsb2JfZW5jYXBfbWFwKGRldiwgcmVxLCBza2Rlc2MpKSB7DQo+ID4gKwkJCQlkZXZfZXJy
KGRldiwgImNhYW0gcmVkYmxvYl9lbmNhcCBtYXAgZmFpbFxuIik7DQo+ID4gKwkJCQlyZXQgPSAt
RU5PTUVNOw0KPiA+ICsJCQkJZ290byBvdXQ7DQo+ID4gKwkJCX0NCj4gPiArDQo+ID4gKwkJCS8q
IERlc2NyaXB0b3IgZnVuY3Rpb24gdG8gY3JlYXRlIHJlZGJsb2IgZnJvbSBkYXRhLiAqLw0KPiA+
ICsJCQljYWFtX3NrX3JlZGJsb2JfZW5jYXBfZGVzYyhyZXEsIHNrZGVzYyk7DQo+ID4gKwkJCWJy
ZWFrOw0KPiA+ICsJCX0NCj4gPiArDQo+ID4gKwljYXNlIHNrX3JlZF9ibG9iX2RlYzoNCj4gPiAr
CQl7DQo+ID4gKwkJCXNrZGVzYyA9IGttYWxsb2Moc2l6ZW9mKCpza2Rlc2MpLCBHRlBfRE1BKTsN
Cj4gPiArCQkJaWYgKCFza2Rlc2MpIHsNCj4gPiArCQkJCXJldCA9IC1FTk9NRU07DQo+ID4gKwkJ
CQlnb3RvIG91dDsNCj4gPiArCQkJfQ0KPiA+ICsNCj4gPiArCQkJc2tkZXNjLT5yZXFfdHlwZSA9
IHJlcS0+dHlwZTsNCj4gPiArDQo+ID4gKwkJCWlmIChjYWFtX3NrX3JlZGJsb2JfZGVjYXBfbWFw
KGRldiwgcmVxLCBza2Rlc2MpKSB7DQo+ID4gKwkJCQlkZXZfZXJyKGRldiwgImNhYW0gcmVkYmxv
Yl9kZWNhcCBtYXAgZmFpbFxuIik7DQo+ID4gKwkJCQlyZXQgPSAtRU5PTUVNOw0KPiA+ICsJCQkJ
Z290byBvdXQ7DQo+ID4gKwkJCX0NCj4gPiArDQo+ID4gKwkJCS8qIERlc2NyaXB0b3IgZnVuY3Rp
b24gdG8gZGVjYXAgZGF0YSBmcm9tIHJlZGJsb2IuICovDQo+ID4gKwkJCWNhYW1fc2tfcmVkYmxv
Yl9kZWNhcF9kZXNjKHJlcSwgc2tkZXNjKTsNCj4gPiArCQkJYnJlYWs7DQo+ID4gKwkJfQ0KPiA+
ICsJZGVmYXVsdDoNCj4gPiArCQlwcl9kZWJ1ZygiVW5rbm93biByZXF1ZXN0IHR5cGVcbiIpOw0K
PiA+ICsJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0K
PiA+ICsJcmVxLT5kZXNjX3BvaW50ZXIgPSAodm9pZCAqKXNrZGVzYzsNCj4gPiArDQo+ID4gK291
dDoNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gKy8qIHN0YXRpYyB2b2lk
IGNhYW1fb3BfZG9uZSAoc3RydWN0IGRldmljZSAqZGV2LCB1MzIgKmRlc2MsIHUzMiByZXQsDQo+
ID4gKyAqCQkJICAgICB2b2lkICpjb250ZXh0KQ0KPiA+ICsgKiBicmllZiBjYWxsYmFjayBmdW5j
dGlvbiB0byBiZSBjYWxsZWQgd2hlbiBkZXNjcmlwdG9yIGV4ZWN1dGVkLg0KPiA+ICsgKiBwYXJh
bVtpbl0gZGV2IFBvaW50ZXIgdG8gZGV2aWNlIHN0cnVjdHVyZQ0KPiA+ICsgKiBwYXJhbVtpbl0g
ZGVzYyBkZXNjcmlwdG9yIHBvaW50ZXINCj4gPiArICogcGFyYW1baW5dIHJldCByZXR1cm4gc3Rh
dHVzIG9mIEpvYiBzdWJtaXR0ZWQNCj4gPiArICogcGFyYW1baW5dIGNvbnRleHQgdm9pZCBwb2lu
dGVyDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgdm9pZCBjYWFtX29wX2RvbmUoc3RydWN0IGRldmlj
ZSAqZGV2LCB1MzIgKmRlc2MsIHUzMiByZXQsDQo+ID4gKwkJCSB2b2lkICpjb250ZXh0KQ0KPiA+
ICt7DQo+ID4gKwlzdHJ1Y3Qgc2tfcmVxICpyZXEgPSBjb250ZXh0Ow0KPiA+ICsNCj4gPiArCWlm
IChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImNhYW0gb3AgZG9uZSBlcnI6ICV4XG4iLCBy
ZXQpOw0KPiA+ICsJCS8qIHByaW50IHRoZSBlcnJvciBzb3VyY2UgbmFtZS4gKi8NCj4gPiArCQlj
YWFtX2pyX3N0cnN0YXR1cyhkZXYsIHJldCk7DQo+ID4gKwl9DQo+ID4gKwkvKiBDYWxsIHNlY3Vy
ZWtleV91bm1hcCBmdW5jdGlvbiBmb3IgdW5tYXBwaW5nIHRoZSBidWZmZXIgcG9pbnRlcnMuICov
DQo+ID4gKwlzZWN1cmVrZXlfdW5tYXAoZGV2LCByZXEtPmRlc2NfcG9pbnRlciwgcmVxKTsNCj4g
PiArDQo+ID4gKwlyZXEtPnJldCA9IHJldDsNCj4gPiArCWNvbXBsZXRlKCZyZXEtPmNvbXApOw0K
PiA+ICt9DQo+ID4gKw0KPiA+ICsNCj4gPiArLyogIHN0YXRpYyBpbnQgc2tfam9iX3N1Ym1pdChz
dHJ1Y3QgZGV2aWNlICpqcmRldiwgc3RydWN0IHNrX3JlcQ0KPiA+ICsqcmVxKQ0KPiA+ICsgKiAg
YnJpZWYgRW5xdWV1ZSBhIEpvYiBkZXNjcmlwdG9yIHRvIEpvYiByaW5nIGFuZCB3YWl0IHVudGls
IFNFQyByZXR1cm5zLg0KPiA+ICsgKiAgcGFyYW1baW5dIGpyZGV2IFBvaW50ZXIgdG8gam9iIHJp
bmcgZGV2aWNlIHN0cnVjdHVyZQ0KPiA+ICsgKiAgcGFyYW1baW5dIHJlcSBQb2ludGVyIHRvIHNl
Y3VyZSBrZXkgcmVxdWVzdCBzdHJ1Y3R1cmUNCj4gPiArICogIHJldHVybiAwIG9uIHN1Y2Nlc3Ms
IGVycm9yIHZhbHVlIG90aGVyd2lzZS4NCj4gPiArICovDQo+ID4gK3N0YXRpYyBpbnQgc2tfam9i
X3N1Ym1pdChzdHJ1Y3QgZGV2aWNlICpqcmRldiwgc3RydWN0IHNrX3JlcSAqcmVxKSB7DQo+ID4g
KwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWluaXRfY29tcGxldGlvbigmcmVxLT5jb21wKTsNCj4g
PiArDQo+ID4gKwkvKiBjYWFtX2pyX2VucXVldWUgZnVuY3Rpb24gZm9yIEVucXVldWUgYSBqb2Ig
ZGVzY3JpcHRvciAqLw0KPiA+ICsJcmV0ID0gY2FhbV9qcl9lbnF1ZXVlKGpyZGV2LCByZXEtPmh3
ZGVzYywgY2FhbV9vcF9kb25lLCByZXEpOw0KPiA+ICsJaWYgKCFyZXQpDQo+ID4gKwkJd2FpdF9m
b3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlKCZyZXEtPmNvbXApOw0KPiA+ICsNCj4gPiArCXJl
dCA9IHJlcS0+cmV0Ow0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyog
Y2FhbV9nZXRfcmFuZG9tKHN0cnVjdCBzZWN1cmVfa2V5X3BheWxvYWQgKnAsICBlbnVtIHNrX3Jl
cV90eXBlIGZldGNoX3JuZCwNCj4gPiArICoJCSAgIHN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiAr
ICogQ3JlYXRlIHRoZSByYW5kb20gbnVtYmVyIG9mIHRoZSBzcGVjaWZpZWQgbGVuZ3RoIHVzaW5n
IENBQU0gYmxvY2sNCj4gPiArICogcGFyYW1baW5dOiBvdXQgcG9pbnRlciB0byBwbGFjZSB0aGUg
cmFuZG9tIGJ5dGVzDQo+ID4gKyAqIHBhcmFtW2luXTogbGVuZ3RoIGZvciB0aGUgcmFuZG9tIGRh
dGEgYnl0ZXMuDQo+ID4gKyAqIHBhcmFtW2luXTogZGV2IFBvaW50ZXIgdG8gam9iIHJpbmcgZGV2
aWNlIHN0cnVjdHVyZQ0KPiA+ICsgKiBJZiBvcGVyYXRpb24gaXMgc3VjY2Vzc2Z1bCByZXR1cm4g
MCwgb3RoZXJ3aXNlIGVycm9yLg0KPiA+ICsgKi8NCj4gPiAraW50IGNhYW1fZ2V0X3JhbmRvbShz
dHJ1Y3Qgc2VjdXJlX2tleV9wYXlsb2FkICpwLCAgZW51bSBza19yZXFfdHlwZSBmZXRjaF9ybmQs
DQo+ID4gKwkJICAgIHN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiArew0KPiA+ICsJc3RydWN0IHNr
X2ZldGNoX3JuZF9kYXRhICpmZXRjaF9ybmRfZGF0YSA9IE5VTEw7DQo+ID4gKwlzdHJ1Y3Qgc2tf
cmVxICpyZXEgPSBOVUxMOw0KPiA+ICsJaW50IHJldCA9IDA7DQo+ID4gKwl2b2lkICp0ZW1wID0g
TlVMTDsNCj4gPiArDQo+ID4gKwlyZXEgPSBrbWFsbG9jKHNpemVvZihzdHJ1Y3Qgc2tfcmVxKSwg
R0ZQX0RNQSk7DQo+ID4gKwlpZiAoIXJlcSkgew0KPiA+ICsJCXJldCA9IC1FTk9NRU07DQo+ID4g
KwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmVxLT50eXBlID0gZmV0Y2hfcm5k
Ow0KPiA+ICsJZmV0Y2hfcm5kX2RhdGEgPSAmKHJlcS0+cmVxX3Uuc2tfZmV0Y2hfcm5kX2RhdGEp
Ow0KPiA+ICsNCj4gPiArCS8qIGluaXRpYWxpc2Ugd2l0aCBrZXkgbGVuZ3RoICovDQo+ID4gKwlm
ZXRjaF9ybmRfZGF0YS0+a2V5X2xlbiA9IHAtPmtleV9sZW47DQo+ID4gKw0KPiA+ICsJdGVtcCA9
IGttYWxsb2MoZmV0Y2hfcm5kX2RhdGEtPmtleV9sZW4sIEdGUF9ETUEpOw0KPiA+ICsJaWYgKCF0
ZW1wKSB7DQo+ID4gKwkJcmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0N
Cj4gPiArCWZldGNoX3JuZF9kYXRhLT5kYXRhID0gdGVtcDsNCj4gPiArDQo+ID4gKwlyZXQgPSBj
YWFtX3NlY3VyZWtleV9kZXNjX2luaXQoZGV2LCByZXEpOw0KPiA+ICsNCj4gPiArCWlmIChyZXQp
IHsNCj4gPiArCQlwcl9pbmZvKCJjYWFtX3NlY3VyZWtleV9kZXNjX2luaXQgZmFpbGVkXG4iKTsN
Cj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXQgPSBza19qb2Jfc3Vi
bWl0KGRldiwgcmVxKTsNCj4gPiArCWlmICghcmV0KSB7DQo+ID4gKwkJLypDb3B5IG91dHB1dCB0
byBrZXkgYnVmZmVyLiAqLw0KPiA+ICsJCW1lbWNweShwLT5rZXksIGZldGNoX3JuZF9kYXRhLT5k
YXRhLCBwLT5rZXlfbGVuKTsNCj4gPiArCX0gZWxzZSB7DQo+ID4gKwkJcmV0ID0gLUVJTlZBTDsN
Cj4gPiArCX0NCj4gPiArDQo+ID4gK291dDoNCj4gPiArCWlmIChyZXEpDQo+ID4gKwkJa2ZyZWUo
cmVxKTsNCj4gPiArDQo+ID4gKwlpZiAodGVtcCkNCj4gPiArCQlrZnJlZSh0ZW1wKTsNCj4gPiAr
DQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICsvKiBrZXlfZGVibG9iKHN0
cnVjdCBzZWN1cmVfa2V5X3BheWxvYWQgKnAsIGVudW0gc2tfcmVxX3R5cGUgZGVjYXBfdHlwZQ0K
PiA+ICsgKgkJc3RydWN0IGRldmljZSAqZGV2KQ0KPiA+ICsgKiBEZWJsb2JpZnkgdGhlIGJsb2Ig
dG8gZ2V0IHRoZSBrZXkgZGF0YSBhbmQgZmlsbCBpbiBzZWN1cmUga2V5DQo+ID4gK3BheWxvYWQg
c3RydWN0DQo+ID4gKyAqIHBhcmFtW2luXSBwIHBvaW50ZXIgdG8gdGhlIHNlY3VyZSBrZXkgcGF5
bG9hZA0KPiA+ICsgKiBwYXJhbVtpbl0gZGVjYXBfdHlwZSBvcGVyYXRpb24gdG8gYmUgZG9uZS4N
Cj4gPiArICogcGFyYW1baW5dIGRldiBkZXYgUG9pbnRlciB0byBqb2IgcmluZyBkZXZpY2Ugc3Ry
dWN0dXJlDQo+ID4gKyAqIElmIG9wZXJhdGlvbiBpcyBzdWNjZXNzZnVsIHJldHVybiAwLCBvdGhl
cndpc2UgZXJyb3IuDQo+ID4gKyAqLw0KPiA+ICtpbnQga2V5X2RlYmxvYihzdHJ1Y3Qgc2VjdXJl
X2tleV9wYXlsb2FkICpwLCBlbnVtIHNrX3JlcV90eXBlIGRlY2FwX3R5cGUsDQo+ID4gKwkgICAg
ICAgc3RydWN0IGRldmljZSAqZGV2KQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBpbnQgYmxvYl9s
ZW47DQo+ID4gKwlzdHJ1Y3Qgc2tfcmVkX2Jsb2JfZGVjYXAgKmRfYmxvYjsNCj4gPiArCXN0cnVj
dCBza19yZXEgKnJlcSA9IE5VTEw7DQo+ID4gKwlpbnQgdG90YWxfc3ogPSAwLCAqdGVtcCA9IE5V
TEwsIHJldCA9IDA7DQo+ID4gKw0KPiA+ICsJcmVxID0ga21hbGxvYyhzaXplb2Yoc3RydWN0IHNr
X3JlcSksIEdGUF9ETUEpOw0KPiA+ICsJaWYgKCFyZXEpIHsNCj4gPiArCQlyZXQgPSAtRU5PTUVN
Ow0KPiA+ICsJCWdvdG8gb3V0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWRfYmxvYiA9ICYocmVx
LT5yZXFfdS5za19yZWRfYmxvYl9kZWNhcCk7DQo+ID4gKwlibG9iX2xlbiA9IHAtPmJsb2JfbGVu
Ow0KPiA+ICsJcmVxLT50eXBlID0gZGVjYXBfdHlwZTsNCj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJ
ICogUmVkIGJsb2Igc2l6ZSBpcyB0aGUgYmxvYl9sZW4gZmlsbGVkIGluIHBheWxvYWQgc3RydWN0
DQo+ID4gKwkgKiBEYXRhX3N6IGkuZS4ga2V5IGlzIHRoZSBibG9iX2xlbiAtIGJsb2IgaGVhZGVy
IHNpemUNCj4gPiArCSAqLw0KPiA+ICsNCj4gPiArCWRfYmxvYi0+cmVkYmxvYl9zeiA9IGJsb2Jf
bGVuOw0KPiA+ICsJZF9ibG9iLT5kYXRhX3N6ID0gYmxvYl9sZW4gLSAoU0tfQkxPQl9LRVlfU1og
KyBTS19CTE9CX01BQ19TWik7DQo+ID4gKwl0b3RhbF9zeiA9IGRfYmxvYi0+ZGF0YV9zeiArIGRf
YmxvYi0+cmVkYmxvYl9zejsNCj4gPiArDQo+ID4gKwl0ZW1wID0ga21hbGxvYyh0b3RhbF9zeiwg
R0ZQX0RNQSk7DQo+ID4gKwlpZiAoIXRlbXApIHsNCj4gPiArCQlyZXQgPSAtRU5PTUVNOw0KPiA+
ICsJCWdvdG8gb3V0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJlcS0+bWVtX3BvaW50ZXIgPSB0
ZW1wOw0KPiA+ICsJZF9ibG9iLT5yZWRibG9iID0gdGVtcDsNCj4gPiArCWRfYmxvYi0+ZGF0YSA9
IGRfYmxvYi0+cmVkYmxvYiArIGRfYmxvYi0+cmVkYmxvYl9zejsNCj4gPiArCW1lbWNweShkX2Js
b2ItPnJlZGJsb2IsIHAtPmJsb2IsIGJsb2JfbGVuKTsNCj4gPiArDQo+ID4gKwlyZXQgPSBjYWFt
X3NlY3VyZWtleV9kZXNjX2luaXQoZGV2LCByZXEpOw0KPiA+ICsNCj4gPiArCWlmIChyZXQpIHsN
Cj4gPiArCQlwcl9pbmZvKCJjYWFtX3NlY3VyZWtleV9kZXNjX2luaXQ6IEZhaWxlZFxuIik7DQo+
ID4gKwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gc2tfam9iX3N1Ym1p
dChkZXYsIHJlcSk7DQo+ID4gKwlpZiAoIXJldCkgew0KPiA+ICsJCS8qQ29weSBvdXRwdXQgdG8g
a2V5IGJ1ZmZlci4gKi8NCj4gPiArCQlwLT5rZXlfbGVuID0gZF9ibG9iLT5kYXRhX3N6Ow0KPiA+
ICsJCW1lbWNweShwLT5rZXksIGRfYmxvYi0+ZGF0YSwgcC0+a2V5X2xlbik7DQo+ID4gKwl9IGVs
c2Ugew0KPiA+ICsJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICtvdXQ6DQo+
ID4gKwlpZiAodGVtcCkNCj4gPiArCQlrZnJlZSh0ZW1wKTsNCj4gPiArCWlmIChyZXEpDQo+ID4g
KwkJa2ZyZWUocmVxKTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gKy8q
IGtleV9ibG9iKHN0cnVjdCBzZWN1cmVfa2V5X3BheWxvYWQgKnAsIGVudW0gc2tfcmVxX3R5cGUg
ZW5jYXBfdHlwZSwNCj4gPiArICoJCXN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiArICogVG8gYmxv
YmlmeSB0aGUga2V5IGRhdGEgdG8gZ2V0IHRoZSBibG9iLiBUaGlzIGJsb2IgY2FuIG9ubHkgYmUN
Cj4gPiArc2VlbiBieQ0KPiA+ICsgKiB1c2Vyc3BhY2UuDQo+ID4gKyAqIHBhcmFtW2luXSBwIHBv
aW50ZXIgdG8gdGhlIHNlY3VyZSBrZXkgcGF5bG9hZA0KPiA+ICsgKiBwYXJhbVtpbl0gZGVjYXBf
dHlwZSBvcGVyYXRpb24gdG8gYmUgZG9uZS4NCj4gPiArICogcGFyYW1baW5dIGRldiBkZXYgUG9p
bnRlciB0byBqb2IgcmluZyBkZXZpY2Ugc3RydWN0dXJlDQo+ID4gKyAqIElmIG9wZXJhdGlvbiBp
cyBzdWNjZXNzZnVsIHJldHVybiAwLCBvdGhlcndpc2UgZXJyb3IuDQo+ID4gKyAqLw0KPiA+ICtp
bnQga2V5X2Jsb2Ioc3RydWN0IHNlY3VyZV9rZXlfcGF5bG9hZCAqcCwgZW51bSBza19yZXFfdHlw
ZSBlbmNhcF90eXBlLA0KPiA+ICsJICAgICBzdHJ1Y3QgZGV2aWNlICpkZXYpDQo+ID4gK3sNCj4g
PiArCXVuc2lnbmVkIGludCBrZXlfbGVuOw0KPiA+ICsJc3RydWN0IHNrX3JlZF9ibG9iX2VuY2Fw
ICprX2Jsb2I7DQo+ID4gKwlzdHJ1Y3Qgc2tfcmVxICpyZXEgPSBOVUxMOw0KPiA+ICsJaW50IHRv
dGFsX3N6ID0gMCwgKnRlbXAgPSBOVUxMLCByZXQgPSAwOw0KPiA+ICsNCj4gPiArCXJlcSA9IGtt
YWxsb2Moc2l6ZW9mKHN0cnVjdCBza19yZXEpLCBHRlBfRE1BKTsNCj4gPiArCWlmICghcmVxKSB7
DQo+ID4gKwkJcmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0NCj4gPiAr
DQo+ID4gKwlrZXlfbGVuID0gcC0+a2V5X2xlbjsNCj4gPiArDQo+ID4gKwlyZXEtPnR5cGUgPSBl
bmNhcF90eXBlOw0KPiA+ICsJa19ibG9iID0gJihyZXEtPnJlcV91LnNrX3JlZF9ibG9iX2VuY2Fw
KTsNCj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJICogRGF0YV9zeiBpLmUuIGtleSBsZW4gYW5kIHRo
ZSBjb3JyZXNwb25kaW5nIGJsb2JfbGVuIGlzDQo+ID4gKwkgKiBrZXlfbGVuICsgQkxPQiBoZWFk
ZXIgc2l6ZS44N2VhNTg0MzMyMDgNCj4gPiArCSAqLw0KPiA+ICsNCj4gPiArCWtfYmxvYi0+ZGF0
YV9zeiA9IGtleV9sZW47DQo+ID4gKwlrX2Jsb2ItPnJlZGJsb2Jfc3ogPSBrZXlfbGVuICsgU0tf
QkxPQl9LRVlfU1ogKyBTS19CTE9CX01BQ19TWjsNCj4gPiArCXRvdGFsX3N6ID0ga19ibG9iLT5k
YXRhX3N6ICsga19ibG9iLT5yZWRibG9iX3N6Ow0KPiA+ICsNCj4gPiArCXRlbXAgPSBrbWFsbG9j
KHRvdGFsX3N6LCBHRlBfRE1BKTsNCj4gPiArCWlmICghdGVtcCkgew0KPiA+ICsJCXJldCA9IC1F
Tk9NRU07DQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmVxLT5tZW1f
cG9pbnRlciA9IHRlbXA7DQo+ID4gKwlrX2Jsb2ItPmRhdGEgPSB0ZW1wOw0KPiA+ICsNCj4gPiAr
CWtfYmxvYi0+cmVkYmxvYiA9IGtfYmxvYi0+ZGF0YSArIGtfYmxvYi0+ZGF0YV9zejsNCj4gPiAr
CW1lbWNweShrX2Jsb2ItPmRhdGEsIHAtPmtleSwga2V5X2xlbik7DQo+ID4gKw0KPiA+ICsJcmV0
ID0gY2FhbV9zZWN1cmVrZXlfZGVzY19pbml0KGRldiwgcmVxKTsNCj4gPiArDQo+ID4gKwlpZiAo
cmV0KSB7DQo+ID4gKwkJcHJfaW5mbygiY2FhbV9zZWN1cmVrZXlfZGVzY19pbml0IGZhaWxlZFxu
Iik7DQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gc2tfam9i
X3N1Ym1pdChkZXYsIHJlcSk7DQo+ID4gKwlpZiAoIXJldCkgew0KPiA+ICsJCS8qQ29weSBvdXRw
dXQgdG8ga2V5IGJ1ZmZlci4gKi8NCj4gPiArCQlwLT5ibG9iX2xlbiA9IGtfYmxvYi0+cmVkYmxv
Yl9zejsNCj4gPiArCQltZW1jcHkocC0+YmxvYiwga19ibG9iLT5yZWRibG9iLCBwLT5ibG9iX2xl
bik7DQo+ID4gKwl9IGVsc2Ugew0KPiA+ICsJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4g
Kw0KPiA+ICtvdXQ6DQo+ID4gKwlpZiAodGVtcCkNCj4gPiArCQlrZnJlZShyZXEtPm1lbV9wb2lu
dGVyKTsNCj4gPiArCWlmIChyZXEpDQo+ID4gKwkJa2ZyZWUocmVxKTsNCj4gPiArCXJldHVybiBy
ZXQ7DQo+ID4gKw0KPiA+ICt9DQo+ID4gKw0KPiA+IGRpZmYgLS1naXQgYS9zZWN1cml0eS9rZXlz
L3NlY3VyZWtleV9kZXNjLmgNCj4gPiBiL3NlY3VyaXR5L2tleXMvc2VjdXJla2V5X2Rlc2MuaCBu
ZXcgZmlsZSBtb2RlIDEwMDY0NCBpbmRleA0KPiA+IDAwMDAwMDAwMDAwMC4uMGVlMjZlOTViMjA1
DQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL3NlY3VyaXR5L2tleXMvc2VjdXJla2V5X2Rl
c2MuaA0KPiA+IEBAIC0wLDAgKzEsMTQxIEBADQo+ID4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlm
aWVyOiBHUEwtMi4wICovDQo+ID4gKy8qDQo+ID4gKyAqIENvcHlyaWdodCAyMDE4IE5YUA0KPiA+
ICsgKg0KPiA+ICsgKi8NCj4gPiArI2lmbmRlZiBfU0VDVVJFS0VZX0RFU0NfSF8NCj4gPiArI2Rl
ZmluZSBfU0VDVVJFS0VZX0RFU0NfSF8NCj4gPiArDQo+ID4gKyNpbmNsdWRlICJjb21wYXQuaCIN
Cj4gPiArI2luY2x1ZGUgInJlZ3MuaCINCj4gPiArI2luY2x1ZGUgImludGVybi5oIg0KPiA+ICsj
aW5jbHVkZSAiZGVzYy5oIg0KPiA+ICsjaW5jbHVkZSAiZGVzY19jb25zdHIuaCINCj4gPiArI2lu
Y2x1ZGUgImpyLmgiDQo+ID4gKyNpbmNsdWRlICJlcnJvci5oIg0KPiA+ICsjaW5jbHVkZSAicGRi
LmgiDQo+ID4gKw0KPiA+ICsjZGVmaW5lIFNLX0JMT0JfS0VZX1NaCQkzMgkvKiBCbG9iIGtleSBz
aXplLiAqLw0KPiA+ICsjZGVmaW5lIFNLX0JMT0JfTUFDX1NaCQkxNgkvKiBCbG9iIE1BQyBzaXpl
LiAqLw0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogYnJpZWYgZGVmaW5lcyBkaWZmZXJlbnQga2lu
ZHMgb2Ygb3BlcmF0aW9ucyBzdXBwb3J0ZWQgYnkgdGhpcyBtb2R1bGUuDQo+ID4gKyAqLw0KPiA+
ICtlbnVtIHNrX3JlcV90eXBlIHsNCj4gPiArCXNrX2dldF9yYW5kb20sDQo+ID4gKwlza19yZWRf
YmxvYl9lbmMsDQo+ID4gKwlza19yZWRfYmxvYl9kZWMsDQo+ID4gK307DQo+ID4gKw0KPiA+ICsN
Cj4gPiArLyoNCj4gPiArICogc3RydWN0IHJhbmRvbV9kZXMNCj4gPiArICogcGFyYW1bb3V0XSBy
bmRfZGF0YSBvdXRwdXQgYnVmZmVyIGZvciByYW5kb20gZGF0YS4NCj4gPiArICovDQo+ID4gK3N0
cnVjdCByYW5kb21fZGVzYyB7DQo+ID4gKwlkbWFfYWRkcl90IHJuZF9kYXRhOw0KPiA+ICt9Ow0K
PiA+ICsNCj4gPiArLyogc3RydWN0IHJlZGJsb2JfZW5jYXBfZGVzYw0KPiA+ICsgKiBkZXRhaWxz
IFN0cnVjdHVyZSBjb250YWluaW5nIGRtYSBhZGRyZXNzIGZvciByZWRibG9iIGVuY2Fwc3VsYXRp
b24uDQo+ID4gKyAqIHBhcmFtW2luXSBpbl9kYXRhIGlucHV0IGRhdGEgdG8gcmVkYmxvYiBlbmNh
cCBkZXNjcmlwdG9yLg0KPiA+ICsgKiBwYXJhbVtvdXRdIHJlZGJsb2Igb3V0cHV0IGJ1ZmZlciBm
b3IgcmVkYmxvYi4NCj4gPiArICovDQo+ID4gK3N0cnVjdCByZWRibG9iX2VuY2FwX2Rlc2Mgew0K
PiA+ICsJZG1hX2FkZHJfdCBpbl9kYXRhOw0KPiA+ICsJZG1hX2FkZHJfdCByZWRibG9iOw0KPiA+
ICt9Ow0KPiA+ICsNCj4gPiArLyogc3RydWN0IHJlZGJsb2JfZGVjYXBfZGVzYw0KPiA+ICsgKiBk
ZXRhaWxzIFN0cnVjdHVyZSBjb250YWluaW5nIGRtYSBhZGRyZXNzIGZvciByZWRibG9iIGRlY2Fw
c3VsYXRpb24uDQo+ID4gKyAqIHBhcmFtW2luXSByZWRibG9iIGlucHV0IGJ1ZmZlciB0byByZWRi
bG9iIGRlY2FwIGRlc2NyaXB0b3IuDQo+ID4gKyAqIHBhcmFtW291dF0gb3V0X2RhdGEgb3V0cHV0
IGRhdGEgZnJvbSByZWRibG9iIGRlY2FwIGRlc2NyaXB0b3IuDQo+ID4gKyAqLw0KPiA+ICtzdHJ1
Y3QgcmVkYmxvYl9kZWNhcF9kZXNjIHsNCj4gPiArCWRtYV9hZGRyX3QgcmVkYmxvYjsNCj4gPiAr
CWRtYV9hZGRyX3Qgb3V0X2RhdGE7DQo+ID4gK307DQo+ID4gKw0KPiA+ICsvKiBzdHJ1Y3Qgc2tf
ZGVzYw0KPiA+ICsgKiBkZXRhaWxzIFN0cnVjdHVyZSBmb3Igc2VjdXJla2V5IGRlc2NyaXB0b3Ig
Y3JlYXRpb24uDQo+ID4gKyAqIHBhcmFtW2luXSByZXFfdHlwZSBvcGVyYXRpb24gc3VwcG9ydGVk
Lg0KPiA+ICsgKiBwYXJhbVtpbl0gZG1hX3UgdW5pb24gb2Ygc3RydWN0IGZvciBzdXBwb3J0ZWQg
b3BlcmF0aW9uLg0KPiA+ICsgKi8NCj4gPiArc3RydWN0IHNrX2Rlc2Mgew0KPiA+ICsJdTMyIHJl
cV90eXBlOw0KPiA+ICsJdW5pb24gew0KPiA+ICsJCXN0cnVjdCByZWRibG9iX2VuY2FwX2Rlc2Mg
cmVkYmxvYl9lbmNhcGRlc2M7DQo+ID4gKwkJc3RydWN0IHJlZGJsb2JfZGVjYXBfZGVzYyByZWRi
bG9iX2RlY2FwZGVzYzsNCj4gPiArCQlzdHJ1Y3QgcmFuZG9tX2Rlc2MgcmFuZG9tX2Rlc2NwOw0K
PiA+ICsJfSBkbWFfdTsNCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIHN0cnVjdCBza19mZXRjaF9y
bmRfZGF0YQ0KPiA+ICsgKiBkZWNyaXB0b3Igc3RydWN0dXJlIGNvbnRhaW5pbmcga2V5IGxlbmd0
aC4NCj4gPiArICovDQo+ID4gK3N0cnVjdCBza19mZXRjaF9ybmRfZGF0YSB7DQo+ID4gKwl2b2lk
ICpkYXRhOw0KPiA+ICsJc2l6ZV90IGtleV9sZW47DQo+ID4gK307DQo+ID4gKw0KPiA+ICsvKiBz
dHJ1Y3Qgc2tfcmVkX2Jsb2JfZW5jYXANCj4gPiArICogZGV0YWlscyBTdHJ1Y3R1cmUgY29udGFp
bmluZyBidWZmZXIgcG9pbnRlcnMgZm9yIHJlZGJsb2IgZW5jYXBzdWxhdGlvbi4NCj4gPiArICog
cGFyYW1baW5dIGRhdGEgSW5wdXQgZGF0YS4NCj4gPiArICogcGFyYW1baW5dIGRhdGFfc3ogc2l6
ZSBvZiBJbnB1dCBkYXRhLg0KPiA+ICsgKiBwYXJhbVtvdXRdIHJlZGJsb2Igb3V0cHV0IGJ1ZmZl
ciBmb3IgcmVkYmxvYi4NCj4gPiArICogcGFyYW1baW5dIHJlZGJsb2Jfc3ogc2l6ZSBvZiByZWRi
bG9iLg0KPiA+ICsgKi8NCj4gPiArc3RydWN0IHNrX3JlZF9ibG9iX2VuY2FwIHsNCj4gPiArCXZv
aWQgKmRhdGE7DQo+ID4gKwl1aW50MzJfdCBkYXRhX3N6Ow0KPiA+ICsJdm9pZCAqcmVkYmxvYjsN
Cj4gPiArCXVpbnQzMl90IHJlZGJsb2Jfc3o7DQo+ID4gK307DQo+ID4gKw0KPiA+ICsvKiBzdHJ1
Y3Qgc2tfcmVkX2Jsb2JfZGVjYXANCj4gPiArICogZGV0YWlscyBTdHJ1Y3R1cmUgY29udGFpbmlu
ZyBidWZmZXIgcG9pbnRlcnMgZm9yIHJlZGJsb2IgZGVjYXBzdWxhdGlvbi4NCj4gPiArICogcGFy
YW1baW5dIHJlZGJsb2IgSW5wdXQgcmVkYmxvYi4NCj4gPiArICogcGFyYW1baW5dIHJlZGJsb2Jf
c3ogc2l6ZSBvZiByZWRibG9iLg0KPiA+ICsgKiBwYXJhbVtvdXRdIGRhdGEgb3V0cHV0IGJ1ZmZl
ciBmb3IgZGF0YS4NCj4gPiArICogcGFyYW1baW5dIGRhdGFfc3ogc2l6ZSBvZiBvdXRwdXQgZGF0
YS4NCj4gPiArICovDQo+ID4gK3N0cnVjdCBza19yZWRfYmxvYl9kZWNhcCB7DQo+ID4gKwl2b2lk
ICpyZWRibG9iOw0KPiA+ICsJdWludDMyX3QgcmVkYmxvYl9zejsNCj4gPiArCXZvaWQgKmRhdGE7
DQo+ID4gKwl1aW50MzJfdCBkYXRhX3N6Ow0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArLyogc3RydWN0
IHNrX3JlcQ0KPiA+ICsgKiBkZXRhaWxzIFN0cnVjdHVyZSBmb3Igc2VjdXJla2V5IHJlcXVlc3Qg
Y3JlYXRpb24uDQo+ID4gKyAqIHBhcmFtW2luXSB0eXBlIG9wZXJhdGlvbiBzdXBwb3J0ZWQuDQo+
ID4gKyAqIHBhcmFtW2luXSByZXFfdSB1bmlvbiBvZiBzdHJ1Y3QgZm9yIHN1cHBvcnRlZCBvcGVy
YXRpb24uDQo+ID4gKyAqIHBhcmFtW291dF0gcmV0IHJldHVybiBzdGF0dXMgb2YgQ0FBTSBvcGVy
YXRpb24uDQo+ID4gKyAqIHBhcmFtW2luXSBtZW1fcG9pbnRlciBtZW1vcnkgcG9pbnRlciBmb3Ig
YWxsb2NhdGVkIGtlcm5lbCBtZW1vcnkuDQo+ID4gKyAqIHBhcmFtW2luXSBkZXNjX3BvaW50ZXIg
UG9pbnRlciB0byBzZWN1cmVrZXkgZGVzY3JpcHRvciBjcmVhdGlvbiBzdHJ1Y3R1cmUuDQo+ID4g
KyAqIHBhcmFtW2luXSBjb21wIHN0cnVjdCBjb21wbGV0aW9uIG9iamVjdC4NCj4gPiArICogcGFy
YW1baW5dIGh3ZGVzYyBjb250YWlucyBkZXNjcmlwdG9yIGluc3RydWN0aW9ucy4NCj4gPiArICov
DQo+ID4gK3N0cnVjdCBza19yZXEgew0KPiA+ICsJZW51bSBza19yZXFfdHlwZSB0eXBlOw0KPiA+
ICsJdm9pZCAqYXJnOw0KPiA+ICsJdW5pb24gew0KPiA+ICsJCXN0cnVjdCBza19yZWRfYmxvYl9l
bmNhcCBza19yZWRfYmxvYl9lbmNhcDsNCj4gPiArCQlzdHJ1Y3Qgc2tfcmVkX2Jsb2JfZGVjYXAg
c2tfcmVkX2Jsb2JfZGVjYXA7DQo+ID4gKwkJc3RydWN0IHNrX2ZldGNoX3JuZF9kYXRhIHNrX2Zl
dGNoX3JuZF9kYXRhOw0KPiA+ICsJfSByZXFfdTsNCj4gPiArCWludCByZXQ7DQo+ID4gKwl2b2lk
ICptZW1fcG9pbnRlcjsNCj4gPiArCXZvaWQgKmRlc2NfcG9pbnRlcjsNCj4gPiArCXN0cnVjdCBj
b21wbGV0aW9uIGNvbXA7DQo+ID4gKwl1MzIgaHdkZXNjW01BWF9DQUFNX0RFU0NTSVpFXTsNCj4g
PiArfTsNCj4gPiArDQo+ID4gK2ludCBjYWFtX2dldF9yYW5kb20oc3RydWN0IHNlY3VyZV9rZXlf
cGF5bG9hZCAqcCwgIGVudW0gc2tfcmVxX3R5cGUgZmV0Y2hfcm5kLA0KPiA+ICsJCSAgICBzdHJ1
Y3QgZGV2aWNlICpkZXYpOw0KPiA+ICtpbnQga2V5X2Jsb2Ioc3RydWN0IHNlY3VyZV9rZXlfcGF5
bG9hZCAqcCwgZW51bSBza19yZXFfdHlwZSBlbmNhcF90eXBlLA0KPiA+ICsJICAgICBzdHJ1Y3Qg
ZGV2aWNlICpkZXYpOw0KPiA+ICtpbnQga2V5X2RlYmxvYihzdHJ1Y3Qgc2VjdXJlX2tleV9wYXls
b2FkICpwLCBlbnVtIHNrX3JlcV90eXBlIGRlY2FwX3R5cGUsDQo+ID4gKwkgICAgICAgc3RydWN0
IGRldmljZSAqZGV2KTsNCj4gPiArDQo+ID4gKyNlbmRpZiAvKl9TRUNVUkVLRVlfREVTQ19IXyov
DQoNCg=

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 12:31     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-24 12:31 UTC (permalink / raw)
  To: Mimi Zohar, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > Secure keys are derieved using CAAM crypto block.
> >
> > Secure keys derieved are the random number symmetric keys from CAAM.
> > Blobs corresponding to the key are formed using CAAM. User space will
> > only be able to view the blob of the key.
> 
> The term "trusted keys" comes from the usage of the Trusted Platform Module
> (TPM).  The term "trusted" now also refers to keyrings, which has nothing to do with a
> TPM.
> 
> What is the correlation between the term "secure keys" and CAAM?  Are "secure keys", as
> defined in this patch, limited to a specific HW crypto device?
> 
> Mimi
> 

Yes the secure keys and CAAM are correlated. Secure keys depends on NXP CAAM crypto HW
accelerator. Secure key is a random data of length X (passed using keyctl command) & derived
using CAAM. Blob of this data is also created using CAAM. Only blob is visible to user space.

Regards,
Udit 

> >
> > Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> > Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> > ---
> >  Documentation/security/keys/secure-key.rst |  67 +++
> >  MAINTAINERS                                |  11 +
> >  include/keys/secure-type.h                 |  33 ++
> >  security/keys/Kconfig                      |  11 +
> >  security/keys/Makefile                     |   3 +
> >  security/keys/secure_key.c                 | 339 ++++++++++++
> >  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
> >  security/keys/securekey_desc.h             | 141 +++++
> >  8 files changed, 1211 insertions(+)
> >  create mode 100644 Documentation/security/keys/secure-key.rst
> >  create mode 100644 include/keys/secure-type.h  create mode 100644
> > security/keys/secure_key.c  create mode 100644
> > security/keys/securekey_desc.c  create mode 100644
> > security/keys/securekey_desc.h
> >
> > diff --git a/Documentation/security/keys/secure-key.rst
> > b/Documentation/security/keys/secure-key.rst
> > new file mode 100644
> > index 000000000000..0fc3367b00f8
> > --- /dev/null
> > +++ b/Documentation/security/keys/secure-key.rst
> > @@ -0,0 +1,67 @@
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> > +
> > +Usage::
> > +
> > +	keyctl add secure <name> "new <keylen>" <ring>
> > +	keyctl load secure <name> "load <hex_blob>" <ring>
> > +	keyctl print <key_id>
> > +
> > +"keyctl add secure" option will create the random data of the
> > +specified key len using CAAM and store it as a key in kernel.
> > +Key contents will be displayed as blobs to the user in hex ascii.
> > +User can input key len from 32 bytes to 128 bytes.
> > +
> > +"keyctl load secure" option will load the blob contents. In kernel,
> > +key will be deirved using input blob and CAAM, along with the secret
> > +key stored in CAAM.
> > +
> > +"keyctl print" will return the hex string of the blob corresponding
> > +to key_id. Returned blob will be of key_len + 48 bytes. Extra 48
> > +bytes are the header bytes added by the CAAM.
> > +
> > +Example of secure key usage::
> > +
> > +1. Create the secure key with name kmk-master of length 32 bytes::
> > +
> > +	$ keyctl add secure kmk-master "new 32" @u
> > +	46001928
> > +
> > +	$keyctl show
> > +	Session Keyring
> > +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> > +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> > +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> > +
> > +2. Print the blob contents for the kmk-master key::
> > +
> > +	$ keyctl print 46001928
> > +	d9743445b640f3d59c1670dddc0bc9c2
> > +	34fc9aab7dd05c965e6120025012f029b
> > +	07faa4776c4f6ed02899e35a135531e9a
> > +	6e5c2b51132f9d5aef28f68738e658296
> > +	3fe583177cfe50d2542b659a13039
> > +
> > +	$ keyctl pipe 46001928 > secure_key.blob
> > +
> > +3. Load the blob in the user key ring::
> > +
> > +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 9fd5e8808208..654be2ee4b0a 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
> >  F:	security/keys/trusted.c
> >  F:	security/keys/trusted.h
> >
> > +KEYS-SECURE
> > +M:	Udit Agarwal <udit.agarwal@nxp.com>
> > +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> > +L:	linux-security-module@vger.kernel.org
> > +L:	keyrings@vger.kernel.org
> > +S:	Supported
> > +F:	include/keys/secure-type.h
> > +F:	security/keys/secure_key.c
> > +F:	security/keys/securekey_desc.c
> > +F:	security/keys/securekey_desc.h
> > +
> >  KEYS/KEYRINGS:
> >  M:	David Howells <dhowells@redhat.com>
> >  L:	keyrings@vger.kernel.org
> > diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> > new file mode 100644 index 000000000000..5b7a5f144e41
> > --- /dev/null
> > +++ b/include/keys/secure-type.h
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2018 NXP.
> > + *
> > + */
> > +
> > +#ifndef _KEYS_SECURE_TYPE_H
> > +#define _KEYS_SECURE_TYPE_H
> > +
> > +#include <linux/key.h>
> > +#include <linux/rcupdate.h>
> > +
> > +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> > + * is 128 bytes.
> > + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> > + */
> > +
> > +#define MIN_KEY_SIZE                    32
> > +#define MAX_KEY_SIZE                    128
> > +#define BLOB_HEADER_SIZE		48
> > +
> > +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> > +
> > +struct secure_key_payload {
> > +	struct rcu_head rcu;
> > +	unsigned int key_len;
> > +	unsigned int blob_len;
> > +	unsigned char key[MAX_KEY_SIZE + 1];
> > +	unsigned char blob[MAX_BLOB_SIZE];
> > +};
> > +
> > +extern struct key_type key_type_secure; #endif
> > diff --git a/security/keys/Kconfig b/security/keys/Kconfig index
> > 6462e6654ccf..7eb138b5a54f 100644
> > --- a/security/keys/Kconfig
> > +++ b/security/keys/Kconfig
> > @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> >
> >  	  If you are unsure as to whether this is required, answer N.
> >
> > +config SECURE_KEYS
> > +	tristate "SECURE_KEYS"
> > +	depends on KEYS && CRYPTO_DEV_FSL_CAAM &&
> CRYPTO_DEV_FSL_CAAM_JR
> > +	help
> > +	  This option provide support for creating secure-type key and blobs
> > +	  in kernel. Secure keys are random number symmetric keys generated
> > +	  from CAAM. The CAAM creates the blobs for the random key.
> > +	  Userspace will only be able to see the blob.
> > +
> > +	  If you are unsure as to whether this is required, answer N.
> > +
> >  config ENCRYPTED_KEYS
> >  	tristate "ENCRYPTED KEYS"
> >  	depends on KEYS
> > diff --git a/security/keys/Makefile b/security/keys/Makefile index
> > ef1581b337a3..606ba4efb9e6 100644
> > --- a/security/keys/Makefile
> > +++ b/security/keys/Makefile
> > @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o  #
> >  obj-$(CONFIG_BIG_KEYS) += big_key.o
> >  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> > +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> > +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> > +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
> >  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ diff --git
> > a/security/keys/secure_key.c b/security/keys/secure_key.c new file
> > mode 100644 index 000000000000..ec8ad4394549
> > --- /dev/null
> > +++ b/security/keys/secure_key.c
> > @@ -0,0 +1,339 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (C) 2018 NXP
> > + * Secure key is generated using NXP CAAM hardware block. CAAM
> > +generates the
> > + * random number (used as a key) and creates its blob for the user.
> > + */
> > +
> > +#include <linux/slab.h>
> > +#include <linux/parser.h>
> > +#include <linux/string.h>
> > +#include <linux/key-type.h>
> > +#include <linux/rcupdate.h>
> > +#include <keys/secure-type.h>
> > +#include <linux/completion.h>
> > +
> > +#include "securekey_desc.h"
> > +
> > +static const char hmac_alg[] = "hmac(sha1)"; static const char
> > +hash_alg[] = "sha1";
> > +
> > +static struct crypto_shash *hashalg;
> > +static struct crypto_shash *hmacalg;
> > +
> > +enum {
> > +	error = -1,
> > +	new_key,
> > +	load_blob,
> > +};
> > +
> > +static const match_table_t key_tokens = {
> > +	{new_key, "new"},
> > +	{load_blob, "load"},
> > +	{error, NULL}
> > +};
> > +
> > +static struct secure_key_payload *secure_payload_alloc(struct key
> > +*key) {
> > +	struct secure_key_payload *sec_key = NULL;
> > +	int ret = 0;
> > +
> > +	ret = key_payload_reserve(key, sizeof(*sec_key));
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> > +	if (!sec_key)
> > +		goto out;
> > +
> > +out:
> > +	return sec_key;
> > +}
> > +
> > +/*
> > + * parse_inputdata - parse the keyctl input data and fill in the
> > + *		     payload structure for key or its blob.
> > + * param[in]: data pointer to the data to be parsed for creating key.
> > + * param[in]: p pointer to secure key payload structure to fill
> > +parsed data
> > + * On success returns 0, otherwise -EINVAL.
> > + */
> > +static int parse_inputdata(char *data, struct secure_key_payload *p)
> > +{
> > +	substring_t args[MAX_OPT_ARGS];
> > +	long keylen = 0;
> > +	int ret = -EINVAL;
> > +	int key_cmd = -EINVAL;
> > +	char *c = NULL;
> > +
> > +	c = strsep(&data, " \t");
> > +	if (!c) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	/* Get the keyctl command i.e. new_key or load_blob etc */
> > +	key_cmd = match_token(c, key_tokens, args);
> > +
> > +	switch (key_cmd) {
> > +	case new_key:
> > +		/* first argument is key size */
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = kstrtol(c, 10, &keylen);
> > +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> > +						keylen > MAX_KEY_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		p->key_len = keylen;
> > +		ret = new_key;
> > +
> > +		break;
> > +	case load_blob:
> > +		/* first argument is blob data for CAAM*/
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		/* Blob_len = No of characters in blob/2 */
> > +		p->blob_len = strlen(c) / 2;
> > +		if (p->blob_len > MAX_BLOB_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = hex2bin(p->blob, c, p->blob_len);
> > +		if (ret < 0) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +		ret = load_blob;
> > +
> > +		break;
> > +	case error:
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_instantiate - create a new secure type key.
> > + * Supports the operation to generate a new key. A random number
> > + * is generated from CAAM as key data and the corresponding red blob
> > + * is formed and stored as key_blob.
> > + * Also supports the operation to load the blob and key is derived
> > +using
> > + * that blob from CAAM.
> > + * On success, return 0. Otherwise return errno.
> > + */
> > +static int secure_instantiate(struct key *key,
> > +		struct key_preparsed_payload *prep) {
> > +	struct secure_key_payload *payload = NULL;
> > +	size_t datalen = prep->datalen;
> > +	char *data = NULL;
> > +	int key_cmd = 0;
> > +	int ret = 0;
> > +	enum sk_req_type sk_op_type;
> > +	struct device *dev = NULL;
> > +
> > +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	data = kmalloc(datalen + 1, GFP_KERNEL);
> > +	if (!data) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	memcpy(data, prep->data, datalen);
> > +	data[datalen] = '\0';
> > +
> > +	payload = secure_payload_alloc(key);
> > +	if (!payload) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	/* Allocate caam job ring for operation to be performed from CAAM */
> > +	dev = caam_jr_alloc();
> > +	if (!dev) {
> > +		pr_info("caam_jr_alloc failed\n");
> > +		ret = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	key_cmd = parse_inputdata(data, payload);
> > +	if (key_cmd < 0) {
> > +		ret = key_cmd;
> > +		goto out;
> > +	}
> > +
> > +	switch (key_cmd) {
> > +	case load_blob:
> > +		/*
> > +		 * Red blob decryption to be done for load operation
> > +		 * to derive the key.
> > +		 */
> > +		sk_op_type = sk_red_blob_dec;
> > +		ret = key_deblob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	case new_key:
> > +		/* Get Random number from caam of the specified length */
> > +		sk_op_type = sk_get_random;
> > +		ret = caam_get_random(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: get_random fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +
> > +		/* Generate red blob of key random bytes with CAAM */
> > +		sk_op_type = sk_red_blob_enc;
> > +		ret = key_blob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	default:
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +out:
> > +	if (data)
> > +		kzfree(data);
> > +	if (dev)
> > +		caam_jr_free(dev);
> > +
> > +	if (!ret)
> > +		rcu_assign_keypointer(key, payload);
> > +	else
> > +		kzfree(payload);
> > +
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_read - copy the  blob data to userspace in hex.
> > + * param[in]: key pointer to key struct
> > + * param[in]: buffer pointer to user data for creating key
> > + * param[in]: buflen is the length of the buffer
> > + * On success, return to userspace the secure key data size.
> > + */
> > +static long secure_read(const struct key *key, char __user *buffer,
> > +			 size_t buflen)
> > +{
> > +	const struct secure_key_payload *p = NULL;
> > +	char *ascii_buf;
> > +	char *bufp;
> > +	int i;
> > +
> > +	p = dereference_key_locked(key);
> > +	if (!p)
> > +		return -EINVAL;
> > +
> > +	if (buffer && buflen >= 2 * p->blob_len) {
> > +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> > +		if (!ascii_buf)
> > +			return -ENOMEM;
> > +
> > +		bufp = ascii_buf;
> > +		for (i = 0; i < p->blob_len; i++)
> > +			bufp = hex_byte_pack(bufp, p->blob[i]);
> > +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> > +			kzfree(ascii_buf);
> > +			return -EFAULT;
> > +		}
> > +		kzfree(ascii_buf);
> > +	}
> > +	return 2 * p->blob_len;
> > +}
> > +
> > +/*
> > + * secure_destroy - clear and free the key's payload  */ static void
> > +secure_destroy(struct key *key) {
> > +	kzfree(key->payload.data[0]);
> > +}
> > +
> > +struct key_type key_type_secure = {
> > +	.name = "secure",
> > +	.instantiate = secure_instantiate,
> > +	.destroy = secure_destroy,
> > +	.read = secure_read,
> > +};
> > +EXPORT_SYMBOL_GPL(key_type_secure);
> > +
> > +static void secure_shash_release(void) {
> > +	if (hashalg)
> > +		crypto_free_shash(hashalg);
> > +	if (hmacalg)
> > +		crypto_free_shash(hmacalg);
> > +}
> > +
> > +static int __init secure_shash_alloc(void) {
> > +	int ret;
> > +
> > +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hmacalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hmac_alg);
> > +		return PTR_ERR(hmacalg);
> > +	}
> > +
> > +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hashalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hash_alg);
> > +		ret = PTR_ERR(hashalg);
> > +		goto hashalg_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +hashalg_fail:
> > +	crypto_free_shash(hmacalg);
> > +	return ret;
> > +}
> > +
> > +static int __init init_secure_key(void) {
> > +	int ret;
> > +
> > +	ret = secure_shash_alloc();
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = register_key_type(&key_type_secure);
> > +	if (ret < 0)
> > +		secure_shash_release();
> > +	return ret;
> > +}
> > +
> > +static void __exit cleanup_secure_key(void) {
> > +	secure_shash_release();
> > +	unregister_key_type(&key_type_secure);
> > +}
> > +
> > +late_initcall(init_secure_key);
> > +module_exit(cleanup_secure_key);
> > +
> > +MODULE_LICENSE("GPL");
> > diff --git a/security/keys/securekey_desc.c
> > b/security/keys/securekey_desc.c new file mode 100644 index
> > 000000000000..a4fa811a5753
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.c
> > @@ -0,0 +1,606 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 NXP
> > + *
> > + */
> > +
> > +#include <keys/secure-type.h>
> > +#include "securekey_desc.h"
> > +
> > +/* key modifier for blob encapsulation & decapsulation descriptor */
> > +u8 key_modifier[] = "SECURE_KEY";
> > +u32 key_modifier_len = 10;
> > +
> > +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc) {
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct random_desc *rnd_desc = NULL;
> > +	size_t len = 0;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +	len = fetch_rnd_data->key_len;
> > +
> > +	/* command 0x82500000 */
> > +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> > +			OP_ALG_ALGSEL_RNG);
> > +	/* command 0x60340000 | len */
> > +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> > +	append_ptr(desc, rnd_desc->rnd_data); }
> > +
> > +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_encap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_encapdesc;
> > +	struct sk_red_blob_encap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_encap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> > +			  0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> > +			   red_blob_req->redblob_sz, 0);
> > +
> > +	/* RedBlob encapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct
> > +sk_desc *skdesc)
> > + * brief CAAM Descriptor creator from redblob to plaindata.
> > + * param[in] skreq Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure  */
> > +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_decap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_decapdesc;
> > +	struct sk_red_blob_decap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_decap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> > +			  red_blob_req->redblob_sz, 0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> > +			   red_blob_req->data_sz, 0);
> > +
> > +	/* RedBlob decapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > + *			      struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > +			   struct sk_desc *skdesc)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data;
> > +	struct random_desc *rnd_desc;
> > +
> > +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> > +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> > +
> > +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_random_map_fail;
> > +	}
> > +	return 0;
> > +
> > +sk_random_map_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > + *					struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_encap *red_blob_encap;
> > +	struct redblob_encap_desc *red_blob_desc;
> > +
> > +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> > +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> > +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_redblob_fail:
> > +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> > +			 DMA_TO_DEVICE);
> > +sk_data_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* static int caam_sk_redblob_decap_map(struct device *dev,
> > + *					    struct sk_req *req,
> > + *					    struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_decap *red_blob_decap;
> > +	struct redblob_decap_desc *red_blob_desc;
> > +
> > +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> > +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> > +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_data_fail:
> > +	dma_unmap_single(dev, red_blob_desc->redblob,
> > +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +sk_redblob_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* @fn void securekey_unmap(struct device *dev,
> > + *			    struct sk_desc *skdesc, struct sk_req *req)
> > + * @brief DMA unmap the buffer pointers.
> > + * @param[in] dev Pointer to job ring device structure
> > + * @param[in] skdesc Pointer to secure key descriptor structure
> > + * @param[in] req Pointer to secure key request structure  */ void
> > +securekey_unmap(struct device *dev,
> > +		     struct sk_desc *skdesc, struct sk_req *req) {
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			struct sk_fetch_rnd_data *fetch_rnd_data;
> > +			struct random_desc *rnd_desc;
> > +
> > +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +			rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, rnd_desc->rnd_data,
> > +					 fetch_rnd_data->key_len,
> > +					 DMA_FROM_DEVICE);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			struct sk_red_blob_encap *red_blob_encap;
> > +			struct redblob_encap_desc *red_blob_desc;
> > +
> > +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->in_data,
> > +					 red_blob_encap->data_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_encap->redblob_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	case sk_red_blob_dec:
> > +		{
> > +			struct sk_red_blob_decap *red_blob_decap;
> > +			struct redblob_decap_desc *red_blob_desc;
> > +
> > +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_decap->redblob_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->out_data,
> > +					 red_blob_decap->data_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	default:
> > +		dev_err(dev, "Unable to find request type\n");
> > +		break;
> > +	}
> > +	kfree(skdesc);
> > +}
> > +
> > +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req
> > +*req)
> > + *  brief CAAM Descriptor creator for secure key operations.
> > + *  param[in] dev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> > +{
> > +	struct sk_desc *skdesc = NULL;
> > +	int ret = 0;
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam get_random map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			caam_sk_rng_desc(req, skdesc);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_encap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to create redblob from data. */
> > +			caam_sk_redblob_encap_desc(req, skdesc);
> > +			break;
> > +		}
> > +
> > +	case sk_red_blob_dec:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_decap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to decap data from redblob. */
> > +			caam_sk_redblob_decap_desc(req, skdesc);
> > +			break;
> > +		}
> > +	default:
> > +		pr_debug("Unknown request type\n");
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	req->desc_pointer = (void *)skdesc;
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> > + *			     void *context)
> > + * brief callback function to be called when descriptor executed.
> > + * param[in] dev Pointer to device structure
> > + * param[in] desc descriptor pointer
> > + * param[in] ret return status of Job submitted
> > + * param[in] context void pointer
> > + */
> > +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> > +			 void *context)
> > +{
> > +	struct sk_req *req = context;
> > +
> > +	if (ret) {
> > +		dev_err(dev, "caam op done err: %x\n", ret);
> > +		/* print the error source name. */
> > +		caam_jr_strstatus(dev, ret);
> > +	}
> > +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> > +	securekey_unmap(dev, req->desc_pointer, req);
> > +
> > +	req->ret = ret;
> > +	complete(&req->comp);
> > +}
> > +
> > +
> > +/*  static int sk_job_submit(struct device *jrdev, struct sk_req
> > +*req)
> > + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> > + *  param[in] jrdev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +static int sk_job_submit(struct device *jrdev, struct sk_req *req) {
> > +	int ret;
> > +
> > +	init_completion(&req->comp);
> > +
> > +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> > +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> > +	if (!ret)
> > +		wait_for_completion_interruptible(&req->comp);
> > +
> > +	ret = req->ret;
> > +	return ret;
> > +}
> > +
> > +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > + *		   struct device *dev)
> > + * Create the random number of the specified length using CAAM block
> > + * param[in]: out pointer to place the random bytes
> > + * param[in]: length for the random data bytes.
> > + * param[in]: dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct sk_req *req = NULL;
> > +	int ret = 0;
> > +	void *temp = NULL;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->type = fetch_rnd;
> > +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> > +
> > +	/* initialise with key length */
> > +	fetch_rnd_data->key_len = p->key_len;
> > +
> > +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +	fetch_rnd_data->data = temp;
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (req)
> > +		kfree(req);
> > +
> > +	if (temp)
> > +		kfree(temp);
> > +
> > +	return ret;
> > +}
> > +
> > +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> > + *		struct device *dev)
> > + * Deblobify the blob to get the key data and fill in secure key
> > +payload struct
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev)
> > +{
> > +	unsigned int blob_len;
> > +	struct sk_red_blob_decap *d_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	d_blob = &(req->req_u.sk_red_blob_decap);
> > +	blob_len = p->blob_len;
> > +	req->type = decap_type;
> > +
> > +	/*
> > +	 * Red blob size is the blob_len filled in payload struct
> > +	 * Data_sz i.e. key is the blob_len - blob header size
> > +	 */
> > +
> > +	d_blob->redblob_sz = blob_len;
> > +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> > +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	d_blob->redblob = temp;
> > +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> > +	memcpy(d_blob->redblob, p->blob, blob_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init: Failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->key_len = d_blob->data_sz;
> > +		memcpy(p->key, d_blob->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(temp);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +}
> > +
> > +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > + *		struct device *dev)
> > + * To blobify the key data to get the blob. This blob can only be
> > +seen by
> > + * userspace.
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev)
> > +{
> > +	unsigned int key_len;
> > +	struct sk_red_blob_encap *k_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	key_len = p->key_len;
> > +
> > +	req->type = encap_type;
> > +	k_blob = &(req->req_u.sk_red_blob_encap);
> > +
> > +	/*
> > +	 * Data_sz i.e. key len and the corresponding blob_len is
> > +	 * key_len + BLOB header size.87ea58433208
> > +	 */
> > +
> > +	k_blob->data_sz = key_len;
> > +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> > +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	k_blob->data = temp;
> > +
> > +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> > +	memcpy(k_blob->data, p->key, key_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->blob_len = k_blob->redblob_sz;
> > +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(req->mem_pointer);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +
> > +}
> > +
> > diff --git a/security/keys/securekey_desc.h
> > b/security/keys/securekey_desc.h new file mode 100644 index
> > 000000000000..0ee26e95b205
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.h
> > @@ -0,0 +1,141 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright 2018 NXP
> > + *
> > + */
> > +#ifndef _SECUREKEY_DESC_H_
> > +#define _SECUREKEY_DESC_H_
> > +
> > +#include "compat.h"
> > +#include "regs.h"
> > +#include "intern.h"
> > +#include "desc.h"
> > +#include "desc_constr.h"
> > +#include "jr.h"
> > +#include "error.h"
> > +#include "pdb.h"
> > +
> > +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> > +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> > +
> > +/*
> > + * brief defines different kinds of operations supported by this module.
> > + */
> > +enum sk_req_type {
> > +	sk_get_random,
> > +	sk_red_blob_enc,
> > +	sk_red_blob_dec,
> > +};
> > +
> > +
> > +/*
> > + * struct random_des
> > + * param[out] rnd_data output buffer for random data.
> > + */
> > +struct random_desc {
> > +	dma_addr_t rnd_data;
> > +};
> > +
> > +/* struct redblob_encap_desc
> > + * details Structure containing dma address for redblob encapsulation.
> > + * param[in] in_data input data to redblob encap descriptor.
> > + * param[out] redblob output buffer for redblob.
> > + */
> > +struct redblob_encap_desc {
> > +	dma_addr_t in_data;
> > +	dma_addr_t redblob;
> > +};
> > +
> > +/* struct redblob_decap_desc
> > + * details Structure containing dma address for redblob decapsulation.
> > + * param[in] redblob input buffer to redblob decap descriptor.
> > + * param[out] out_data output data from redblob decap descriptor.
> > + */
> > +struct redblob_decap_desc {
> > +	dma_addr_t redblob;
> > +	dma_addr_t out_data;
> > +};
> > +
> > +/* struct sk_desc
> > + * details Structure for securekey descriptor creation.
> > + * param[in] req_type operation supported.
> > + * param[in] dma_u union of struct for supported operation.
> > + */
> > +struct sk_desc {
> > +	u32 req_type;
> > +	union {
> > +		struct redblob_encap_desc redblob_encapdesc;
> > +		struct redblob_decap_desc redblob_decapdesc;
> > +		struct random_desc random_descp;
> > +	} dma_u;
> > +};
> > +
> > +/* struct sk_fetch_rnd_data
> > + * decriptor structure containing key length.
> > + */
> > +struct sk_fetch_rnd_data {
> > +	void *data;
> > +	size_t key_len;
> > +};
> > +
> > +/* struct sk_red_blob_encap
> > + * details Structure containing buffer pointers for redblob encapsulation.
> > + * param[in] data Input data.
> > + * param[in] data_sz size of Input data.
> > + * param[out] redblob output buffer for redblob.
> > + * param[in] redblob_sz size of redblob.
> > + */
> > +struct sk_red_blob_encap {
> > +	void *data;
> > +	uint32_t data_sz;
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +};
> > +
> > +/* struct sk_red_blob_decap
> > + * details Structure containing buffer pointers for redblob decapsulation.
> > + * param[in] redblob Input redblob.
> > + * param[in] redblob_sz size of redblob.
> > + * param[out] data output buffer for data.
> > + * param[in] data_sz size of output data.
> > + */
> > +struct sk_red_blob_decap {
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +	void *data;
> > +	uint32_t data_sz;
> > +};
> > +
> > +/* struct sk_req
> > + * details Structure for securekey request creation.
> > + * param[in] type operation supported.
> > + * param[in] req_u union of struct for supported operation.
> > + * param[out] ret return status of CAAM operation.
> > + * param[in] mem_pointer memory pointer for allocated kernel memory.
> > + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> > + * param[in] comp struct completion object.
> > + * param[in] hwdesc contains descriptor instructions.
> > + */
> > +struct sk_req {
> > +	enum sk_req_type type;
> > +	void *arg;
> > +	union {
> > +		struct sk_red_blob_encap sk_red_blob_encap;
> > +		struct sk_red_blob_decap sk_red_blob_decap;
> > +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> > +	} req_u;
> > +	int ret;
> > +	void *mem_pointer;
> > +	void *desc_pointer;
> > +	struct completion comp;
> > +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> > +};
> > +
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev);
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev);
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev);
> > +
> > +#endif /*_SECUREKEY_DESC_H_*/


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 12:31     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-24 12:31 UTC (permalink / raw)
  To: linux-security-module

> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > Secure keys are derieved using CAAM crypto block.
> >
> > Secure keys derieved are the random number symmetric keys from CAAM.
> > Blobs corresponding to the key are formed using CAAM. User space will
> > only be able to view the blob of the key.
> 
> The term "trusted keys" comes from the usage of the Trusted Platform Module
> (TPM). ??The term "trusted" now also refers to keyrings, which has nothing to do with a
> TPM.
> 
> What is the correlation between the term "secure keys" and CAAM? ??Are "secure keys", as
> defined in this patch, limited to a specific HW crypto device?
> 
> Mimi
> 

Yes the secure keys and CAAM are correlated. Secure keys depends on NXP CAAM crypto HW
accelerator. Secure key is a random data of length X (passed using keyctl command) & derived
using CAAM. Blob of this data is also created using CAAM. Only blob is visible to user space.

Regards,
Udit 

> >
> > Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> > Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> > ---
> >  Documentation/security/keys/secure-key.rst |  67 +++
> >  MAINTAINERS                                |  11 +
> >  include/keys/secure-type.h                 |  33 ++
> >  security/keys/Kconfig                      |  11 +
> >  security/keys/Makefile                     |   3 +
> >  security/keys/secure_key.c                 | 339 ++++++++++++
> >  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
> >  security/keys/securekey_desc.h             | 141 +++++
> >  8 files changed, 1211 insertions(+)
> >  create mode 100644 Documentation/security/keys/secure-key.rst
> >  create mode 100644 include/keys/secure-type.h  create mode 100644
> > security/keys/secure_key.c  create mode 100644
> > security/keys/securekey_desc.c  create mode 100644
> > security/keys/securekey_desc.h
> >
> > diff --git a/Documentation/security/keys/secure-key.rst
> > b/Documentation/security/keys/secure-key.rst
> > new file mode 100644
> > index 000000000000..0fc3367b00f8
> > --- /dev/null
> > +++ b/Documentation/security/keys/secure-key.rst
> > @@ -0,0 +1,67 @@
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> > +
> > +Usage::
> > +
> > +	keyctl add secure <name> "new <keylen>" <ring>
> > +	keyctl load secure <name> "load <hex_blob>" <ring>
> > +	keyctl print <key_id>
> > +
> > +"keyctl add secure" option will create the random data of the
> > +specified key len using CAAM and store it as a key in kernel.
> > +Key contents will be displayed as blobs to the user in hex ascii.
> > +User can input key len from 32 bytes to 128 bytes.
> > +
> > +"keyctl load secure" option will load the blob contents. In kernel,
> > +key will be deirved using input blob and CAAM, along with the secret
> > +key stored in CAAM.
> > +
> > +"keyctl print" will return the hex string of the blob corresponding
> > +to key_id. Returned blob will be of key_len + 48 bytes. Extra 48
> > +bytes are the header bytes added by the CAAM.
> > +
> > +Example of secure key usage::
> > +
> > +1. Create the secure key with name kmk-master of length 32 bytes::
> > +
> > +	$ keyctl add secure kmk-master "new 32" @u
> > +	46001928
> > +
> > +	$keyctl show
> > +	Session Keyring
> > +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> > +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> > +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> > +
> > +2. Print the blob contents for the kmk-master key::
> > +
> > +	$ keyctl print 46001928
> > +	d9743445b640f3d59c1670dddc0bc9c2
> > +	34fc9aab7dd05c965e6120025012f029b
> > +	07faa4776c4f6ed02899e35a135531e9a
> > +	6e5c2b51132f9d5aef28f68738e658296
> > +	3fe583177cfe50d2542b659a13039
> > +
> > +	$ keyctl pipe 46001928 > secure_key.blob
> > +
> > +3. Load the blob in the user key ring::
> > +
> > +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 9fd5e8808208..654be2ee4b0a 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
> >  F:	security/keys/trusted.c
> >  F:	security/keys/trusted.h
> >
> > +KEYS-SECURE
> > +M:	Udit Agarwal <udit.agarwal@nxp.com>
> > +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> > +L:	linux-security-module at vger.kernel.org
> > +L:	keyrings at vger.kernel.org
> > +S:	Supported
> > +F:	include/keys/secure-type.h
> > +F:	security/keys/secure_key.c
> > +F:	security/keys/securekey_desc.c
> > +F:	security/keys/securekey_desc.h
> > +
> >  KEYS/KEYRINGS:
> >  M:	David Howells <dhowells@redhat.com>
> >  L:	keyrings at vger.kernel.org
> > diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> > new file mode 100644 index 000000000000..5b7a5f144e41
> > --- /dev/null
> > +++ b/include/keys/secure-type.h
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2018 NXP.
> > + *
> > + */
> > +
> > +#ifndef _KEYS_SECURE_TYPE_H
> > +#define _KEYS_SECURE_TYPE_H
> > +
> > +#include <linux/key.h>
> > +#include <linux/rcupdate.h>
> > +
> > +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> > + * is 128 bytes.
> > + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> > + */
> > +
> > +#define MIN_KEY_SIZE                    32
> > +#define MAX_KEY_SIZE                    128
> > +#define BLOB_HEADER_SIZE		48
> > +
> > +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> > +
> > +struct secure_key_payload {
> > +	struct rcu_head rcu;
> > +	unsigned int key_len;
> > +	unsigned int blob_len;
> > +	unsigned char key[MAX_KEY_SIZE + 1];
> > +	unsigned char blob[MAX_BLOB_SIZE];
> > +};
> > +
> > +extern struct key_type key_type_secure; #endif
> > diff --git a/security/keys/Kconfig b/security/keys/Kconfig index
> > 6462e6654ccf..7eb138b5a54f 100644
> > --- a/security/keys/Kconfig
> > +++ b/security/keys/Kconfig
> > @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> >
> >  	  If you are unsure as to whether this is required, answer N.
> >
> > +config SECURE_KEYS
> > +	tristate "SECURE_KEYS"
> > +	depends on KEYS && CRYPTO_DEV_FSL_CAAM &&
> CRYPTO_DEV_FSL_CAAM_JR
> > +	help
> > +	  This option provide support for creating secure-type key and blobs
> > +	  in kernel. Secure keys are random number symmetric keys generated
> > +	  from CAAM. The CAAM creates the blobs for the random key.
> > +	  Userspace will only be able to see the blob.
> > +
> > +	  If you are unsure as to whether this is required, answer N.
> > +
> >  config ENCRYPTED_KEYS
> >  	tristate "ENCRYPTED KEYS"
> >  	depends on KEYS
> > diff --git a/security/keys/Makefile b/security/keys/Makefile index
> > ef1581b337a3..606ba4efb9e6 100644
> > --- a/security/keys/Makefile
> > +++ b/security/keys/Makefile
> > @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o  #
> >  obj-$(CONFIG_BIG_KEYS) += big_key.o
> >  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> > +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> > +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> > +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
> >  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ diff --git
> > a/security/keys/secure_key.c b/security/keys/secure_key.c new file
> > mode 100644 index 000000000000..ec8ad4394549
> > --- /dev/null
> > +++ b/security/keys/secure_key.c
> > @@ -0,0 +1,339 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (C) 2018 NXP
> > + * Secure key is generated using NXP CAAM hardware block. CAAM
> > +generates the
> > + * random number (used as a key) and creates its blob for the user.
> > + */
> > +
> > +#include <linux/slab.h>
> > +#include <linux/parser.h>
> > +#include <linux/string.h>
> > +#include <linux/key-type.h>
> > +#include <linux/rcupdate.h>
> > +#include <keys/secure-type.h>
> > +#include <linux/completion.h>
> > +
> > +#include "securekey_desc.h"
> > +
> > +static const char hmac_alg[] = "hmac(sha1)"; static const char
> > +hash_alg[] = "sha1";
> > +
> > +static struct crypto_shash *hashalg;
> > +static struct crypto_shash *hmacalg;
> > +
> > +enum {
> > +	error = -1,
> > +	new_key,
> > +	load_blob,
> > +};
> > +
> > +static const match_table_t key_tokens = {
> > +	{new_key, "new"},
> > +	{load_blob, "load"},
> > +	{error, NULL}
> > +};
> > +
> > +static struct secure_key_payload *secure_payload_alloc(struct key
> > +*key) {
> > +	struct secure_key_payload *sec_key = NULL;
> > +	int ret = 0;
> > +
> > +	ret = key_payload_reserve(key, sizeof(*sec_key));
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> > +	if (!sec_key)
> > +		goto out;
> > +
> > +out:
> > +	return sec_key;
> > +}
> > +
> > +/*
> > + * parse_inputdata - parse the keyctl input data and fill in the
> > + *		     payload structure for key or its blob.
> > + * param[in]: data pointer to the data to be parsed for creating key.
> > + * param[in]: p pointer to secure key payload structure to fill
> > +parsed data
> > + * On success returns 0, otherwise -EINVAL.
> > + */
> > +static int parse_inputdata(char *data, struct secure_key_payload *p)
> > +{
> > +	substring_t args[MAX_OPT_ARGS];
> > +	long keylen = 0;
> > +	int ret = -EINVAL;
> > +	int key_cmd = -EINVAL;
> > +	char *c = NULL;
> > +
> > +	c = strsep(&data, " \t");
> > +	if (!c) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	/* Get the keyctl command i.e. new_key or load_blob etc */
> > +	key_cmd = match_token(c, key_tokens, args);
> > +
> > +	switch (key_cmd) {
> > +	case new_key:
> > +		/* first argument is key size */
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = kstrtol(c, 10, &keylen);
> > +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> > +						keylen > MAX_KEY_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		p->key_len = keylen;
> > +		ret = new_key;
> > +
> > +		break;
> > +	case load_blob:
> > +		/* first argument is blob data for CAAM*/
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		/* Blob_len = No of characters in blob/2 */
> > +		p->blob_len = strlen(c) / 2;
> > +		if (p->blob_len > MAX_BLOB_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = hex2bin(p->blob, c, p->blob_len);
> > +		if (ret < 0) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +		ret = load_blob;
> > +
> > +		break;
> > +	case error:
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_instantiate - create a new secure type key.
> > + * Supports the operation to generate a new key. A random number
> > + * is generated from CAAM as key data and the corresponding red blob
> > + * is formed and stored as key_blob.
> > + * Also supports the operation to load the blob and key is derived
> > +using
> > + * that blob from CAAM.
> > + * On success, return 0. Otherwise return errno.
> > + */
> > +static int secure_instantiate(struct key *key,
> > +		struct key_preparsed_payload *prep) {
> > +	struct secure_key_payload *payload = NULL;
> > +	size_t datalen = prep->datalen;
> > +	char *data = NULL;
> > +	int key_cmd = 0;
> > +	int ret = 0;
> > +	enum sk_req_type sk_op_type;
> > +	struct device *dev = NULL;
> > +
> > +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	data = kmalloc(datalen + 1, GFP_KERNEL);
> > +	if (!data) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	memcpy(data, prep->data, datalen);
> > +	data[datalen] = '\0';
> > +
> > +	payload = secure_payload_alloc(key);
> > +	if (!payload) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	/* Allocate caam job ring for operation to be performed from CAAM */
> > +	dev = caam_jr_alloc();
> > +	if (!dev) {
> > +		pr_info("caam_jr_alloc failed\n");
> > +		ret = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	key_cmd = parse_inputdata(data, payload);
> > +	if (key_cmd < 0) {
> > +		ret = key_cmd;
> > +		goto out;
> > +	}
> > +
> > +	switch (key_cmd) {
> > +	case load_blob:
> > +		/*
> > +		 * Red blob decryption to be done for load operation
> > +		 * to derive the key.
> > +		 */
> > +		sk_op_type = sk_red_blob_dec;
> > +		ret = key_deblob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	case new_key:
> > +		/* Get Random number from caam of the specified length */
> > +		sk_op_type = sk_get_random;
> > +		ret = caam_get_random(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: get_random fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +
> > +		/* Generate red blob of key random bytes with CAAM */
> > +		sk_op_type = sk_red_blob_enc;
> > +		ret = key_blob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	default:
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +out:
> > +	if (data)
> > +		kzfree(data);
> > +	if (dev)
> > +		caam_jr_free(dev);
> > +
> > +	if (!ret)
> > +		rcu_assign_keypointer(key, payload);
> > +	else
> > +		kzfree(payload);
> > +
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_read - copy the  blob data to userspace in hex.
> > + * param[in]: key pointer to key struct
> > + * param[in]: buffer pointer to user data for creating key
> > + * param[in]: buflen is the length of the buffer
> > + * On success, return to userspace the secure key data size.
> > + */
> > +static long secure_read(const struct key *key, char __user *buffer,
> > +			 size_t buflen)
> > +{
> > +	const struct secure_key_payload *p = NULL;
> > +	char *ascii_buf;
> > +	char *bufp;
> > +	int i;
> > +
> > +	p = dereference_key_locked(key);
> > +	if (!p)
> > +		return -EINVAL;
> > +
> > +	if (buffer && buflen >= 2 * p->blob_len) {
> > +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> > +		if (!ascii_buf)
> > +			return -ENOMEM;
> > +
> > +		bufp = ascii_buf;
> > +		for (i = 0; i < p->blob_len; i++)
> > +			bufp = hex_byte_pack(bufp, p->blob[i]);
> > +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> > +			kzfree(ascii_buf);
> > +			return -EFAULT;
> > +		}
> > +		kzfree(ascii_buf);
> > +	}
> > +	return 2 * p->blob_len;
> > +}
> > +
> > +/*
> > + * secure_destroy - clear and free the key's payload  */ static void
> > +secure_destroy(struct key *key) {
> > +	kzfree(key->payload.data[0]);
> > +}
> > +
> > +struct key_type key_type_secure = {
> > +	.name = "secure",
> > +	.instantiate = secure_instantiate,
> > +	.destroy = secure_destroy,
> > +	.read = secure_read,
> > +};
> > +EXPORT_SYMBOL_GPL(key_type_secure);
> > +
> > +static void secure_shash_release(void) {
> > +	if (hashalg)
> > +		crypto_free_shash(hashalg);
> > +	if (hmacalg)
> > +		crypto_free_shash(hmacalg);
> > +}
> > +
> > +static int __init secure_shash_alloc(void) {
> > +	int ret;
> > +
> > +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hmacalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hmac_alg);
> > +		return PTR_ERR(hmacalg);
> > +	}
> > +
> > +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hashalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hash_alg);
> > +		ret = PTR_ERR(hashalg);
> > +		goto hashalg_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +hashalg_fail:
> > +	crypto_free_shash(hmacalg);
> > +	return ret;
> > +}
> > +
> > +static int __init init_secure_key(void) {
> > +	int ret;
> > +
> > +	ret = secure_shash_alloc();
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = register_key_type(&key_type_secure);
> > +	if (ret < 0)
> > +		secure_shash_release();
> > +	return ret;
> > +}
> > +
> > +static void __exit cleanup_secure_key(void) {
> > +	secure_shash_release();
> > +	unregister_key_type(&key_type_secure);
> > +}
> > +
> > +late_initcall(init_secure_key);
> > +module_exit(cleanup_secure_key);
> > +
> > +MODULE_LICENSE("GPL");
> > diff --git a/security/keys/securekey_desc.c
> > b/security/keys/securekey_desc.c new file mode 100644 index
> > 000000000000..a4fa811a5753
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.c
> > @@ -0,0 +1,606 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 NXP
> > + *
> > + */
> > +
> > +#include <keys/secure-type.h>
> > +#include "securekey_desc.h"
> > +
> > +/* key modifier for blob encapsulation & decapsulation descriptor */
> > +u8 key_modifier[] = "SECURE_KEY";
> > +u32 key_modifier_len = 10;
> > +
> > +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc) {
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct random_desc *rnd_desc = NULL;
> > +	size_t len = 0;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +	len = fetch_rnd_data->key_len;
> > +
> > +	/* command 0x82500000 */
> > +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> > +			OP_ALG_ALGSEL_RNG);
> > +	/* command 0x60340000 | len */
> > +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> > +	append_ptr(desc, rnd_desc->rnd_data); }
> > +
> > +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_encap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_encapdesc;
> > +	struct sk_red_blob_encap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_encap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> > +			  0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> > +			   red_blob_req->redblob_sz, 0);
> > +
> > +	/* RedBlob encapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct
> > +sk_desc *skdesc)
> > + * brief CAAM Descriptor creator from redblob to plaindata.
> > + * param[in] skreq Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure  */
> > +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_decap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_decapdesc;
> > +	struct sk_red_blob_decap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_decap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> > +			  red_blob_req->redblob_sz, 0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> > +			   red_blob_req->data_sz, 0);
> > +
> > +	/* RedBlob decapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > + *			      struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > +			   struct sk_desc *skdesc)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data;
> > +	struct random_desc *rnd_desc;
> > +
> > +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> > +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> > +
> > +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_random_map_fail;
> > +	}
> > +	return 0;
> > +
> > +sk_random_map_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > + *					struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_encap *red_blob_encap;
> > +	struct redblob_encap_desc *red_blob_desc;
> > +
> > +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> > +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> > +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_redblob_fail:
> > +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> > +			 DMA_TO_DEVICE);
> > +sk_data_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* static int caam_sk_redblob_decap_map(struct device *dev,
> > + *					    struct sk_req *req,
> > + *					    struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_decap *red_blob_decap;
> > +	struct redblob_decap_desc *red_blob_desc;
> > +
> > +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> > +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> > +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_data_fail:
> > +	dma_unmap_single(dev, red_blob_desc->redblob,
> > +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +sk_redblob_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* @fn void securekey_unmap(struct device *dev,
> > + *			    struct sk_desc *skdesc, struct sk_req *req)
> > + * @brief DMA unmap the buffer pointers.
> > + * @param[in] dev Pointer to job ring device structure
> > + * @param[in] skdesc Pointer to secure key descriptor structure
> > + * @param[in] req Pointer to secure key request structure  */ void
> > +securekey_unmap(struct device *dev,
> > +		     struct sk_desc *skdesc, struct sk_req *req) {
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			struct sk_fetch_rnd_data *fetch_rnd_data;
> > +			struct random_desc *rnd_desc;
> > +
> > +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +			rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, rnd_desc->rnd_data,
> > +					 fetch_rnd_data->key_len,
> > +					 DMA_FROM_DEVICE);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			struct sk_red_blob_encap *red_blob_encap;
> > +			struct redblob_encap_desc *red_blob_desc;
> > +
> > +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->in_data,
> > +					 red_blob_encap->data_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_encap->redblob_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	case sk_red_blob_dec:
> > +		{
> > +			struct sk_red_blob_decap *red_blob_decap;
> > +			struct redblob_decap_desc *red_blob_desc;
> > +
> > +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_decap->redblob_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->out_data,
> > +					 red_blob_decap->data_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	default:
> > +		dev_err(dev, "Unable to find request type\n");
> > +		break;
> > +	}
> > +	kfree(skdesc);
> > +}
> > +
> > +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req
> > +*req)
> > + *  brief CAAM Descriptor creator for secure key operations.
> > + *  param[in] dev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> > +{
> > +	struct sk_desc *skdesc = NULL;
> > +	int ret = 0;
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam get_random map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			caam_sk_rng_desc(req, skdesc);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_encap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to create redblob from data. */
> > +			caam_sk_redblob_encap_desc(req, skdesc);
> > +			break;
> > +		}
> > +
> > +	case sk_red_blob_dec:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_decap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to decap data from redblob. */
> > +			caam_sk_redblob_decap_desc(req, skdesc);
> > +			break;
> > +		}
> > +	default:
> > +		pr_debug("Unknown request type\n");
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	req->desc_pointer = (void *)skdesc;
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> > + *			     void *context)
> > + * brief callback function to be called when descriptor executed.
> > + * param[in] dev Pointer to device structure
> > + * param[in] desc descriptor pointer
> > + * param[in] ret return status of Job submitted
> > + * param[in] context void pointer
> > + */
> > +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> > +			 void *context)
> > +{
> > +	struct sk_req *req = context;
> > +
> > +	if (ret) {
> > +		dev_err(dev, "caam op done err: %x\n", ret);
> > +		/* print the error source name. */
> > +		caam_jr_strstatus(dev, ret);
> > +	}
> > +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> > +	securekey_unmap(dev, req->desc_pointer, req);
> > +
> > +	req->ret = ret;
> > +	complete(&req->comp);
> > +}
> > +
> > +
> > +/*  static int sk_job_submit(struct device *jrdev, struct sk_req
> > +*req)
> > + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> > + *  param[in] jrdev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +static int sk_job_submit(struct device *jrdev, struct sk_req *req) {
> > +	int ret;
> > +
> > +	init_completion(&req->comp);
> > +
> > +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> > +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> > +	if (!ret)
> > +		wait_for_completion_interruptible(&req->comp);
> > +
> > +	ret = req->ret;
> > +	return ret;
> > +}
> > +
> > +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > + *		   struct device *dev)
> > + * Create the random number of the specified length using CAAM block
> > + * param[in]: out pointer to place the random bytes
> > + * param[in]: length for the random data bytes.
> > + * param[in]: dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct sk_req *req = NULL;
> > +	int ret = 0;
> > +	void *temp = NULL;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->type = fetch_rnd;
> > +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> > +
> > +	/* initialise with key length */
> > +	fetch_rnd_data->key_len = p->key_len;
> > +
> > +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +	fetch_rnd_data->data = temp;
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (req)
> > +		kfree(req);
> > +
> > +	if (temp)
> > +		kfree(temp);
> > +
> > +	return ret;
> > +}
> > +
> > +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> > + *		struct device *dev)
> > + * Deblobify the blob to get the key data and fill in secure key
> > +payload struct
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev)
> > +{
> > +	unsigned int blob_len;
> > +	struct sk_red_blob_decap *d_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	d_blob = &(req->req_u.sk_red_blob_decap);
> > +	blob_len = p->blob_len;
> > +	req->type = decap_type;
> > +
> > +	/*
> > +	 * Red blob size is the blob_len filled in payload struct
> > +	 * Data_sz i.e. key is the blob_len - blob header size
> > +	 */
> > +
> > +	d_blob->redblob_sz = blob_len;
> > +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> > +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	d_blob->redblob = temp;
> > +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> > +	memcpy(d_blob->redblob, p->blob, blob_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init: Failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->key_len = d_blob->data_sz;
> > +		memcpy(p->key, d_blob->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(temp);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +}
> > +
> > +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > + *		struct device *dev)
> > + * To blobify the key data to get the blob. This blob can only be
> > +seen by
> > + * userspace.
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev)
> > +{
> > +	unsigned int key_len;
> > +	struct sk_red_blob_encap *k_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	key_len = p->key_len;
> > +
> > +	req->type = encap_type;
> > +	k_blob = &(req->req_u.sk_red_blob_encap);
> > +
> > +	/*
> > +	 * Data_sz i.e. key len and the corresponding blob_len is
> > +	 * key_len + BLOB header size.87ea58433208
> > +	 */
> > +
> > +	k_blob->data_sz = key_len;
> > +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> > +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	k_blob->data = temp;
> > +
> > +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> > +	memcpy(k_blob->data, p->key, key_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->blob_len = k_blob->redblob_sz;
> > +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(req->mem_pointer);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +
> > +}
> > +
> > diff --git a/security/keys/securekey_desc.h
> > b/security/keys/securekey_desc.h new file mode 100644 index
> > 000000000000..0ee26e95b205
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.h
> > @@ -0,0 +1,141 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright 2018 NXP
> > + *
> > + */
> > +#ifndef _SECUREKEY_DESC_H_
> > +#define _SECUREKEY_DESC_H_
> > +
> > +#include "compat.h"
> > +#include "regs.h"
> > +#include "intern.h"
> > +#include "desc.h"
> > +#include "desc_constr.h"
> > +#include "jr.h"
> > +#include "error.h"
> > +#include "pdb.h"
> > +
> > +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> > +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> > +
> > +/*
> > + * brief defines different kinds of operations supported by this module.
> > + */
> > +enum sk_req_type {
> > +	sk_get_random,
> > +	sk_red_blob_enc,
> > +	sk_red_blob_dec,
> > +};
> > +
> > +
> > +/*
> > + * struct random_des
> > + * param[out] rnd_data output buffer for random data.
> > + */
> > +struct random_desc {
> > +	dma_addr_t rnd_data;
> > +};
> > +
> > +/* struct redblob_encap_desc
> > + * details Structure containing dma address for redblob encapsulation.
> > + * param[in] in_data input data to redblob encap descriptor.
> > + * param[out] redblob output buffer for redblob.
> > + */
> > +struct redblob_encap_desc {
> > +	dma_addr_t in_data;
> > +	dma_addr_t redblob;
> > +};
> > +
> > +/* struct redblob_decap_desc
> > + * details Structure containing dma address for redblob decapsulation.
> > + * param[in] redblob input buffer to redblob decap descriptor.
> > + * param[out] out_data output data from redblob decap descriptor.
> > + */
> > +struct redblob_decap_desc {
> > +	dma_addr_t redblob;
> > +	dma_addr_t out_data;
> > +};
> > +
> > +/* struct sk_desc
> > + * details Structure for securekey descriptor creation.
> > + * param[in] req_type operation supported.
> > + * param[in] dma_u union of struct for supported operation.
> > + */
> > +struct sk_desc {
> > +	u32 req_type;
> > +	union {
> > +		struct redblob_encap_desc redblob_encapdesc;
> > +		struct redblob_decap_desc redblob_decapdesc;
> > +		struct random_desc random_descp;
> > +	} dma_u;
> > +};
> > +
> > +/* struct sk_fetch_rnd_data
> > + * decriptor structure containing key length.
> > + */
> > +struct sk_fetch_rnd_data {
> > +	void *data;
> > +	size_t key_len;
> > +};
> > +
> > +/* struct sk_red_blob_encap
> > + * details Structure containing buffer pointers for redblob encapsulation.
> > + * param[in] data Input data.
> > + * param[in] data_sz size of Input data.
> > + * param[out] redblob output buffer for redblob.
> > + * param[in] redblob_sz size of redblob.
> > + */
> > +struct sk_red_blob_encap {
> > +	void *data;
> > +	uint32_t data_sz;
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +};
> > +
> > +/* struct sk_red_blob_decap
> > + * details Structure containing buffer pointers for redblob decapsulation.
> > + * param[in] redblob Input redblob.
> > + * param[in] redblob_sz size of redblob.
> > + * param[out] data output buffer for data.
> > + * param[in] data_sz size of output data.
> > + */
> > +struct sk_red_blob_decap {
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +	void *data;
> > +	uint32_t data_sz;
> > +};
> > +
> > +/* struct sk_req
> > + * details Structure for securekey request creation.
> > + * param[in] type operation supported.
> > + * param[in] req_u union of struct for supported operation.
> > + * param[out] ret return status of CAAM operation.
> > + * param[in] mem_pointer memory pointer for allocated kernel memory.
> > + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> > + * param[in] comp struct completion object.
> > + * param[in] hwdesc contains descriptor instructions.
> > + */
> > +struct sk_req {
> > +	enum sk_req_type type;
> > +	void *arg;
> > +	union {
> > +		struct sk_red_blob_encap sk_red_blob_encap;
> > +		struct sk_red_blob_decap sk_red_blob_decap;
> > +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> > +	} req_u;
> > +	int ret;
> > +	void *mem_pointer;
> > +	void *desc_pointer;
> > +	struct completion comp;
> > +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> > +};
> > +
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev);
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev);
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev);
> > +
> > +#endif /*_SECUREKEY_DESC_H_*/

????{.n?+???????+%???????\x17??w??{.n?+????{??????????v?^?)????w*\x1fjg???\x1e???????j??\a??G??????\f???j:+v???w?j?m?????\x1e??\x1e?w?????f???h?????????

^ permalink raw reply	[flat|nested] 32+ messages in thread

* RE: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 12:31     ` Udit Agarwal
  0 siblings, 0 replies; 32+ messages in thread
From: Udit Agarwal @ 2018-07-24 12:31 UTC (permalink / raw)
  To: Mimi Zohar, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

> On Fri, 2018-07-20 at 11:16 +0530, Udit Agarwal wrote:
> > Secure keys are derieved using CAAM crypto block.
> >
> > Secure keys derieved are the random number symmetric keys from CAAM.
> > Blobs corresponding to the key are formed using CAAM. User space will
> > only be able to view the blob of the key.
> 
> The term "trusted keys" comes from the usage of the Trusted Platform Module
> (TPM).  The term "trusted" now also refers to keyrings, which has nothing to do with a
> TPM.
> 
> What is the correlation between the term "secure keys" and CAAM?  Are "secure keys", as
> defined in this patch, limited to a specific HW crypto device?
> 
> Mimi
> 

Yes the secure keys and CAAM are correlated. Secure keys depends on NXP CAAM crypto HW
accelerator. Secure key is a random data of length X (passed using keyctl command) & derived
using CAAM. Blob of this data is also created using CAAM. Only blob is visible to user space.

Regards,
Udit 

> >
> > Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com>
> > Reviewed-by: Sahil Malhotra <sahil.malhotra@nxp.com>
> > ---
> >  Documentation/security/keys/secure-key.rst |  67 +++
> >  MAINTAINERS                                |  11 +
> >  include/keys/secure-type.h                 |  33 ++
> >  security/keys/Kconfig                      |  11 +
> >  security/keys/Makefile                     |   3 +
> >  security/keys/secure_key.c                 | 339 ++++++++++++
> >  security/keys/securekey_desc.c             | 606 +++++++++++++++++++++
> >  security/keys/securekey_desc.h             | 141 +++++
> >  8 files changed, 1211 insertions(+)
> >  create mode 100644 Documentation/security/keys/secure-key.rst
> >  create mode 100644 include/keys/secure-type.h  create mode 100644
> > security/keys/secure_key.c  create mode 100644
> > security/keys/securekey_desc.c  create mode 100644
> > security/keys/securekey_desc.h
> >
> > diff --git a/Documentation/security/keys/secure-key.rst
> > b/Documentation/security/keys/secure-key.rst
> > new file mode 100644
> > index 000000000000..0fc3367b00f8
> > --- /dev/null
> > +++ b/Documentation/security/keys/secure-key.rst
> > @@ -0,0 +1,67 @@
> > +==========
> > +Secure Key
> > +==========
> > +
> > +Secure key is the new type added to kernel key ring service.
> > +Secure key is a symmetric type key of minimum length 32 bytes and
> > +with maximum possible length to be 128 bytes. It is produced in
> > +kernel using the CAAM crypto engine. Userspace can only see the blob
> > +for the corresponding key. All the blobs are displayed or loaded in
> > +hex ascii.
> > +
> > +Secure key can only be created on platforms which supports CAAM
> > +hardware block. Secure key can also be used as a master key to create
> > +the encrypted keys along with the existing key types in kernel.
> > +
> > +Secure key uses CAAM hardware to generate the key and blobify its
> > +content for userspace. Generated blobs are tied up with the hardware
> > +secret key stored in CAAM, hence the same blob will not be able to
> > +de-blobify with the different secret key on another machine.
> > +
> > +Usage::
> > +
> > +	keyctl add secure <name> "new <keylen>" <ring>
> > +	keyctl load secure <name> "load <hex_blob>" <ring>
> > +	keyctl print <key_id>
> > +
> > +"keyctl add secure" option will create the random data of the
> > +specified key len using CAAM and store it as a key in kernel.
> > +Key contents will be displayed as blobs to the user in hex ascii.
> > +User can input key len from 32 bytes to 128 bytes.
> > +
> > +"keyctl load secure" option will load the blob contents. In kernel,
> > +key will be deirved using input blob and CAAM, along with the secret
> > +key stored in CAAM.
> > +
> > +"keyctl print" will return the hex string of the blob corresponding
> > +to key_id. Returned blob will be of key_len + 48 bytes. Extra 48
> > +bytes are the header bytes added by the CAAM.
> > +
> > +Example of secure key usage::
> > +
> > +1. Create the secure key with name kmk-master of length 32 bytes::
> > +
> > +	$ keyctl add secure kmk-master "new 32" @u
> > +	46001928
> > +
> > +	$keyctl show
> > +	Session Keyring
> > +	1030783626 --alswrv      0 65534  keyring: _uid_ses.0
> > +	 695927745 --alswrv      0 65534   \_ keyring: _uid.0
> > +	  46001928 --als-rv      0     0       \_ secure: kmk-master
> > +
> > +2. Print the blob contents for the kmk-master key::
> > +
> > +	$ keyctl print 46001928
> > +	d9743445b640f3d59c1670dddc0bc9c2
> > +	34fc9aab7dd05c965e6120025012f029b
> > +	07faa4776c4f6ed02899e35a135531e9a
> > +	6e5c2b51132f9d5aef28f68738e658296
> > +	3fe583177cfe50d2542b659a13039
> > +
> > +	$ keyctl pipe 46001928 > secure_key.blob
> > +
> > +3. Load the blob in the user key ring::
> > +
> > +	$ keyctl load secure kmk-master "load 'cat secure_key.blob'" @u
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 9fd5e8808208..654be2ee4b0a 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -7939,6 +7939,17 @@ F:	include/keys/trusted-type.h
> >  F:	security/keys/trusted.c
> >  F:	security/keys/trusted.h
> >
> > +KEYS-SECURE
> > +M:	Udit Agarwal <udit.agarwal@nxp.com>
> > +R:	Sahil Malhotra <sahil.malhotra@nxp.com>
> > +L:	linux-security-module@vger.kernel.org
> > +L:	keyrings@vger.kernel.org
> > +S:	Supported
> > +F:	include/keys/secure-type.h
> > +F:	security/keys/secure_key.c
> > +F:	security/keys/securekey_desc.c
> > +F:	security/keys/securekey_desc.h
> > +
> >  KEYS/KEYRINGS:
> >  M:	David Howells <dhowells@redhat.com>
> >  L:	keyrings@vger.kernel.org
> > diff --git a/include/keys/secure-type.h b/include/keys/secure-type.h
> > new file mode 100644 index 000000000000..5b7a5f144e41
> > --- /dev/null
> > +++ b/include/keys/secure-type.h
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (C) 2018 NXP.
> > + *
> > + */
> > +
> > +#ifndef _KEYS_SECURE_TYPE_H
> > +#define _KEYS_SECURE_TYPE_H
> > +
> > +#include <linux/key.h>
> > +#include <linux/rcupdate.h>
> > +
> > +/* Minimum key size to be used is 32 bytes and maximum key size fixed
> > + * is 128 bytes.
> > + * Blob size to be kept is Maximum key size + blob header added by CAAM.
> > + */
> > +
> > +#define MIN_KEY_SIZE                    32
> > +#define MAX_KEY_SIZE                    128
> > +#define BLOB_HEADER_SIZE		48
> > +
> > +#define MAX_BLOB_SIZE                   (MAX_KEY_SIZE + BLOB_HEADER_SIZE)
> > +
> > +struct secure_key_payload {
> > +	struct rcu_head rcu;
> > +	unsigned int key_len;
> > +	unsigned int blob_len;
> > +	unsigned char key[MAX_KEY_SIZE + 1];
> > +	unsigned char blob[MAX_BLOB_SIZE];
> > +};
> > +
> > +extern struct key_type key_type_secure; #endif
> > diff --git a/security/keys/Kconfig b/security/keys/Kconfig index
> > 6462e6654ccf..7eb138b5a54f 100644
> > --- a/security/keys/Kconfig
> > +++ b/security/keys/Kconfig
> > @@ -71,6 +71,17 @@ config TRUSTED_KEYS
> >
> >  	  If you are unsure as to whether this is required, answer N.
> >
> > +config SECURE_KEYS
> > +	tristate "SECURE_KEYS"
> > +	depends on KEYS && CRYPTO_DEV_FSL_CAAM &&
> CRYPTO_DEV_FSL_CAAM_JR
> > +	help
> > +	  This option provide support for creating secure-type key and blobs
> > +	  in kernel. Secure keys are random number symmetric keys generated
> > +	  from CAAM. The CAAM creates the blobs for the random key.
> > +	  Userspace will only be able to see the blob.
> > +
> > +	  If you are unsure as to whether this is required, answer N.
> > +
> >  config ENCRYPTED_KEYS
> >  	tristate "ENCRYPTED KEYS"
> >  	depends on KEYS
> > diff --git a/security/keys/Makefile b/security/keys/Makefile index
> > ef1581b337a3..606ba4efb9e6 100644
> > --- a/security/keys/Makefile
> > +++ b/security/keys/Makefile
> > @@ -28,4 +28,7 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o  #
> >  obj-$(CONFIG_BIG_KEYS) += big_key.o
> >  obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
> > +ccflags-$(CONFIG_SECURE_KEYS) += -I$(obj)/../../drivers/crypto/caam/
> > +obj-$(CONFIG_SECURE_KEYS) += securekey_desc.o
> > +obj-$(CONFIG_SECURE_KEYS) += secure_key.o
> >  obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ diff --git
> > a/security/keys/secure_key.c b/security/keys/secure_key.c new file
> > mode 100644 index 000000000000..ec8ad4394549
> > --- /dev/null
> > +++ b/security/keys/secure_key.c
> > @@ -0,0 +1,339 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (C) 2018 NXP
> > + * Secure key is generated using NXP CAAM hardware block. CAAM
> > +generates the
> > + * random number (used as a key) and creates its blob for the user.
> > + */
> > +
> > +#include <linux/slab.h>
> > +#include <linux/parser.h>
> > +#include <linux/string.h>
> > +#include <linux/key-type.h>
> > +#include <linux/rcupdate.h>
> > +#include <keys/secure-type.h>
> > +#include <linux/completion.h>
> > +
> > +#include "securekey_desc.h"
> > +
> > +static const char hmac_alg[] = "hmac(sha1)"; static const char
> > +hash_alg[] = "sha1";
> > +
> > +static struct crypto_shash *hashalg;
> > +static struct crypto_shash *hmacalg;
> > +
> > +enum {
> > +	error = -1,
> > +	new_key,
> > +	load_blob,
> > +};
> > +
> > +static const match_table_t key_tokens = {
> > +	{new_key, "new"},
> > +	{load_blob, "load"},
> > +	{error, NULL}
> > +};
> > +
> > +static struct secure_key_payload *secure_payload_alloc(struct key
> > +*key) {
> > +	struct secure_key_payload *sec_key = NULL;
> > +	int ret = 0;
> > +
> > +	ret = key_payload_reserve(key, sizeof(*sec_key));
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	sec_key = kzalloc(sizeof(*sec_key), GFP_KERNEL);
> > +	if (!sec_key)
> > +		goto out;
> > +
> > +out:
> > +	return sec_key;
> > +}
> > +
> > +/*
> > + * parse_inputdata - parse the keyctl input data and fill in the
> > + *		     payload structure for key or its blob.
> > + * param[in]: data pointer to the data to be parsed for creating key.
> > + * param[in]: p pointer to secure key payload structure to fill
> > +parsed data
> > + * On success returns 0, otherwise -EINVAL.
> > + */
> > +static int parse_inputdata(char *data, struct secure_key_payload *p)
> > +{
> > +	substring_t args[MAX_OPT_ARGS];
> > +	long keylen = 0;
> > +	int ret = -EINVAL;
> > +	int key_cmd = -EINVAL;
> > +	char *c = NULL;
> > +
> > +	c = strsep(&data, " \t");
> > +	if (!c) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	/* Get the keyctl command i.e. new_key or load_blob etc */
> > +	key_cmd = match_token(c, key_tokens, args);
> > +
> > +	switch (key_cmd) {
> > +	case new_key:
> > +		/* first argument is key size */
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = kstrtol(c, 10, &keylen);
> > +		if (ret < 0 || keylen < MIN_KEY_SIZE ||
> > +						keylen > MAX_KEY_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		p->key_len = keylen;
> > +		ret = new_key;
> > +
> > +		break;
> > +	case load_blob:
> > +		/* first argument is blob data for CAAM*/
> > +		c = strsep(&data, " \t");
> > +		if (!c) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		/* Blob_len = No of characters in blob/2 */
> > +		p->blob_len = strlen(c) / 2;
> > +		if (p->blob_len > MAX_BLOB_SIZE) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +
> > +		ret = hex2bin(p->blob, c, p->blob_len);
> > +		if (ret < 0) {
> > +			ret = -EINVAL;
> > +			goto out;
> > +		}
> > +		ret = load_blob;
> > +
> > +		break;
> > +	case error:
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_instantiate - create a new secure type key.
> > + * Supports the operation to generate a new key. A random number
> > + * is generated from CAAM as key data and the corresponding red blob
> > + * is formed and stored as key_blob.
> > + * Also supports the operation to load the blob and key is derived
> > +using
> > + * that blob from CAAM.
> > + * On success, return 0. Otherwise return errno.
> > + */
> > +static int secure_instantiate(struct key *key,
> > +		struct key_preparsed_payload *prep) {
> > +	struct secure_key_payload *payload = NULL;
> > +	size_t datalen = prep->datalen;
> > +	char *data = NULL;
> > +	int key_cmd = 0;
> > +	int ret = 0;
> > +	enum sk_req_type sk_op_type;
> > +	struct device *dev = NULL;
> > +
> > +	if (datalen <= 0 || datalen > 32767 || !prep->data) {
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	data = kmalloc(datalen + 1, GFP_KERNEL);
> > +	if (!data) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	memcpy(data, prep->data, datalen);
> > +	data[datalen] = '\0';
> > +
> > +	payload = secure_payload_alloc(key);
> > +	if (!payload) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	/* Allocate caam job ring for operation to be performed from CAAM */
> > +	dev = caam_jr_alloc();
> > +	if (!dev) {
> > +		pr_info("caam_jr_alloc failed\n");
> > +		ret = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	key_cmd = parse_inputdata(data, payload);
> > +	if (key_cmd < 0) {
> > +		ret = key_cmd;
> > +		goto out;
> > +	}
> > +
> > +	switch (key_cmd) {
> > +	case load_blob:
> > +		/*
> > +		 * Red blob decryption to be done for load operation
> > +		 * to derive the key.
> > +		 */
> > +		sk_op_type = sk_red_blob_dec;
> > +		ret = key_deblob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob decap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	case new_key:
> > +		/* Get Random number from caam of the specified length */
> > +		sk_op_type = sk_get_random;
> > +		ret = caam_get_random(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: get_random fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +
> > +		/* Generate red blob of key random bytes with CAAM */
> > +		sk_op_type = sk_red_blob_enc;
> > +		ret = key_blob(payload, sk_op_type, dev);
> > +		if (ret != 0) {
> > +			pr_info("secure_key: key_blob encap fail (%d)\n", ret);
> > +			goto out;
> > +		}
> > +		break;
> > +	default:
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +out:
> > +	if (data)
> > +		kzfree(data);
> > +	if (dev)
> > +		caam_jr_free(dev);
> > +
> > +	if (!ret)
> > +		rcu_assign_keypointer(key, payload);
> > +	else
> > +		kzfree(payload);
> > +
> > +	return ret;
> > +}
> > +
> > +/*
> > + * secure_read - copy the  blob data to userspace in hex.
> > + * param[in]: key pointer to key struct
> > + * param[in]: buffer pointer to user data for creating key
> > + * param[in]: buflen is the length of the buffer
> > + * On success, return to userspace the secure key data size.
> > + */
> > +static long secure_read(const struct key *key, char __user *buffer,
> > +			 size_t buflen)
> > +{
> > +	const struct secure_key_payload *p = NULL;
> > +	char *ascii_buf;
> > +	char *bufp;
> > +	int i;
> > +
> > +	p = dereference_key_locked(key);
> > +	if (!p)
> > +		return -EINVAL;
> > +
> > +	if (buffer && buflen >= 2 * p->blob_len) {
> > +		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
> > +		if (!ascii_buf)
> > +			return -ENOMEM;
> > +
> > +		bufp = ascii_buf;
> > +		for (i = 0; i < p->blob_len; i++)
> > +			bufp = hex_byte_pack(bufp, p->blob[i]);
> > +		if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
> > +			kzfree(ascii_buf);
> > +			return -EFAULT;
> > +		}
> > +		kzfree(ascii_buf);
> > +	}
> > +	return 2 * p->blob_len;
> > +}
> > +
> > +/*
> > + * secure_destroy - clear and free the key's payload  */ static void
> > +secure_destroy(struct key *key) {
> > +	kzfree(key->payload.data[0]);
> > +}
> > +
> > +struct key_type key_type_secure = {
> > +	.name = "secure",
> > +	.instantiate = secure_instantiate,
> > +	.destroy = secure_destroy,
> > +	.read = secure_read,
> > +};
> > +EXPORT_SYMBOL_GPL(key_type_secure);
> > +
> > +static void secure_shash_release(void) {
> > +	if (hashalg)
> > +		crypto_free_shash(hashalg);
> > +	if (hmacalg)
> > +		crypto_free_shash(hmacalg);
> > +}
> > +
> > +static int __init secure_shash_alloc(void) {
> > +	int ret;
> > +
> > +	hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hmacalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hmac_alg);
> > +		return PTR_ERR(hmacalg);
> > +	}
> > +
> > +	hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> > +	if (IS_ERR(hashalg)) {
> > +		pr_info("secure_key: could not allocate crypto %s\n",
> > +				hash_alg);
> > +		ret = PTR_ERR(hashalg);
> > +		goto hashalg_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +hashalg_fail:
> > +	crypto_free_shash(hmacalg);
> > +	return ret;
> > +}
> > +
> > +static int __init init_secure_key(void) {
> > +	int ret;
> > +
> > +	ret = secure_shash_alloc();
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = register_key_type(&key_type_secure);
> > +	if (ret < 0)
> > +		secure_shash_release();
> > +	return ret;
> > +}
> > +
> > +static void __exit cleanup_secure_key(void) {
> > +	secure_shash_release();
> > +	unregister_key_type(&key_type_secure);
> > +}
> > +
> > +late_initcall(init_secure_key);
> > +module_exit(cleanup_secure_key);
> > +
> > +MODULE_LICENSE("GPL");
> > diff --git a/security/keys/securekey_desc.c
> > b/security/keys/securekey_desc.c new file mode 100644 index
> > 000000000000..a4fa811a5753
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.c
> > @@ -0,0 +1,606 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018 NXP
> > + *
> > + */
> > +
> > +#include <keys/secure-type.h>
> > +#include "securekey_desc.h"
> > +
> > +/* key modifier for blob encapsulation & decapsulation descriptor */
> > +u8 key_modifier[] = "SECURE_KEY";
> > +u32 key_modifier_len = 10;
> > +
> > +void caam_sk_rng_desc(struct sk_req *skreq, struct sk_desc *skdesc) {
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct random_desc *rnd_desc = NULL;
> > +	size_t len = 0;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	fetch_rnd_data = &skreq->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +	len = fetch_rnd_data->key_len;
> > +
> > +	/* command 0x82500000 */
> > +	append_cmd(desc, CMD_OPERATION | OP_TYPE_CLASS1_ALG |
> > +			OP_ALG_ALGSEL_RNG);
> > +	/* command 0x60340000 | len */
> > +	append_cmd(desc, CMD_FIFO_STORE | FIFOST_TYPE_RNGSTORE | len);
> > +	append_ptr(desc, rnd_desc->rnd_data); }
> > +
> > +void caam_sk_redblob_encap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_encap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_encapdesc;
> > +	struct sk_red_blob_encap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_encap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->in_data, red_blob_req->data_sz,
> > +			  0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->redblob,
> > +			   red_blob_req->redblob_sz, 0);
> > +
> > +	/* RedBlob encapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct
> > +sk_desc *skdesc)
> > + * brief CAAM Descriptor creator from redblob to plaindata.
> > + * param[in] skreq Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure  */
> > +void caam_sk_redblob_decap_desc(struct sk_req *skreq, struct sk_desc
> > +*skdesc) {
> > +	struct redblob_decap_desc *red_blob_desc =
> > +					&skdesc->dma_u.redblob_decapdesc;
> > +	struct sk_red_blob_decap *red_blob_req =
> > +					&skreq->req_u.sk_red_blob_decap;
> > +	u32 *desc = skreq->hwdesc;
> > +
> > +	init_job_desc(desc, 0);
> > +
> > +	/* Load class 2 key with key modifier. */
> > +	append_key_as_imm(desc, key_modifier, key_modifier_len,
> > +			  key_modifier_len, CLASS_2 | KEY_DEST_CLASS_REG);
> > +
> > +	/* SEQ IN PTR Command. */
> > +	append_seq_in_ptr(desc, red_blob_desc->redblob,
> > +			  red_blob_req->redblob_sz, 0);
> > +
> > +	/* SEQ OUT PTR Command. */
> > +	append_seq_out_ptr(desc, red_blob_desc->out_data,
> > +			   red_blob_req->data_sz, 0);
> > +
> > +	/* RedBlob decapsulation PROTOCOL Command. */
> > +	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB); }
> > +
> > +/* int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > + *			      struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_get_random_map(struct device *dev, struct sk_req *req,
> > +			   struct sk_desc *skdesc)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data;
> > +	struct random_desc *rnd_desc;
> > +
> > +	fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +	rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +	rnd_desc->rnd_data = dma_map_single(dev, fetch_rnd_data->data,
> > +				fetch_rnd_data->key_len, DMA_FROM_DEVICE);
> > +
> > +	if (dma_mapping_error(dev, rnd_desc->rnd_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_random_map_fail;
> > +	}
> > +	return 0;
> > +
> > +sk_random_map_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > + *					struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_encap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_encap *red_blob_encap;
> > +	struct redblob_encap_desc *red_blob_desc;
> > +
> > +	red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +	red_blob_desc->in_data = dma_map_single(dev, red_blob_encap->data,
> > +					red_blob_encap->data_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->in_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_encap->redblob,
> > +				red_blob_encap->redblob_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_redblob_fail:
> > +	dma_unmap_single(dev, red_blob_desc->in_data, red_blob_encap->data_sz,
> > +			 DMA_TO_DEVICE);
> > +sk_data_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* static int caam_sk_redblob_decap_map(struct device *dev,
> > + *					    struct sk_req *req,
> > + *					    struct sk_desc *skdesc)
> > + * brief DMA map the buffer virtual pointers to physical address.
> > + * param[in] dev Pointer to job ring device structure
> > + * param[in] req Pointer to secure key request structure
> > + * param[in] skdesc Pointer to secure key descriptor structure
> > + * return 0 on success, error value otherwise.
> > + */
> > +int caam_sk_redblob_decap_map(struct device *dev, struct sk_req *req,
> > +			      struct sk_desc *skdesc)
> > +{
> > +	struct sk_red_blob_decap *red_blob_decap;
> > +	struct redblob_decap_desc *red_blob_desc;
> > +
> > +	red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +	red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +	red_blob_desc->redblob = dma_map_single(dev, red_blob_decap->redblob,
> > +				red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->redblob)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_redblob_fail;
> > +	}
> > +
> > +	red_blob_desc->out_data = dma_map_single(dev, red_blob_decap->data,
> > +				red_blob_decap->data_sz, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(dev, red_blob_desc->out_data)) {
> > +		dev_err(dev, "Unable to map memory\n");
> > +		goto sk_data_fail;
> > +	}
> > +
> > +	return 0;
> > +
> > +sk_data_fail:
> > +	dma_unmap_single(dev, red_blob_desc->redblob,
> > +			 red_blob_decap->redblob_sz, DMA_TO_DEVICE);
> > +sk_redblob_fail:
> > +	return -ENOMEM;
> > +}
> > +
> > +/* @fn void securekey_unmap(struct device *dev,
> > + *			    struct sk_desc *skdesc, struct sk_req *req)
> > + * @brief DMA unmap the buffer pointers.
> > + * @param[in] dev Pointer to job ring device structure
> > + * @param[in] skdesc Pointer to secure key descriptor structure
> > + * @param[in] req Pointer to secure key request structure  */ void
> > +securekey_unmap(struct device *dev,
> > +		     struct sk_desc *skdesc, struct sk_req *req) {
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			struct sk_fetch_rnd_data *fetch_rnd_data;
> > +			struct random_desc *rnd_desc;
> > +
> > +			fetch_rnd_data = &req->req_u.sk_fetch_rnd_data;
> > +			rnd_desc = &skdesc->dma_u.random_descp;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, rnd_desc->rnd_data,
> > +					 fetch_rnd_data->key_len,
> > +					 DMA_FROM_DEVICE);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			struct sk_red_blob_encap *red_blob_encap;
> > +			struct redblob_encap_desc *red_blob_desc;
> > +
> > +			red_blob_encap = &req->req_u.sk_red_blob_encap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_encapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->in_data,
> > +					 red_blob_encap->data_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_encap->redblob_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	case sk_red_blob_dec:
> > +		{
> > +			struct sk_red_blob_decap *red_blob_decap;
> > +			struct redblob_decap_desc *red_blob_desc;
> > +
> > +			red_blob_decap = &req->req_u.sk_red_blob_decap;
> > +			red_blob_desc = &skdesc->dma_u.redblob_decapdesc;
> > +
> > +			/* Unmap Descriptor buffer pointers. */
> > +			dma_unmap_single(dev, red_blob_desc->redblob,
> > +					 red_blob_decap->redblob_sz,
> > +					 DMA_TO_DEVICE);
> > +
> > +			dma_unmap_single(dev, red_blob_desc->out_data,
> > +					 red_blob_decap->data_sz,
> > +					 DMA_FROM_DEVICE);
> > +
> > +			break;
> > +		}
> > +	default:
> > +		dev_err(dev, "Unable to find request type\n");
> > +		break;
> > +	}
> > +	kfree(skdesc);
> > +}
> > +
> > +/*  int caam_securekey_desc_init(struct device *dev, struct sk_req
> > +*req)
> > + *  brief CAAM Descriptor creator for secure key operations.
> > + *  param[in] dev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +int caam_securekey_desc_init(struct device *dev, struct sk_req *req)
> > +{
> > +	struct sk_desc *skdesc = NULL;
> > +	int ret = 0;
> > +
> > +	switch (req->type) {
> > +	case sk_get_random:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_get_random_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam get_random map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +			caam_sk_rng_desc(req, skdesc);
> > +			break;
> > +		}
> > +	case sk_red_blob_enc:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_encap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_encap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to create redblob from data. */
> > +			caam_sk_redblob_encap_desc(req, skdesc);
> > +			break;
> > +		}
> > +
> > +	case sk_red_blob_dec:
> > +		{
> > +			skdesc = kmalloc(sizeof(*skdesc), GFP_DMA);
> > +			if (!skdesc) {
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			skdesc->req_type = req->type;
> > +
> > +			if (caam_sk_redblob_decap_map(dev, req, skdesc)) {
> > +				dev_err(dev, "caam redblob_decap map fail\n");
> > +				ret = -ENOMEM;
> > +				goto out;
> > +			}
> > +
> > +			/* Descriptor function to decap data from redblob. */
> > +			caam_sk_redblob_decap_desc(req, skdesc);
> > +			break;
> > +		}
> > +	default:
> > +		pr_debug("Unknown request type\n");
> > +		ret = -EINVAL;
> > +		goto out;
> > +	}
> > +
> > +	req->desc_pointer = (void *)skdesc;
> > +
> > +out:
> > +	return ret;
> > +}
> > +
> > +/* static void caam_op_done (struct device *dev, u32 *desc, u32 ret,
> > + *			     void *context)
> > + * brief callback function to be called when descriptor executed.
> > + * param[in] dev Pointer to device structure
> > + * param[in] desc descriptor pointer
> > + * param[in] ret return status of Job submitted
> > + * param[in] context void pointer
> > + */
> > +static void caam_op_done(struct device *dev, u32 *desc, u32 ret,
> > +			 void *context)
> > +{
> > +	struct sk_req *req = context;
> > +
> > +	if (ret) {
> > +		dev_err(dev, "caam op done err: %x\n", ret);
> > +		/* print the error source name. */
> > +		caam_jr_strstatus(dev, ret);
> > +	}
> > +	/* Call securekey_unmap function for unmapping the buffer pointers. */
> > +	securekey_unmap(dev, req->desc_pointer, req);
> > +
> > +	req->ret = ret;
> > +	complete(&req->comp);
> > +}
> > +
> > +
> > +/*  static int sk_job_submit(struct device *jrdev, struct sk_req
> > +*req)
> > + *  brief Enqueue a Job descriptor to Job ring and wait until SEC returns.
> > + *  param[in] jrdev Pointer to job ring device structure
> > + *  param[in] req Pointer to secure key request structure
> > + *  return 0 on success, error value otherwise.
> > + */
> > +static int sk_job_submit(struct device *jrdev, struct sk_req *req) {
> > +	int ret;
> > +
> > +	init_completion(&req->comp);
> > +
> > +	/* caam_jr_enqueue function for Enqueue a job descriptor */
> > +	ret = caam_jr_enqueue(jrdev, req->hwdesc, caam_op_done, req);
> > +	if (!ret)
> > +		wait_for_completion_interruptible(&req->comp);
> > +
> > +	ret = req->ret;
> > +	return ret;
> > +}
> > +
> > +/* caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > + *		   struct device *dev)
> > + * Create the random number of the specified length using CAAM block
> > + * param[in]: out pointer to place the random bytes
> > + * param[in]: length for the random data bytes.
> > + * param[in]: dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev)
> > +{
> > +	struct sk_fetch_rnd_data *fetch_rnd_data = NULL;
> > +	struct sk_req *req = NULL;
> > +	int ret = 0;
> > +	void *temp = NULL;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->type = fetch_rnd;
> > +	fetch_rnd_data = &(req->req_u.sk_fetch_rnd_data);
> > +
> > +	/* initialise with key length */
> > +	fetch_rnd_data->key_len = p->key_len;
> > +
> > +	temp = kmalloc(fetch_rnd_data->key_len, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +	fetch_rnd_data->data = temp;
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		memcpy(p->key, fetch_rnd_data->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (req)
> > +		kfree(req);
> > +
> > +	if (temp)
> > +		kfree(temp);
> > +
> > +	return ret;
> > +}
> > +
> > +/* key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type
> > + *		struct device *dev)
> > + * Deblobify the blob to get the key data and fill in secure key
> > +payload struct
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev)
> > +{
> > +	unsigned int blob_len;
> > +	struct sk_red_blob_decap *d_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	d_blob = &(req->req_u.sk_red_blob_decap);
> > +	blob_len = p->blob_len;
> > +	req->type = decap_type;
> > +
> > +	/*
> > +	 * Red blob size is the blob_len filled in payload struct
> > +	 * Data_sz i.e. key is the blob_len - blob header size
> > +	 */
> > +
> > +	d_blob->redblob_sz = blob_len;
> > +	d_blob->data_sz = blob_len - (SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ);
> > +	total_sz = d_blob->data_sz + d_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	d_blob->redblob = temp;
> > +	d_blob->data = d_blob->redblob + d_blob->redblob_sz;
> > +	memcpy(d_blob->redblob, p->blob, blob_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init: Failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->key_len = d_blob->data_sz;
> > +		memcpy(p->key, d_blob->data, p->key_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(temp);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +}
> > +
> > +/* key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > + *		struct device *dev)
> > + * To blobify the key data to get the blob. This blob can only be
> > +seen by
> > + * userspace.
> > + * param[in] p pointer to the secure key payload
> > + * param[in] decap_type operation to be done.
> > + * param[in] dev dev Pointer to job ring device structure
> > + * If operation is successful return 0, otherwise error.
> > + */
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev)
> > +{
> > +	unsigned int key_len;
> > +	struct sk_red_blob_encap *k_blob;
> > +	struct sk_req *req = NULL;
> > +	int total_sz = 0, *temp = NULL, ret = 0;
> > +
> > +	req = kmalloc(sizeof(struct sk_req), GFP_DMA);
> > +	if (!req) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	key_len = p->key_len;
> > +
> > +	req->type = encap_type;
> > +	k_blob = &(req->req_u.sk_red_blob_encap);
> > +
> > +	/*
> > +	 * Data_sz i.e. key len and the corresponding blob_len is
> > +	 * key_len + BLOB header size.87ea58433208
> > +	 */
> > +
> > +	k_blob->data_sz = key_len;
> > +	k_blob->redblob_sz = key_len + SK_BLOB_KEY_SZ + SK_BLOB_MAC_SZ;
> > +	total_sz = k_blob->data_sz + k_blob->redblob_sz;
> > +
> > +	temp = kmalloc(total_sz, GFP_DMA);
> > +	if (!temp) {
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	req->mem_pointer = temp;
> > +	k_blob->data = temp;
> > +
> > +	k_blob->redblob = k_blob->data + k_blob->data_sz;
> > +	memcpy(k_blob->data, p->key, key_len);
> > +
> > +	ret = caam_securekey_desc_init(dev, req);
> > +
> > +	if (ret) {
> > +		pr_info("caam_securekey_desc_init failed\n");
> > +		goto out;
> > +	}
> > +
> > +	ret = sk_job_submit(dev, req);
> > +	if (!ret) {
> > +		/*Copy output to key buffer. */
> > +		p->blob_len = k_blob->redblob_sz;
> > +		memcpy(p->blob, k_blob->redblob, p->blob_len);
> > +	} else {
> > +		ret = -EINVAL;
> > +	}
> > +
> > +out:
> > +	if (temp)
> > +		kfree(req->mem_pointer);
> > +	if (req)
> > +		kfree(req);
> > +	return ret;
> > +
> > +}
> > +
> > diff --git a/security/keys/securekey_desc.h
> > b/security/keys/securekey_desc.h new file mode 100644 index
> > 000000000000..0ee26e95b205
> > --- /dev/null
> > +++ b/security/keys/securekey_desc.h
> > @@ -0,0 +1,141 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright 2018 NXP
> > + *
> > + */
> > +#ifndef _SECUREKEY_DESC_H_
> > +#define _SECUREKEY_DESC_H_
> > +
> > +#include "compat.h"
> > +#include "regs.h"
> > +#include "intern.h"
> > +#include "desc.h"
> > +#include "desc_constr.h"
> > +#include "jr.h"
> > +#include "error.h"
> > +#include "pdb.h"
> > +
> > +#define SK_BLOB_KEY_SZ		32	/* Blob key size. */
> > +#define SK_BLOB_MAC_SZ		16	/* Blob MAC size. */
> > +
> > +/*
> > + * brief defines different kinds of operations supported by this module.
> > + */
> > +enum sk_req_type {
> > +	sk_get_random,
> > +	sk_red_blob_enc,
> > +	sk_red_blob_dec,
> > +};
> > +
> > +
> > +/*
> > + * struct random_des
> > + * param[out] rnd_data output buffer for random data.
> > + */
> > +struct random_desc {
> > +	dma_addr_t rnd_data;
> > +};
> > +
> > +/* struct redblob_encap_desc
> > + * details Structure containing dma address for redblob encapsulation.
> > + * param[in] in_data input data to redblob encap descriptor.
> > + * param[out] redblob output buffer for redblob.
> > + */
> > +struct redblob_encap_desc {
> > +	dma_addr_t in_data;
> > +	dma_addr_t redblob;
> > +};
> > +
> > +/* struct redblob_decap_desc
> > + * details Structure containing dma address for redblob decapsulation.
> > + * param[in] redblob input buffer to redblob decap descriptor.
> > + * param[out] out_data output data from redblob decap descriptor.
> > + */
> > +struct redblob_decap_desc {
> > +	dma_addr_t redblob;
> > +	dma_addr_t out_data;
> > +};
> > +
> > +/* struct sk_desc
> > + * details Structure for securekey descriptor creation.
> > + * param[in] req_type operation supported.
> > + * param[in] dma_u union of struct for supported operation.
> > + */
> > +struct sk_desc {
> > +	u32 req_type;
> > +	union {
> > +		struct redblob_encap_desc redblob_encapdesc;
> > +		struct redblob_decap_desc redblob_decapdesc;
> > +		struct random_desc random_descp;
> > +	} dma_u;
> > +};
> > +
> > +/* struct sk_fetch_rnd_data
> > + * decriptor structure containing key length.
> > + */
> > +struct sk_fetch_rnd_data {
> > +	void *data;
> > +	size_t key_len;
> > +};
> > +
> > +/* struct sk_red_blob_encap
> > + * details Structure containing buffer pointers for redblob encapsulation.
> > + * param[in] data Input data.
> > + * param[in] data_sz size of Input data.
> > + * param[out] redblob output buffer for redblob.
> > + * param[in] redblob_sz size of redblob.
> > + */
> > +struct sk_red_blob_encap {
> > +	void *data;
> > +	uint32_t data_sz;
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +};
> > +
> > +/* struct sk_red_blob_decap
> > + * details Structure containing buffer pointers for redblob decapsulation.
> > + * param[in] redblob Input redblob.
> > + * param[in] redblob_sz size of redblob.
> > + * param[out] data output buffer for data.
> > + * param[in] data_sz size of output data.
> > + */
> > +struct sk_red_blob_decap {
> > +	void *redblob;
> > +	uint32_t redblob_sz;
> > +	void *data;
> > +	uint32_t data_sz;
> > +};
> > +
> > +/* struct sk_req
> > + * details Structure for securekey request creation.
> > + * param[in] type operation supported.
> > + * param[in] req_u union of struct for supported operation.
> > + * param[out] ret return status of CAAM operation.
> > + * param[in] mem_pointer memory pointer for allocated kernel memory.
> > + * param[in] desc_pointer Pointer to securekey descriptor creation structure.
> > + * param[in] comp struct completion object.
> > + * param[in] hwdesc contains descriptor instructions.
> > + */
> > +struct sk_req {
> > +	enum sk_req_type type;
> > +	void *arg;
> > +	union {
> > +		struct sk_red_blob_encap sk_red_blob_encap;
> > +		struct sk_red_blob_decap sk_red_blob_decap;
> > +		struct sk_fetch_rnd_data sk_fetch_rnd_data;
> > +	} req_u;
> > +	int ret;
> > +	void *mem_pointer;
> > +	void *desc_pointer;
> > +	struct completion comp;
> > +	u32 hwdesc[MAX_CAAM_DESCSIZE];
> > +};
> > +
> > +int caam_get_random(struct secure_key_payload *p,  enum sk_req_type fetch_rnd,
> > +		    struct device *dev);
> > +int key_blob(struct secure_key_payload *p, enum sk_req_type encap_type,
> > +	     struct device *dev);
> > +int key_deblob(struct secure_key_payload *p, enum sk_req_type decap_type,
> > +	       struct device *dev);
> > +
> > +#endif /*_SECUREKEY_DESC_H_*/

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
  2018-07-24 12:31     ` Udit Agarwal
  (?)
  (?)
@ 2018-07-24 13:34       ` Mimi Zohar
  -1 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-24 13:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

On Tue, 2018-07-24 at 12:31 +0000, Udit Agarwal wrote:
> Yes the secure keys and CAAM are correlated. Secure keys depends on
> NXP CAAM crypto HW accelerator.  Secure key is a random data of
> length X (passed using keyctl command) & derived using CAAM. Blob of
> this data is also created using CAAM. Only blob is visible to user
> space.

The term "secure keys" is really generic.  What makes the "secure
keys" secure?  We introduced "trusted keys", because TPM 1.2 didn't
support symmetric keys.  We shouldn't just duplicate "trusted keys"
for different HW, but improve upon it (eg. symmetric keys never leave
the device).

The new key type should define generic methods, which are implemented
for NXP CAAM rypto HW accelerator as an example.

Mimi


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 13:34       ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-24 13:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

On Tue, 2018-07-24 at 12:31 +0000, Udit Agarwal wrote:
> Yes the secure keys and CAAM are correlated. Secure keys depends on
> NXP CAAM crypto HW accelerator.  Secure key is a random data of
> length X (passed using keyctl command) & derived using CAAM. Blob of
> this data is also created using CAAM. Only blob is visible to user
> space.

The term "secure keys" is really generic.  What makes the "secure
keys" secure?  We introduced "trusted keys", because TPM 1.2 didn't
support symmetric keys.  We shouldn't just duplicate "trusted keys"
for different HW, but improve upon it (eg. symmetric keys never leave
the device).

The new key type should define generic methods, which are implemented
for NXP CAAM rypto HW accelerator as an example.

Mimi


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 13:34       ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-24 13:34 UTC (permalink / raw)
  To: linux-security-module

On Tue, 2018-07-24 at 12:31 +0000, Udit Agarwal wrote:
> Yes the secure keys and CAAM are correlated. Secure keys depends on
> NXP CAAM crypto HW accelerator. ?Secure key is a random data of
> length X (passed using keyctl command) & derived using CAAM. Blob of
> this data is also created using CAAM. Only blob is visible to user
> space.

The term "secure keys" is really generic. ?What makes the "secure
keys" secure? ?We introduced "trusted keys", because TPM 1.2 didn't
support symmetric keys. ?We shouldn't just duplicate "trusted keys"
for different HW, but improve upon it (eg. symmetric keys never leave
the device).

The new key type should define generic methods, which are implemented
for NXP CAAM rypto HW accelerator as an example.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM.
@ 2018-07-24 13:34       ` Mimi Zohar
  0 siblings, 0 replies; 32+ messages in thread
From: Mimi Zohar @ 2018-07-24 13:34 UTC (permalink / raw)
  To: Udit Agarwal, dhowells, zohar, jmorris, serge, linux-integrity,
	keyrings, linux-security-module, linux-kernel
  Cc: Sahil Malhotra, Ruchika Gupta, Horia Geanta, Aymen Sghaier

On Tue, 2018-07-24 at 12:31 +0000, Udit Agarwal wrote:
> Yes the secure keys and CAAM are correlated. Secure keys depends on
> NXP CAAM crypto HW accelerator.  Secure key is a random data of
> length X (passed using keyctl command) & derived using CAAM. Blob of
> this data is also created using CAAM. Only blob is visible to user
> space.

The term "secure keys" is really generic.  What makes the "secure
keys" secure?  We introduced "trusted keys", because TPM 1.2 didn't
support symmetric keys.  We shouldn't just duplicate "trusted keys"
for different HW, but improve upon it (eg. symmetric keys never leave
the device).

The new key type should define generic methods, which are implemented
for NXP CAAM rypto HW accelerator as an example.

Mimi

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2018-07-24 14:41 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-20  5:46 [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM Udit Agarwal
2018-07-20  5:58 ` Udit Agarwal
2018-07-20  5:46 ` Udit Agarwal
2018-07-20  5:46 ` [PATCH 2/2] encrypted_keys: Adds support for secure key-type as master key Udit Agarwal
2018-07-20  5:58   ` Udit Agarwal
2018-07-20  5:46   ` Udit Agarwal
2018-07-20  8:40 ` [PATCH 1/2] security/keys/secure_key: Adds the secure key support based on CAAM Jan Lübbe
2018-07-20  8:40   ` Jan Lübbe
2018-07-20  8:40   ` Jan Lübbe
2018-07-21 14:44   ` Udit Agarwal
2018-07-21 14:44     ` Udit Agarwal
2018-07-21 14:44     ` Udit Agarwal
2018-07-21 14:44     ` Udit Agarwal
2018-07-23 12:42     ` Jan Lübbe
2018-07-23 12:42       ` Jan Lübbe
2018-07-23 12:42       ` Jan Lübbe
2018-07-23 12:42       ` Jan Lübbe
2018-07-20 18:37 ` kbuild test robot
2018-07-20 18:37   ` kbuild test robot
2018-07-20 18:37   ` kbuild test robot
2018-07-22 23:34 ` Mimi Zohar
2018-07-22 23:34   ` Mimi Zohar
2018-07-22 23:34   ` Mimi Zohar
2018-07-22 23:34   ` Mimi Zohar
2018-07-24 12:31   ` Udit Agarwal
2018-07-24 12:31     ` Udit Agarwal
2018-07-24 12:31     ` Udit Agarwal
2018-07-24 12:31     ` Udit Agarwal
2018-07-24 13:34     ` Mimi Zohar
2018-07-24 13:34       ` Mimi Zohar
2018-07-24 13:34       ` Mimi Zohar
2018-07-24 13:34       ` Mimi Zohar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.