diff options
Diffstat (limited to 'security/keys')
| -rw-r--r-- | security/keys/big_key.c | 2 | ||||
| -rw-r--r-- | security/keys/encrypted-keys/ecryptfs_format.c | 3 | ||||
| -rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 4 | ||||
| -rw-r--r-- | security/keys/trusted-keys/trusted_caam.c | 108 | ||||
| -rw-r--r-- | security/keys/trusted-keys/trusted_core.c | 4 | ||||
| -rw-r--r-- | security/keys/trusted-keys/trusted_tpm2.c | 29 | ||||
| -rw-r--r-- | security/keys/user_defined.c | 2 |
7 files changed, 123 insertions, 29 deletions
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index c3367622c683..d46862ab90d6 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c @@ -66,7 +66,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) BUILD_BUG_ON(sizeof(*payload) != sizeof(prep->payload.data)); - if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) + if (datalen == 0 || datalen > 1024 * 1024 || !prep->data) return -EINVAL; /* Set an arbitrary quota */ diff --git a/security/keys/encrypted-keys/ecryptfs_format.c b/security/keys/encrypted-keys/ecryptfs_format.c index 8fdd76105ce3..2fc6f3a66135 100644 --- a/security/keys/encrypted-keys/ecryptfs_format.c +++ b/security/keys/encrypted-keys/ecryptfs_format.c @@ -54,8 +54,7 @@ int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok, auth_tok->version = (((uint16_t)(major << 8) & 0xFF00) | ((uint16_t)minor & 0x00FF)); auth_tok->token_type = ECRYPTFS_PASSWORD; - strncpy((char *)auth_tok->token.password.signature, key_desc, - ECRYPTFS_PASSWORD_SIG_SIZE); + strscpy_pad(auth_tok->token.password.signature, key_desc); auth_tok->token.password.session_key_encryption_key_bytes = ECRYPTFS_MAX_KEY_BYTES; /* diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 513c09e2b01c..596e7a30bd3c 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -795,7 +795,7 @@ static int encrypted_instantiate(struct key *key, size_t datalen = prep->datalen; int ret; - if (datalen <= 0 || datalen > 32767 || !prep->data) + if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; datablob = kmalloc(datalen + 1, GFP_KERNEL); @@ -856,7 +856,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) if (key_is_negative(key)) return -ENOKEY; - if (datalen <= 0 || datalen > 32767 || !prep->data) + if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; buf = kmalloc(datalen + 1, GFP_KERNEL); diff --git a/security/keys/trusted-keys/trusted_caam.c b/security/keys/trusted-keys/trusted_caam.c index e3415c520c0a..601943ce0d60 100644 --- a/security/keys/trusted-keys/trusted_caam.c +++ b/security/keys/trusted-keys/trusted_caam.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de> + * Copyright 2025 NXP */ #include <keys/trusted_caam.h> #include <keys/trusted-type.h> #include <linux/build_bug.h> #include <linux/key-type.h> +#include <linux/parser.h> #include <soc/fsl/caam-blob.h> static struct caam_blob_priv *blobifier; @@ -16,6 +18,77 @@ static struct caam_blob_priv *blobifier; static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN); static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN); +enum { + opt_err, + opt_key_enc_algo, +}; + +static const match_table_t key_tokens = { + {opt_key_enc_algo, "key_enc_algo=%s"}, + {opt_err, NULL} +}; + +#ifdef CAAM_DEBUG +static inline void dump_options(const struct caam_pkey_info *pkey_info) +{ + pr_info("key encryption algo %d\n", pkey_info->key_enc_algo); +} +#else +static inline void dump_options(const struct caam_pkey_info *pkey_info) +{ +} +#endif + +static int get_pkey_options(char *c, + struct caam_pkey_info *pkey_info) +{ + substring_t args[MAX_OPT_ARGS]; + unsigned long token_mask = 0; + u16 key_enc_algo; + char *p = c; + int token; + int res; + + if (!c) + return 0; + + while ((p = strsep(&c, " \t"))) { + if (*p == '\0' || *p == ' ' || *p == '\t') + continue; + token = match_token(p, key_tokens, args); + if (test_and_set_bit(token, &token_mask)) + return -EINVAL; + + switch (token) { + case opt_key_enc_algo: + res = kstrtou16(args[0].from, 16, &key_enc_algo); + if (res < 0) + return -EINVAL; + pkey_info->key_enc_algo = key_enc_algo; + break; + default: + return -EINVAL; + } + } + return 0; +} + +static bool is_key_pkey(char **datablob) +{ + char *c = NULL; + + do { + /* Second argument onwards, + * determine if tied to HW + */ + c = strsep(datablob, " \t"); + if (c && (strcmp(c, "pk") == 0)) + return true; + } while (c); + + return false; +} + static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob) { int ret; @@ -25,11 +98,30 @@ static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob) .key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1, }; + /* + * If it is to be treated as protected key, + * read next arguments too. + */ + if (is_key_pkey(&datablob)) { + info.pkey_info.plain_key_sz = p->key_len; + info.pkey_info.is_pkey = 1; + ret = get_pkey_options(datablob, &info.pkey_info); + if (ret < 0) + return 0; + dump_options(&info.pkey_info); + } + ret = caam_encap_blob(blobifier, &info); if (ret) return ret; p->blob_len = info.output_len; + if (info.pkey_info.is_pkey) { + p->key_len = p->blob_len + sizeof(struct caam_pkey_info); + memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info)); + memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len); + } + return 0; } @@ -42,11 +134,27 @@ static int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob) .key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1, }; + if (is_key_pkey(&datablob)) { + info.pkey_info.plain_key_sz = p->blob_len - CAAM_BLOB_OVERHEAD; + info.pkey_info.is_pkey = 1; + ret = get_pkey_options(datablob, &info.pkey_info); + if (ret < 0) + return 0; + dump_options(&info.pkey_info); + + p->key_len = p->blob_len + sizeof(struct caam_pkey_info); + memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info)); + memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len); + + return 0; + } + ret = caam_decap_blob(blobifier, &info); if (ret) return ret; p->key_len = info.output_len; + return 0; } diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c index e2d9644efde1..b1680ee53f86 100644 --- a/security/keys/trusted-keys/trusted_core.c +++ b/security/keys/trusted-keys/trusted_core.c @@ -157,7 +157,7 @@ static int trusted_instantiate(struct key *key, int key_cmd; size_t key_len; - if (datalen <= 0 || datalen > 32767 || !prep->data) + if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL); @@ -240,7 +240,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) p = key->payload.data[0]; if (!p->migratable) return -EPERM; - if (datalen <= 0 || datalen > 32767 || !prep->data) + if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL); diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 024be262702f..91656e44b326 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -18,14 +18,6 @@ #include "tpm2key.asn1.h" -static struct tpm2_hash tpm2_hash_map[] = { - {HASH_ALGO_SHA1, TPM_ALG_SHA1}, - {HASH_ALGO_SHA256, TPM_ALG_SHA256}, - {HASH_ALGO_SHA384, TPM_ALG_SHA384}, - {HASH_ALGO_SHA512, TPM_ALG_SHA512}, - {HASH_ALGO_SM3_256, TPM_ALG_SM3_256}, -}; - static u32 tpm2key_oid[] = { 2, 23, 133, 10, 1, 5 }; static int tpm2_key_encode(struct trusted_key_payload *payload, @@ -244,20 +236,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip, off_t offset = TPM_HEADER_SIZE; struct tpm_buf buf, sized; int blob_len = 0; - u32 hash; + int hash; u32 flags; - int i; int rc; - for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) { - if (options->hash == tpm2_hash_map[i].crypto_id) { - hash = tpm2_hash_map[i].tpm_id; - break; - } - } - - if (i == ARRAY_SIZE(tpm2_hash_map)) - return -EINVAL; + hash = tpm2_find_hash_alg(options->hash); + if (hash < 0) + return hash; if (!options->keyhandle) return -EINVAL; @@ -387,6 +372,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, struct trusted_key_options *options, u32 *blob_handle) { + u8 *blob_ref __free(kfree) = NULL; struct tpm_buf buf; unsigned int private_len; unsigned int public_len; @@ -400,6 +386,9 @@ static int tpm2_load_cmd(struct tpm_chip *chip, /* old form */ blob = payload->blob; payload->old_format = 1; + } else { + /* Bind for cleanup: */ + blob_ref = blob; } /* new format carries keyhandle but old format doesn't */ @@ -464,8 +453,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip, (__be32 *) &buf.data[TPM_HEADER_SIZE]); out: - if (blob != payload->blob) - kfree(blob); tpm_buf_destroy(&buf); if (rc > 0) diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 749e2a4dcb13..686d56e4cc85 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -61,7 +61,7 @@ int user_preparse(struct key_preparsed_payload *prep) struct user_key_payload *upayload; size_t datalen = prep->datalen; - if (datalen <= 0 || datalen > 32767 || !prep->data) + if (datalen == 0 || datalen > 32767 || !prep->data) return -EINVAL; upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); |
