mirror of
https://github.com/brain-hackers/linux-brain.git
synced 2024-06-09 23:36:23 +09:00
Merge branch 'keys/next' into next
* keys/next: encrypted_keys: Adds support for secure key-type as master key. security/keys/secure_key: Adds the secure key support based on CAAM.
This commit is contained in:
commit
0e41cf483e
67
Documentation/security/keys/secure-key.rst
Normal file
67
Documentation/security/keys/secure-key.rst
Normal file
|
@ -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
|
12
MAINTAINERS
12
MAINTAINERS
|
@ -9062,6 +9062,18 @@ 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
|
||||
F: security/keys/encrypted-keys/masterkey_secure.c
|
||||
|
||||
KEYS/KEYRINGS:
|
||||
M: David Howells <dhowells@redhat.com>
|
||||
M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
|
||||
|
|
33
include/keys/secure-type.h
Normal file
33
include/keys/secure-type.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -29,4 +29,9 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.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/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -36,6 +36,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)";
|
||||
|
@ -47,6 +48,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 +
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
37
security/keys/encrypted-keys/masterkey_secure.c
Normal file
37
security/keys/encrypted-keys/masterkey_secure.c
Normal file
|
@ -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;
|
||||
}
|
339
security/keys/secure_key.c
Normal file
339
security/keys/secure_key.c
Normal file
|
@ -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");
|
608
security/keys/securekey_desc.c
Normal file
608
security/keys/securekey_desc.c
Normal file
|
@ -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);
|
141
security/keys/securekey_desc.h
Normal file
141
security/keys/securekey_desc.h
Normal file
|
@ -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_*/
|
Loading…
Reference in New Issue
Block a user