summaryrefslogtreecommitdiffstats
path: root/kernel/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/security/keys')
-rw-r--r--kernel/security/keys/big_key.c47
-rw-r--r--kernel/security/keys/encrypted-keys/encrypted.c20
-rw-r--r--kernel/security/keys/encrypted-keys/encrypted.h4
-rw-r--r--kernel/security/keys/encrypted-keys/masterkey_trusted.c4
-rw-r--r--kernel/security/keys/gc.c10
-rw-r--r--kernel/security/keys/key.c20
-rw-r--r--kernel/security/keys/keyctl.c30
-rw-r--r--kernel/security/keys/keyring.c12
-rw-r--r--kernel/security/keys/process_keys.c6
-rw-r--r--kernel/security/keys/request_key.c7
-rw-r--r--kernel/security/keys/request_key_auth.c12
-rw-r--r--kernel/security/keys/trusted.c45
-rw-r--r--kernel/security/keys/trusted.h11
-rw-r--r--kernel/security/keys/user_defined.c17
14 files changed, 144 insertions, 101 deletions
diff --git a/kernel/security/keys/big_key.c b/kernel/security/keys/big_key.c
index b6adb94f6..907c1522e 100644
--- a/kernel/security/keys/big_key.c
+++ b/kernel/security/keys/big_key.c
@@ -21,6 +21,16 @@
MODULE_LICENSE("GPL");
/*
+ * Layout of key payload words.
+ */
+enum {
+ big_key_data,
+ big_key_path,
+ big_key_path_2nd_part,
+ big_key_len,
+};
+
+/*
* If the data is under this limit, there's no point creating a shm file to
* hold it as the permanently resident metadata for the shmem fs will be at
* least as large as the data.
@@ -47,7 +57,7 @@ struct key_type key_type_big_key = {
*/
int big_key_preparse(struct key_preparsed_payload *prep)
{
- struct path *path = (struct path *)&prep->payload;
+ struct path *path = (struct path *)&prep->payload.data[big_key_path];
struct file *file;
ssize_t written;
size_t datalen = prep->datalen;
@@ -60,7 +70,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
/* Set an arbitrary quota */
prep->quotalen = 16;
- prep->type_data[1] = (void *)(unsigned long)datalen;
+ prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
if (datalen > BIG_KEY_FILE_THRESHOLD) {
/* Create a shmem file to store the data in. This will permit the data
@@ -94,7 +104,8 @@ int big_key_preparse(struct key_preparsed_payload *prep)
if (!data)
return -ENOMEM;
- prep->payload[0] = memcpy(data, prep->data, prep->datalen);
+ prep->payload.data[big_key_data] = data;
+ memcpy(data, prep->data, prep->datalen);
}
return 0;
@@ -110,10 +121,10 @@ error:
void big_key_free_preparse(struct key_preparsed_payload *prep)
{
if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
- struct path *path = (struct path *)&prep->payload;
+ struct path *path = (struct path *)&prep->payload.data[big_key_path];
path_put(path);
} else {
- kfree(prep->payload[0]);
+ kfree(prep->payload.data[big_key_data]);
}
}
@@ -123,11 +134,12 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
*/
void big_key_revoke(struct key *key)
{
- struct path *path = (struct path *)&key->payload.data2;
+ struct path *path = (struct path *)&key->payload.data[big_key_path];
/* clear the quota */
key_payload_reserve(key, 0);
- if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD)
+ if (key_is_instantiated(key) &&
+ (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
vfs_truncate(path, 0);
}
@@ -136,14 +148,16 @@ void big_key_revoke(struct key *key)
*/
void big_key_destroy(struct key *key)
{
- if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) {
- struct path *path = (struct path *)&key->payload.data2;
+ size_t datalen = (size_t)key->payload.data[big_key_len];
+
+ if (datalen) {
+ struct path *path = (struct path *)&key->payload.data[big_key_path];
path_put(path);
path->mnt = NULL;
path->dentry = NULL;
} else {
- kfree(key->payload.data);
- key->payload.data = NULL;
+ kfree(key->payload.data[big_key_data]);
+ key->payload.data[big_key_data] = NULL;
}
}
@@ -152,12 +166,12 @@ void big_key_destroy(struct key *key)
*/
void big_key_describe(const struct key *key, struct seq_file *m)
{
- unsigned long datalen = key->type_data.x[1];
+ size_t datalen = (size_t)key->payload.data[big_key_len];
seq_puts(m, key->description);
if (key_is_instantiated(key))
- seq_printf(m, ": %lu [%s]",
+ seq_printf(m, ": %zu [%s]",
datalen,
datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
}
@@ -168,14 +182,14 @@ void big_key_describe(const struct key *key, struct seq_file *m)
*/
long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
{
- unsigned long datalen = key->type_data.x[1];
+ size_t datalen = (size_t)key->payload.data[big_key_len];
long ret;
if (!buffer || buflen < datalen)
return datalen;
if (datalen > BIG_KEY_FILE_THRESHOLD) {
- struct path *path = (struct path *)&key->payload.data2;
+ struct path *path = (struct path *)&key->payload.data[big_key_path];
struct file *file;
loff_t pos;
@@ -190,7 +204,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
ret = -EIO;
} else {
ret = datalen;
- if (copy_to_user(buffer, key->payload.data, datalen) != 0)
+ if (copy_to_user(buffer, key->payload.data[big_key_data],
+ datalen) != 0)
ret = -EFAULT;
}
diff --git a/kernel/security/keys/encrypted-keys/encrypted.c b/kernel/security/keys/encrypted-keys/encrypted.c
index 7bed4ad7c..696ccfa08 100644
--- a/kernel/security/keys/encrypted-keys/encrypted.c
+++ b/kernel/security/keys/encrypted-keys/encrypted.c
@@ -303,10 +303,10 @@ out:
*
* Use a user provided key to encrypt/decrypt an encrypted-key.
*/
-static struct key *request_user_key(const char *master_desc, u8 **master_key,
+static struct key *request_user_key(const char *master_desc, const u8 **master_key,
size_t *master_keylen)
{
- struct user_key_payload *upayload;
+ const struct user_key_payload *upayload;
struct key *ukey;
ukey = request_key(&key_type_user, master_desc, NULL);
@@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, u8 **master_key,
goto error;
down_read(&ukey->sem);
- upayload = ukey->payload.data;
+ upayload = user_key_payload(ukey);
*master_key = upayload->data;
*master_keylen = upayload->datalen;
error:
@@ -426,7 +426,7 @@ static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key,
}
static struct key *request_master_key(struct encrypted_key_payload *epayload,
- u8 **master_key, size_t *master_keylen)
+ const u8 **master_key, size_t *master_keylen)
{
struct key *mkey = NULL;
@@ -653,7 +653,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
{
struct key *mkey;
u8 derived_key[HASH_SIZE];
- u8 *master_key;
+ const u8 *master_key;
u8 *hmac;
const char *hex_encoded_data;
unsigned int encrypted_datalen;
@@ -837,7 +837,7 @@ static void encrypted_rcu_free(struct rcu_head *rcu)
*/
static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
{
- struct encrypted_key_payload *epayload = key->payload.data;
+ struct encrypted_key_payload *epayload = key->payload.data[0];
struct encrypted_key_payload *new_epayload;
char *buf;
char *new_master_desc = NULL;
@@ -845,6 +845,8 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
size_t datalen = prep->datalen;
int ret = 0;
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+ return -ENOKEY;
if (datalen <= 0 || datalen > 32767 || !prep->data)
return -EINVAL;
@@ -896,7 +898,7 @@ static long encrypted_read(const struct key *key, char __user *buffer,
{
struct encrypted_key_payload *epayload;
struct key *mkey;
- u8 *master_key;
+ const u8 *master_key;
size_t master_keylen;
char derived_key[HASH_SIZE];
char *ascii_buf;
@@ -957,13 +959,13 @@ out:
*/
static void encrypted_destroy(struct key *key)
{
- struct encrypted_key_payload *epayload = key->payload.data;
+ struct encrypted_key_payload *epayload = key->payload.data[0];
if (!epayload)
return;
memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
- kfree(key->payload.data);
+ kfree(key->payload.data[0]);
}
struct key_type key_type_encrypted = {
diff --git a/kernel/security/keys/encrypted-keys/encrypted.h b/kernel/security/keys/encrypted-keys/encrypted.h
index 8136a2d44..47802c0de 100644
--- a/kernel/security/keys/encrypted-keys/encrypted.h
+++ b/kernel/security/keys/encrypted-keys/encrypted.h
@@ -5,10 +5,10 @@
#if defined(CONFIG_TRUSTED_KEYS) || \
(defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
extern struct key *request_trusted_key(const char *trusted_desc,
- u8 **master_key, size_t *master_keylen);
+ const u8 **master_key, size_t *master_keylen);
#else
static inline struct key *request_trusted_key(const char *trusted_desc,
- u8 **master_key,
+ const u8 **master_key,
size_t *master_keylen)
{
return ERR_PTR(-EOPNOTSUPP);
diff --git a/kernel/security/keys/encrypted-keys/masterkey_trusted.c b/kernel/security/keys/encrypted-keys/masterkey_trusted.c
index 013f7e5d3..b5b4812db 100644
--- a/kernel/security/keys/encrypted-keys/masterkey_trusted.c
+++ b/kernel/security/keys/encrypted-keys/masterkey_trusted.c
@@ -29,7 +29,7 @@
* data, trusted key type data is not visible decrypted from userspace.
*/
struct key *request_trusted_key(const char *trusted_desc,
- u8 **master_key, size_t *master_keylen)
+ const u8 **master_key, size_t *master_keylen)
{
struct trusted_key_payload *tpayload;
struct key *tkey;
@@ -39,7 +39,7 @@ struct key *request_trusted_key(const char *trusted_desc,
goto error;
down_read(&tkey->sem);
- tpayload = tkey->payload.data;
+ tpayload = tkey->payload.data[0];
*master_key = tpayload->key;
*master_keylen = tpayload->key_len;
error:
diff --git a/kernel/security/keys/gc.c b/kernel/security/keys/gc.c
index c7952375a..addf06039 100644
--- a/kernel/security/keys/gc.c
+++ b/kernel/security/keys/gc.c
@@ -134,6 +134,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
kdebug("- %u", key->serial);
key_check(key);
+ /* Throw away the key data if the key is instantiated */
+ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+ !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+ key->type->destroy)
+ key->type->destroy(key);
+
security_key_free(key);
/* deal with the user's key tracking and quota */
@@ -148,10 +154,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
atomic_dec(&key->user->nikeys);
- /* now throw away the key memory */
- if (key->type->destroy)
- key->type->destroy(key);
-
key_user_put(key->user);
kfree(key->description);
diff --git a/kernel/security/keys/key.c b/kernel/security/keys/key.c
index aee2ec5a1..ab7997ded 100644
--- a/kernel/security/keys/key.c
+++ b/kernel/security/keys/key.c
@@ -278,7 +278,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->index_key.desc_len = desclen;
key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL);
- if (!key->description)
+ if (!key->index_key.description)
goto no_memory_3;
atomic_set(&key->usage, 1);
@@ -554,7 +554,7 @@ int key_reject_and_link(struct key *key,
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
/* mark the key as being negatively instantiated */
atomic_inc(&key->user->nikeys);
- key->type_data.reject_error = -error;
+ key->reject_error = -error;
smp_wmb();
set_bit(KEY_FLAG_NEGATIVE, &key->flags);
set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
@@ -1046,14 +1046,14 @@ int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
ret = key_payload_reserve(key, prep->quotalen);
if (ret == 0) {
- key->type_data.p[0] = prep->type_data[0];
- key->type_data.p[1] = prep->type_data[1];
- rcu_assign_keypointer(key, prep->payload[0]);
- key->payload.data2[1] = prep->payload[1];
- prep->type_data[0] = NULL;
- prep->type_data[1] = NULL;
- prep->payload[0] = NULL;
- prep->payload[1] = NULL;
+ rcu_assign_keypointer(key, prep->payload.data[0]);
+ key->payload.data[1] = prep->payload.data[1];
+ key->payload.data[2] = prep->payload.data[2];
+ key->payload.data[3] = prep->payload.data[3];
+ prep->payload.data[0] = NULL;
+ prep->payload.data[1] = NULL;
+ prep->payload.data[2] = NULL;
+ prep->payload.data[3] = NULL;
}
pr_devel("<==%s() = %d\n", __func__, ret);
return ret;
diff --git a/kernel/security/keys/keyctl.c b/kernel/security/keys/keyctl.c
index 0b9ec78a7..1c3872aee 100644
--- a/kernel/security/keys/keyctl.c
+++ b/kernel/security/keys/keyctl.c
@@ -67,7 +67,6 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
char type[32], *description;
void *payload;
long ret;
- bool vm;
ret = -EINVAL;
if (plen > 1024 * 1024 - 1)
@@ -98,14 +97,12 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
/* pull the payload in if one was supplied */
payload = NULL;
- vm = false;
if (_payload) {
ret = -ENOMEM;
payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
if (!payload) {
if (plen <= PAGE_SIZE)
goto error2;
- vm = true;
payload = vmalloc(plen);
if (!payload)
goto error2;
@@ -138,10 +135,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
key_ref_put(keyring_ref);
error3:
- if (!vm)
- kfree(payload);
- else
- vfree(payload);
+ kvfree(payload);
error2:
kfree(description);
error:
@@ -757,16 +751,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
/* the key is probably readable - now try to read it */
can_read_key:
- ret = key_validate(key);
- if (ret == 0) {
- ret = -EOPNOTSUPP;
- if (key->type->read) {
- /* read the data with the semaphore held (since we
- * might sleep) */
- down_read(&key->sem);
+ ret = -EOPNOTSUPP;
+ if (key->type->read) {
+ /* Read the data with the semaphore held (since we might sleep)
+ * to protect against the key being updated or revoked.
+ */
+ down_read(&key->sem);
+ ret = key_validate(key);
+ if (ret == 0)
ret = key->type->read(key, buffer, buflen);
- up_read(&key->sem);
- }
+ up_read(&key->sem);
}
error2:
@@ -1033,7 +1027,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
if (!instkey)
goto error;
- rka = instkey->payload.data;
+ rka = instkey->payload.data[0];
if (rka->target_key->serial != id)
goto error;
@@ -1200,7 +1194,7 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
if (!instkey)
goto error;
- rka = instkey->payload.data;
+ rka = instkey->payload.data[0];
if (rka->target_key->serial != id)
goto error;
diff --git a/kernel/security/keys/keyring.c b/kernel/security/keys/keyring.c
index d33437007..f931ccfee 100644
--- a/kernel/security/keys/keyring.c
+++ b/kernel/security/keys/keyring.c
@@ -118,7 +118,7 @@ static void keyring_publish_name(struct key *keyring)
if (!keyring_name_hash[bucket].next)
INIT_LIST_HEAD(&keyring_name_hash[bucket]);
- list_add_tail(&keyring->type_data.link,
+ list_add_tail(&keyring->name_link,
&keyring_name_hash[bucket]);
write_unlock(&keyring_name_lock);
@@ -387,9 +387,9 @@ static void keyring_destroy(struct key *keyring)
if (keyring->description) {
write_lock(&keyring_name_lock);
- if (keyring->type_data.link.next != NULL &&
- !list_empty(&keyring->type_data.link))
- list_del(&keyring->type_data.link);
+ if (keyring->name_link.next != NULL &&
+ !list_empty(&keyring->name_link))
+ list_del(&keyring->name_link);
write_unlock(&keyring_name_lock);
}
@@ -572,7 +572,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
/* we set a different error code if we pass a negative key */
if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
smp_rmb();
- ctx->result = ERR_PTR(key->type_data.reject_error);
+ ctx->result = ERR_PTR(key->reject_error);
kleave(" = %d [neg]", ctx->skipped_ret);
goto skipped;
}
@@ -990,7 +990,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
* that's readable and that hasn't been revoked */
list_for_each_entry(keyring,
&keyring_name_hash[bucket],
- type_data.link
+ name_link
) {
if (!kuid_has_mapping(current_user_ns(), keyring->user->uid))
continue;
diff --git a/kernel/security/keys/process_keys.c b/kernel/security/keys/process_keys.c
index bd536cb22..e6d501728 100644
--- a/kernel/security/keys/process_keys.c
+++ b/kernel/security/keys/process_keys.c
@@ -457,7 +457,7 @@ key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
down_read(&cred->request_key_auth->sem);
if (key_validate(ctx->cred->request_key_auth) == 0) {
- rka = ctx->cred->request_key_auth->payload.data;
+ rka = ctx->cred->request_key_auth->payload.data[0];
ctx->cred = rka->cred;
key_ref = search_process_keyrings(ctx);
@@ -647,7 +647,7 @@ try_again:
key_ref = ERR_PTR(-EKEYREVOKED);
key = NULL;
} else {
- rka = ctx.cred->request_key_auth->payload.data;
+ rka = ctx.cred->request_key_auth->payload.data[0];
key = rka->dest_keyring;
__key_get(key);
}
@@ -794,6 +794,7 @@ long join_session_keyring(const char *name)
ret = PTR_ERR(keyring);
goto error2;
} else if (keyring == new->session_keyring) {
+ key_put(keyring);
ret = 0;
goto error2;
}
@@ -848,6 +849,7 @@ void key_change_session_keyring(struct callback_head *twork)
new->cap_inheritable = old->cap_inheritable;
new->cap_permitted = old->cap_permitted;
new->cap_effective = old->cap_effective;
+ new->cap_ambient = old->cap_ambient;
new->cap_bset = old->cap_bset;
new->jit_keyring = old->jit_keyring;
diff --git a/kernel/security/keys/request_key.c b/kernel/security/keys/request_key.c
index 486ef6fa3..c7a117c9a 100644
--- a/kernel/security/keys/request_key.c
+++ b/kernel/security/keys/request_key.c
@@ -271,7 +271,7 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
if (cred->request_key_auth) {
authkey = cred->request_key_auth;
down_read(&authkey->sem);
- rka = authkey->payload.data;
+ rka = authkey->payload.data[0];
if (!test_bit(KEY_FLAG_REVOKED,
&authkey->flags))
dest_keyring =
@@ -440,6 +440,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
kenter("");
+ if (ctx->index_key.type == &key_type_keyring)
+ return ERR_PTR(-EPERM);
+
user = key_user_lookup(current_fsuid());
if (!user)
return ERR_PTR(-ENOMEM);
@@ -593,7 +596,7 @@ int wait_for_key_construction(struct key *key, bool intr)
return -ERESTARTSYS;
if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
smp_rmb();
- return key->type_data.reject_error;
+ return key->reject_error;
}
return key_validate(key);
}
diff --git a/kernel/security/keys/request_key_auth.c b/kernel/security/keys/request_key_auth.c
index 5d672f758..4f0f112fe 100644
--- a/kernel/security/keys/request_key_auth.c
+++ b/kernel/security/keys/request_key_auth.c
@@ -59,7 +59,7 @@ static void request_key_auth_free_preparse(struct key_preparsed_payload *prep)
static int request_key_auth_instantiate(struct key *key,
struct key_preparsed_payload *prep)
{
- key->payload.data = (struct request_key_auth *)prep->data;
+ key->payload.data[0] = (struct request_key_auth *)prep->data;
return 0;
}
@@ -69,7 +69,7 @@ static int request_key_auth_instantiate(struct key *key,
static void request_key_auth_describe(const struct key *key,
struct seq_file *m)
{
- struct request_key_auth *rka = key->payload.data;
+ struct request_key_auth *rka = key->payload.data[0];
seq_puts(m, "key:");
seq_puts(m, key->description);
@@ -84,7 +84,7 @@ static void request_key_auth_describe(const struct key *key,
static long request_key_auth_read(const struct key *key,
char __user *buffer, size_t buflen)
{
- struct request_key_auth *rka = key->payload.data;
+ struct request_key_auth *rka = key->payload.data[0];
size_t datalen;
long ret;
@@ -110,7 +110,7 @@ static long request_key_auth_read(const struct key *key,
*/
static void request_key_auth_revoke(struct key *key)
{
- struct request_key_auth *rka = key->payload.data;
+ struct request_key_auth *rka = key->payload.data[0];
kenter("{%d}", key->serial);
@@ -125,7 +125,7 @@ static void request_key_auth_revoke(struct key *key)
*/
static void request_key_auth_destroy(struct key *key)
{
- struct request_key_auth *rka = key->payload.data;
+ struct request_key_auth *rka = key->payload.data[0];
kenter("{%d}", key->serial);
@@ -179,7 +179,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
goto auth_key_revoked;
- irka = cred->request_key_auth->payload.data;
+ irka = cred->request_key_auth->payload.data[0];
rka->cred = get_cred(irka->cred);
rka->pid = irka->pid;
diff --git a/kernel/security/keys/trusted.c b/kernel/security/keys/trusted.c
index c0594cb07..16dec5318 100644
--- a/kernel/security/keys/trusted.c
+++ b/kernel/security/keys/trusted.c
@@ -862,12 +862,19 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p,
static struct trusted_key_options *trusted_options_alloc(void)
{
struct trusted_key_options *options;
+ int tpm2;
+
+ tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
+ if (tpm2 < 0)
+ return NULL;
options = kzalloc(sizeof *options, GFP_KERNEL);
if (options) {
/* set any non-zero defaults */
options->keytype = SRK_keytype;
- options->keyhandle = SRKHANDLE;
+
+ if (!tpm2)
+ options->keyhandle = SRKHANDLE;
}
return options;
}
@@ -905,6 +912,11 @@ static int trusted_instantiate(struct key *key,
int ret = 0;
int key_cmd;
size_t key_len;
+ int tpm2;
+
+ tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
+ if (tpm2 < 0)
+ return tpm2;
if (datalen <= 0 || datalen > 32767 || !prep->data)
return -EINVAL;
@@ -932,12 +944,20 @@ static int trusted_instantiate(struct key *key,
goto out;
}
+ if (!options->keyhandle) {
+ ret = -EINVAL;
+ goto out;
+ }
+
dump_payload(payload);
dump_options(options);
switch (key_cmd) {
case Opt_load:
- ret = key_unseal(payload, options);
+ if (tpm2)
+ ret = tpm_unseal_trusted(TPM_ANY_NUM, payload, options);
+ else
+ ret = key_unseal(payload, options);
dump_payload(payload);
dump_options(options);
if (ret < 0)
@@ -950,7 +970,10 @@ static int trusted_instantiate(struct key *key,
pr_info("trusted_key: key_create failed (%d)\n", ret);
goto out;
}
- ret = key_seal(payload, options);
+ if (tpm2)
+ ret = tpm_seal_trusted(TPM_ANY_NUM, payload, options);
+ else
+ ret = key_seal(payload, options);
if (ret < 0)
pr_info("trusted_key: key_seal failed (%d)\n", ret);
break;
@@ -984,13 +1007,16 @@ static void trusted_rcu_free(struct rcu_head *rcu)
*/
static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
{
- struct trusted_key_payload *p = key->payload.data;
+ struct trusted_key_payload *p;
struct trusted_key_payload *new_p;
struct trusted_key_options *new_o;
size_t datalen = prep->datalen;
char *datablob;
int ret = 0;
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+ return -ENOKEY;
+ p = key->payload.data[0];
if (!p->migratable)
return -EPERM;
if (datalen <= 0 || datalen > 32767 || !prep->data)
@@ -1018,6 +1044,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
kfree(new_p);
goto out;
}
+
+ if (!new_o->keyhandle) {
+ ret = -EINVAL;
+ kfree(new_p);
+ goto out;
+ }
+
/* copy old key values, and reseal with new pcrs */
new_p->migratable = p->migratable;
new_p->key_len = p->key_len;
@@ -1084,12 +1117,12 @@ static long trusted_read(const struct key *key, char __user *buffer,
*/
static void trusted_destroy(struct key *key)
{
- struct trusted_key_payload *p = key->payload.data;
+ struct trusted_key_payload *p = key->payload.data[0];
if (!p)
return;
memset(p->key, 0, p->key_len);
- kfree(key->payload.data);
+ kfree(key->payload.data[0]);
}
struct key_type key_type_trusted = {
diff --git a/kernel/security/keys/trusted.h b/kernel/security/keys/trusted.h
index 3249fbd2b..ff001a5dc 100644
--- a/kernel/security/keys/trusted.h
+++ b/kernel/security/keys/trusted.h
@@ -2,7 +2,6 @@
#define __TRUSTED_KEY_H
/* implementation specific TPM constants */
-#define MAX_PCRINFO_SIZE 64
#define MAX_BUF_SIZE 512
#define TPM_GETRANDOM_SIZE 14
#define TPM_OSAP_SIZE 36
@@ -36,16 +35,6 @@ enum {
SRK_keytype = 4
};
-struct trusted_key_options {
- uint16_t keytype;
- uint32_t keyhandle;
- unsigned char keyauth[SHA1_DIGEST_SIZE];
- unsigned char blobauth[SHA1_DIGEST_SIZE];
- uint32_t pcrinfo_len;
- unsigned char pcrinfo[MAX_PCRINFO_SIZE];
- int pcrlock;
-};
-
#define TPM_DEBUG 0
#if TPM_DEBUG
diff --git a/kernel/security/keys/user_defined.c b/kernel/security/keys/user_defined.c
index 36b47bbd3..8705d79b2 100644
--- a/kernel/security/keys/user_defined.c
+++ b/kernel/security/keys/user_defined.c
@@ -74,7 +74,7 @@ int user_preparse(struct key_preparsed_payload *prep)
/* attach the data */
prep->quotalen = datalen;
- prep->payload[0] = upayload;
+ prep->payload.data[0] = upayload;
upayload->datalen = datalen;
memcpy(upayload->data, prep->data, datalen);
return 0;
@@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(user_preparse);
*/
void user_free_preparse(struct key_preparsed_payload *prep)
{
- kfree(prep->payload[0]);
+ kfree(prep->payload.data[0]);
}
EXPORT_SYMBOL_GPL(user_free_preparse);
@@ -120,7 +120,10 @@ int user_update(struct key *key, struct key_preparsed_payload *prep)
if (ret == 0) {
/* attach the new data, displacing the old */
- zap = key->payload.data;
+ if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+ zap = key->payload.data[0];
+ else
+ zap = NULL;
rcu_assign_keypointer(key, upayload);
key->expiry = 0;
}
@@ -140,7 +143,7 @@ EXPORT_SYMBOL_GPL(user_update);
*/
void user_revoke(struct key *key)
{
- struct user_key_payload *upayload = key->payload.data;
+ struct user_key_payload *upayload = key->payload.data[0];
/* clear the quota */
key_payload_reserve(key, 0);
@@ -158,7 +161,7 @@ EXPORT_SYMBOL(user_revoke);
*/
void user_destroy(struct key *key)
{
- struct user_key_payload *upayload = key->payload.data;
+ struct user_key_payload *upayload = key->payload.data[0];
kfree(upayload);
}
@@ -183,10 +186,10 @@ EXPORT_SYMBOL_GPL(user_describe);
*/
long user_read(const struct key *key, char __user *buffer, size_t buflen)
{
- struct user_key_payload *upayload;
+ const struct user_key_payload *upayload;
long ret;
- upayload = rcu_dereference_key(key);
+ upayload = user_key_payload(key);
ret = upayload->datalen;
/* we can return the data as is */