diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/810-keys-0001-security-keys-secure_key-Adds-the-secure-key-support.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/810-keys-0001-security-keys-secure_key-Adds-the-secure-key-support.patch | 1285 |
1 files changed, 0 insertions, 1285 deletions
diff --git a/target/linux/layerscape/patches-5.4/810-keys-0001-security-keys-secure_key-Adds-the-secure-key-support.patch b/target/linux/layerscape/patches-5.4/810-keys-0001-security-keys-secure_key-Adds-the-secure-key-support.patch deleted file mode 100644 index 2347212a91..0000000000 --- a/target/linux/layerscape/patches-5.4/810-keys-0001-security-keys-secure_key-Adds-the-secure-key-support.patch +++ /dev/null @@ -1,1285 +0,0 @@ -From 808871b2943a386165614daf2e7f5fb5b33e9fd1 Mon Sep 17 00:00:00 2001 -From: Udit Agarwal <udit.agarwal@nxp.com> -Date: Wed, 4 Jul 2018 09:51:59 +0530 -Subject: [PATCH] security/keys/secure_key: Adds the secure key support based - on CAAM. - -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 | 5 + - security/keys/secure_key.c | 339 ++++++++++++++++ - security/keys/securekey_desc.c | 608 +++++++++++++++++++++++++++++ - security/keys/securekey_desc.h | 141 +++++++ - 8 files changed, 1215 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 - ---- /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 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 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -9075,6 +9075,17 @@ F: include/keys/trusted-type.h - F: security/keys/trusted.c - F: include/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> - M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> ---- /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 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -90,6 +90,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 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -29,4 +29,9 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += key - # - obj-$(CONFIG_BIG_KEYS) += big_key.o - obj-$(CONFIG_TRUSTED_KEYS) += trusted.o -+CFLAGS_secure_key.o += -I$(obj)/../../drivers/crypto/caam/ -+CFLAGS_securekey_desc.o += -I$(obj)/../../drivers/crypto/caam/ -+obj-$(CONFIG_SECURE_KEYS) += securekey.o -+securekey-y := securekey_desc.o \ -+ secure_key.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ ---- /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"); ---- /dev/null -+++ b/security/keys/securekey_desc.c -@@ -0,0 +1,608 @@ -+// 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; -+} -+EXPORT_SYMBOL(caam_get_random); -+ -+/* 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; -+} -+EXPORT_SYMBOL(key_deblob); -+ -+/* 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; -+ -+} -+EXPORT_SYMBOL(key_blob); ---- /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_*/ |