summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt16
-rw-r--r--include/keys/request_key_auth-type.h2
-rw-r--r--include/keys/trusted-type.h21
-rw-r--r--security/keys/Kconfig1
-rw-r--r--security/keys/encrypted-keys/encrypted.c4
-rw-r--r--security/keys/internal.h2
-rw-r--r--security/keys/key.c2
-rw-r--r--security/keys/keyctl.c24
-rw-r--r--security/keys/keyctl_pkey.c14
-rw-r--r--security/keys/keyring.c2
-rw-r--r--security/keys/request_key.c2
-rw-r--r--security/keys/request_key_auth.c33
-rw-r--r--security/keys/trusted-keys/Kconfig23
-rw-r--r--security/keys/trusted-keys/trusted_caam.c7
-rw-r--r--security/keys/trusted-keys/trusted_core.c8
-rw-r--r--security/keys/trusted-keys/trusted_tpm1.c44
-rw-r--r--security/keys/user_defined.c2
17 files changed, 158 insertions, 49 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 5602e42ebf97..a68003c3599c 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -7872,6 +7872,22 @@ Kernel parameters
first trust source as a backend which is initialized
successfully during iteration.
+ trusted.debug= [KEYS]
+ Format: <bool>
+ Enable trusted keys debug traces at runtime when
+ CONFIG_TRUSTED_KEYS_DEBUG=y.
+
+ To make the traces visible after enabling the option,
+ use trusted.dyndbg='+p' as needed. By convention,
+ the subsystem uses pr_debug() for these traces.
+
+ SAFETY: The traces can leak sensitive data, so be
+ cautious before enabling this. They remain inactive
+ unless this parameter is set this option to a true
+ value.
+
+ Default: false
+
trusted.rng= [KEYS]
Format: <string>
The RNG used to generate key material for trusted keys.
diff --git a/include/keys/request_key_auth-type.h b/include/keys/request_key_auth-type.h
index 36b89a933310..01e42ee5f409 100644
--- a/include/keys/request_key_auth-type.h
+++ b/include/keys/request_key_auth-type.h
@@ -9,12 +9,14 @@
#define _KEYS_REQUEST_KEY_AUTH_TYPE_H
#include <linux/key.h>
+#include <linux/refcount.h>
/*
* Authorisation record for request_key().
*/
struct request_key_auth {
struct rcu_head rcu;
+ refcount_t usage;
struct key *target_key;
struct key *dest_keyring;
const struct cred *cred;
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 03527162613f..9f9940482da4 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -83,18 +83,21 @@ struct trusted_key_source {
extern struct key_type key_type_trusted;
-#define TRUSTED_DEBUG 0
+#ifdef CONFIG_TRUSTED_KEYS_DEBUG
+extern bool trusted_debug;
-#if TRUSTED_DEBUG
static inline void dump_payload(struct trusted_key_payload *p)
{
- pr_info("key_len %d\n", p->key_len);
- print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE,
- 16, 1, p->key, p->key_len, 0);
- pr_info("bloblen %d\n", p->blob_len);
- print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE,
- 16, 1, p->blob, p->blob_len, 0);
- pr_info("migratable %d\n", p->migratable);
+ if (!trusted_debug)
+ return;
+
+ pr_debug("key_len %d\n", p->key_len);
+ print_hex_dump_debug("key ", DUMP_PREFIX_NONE,
+ 16, 1, p->key, p->key_len, 0);
+ pr_debug("bloblen %d\n", p->blob_len);
+ print_hex_dump_debug("blob ", DUMP_PREFIX_NONE,
+ 16, 1, p->blob, p->blob_len, 0);
+ pr_debug("migratable %d\n", p->migratable);
}
#else
static inline void dump_payload(struct trusted_key_payload *p)
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 84f39e50ca36..f4510d8cb485 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -87,7 +87,6 @@ config ENCRYPTED_KEYS
select CRYPTO_AES
select CRYPTO_CBC
select CRYPTO_LIB_SHA256
- select CRYPTO_RNG
help
This option provides support for create/encrypting/decrypting keys
in the kernel. Encrypted keys are instantiated using kernel
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 56b531587a1e..59cb77b237b3 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -343,9 +343,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
return -ENOMEM;
if (key_type)
- strcpy(derived_buf, "AUTH_KEY");
+ strscpy(derived_buf, "AUTH_KEY", HASH_SIZE);
else
- strcpy(derived_buf, "ENC_KEY");
+ strscpy(derived_buf, "ENC_KEY", HASH_SIZE);
memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
master_keylen);
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 2cffa6dc8255..b7b622bc36a1 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -208,6 +208,8 @@ extern struct key *request_key_auth_new(struct key *target,
const void *callout_info,
size_t callout_len,
struct key *dest_keyring);
+struct request_key_auth *request_key_auth_get(struct key *authkey);
+void request_key_auth_put(struct request_key_auth *rka);
extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
diff --git a/security/keys/key.c b/security/keys/key.c
index 091ee084bc30..b34a64d81d47 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1275,7 +1275,7 @@ void __init key_init(void)
{
/* allocate a slab in which we can store keys */
key_jar = kmem_cache_create("key_jar", sizeof(struct key),
- 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+ 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_NO_MERGE, NULL);
/* add the special key types */
list_add_tail(&key_type_keyring.link, &key_types_list);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ef855d69c97a..d14ace88e529 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1197,9 +1197,13 @@ static long keyctl_instantiate_key_common(key_serial_t id,
if (!instkey)
goto error;
- rka = instkey->payload.data[0];
- if (rka->target_key->serial != id)
+ rka = request_key_auth_get(instkey);
+ if (!rka) {
+ ret = -EKEYREVOKED;
goto error;
+ }
+ if (rka->target_key->serial != id)
+ goto error_put_rka;
/* pull the payload in if one was supplied */
payload = NULL;
@@ -1208,7 +1212,7 @@ static long keyctl_instantiate_key_common(key_serial_t id,
ret = -ENOMEM;
payload = kvmalloc(plen, GFP_KERNEL);
if (!payload)
- goto error;
+ goto error_put_rka;
ret = -EFAULT;
if (!copy_from_iter_full(payload, plen, from))
@@ -1234,6 +1238,8 @@ static long keyctl_instantiate_key_common(key_serial_t id,
error2:
kvfree_sensitive(payload, plen);
+error_put_rka:
+ request_key_auth_put(rka);
error:
return ret;
}
@@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
if (!instkey)
goto error;
- rka = instkey->payload.data[0];
- if (rka->target_key->serial != id)
+ rka = request_key_auth_get(instkey);
+ if (!rka) {
+ ret = -EKEYREVOKED;
goto error;
+ }
+ if (rka->target_key->serial != id)
+ goto error_put_rka;
/* find the destination keyring if present (which must also be
* writable) */
ret = get_instantiation_keyring(ringid, rka, &dest_keyring);
if (ret < 0)
- goto error;
+ goto error_put_rka;
/* instantiate the key and link it into a keyring */
ret = key_reject_and_link(rka->target_key, timeout, error,
@@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
if (ret == 0)
keyctl_change_reqkey_auth(NULL);
+error_put_rka:
+ request_key_auth_put(rka);
error:
return ret;
}
diff --git a/security/keys/keyctl_pkey.c b/security/keys/keyctl_pkey.c
index 97bc27bbf079..15b6bf6399b5 100644
--- a/security/keys/keyctl_pkey.c
+++ b/security/keys/keyctl_pkey.c
@@ -138,28 +138,35 @@ static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_par
if (uparams.in_len > info.max_dec_size ||
uparams.out_len > info.max_enc_size)
return -EINVAL;
+
+ params->out_len = info.max_enc_size;
break;
case KEYCTL_PKEY_DECRYPT:
if (uparams.in_len > info.max_enc_size ||
uparams.out_len > info.max_dec_size)
return -EINVAL;
+
+ params->out_len = info.max_dec_size;
break;
case KEYCTL_PKEY_SIGN:
if (uparams.in_len > info.max_data_size ||
uparams.out_len > info.max_sig_size)
return -EINVAL;
+
+ params->out_len = info.max_sig_size;
break;
case KEYCTL_PKEY_VERIFY:
if (uparams.in_len > info.max_data_size ||
uparams.in2_len > info.max_sig_size)
return -EINVAL;
+
+ params->out_len = info.max_sig_size;
break;
default:
- BUG();
+ return -EOPNOTSUPP;
}
params->in_len = uparams.in_len;
- params->out_len = uparams.out_len; /* Note: same as in2_len */
return 0;
}
@@ -238,7 +245,8 @@ long keyctl_pkey_e_d_s(int op,
params.op = kernel_pkey_sign;
break;
default:
- BUG();
+ ret = -EOPNOTSUPP;
+ goto error_params;
}
in = memdup_user(_in, params.in_len);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5a9887d6b7be..7a2ee0ded7c9 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -576,7 +576,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
struct keyring_search_context *ctx = iterator_data;
const struct key *key = keyring_ptr_to_key(object);
unsigned long kflags = READ_ONCE(key->flags);
- short state = READ_ONCE(key->state);
+ short state = key_read_state(key);
kenter("{%d}", key->serial);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index a7673ad86d18..fa2bb9f2f538 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -332,7 +332,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)
case KEY_REQKEY_DEFL_GROUP_KEYRING:
default:
- BUG();
+ return -EINVAL;
}
/*
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index a7d7538c1f70..282e09d8fa46 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -23,6 +23,7 @@ static void request_key_auth_describe(const struct key *, struct seq_file *);
static void request_key_auth_revoke(struct key *);
static void request_key_auth_destroy(struct key *);
static long request_key_auth_read(const struct key *, char *, size_t);
+static void request_key_auth_rcu_disposal(struct rcu_head *);
/*
* The request-key authorisation key type definition.
@@ -116,6 +117,31 @@ static void free_request_key_auth(struct request_key_auth *rka)
}
/*
+ * Take a reference to the request-key authorisation payload so callers can
+ * drop authkey->sem before doing operations that may sleep.
+ */
+struct request_key_auth *request_key_auth_get(struct key *authkey)
+{
+ struct request_key_auth *rka;
+
+ down_read(&authkey->sem);
+ rka = dereference_key_locked(authkey);
+ if (rka && !test_bit(KEY_FLAG_REVOKED, &authkey->flags))
+ refcount_inc(&rka->usage);
+ else
+ rka = NULL;
+ up_read(&authkey->sem);
+
+ return rka;
+}
+
+void request_key_auth_put(struct request_key_auth *rka)
+{
+ if (rka && refcount_dec_and_test(&rka->usage))
+ call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+}
+
+/*
* Dispose of the request_key_auth record under RCU conditions
*/
static void request_key_auth_rcu_disposal(struct rcu_head *rcu)
@@ -136,8 +162,10 @@ static void request_key_auth_revoke(struct key *key)
struct request_key_auth *rka = dereference_key_locked(key);
kenter("{%d}", key->serial);
+ if (!rka)
+ return;
rcu_assign_keypointer(key, NULL);
- call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+ request_key_auth_put(rka);
}
/*
@@ -150,7 +178,7 @@ static void request_key_auth_destroy(struct key *key)
kenter("{%d}", key->serial);
if (rka) {
rcu_assign_keypointer(key, NULL);
- call_rcu(&rka->rcu, request_key_auth_rcu_disposal);
+ request_key_auth_put(rka);
}
}
@@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct key *target, const char *op,
rka = kzalloc_obj(*rka);
if (!rka)
goto error;
+ refcount_set(&rka->usage, 1);
rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL);
if (!rka->callout_info)
goto error_free_rka;
diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig
index 9e00482d886a..e5a4a53aeab2 100644
--- a/security/keys/trusted-keys/Kconfig
+++ b/security/keys/trusted-keys/Kconfig
@@ -1,10 +1,29 @@
config HAVE_TRUSTED_KEYS
bool
+config HAVE_TRUSTED_KEYS_DEBUG
+ bool
+
+config TRUSTED_KEYS_DEBUG
+ bool "Debug trusted keys"
+ depends on HAVE_TRUSTED_KEYS_DEBUG
+ default n
+ help
+ Trusted key backends and core code that support debug traces can
+ opt-in that feature here. Traces must only use debug level output, as
+ sensitive data may pass by. In the kernel-command line traces can be
+ enabled via trusted.dyndbg='+p'.
+
+ SAFETY: Debug dumps are inactive at runtime until trusted.debug is set
+ to a true value on the kernel command-line. Use at your utmost
+ consideration when enabling this feature on a production build. The
+ general advice is not to do this.
+
config TRUSTED_KEYS_TPM
bool "TPM-based trusted keys"
depends on TCG_TPM >= TRUSTED_KEYS
default y
+ select HAVE_TRUSTED_KEYS_DEBUG
select CRYPTO_HASH_INFO
select CRYPTO_LIB_SHA1
select CRYPTO_LIB_UTILS
@@ -23,6 +42,7 @@ config TRUSTED_KEYS_TEE
bool "TEE-based trusted keys"
depends on TEE >= TRUSTED_KEYS
default y
+ select HAVE_TRUSTED_KEYS_DEBUG
select HAVE_TRUSTED_KEYS
help
Enable use of the Trusted Execution Environment (TEE) as trusted
@@ -33,6 +53,7 @@ config TRUSTED_KEYS_CAAM
depends on CRYPTO_DEV_FSL_CAAM_JR >= TRUSTED_KEYS
select CRYPTO_DEV_FSL_CAAM_BLOB_GEN
default y
+ select HAVE_TRUSTED_KEYS_DEBUG
select HAVE_TRUSTED_KEYS
help
Enable use of NXP's Cryptographic Accelerator and Assurance Module
@@ -42,6 +63,7 @@ config TRUSTED_KEYS_DCP
bool "DCP-based trusted keys"
depends on CRYPTO_DEV_MXS_DCP >= TRUSTED_KEYS
default y
+ select HAVE_TRUSTED_KEYS_DEBUG
select HAVE_TRUSTED_KEYS
help
Enable use of NXP's DCP (Data Co-Processor) as trusted key backend.
@@ -50,6 +72,7 @@ config TRUSTED_KEYS_PKWM
bool "PKWM-based trusted keys"
depends on PSERIES_PLPKS >= TRUSTED_KEYS
default y
+ select HAVE_TRUSTED_KEYS_DEBUG
select HAVE_TRUSTED_KEYS
help
Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key backend.
diff --git a/security/keys/trusted-keys/trusted_caam.c b/security/keys/trusted-keys/trusted_caam.c
index 601943ce0d60..6a33dbf2a7f5 100644
--- a/security/keys/trusted-keys/trusted_caam.c
+++ b/security/keys/trusted-keys/trusted_caam.c
@@ -28,10 +28,13 @@ static const match_table_t key_tokens = {
{opt_err, NULL}
};
-#ifdef CAAM_DEBUG
+#ifdef CONFIG_TRUSTED_KEYS_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);
+ if (!trusted_debug)
+ return;
+
+ pr_debug("key encryption algo %d\n", pkey_info->key_enc_algo);
}
#else
static inline void dump_options(const struct caam_pkey_info *pkey_info)
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index 0b142d941cd2..0509d9955f2a 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -31,6 +31,12 @@ static char *trusted_rng = "default";
module_param_named(rng, trusted_rng, charp, 0);
MODULE_PARM_DESC(rng, "Select trusted key RNG");
+#ifdef CONFIG_TRUSTED_KEYS_DEBUG
+bool trusted_debug;
+module_param_named(debug, trusted_debug, bool, 0);
+MODULE_PARM_DESC(debug, "Enable trusted keys debug traces (default: 0)");
+#endif
+
static char *trusted_key_source;
module_param_named(source, trusted_key_source, charp, 0);
MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)");
@@ -59,7 +65,7 @@ DEFINE_STATIC_CALL_NULL(trusted_key_unseal,
DEFINE_STATIC_CALL_NULL(trusted_key_get_random,
*trusted_key_sources[0].ops->get_random);
static void (*trusted_key_exit)(void);
-static unsigned char migratable;
+static unsigned char migratable __ro_after_init;
enum {
Opt_err,
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index 6ea728f1eae6..13513819991e 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -46,38 +46,44 @@ enum {
SRK_keytype = 4
};
-#define TPM_DEBUG 0
-
-#if TPM_DEBUG
+#ifdef CONFIG_TRUSTED_KEYS_DEBUG
static inline void dump_options(struct trusted_key_options *o)
{
- pr_info("sealing key type %d\n", o->keytype);
- pr_info("sealing key handle %0X\n", o->keyhandle);
- pr_info("pcrlock %d\n", o->pcrlock);
- pr_info("pcrinfo %d\n", o->pcrinfo_len);
- print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
- 16, 1, o->pcrinfo, o->pcrinfo_len, 0);
+ if (!trusted_debug)
+ return;
+
+ pr_debug("sealing key type %d\n", o->keytype);
+ pr_debug("sealing key handle %0X\n", o->keyhandle);
+ pr_debug("pcrlock %d\n", o->pcrlock);
+ pr_debug("pcrinfo %d\n", o->pcrinfo_len);
+ print_hex_dump_debug("pcrinfo ", DUMP_PREFIX_NONE,
+ 16, 1, o->pcrinfo, o->pcrinfo_len, 0);
}
static inline void dump_sess(struct osapsess *s)
{
- print_hex_dump(KERN_INFO, "trusted-key: handle ", DUMP_PREFIX_NONE,
- 16, 1, &s->handle, 4, 0);
- pr_info("secret:\n");
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
- 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
- pr_info("trusted-key: enonce:\n");
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
- 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
+ if (!trusted_debug)
+ return;
+
+ print_hex_dump_debug("trusted-key: handle ", DUMP_PREFIX_NONE,
+ 16, 1, &s->handle, 4, 0);
+ pr_debug("secret:\n");
+ print_hex_dump_debug("", DUMP_PREFIX_NONE,
+ 16, 1, &s->secret, SHA1_DIGEST_SIZE, 0);
+ pr_debug("trusted-key: enonce:\n");
+ print_hex_dump_debug("", DUMP_PREFIX_NONE,
+ 16, 1, &s->enonce, SHA1_DIGEST_SIZE, 0);
}
static inline void dump_tpm_buf(unsigned char *buf)
{
int len;
- pr_info("\ntpm buffer\n");
+ if (!trusted_debug)
+ return;
+ pr_debug("\ntpm buffer\n");
len = LOAD32(buf, TPM_SIZE_OFFSET);
- print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
+ print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
}
#else
static inline void dump_options(struct trusted_key_options *o)
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 686d56e4cc85..6f88b507f927 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -64,7 +64,7 @@ int user_preparse(struct key_preparsed_payload *prep)
if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
- upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
+ upayload = kmalloc_flex(*upayload, data, datalen);
if (!upayload)
return -ENOMEM;