diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.14/817-platform-security-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.14/817-platform-security-support-layerscape.patch | 1443 |
1 files changed, 1443 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-4.14/817-platform-security-support-layerscape.patch b/target/linux/layerscape/patches-4.14/817-platform-security-support-layerscape.patch new file mode 100644 index 0000000000..8f378d40ca --- /dev/null +++ b/target/linux/layerscape/patches-4.14/817-platform-security-support-layerscape.patch @@ -0,0 +1,1443 @@ +From d2e808b0dcca1b5e850274f770775c355ae36c48 Mon Sep 17 00:00:00 2001 +From: Biwen Li <biwen.li@nxp.com> +Date: Tue, 30 Oct 2018 18:27:03 +0800 +Subject: [PATCH 34/40] platfrom-security: support layerscape +This is an integrated patch of platform-security for + layerscape + +Signed-off-by: Sahil Malhotra <sahil.malhotra@nxp.com> +Signed-off-by: Udit Agarwal <udit.agarwal@nxp.com> +Signed-off-by: Biwen Li <biwen.li@nxp.com> +--- + Documentation/security/keys/secure-key.rst | 67 ++ + MAINTAINERS | 12 + + drivers/tee/optee/Kconfig | 8 + + drivers/tee/optee/core.c | 2 +- + include/keys/secure-type.h | 33 + + security/keys/Kconfig | 11 + + security/keys/Makefile | 5 + + 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 ++ + security/keys/secure_key.c | 339 ++++++++++ + security/keys/securekey_desc.c | 608 ++++++++++++++++++ + security/keys/securekey_desc.h | 141 ++++ + 14 files changed, 1288 insertions(+), 3 deletions(-) + create mode 100644 Documentation/security/keys/secure-key.rst + create mode 100644 include/keys/secure-type.h + create mode 100644 security/keys/encrypted-keys/masterkey_secure.c + 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 +@@ -7645,6 +7645,18 @@ 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 ++F: security/keys/encrypted-keys/masterkey_secure.c ++ + KEYS/KEYRINGS: + M: David Howells <dhowells@redhat.com> + L: keyrings@vger.kernel.org +--- a/drivers/tee/optee/Kconfig ++++ b/drivers/tee/optee/Kconfig +@@ -5,3 +5,11 @@ config OPTEE + help + This implements the OP-TEE Trusted Execution Environment (TEE) + driver. ++ ++config OPTEE_SHM_NUM_PRIV_PAGES ++ int "Private Shared Memory Pages" ++ default 1 ++ depends on OPTEE ++ help ++ This sets the number of private shared memory pages to be ++ used by OP-TEE TEE driver. +--- a/drivers/tee/optee/core.c ++++ b/drivers/tee/optee/core.c +@@ -31,7 +31,7 @@ + + #define DRIVER_NAME "optee" + +-#define OPTEE_SHM_NUM_PRIV_PAGES 1 ++#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES + + /** + * optee_from_msg_param() - convert from OPTEE_MSG parameters to +--- /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 +@@ -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 +--- a/security/keys/Makefile ++++ b/security/keys/Makefile +@@ -28,4 +28,9 @@ obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o + # + 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/ +--- a/security/keys/encrypted-keys/Makefile ++++ b/security/keys/encrypted-keys/Makefile +@@ -7,5 +7,7 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypte + + 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) +--- 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 cha + /* + * 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 + + 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 u + + 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(st + 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 + +--- a/security/keys/encrypted-keys/encrypted.h ++++ b/security/keys/encrypted-keys/encrypted.h +@@ -16,6 +16,19 @@ static inline struct key *request_truste + } + #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) + { +--- /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; ++} +--- /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_*/ |