Merge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module signing support from Rusty Russell: "module signing is the highlight, but it's an all-over David Howells frenzy..." Hmm "Magrathea: Glacier signing key". Somebody has been reading too much HHGTTG. * 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (37 commits) X.509: Fix indefinite length element skip error handling X.509: Convert some printk calls to pr_devel asymmetric keys: fix printk format warning MODSIGN: Fix 32-bit overflow in X.509 certificate validity date checking MODSIGN: Make mrproper should remove generated files. MODSIGN: Use utf8 strings in signer's name in autogenerated X.509 certs MODSIGN: Use the same digest for the autogen key sig as for the module sig MODSIGN: Sign modules during the build process MODSIGN: Provide a script for generating a key ID from an X.509 cert MODSIGN: Implement module signature checking MODSIGN: Provide module signing public keys to the kernel MODSIGN: Automatically generate module signing keys if missing MODSIGN: Provide Kconfig options MODSIGN: Provide gitignore and make clean rules for extra files MODSIGN: Add FIPS policy module: signature checking hook X.509: Add a crypto key parser for binary (DER) X.509 certificates MPILIB: Provide a function to read raw data into an MPI X.509: Add an ASN.1 decoder X.509: Add simple ASN.1 grammar compiler ...
This commit is contained in:
@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
|
||||
*
|
||||
* On success, return 0. Otherwise return errno.
|
||||
*/
|
||||
static int encrypted_instantiate(struct key *key, const void *data,
|
||||
size_t datalen)
|
||||
static int encrypted_instantiate(struct key *key,
|
||||
struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct encrypted_key_payload *epayload = NULL;
|
||||
char *datablob = NULL;
|
||||
@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data,
|
||||
char *master_desc = NULL;
|
||||
char *decrypted_datalen = NULL;
|
||||
char *hex_encoded_iv = NULL;
|
||||
size_t datalen = prep->datalen;
|
||||
int ret;
|
||||
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
return -EINVAL;
|
||||
|
||||
datablob = kmalloc(datalen + 1, GFP_KERNEL);
|
||||
if (!datablob)
|
||||
return -ENOMEM;
|
||||
datablob[datalen] = 0;
|
||||
memcpy(datablob, data, datalen);
|
||||
memcpy(datablob, prep->data, datalen);
|
||||
ret = datablob_parse(datablob, &format, &master_desc,
|
||||
&decrypted_datalen, &hex_encoded_iv);
|
||||
if (ret < 0)
|
||||
@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu)
|
||||
*
|
||||
* On success, return 0. Otherwise return errno.
|
||||
*/
|
||||
static int encrypted_update(struct key *key, const void *data, size_t datalen)
|
||||
static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct encrypted_key_payload *epayload = key->payload.data;
|
||||
struct encrypted_key_payload *new_epayload;
|
||||
char *buf;
|
||||
char *new_master_desc = NULL;
|
||||
const char *format = NULL;
|
||||
size_t datalen = prep->datalen;
|
||||
int ret = 0;
|
||||
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kmalloc(datalen + 1, GFP_KERNEL);
|
||||
@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
|
||||
return -ENOMEM;
|
||||
|
||||
buf[datalen] = 0;
|
||||
memcpy(buf, data, datalen);
|
||||
memcpy(buf, prep->data, datalen);
|
||||
ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@@ -405,8 +405,7 @@ EXPORT_SYMBOL(key_payload_reserve);
|
||||
* key_construction_mutex.
|
||||
*/
|
||||
static int __key_instantiate_and_link(struct key *key,
|
||||
const void *data,
|
||||
size_t datalen,
|
||||
struct key_preparsed_payload *prep,
|
||||
struct key *keyring,
|
||||
struct key *authkey,
|
||||
unsigned long *_prealloc)
|
||||
@@ -424,7 +423,7 @@ static int __key_instantiate_and_link(struct key *key,
|
||||
/* can't instantiate twice */
|
||||
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
|
||||
/* instantiate the key */
|
||||
ret = key->type->instantiate(key, data, datalen);
|
||||
ret = key->type->instantiate(key, prep);
|
||||
|
||||
if (ret == 0) {
|
||||
/* mark the key as being instantiated */
|
||||
@@ -475,22 +474,37 @@ int key_instantiate_and_link(struct key *key,
|
||||
struct key *keyring,
|
||||
struct key *authkey)
|
||||
{
|
||||
struct key_preparsed_payload prep;
|
||||
unsigned long prealloc;
|
||||
int ret;
|
||||
|
||||
memset(&prep, 0, sizeof(prep));
|
||||
prep.data = data;
|
||||
prep.datalen = datalen;
|
||||
prep.quotalen = key->type->def_datalen;
|
||||
if (key->type->preparse) {
|
||||
ret = key->type->preparse(&prep);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (keyring) {
|
||||
ret = __key_link_begin(keyring, key->type, key->description,
|
||||
&prealloc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto error_free_preparse;
|
||||
}
|
||||
|
||||
ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey,
|
||||
ret = __key_instantiate_and_link(key, &prep, keyring, authkey,
|
||||
&prealloc);
|
||||
|
||||
if (keyring)
|
||||
__key_link_end(keyring, key->type, prealloc);
|
||||
|
||||
error_free_preparse:
|
||||
if (key->type->preparse)
|
||||
key->type->free_preparse(&prep);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -699,7 +713,7 @@ void key_type_put(struct key_type *ktype)
|
||||
* if we get an error.
|
||||
*/
|
||||
static inline key_ref_t __key_update(key_ref_t key_ref,
|
||||
const void *payload, size_t plen)
|
||||
struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct key *key = key_ref_to_ptr(key_ref);
|
||||
int ret;
|
||||
@@ -715,7 +729,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
|
||||
|
||||
down_write(&key->sem);
|
||||
|
||||
ret = key->type->update(key, payload, plen);
|
||||
ret = key->type->update(key, prep);
|
||||
if (ret == 0)
|
||||
/* updating a negative key instantiates it */
|
||||
clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
|
||||
@@ -767,6 +781,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||
unsigned long flags)
|
||||
{
|
||||
unsigned long prealloc;
|
||||
struct key_preparsed_payload prep;
|
||||
const struct cred *cred = current_cred();
|
||||
struct key_type *ktype;
|
||||
struct key *keyring, *key = NULL;
|
||||
@@ -782,8 +797,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||
}
|
||||
|
||||
key_ref = ERR_PTR(-EINVAL);
|
||||
if (!ktype->match || !ktype->instantiate)
|
||||
goto error_2;
|
||||
if (!ktype->match || !ktype->instantiate ||
|
||||
(!description && !ktype->preparse))
|
||||
goto error_put_type;
|
||||
|
||||
keyring = key_ref_to_ptr(keyring_ref);
|
||||
|
||||
@@ -791,18 +807,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||
|
||||
key_ref = ERR_PTR(-ENOTDIR);
|
||||
if (keyring->type != &key_type_keyring)
|
||||
goto error_2;
|
||||
goto error_put_type;
|
||||
|
||||
memset(&prep, 0, sizeof(prep));
|
||||
prep.data = payload;
|
||||
prep.datalen = plen;
|
||||
prep.quotalen = ktype->def_datalen;
|
||||
if (ktype->preparse) {
|
||||
ret = ktype->preparse(&prep);
|
||||
if (ret < 0) {
|
||||
key_ref = ERR_PTR(ret);
|
||||
goto error_put_type;
|
||||
}
|
||||
if (!description)
|
||||
description = prep.description;
|
||||
key_ref = ERR_PTR(-EINVAL);
|
||||
if (!description)
|
||||
goto error_free_prep;
|
||||
}
|
||||
|
||||
ret = __key_link_begin(keyring, ktype, description, &prealloc);
|
||||
if (ret < 0)
|
||||
goto error_2;
|
||||
if (ret < 0) {
|
||||
key_ref = ERR_PTR(ret);
|
||||
goto error_free_prep;
|
||||
}
|
||||
|
||||
/* if we're going to allocate a new key, we're going to have
|
||||
* to modify the keyring */
|
||||
ret = key_permission(keyring_ref, KEY_WRITE);
|
||||
if (ret < 0) {
|
||||
key_ref = ERR_PTR(ret);
|
||||
goto error_3;
|
||||
goto error_link_end;
|
||||
}
|
||||
|
||||
/* if it's possible to update this type of key, search for an existing
|
||||
@@ -833,25 +868,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||
perm, flags);
|
||||
if (IS_ERR(key)) {
|
||||
key_ref = ERR_CAST(key);
|
||||
goto error_3;
|
||||
goto error_link_end;
|
||||
}
|
||||
|
||||
/* instantiate it and link it into the target keyring */
|
||||
ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL,
|
||||
&prealloc);
|
||||
ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc);
|
||||
if (ret < 0) {
|
||||
key_put(key);
|
||||
key_ref = ERR_PTR(ret);
|
||||
goto error_3;
|
||||
goto error_link_end;
|
||||
}
|
||||
|
||||
key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
|
||||
|
||||
error_3:
|
||||
error_link_end:
|
||||
__key_link_end(keyring, ktype, prealloc);
|
||||
error_2:
|
||||
error_free_prep:
|
||||
if (ktype->preparse)
|
||||
ktype->free_preparse(&prep);
|
||||
error_put_type:
|
||||
key_type_put(ktype);
|
||||
error:
|
||||
error:
|
||||
return key_ref;
|
||||
|
||||
found_matching_key:
|
||||
@@ -859,10 +896,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||
* - we can drop the locks first as we have the key pinned
|
||||
*/
|
||||
__key_link_end(keyring, ktype, prealloc);
|
||||
key_type_put(ktype);
|
||||
|
||||
key_ref = __key_update(key_ref, payload, plen);
|
||||
goto error;
|
||||
key_ref = __key_update(key_ref, &prep);
|
||||
goto error_free_prep;
|
||||
}
|
||||
EXPORT_SYMBOL(key_create_or_update);
|
||||
|
||||
@@ -881,6 +917,7 @@ EXPORT_SYMBOL(key_create_or_update);
|
||||
*/
|
||||
int key_update(key_ref_t key_ref, const void *payload, size_t plen)
|
||||
{
|
||||
struct key_preparsed_payload prep;
|
||||
struct key *key = key_ref_to_ptr(key_ref);
|
||||
int ret;
|
||||
|
||||
@@ -893,18 +930,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
|
||||
|
||||
/* attempt to update it if supported */
|
||||
ret = -EOPNOTSUPP;
|
||||
if (key->type->update) {
|
||||
down_write(&key->sem);
|
||||
if (!key->type->update)
|
||||
goto error;
|
||||
|
||||
ret = key->type->update(key, payload, plen);
|
||||
if (ret == 0)
|
||||
/* updating a negative key instantiates it */
|
||||
clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
|
||||
|
||||
up_write(&key->sem);
|
||||
memset(&prep, 0, sizeof(prep));
|
||||
prep.data = payload;
|
||||
prep.datalen = plen;
|
||||
prep.quotalen = key->type->def_datalen;
|
||||
if (key->type->preparse) {
|
||||
ret = key->type->preparse(&prep);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
down_write(&key->sem);
|
||||
|
||||
ret = key->type->update(key, &prep);
|
||||
if (ret == 0)
|
||||
/* updating a negative key instantiates it */
|
||||
clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
|
||||
|
||||
up_write(&key->sem);
|
||||
|
||||
if (key->type->preparse)
|
||||
key->type->free_preparse(&prep);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(key_update);
|
||||
|
@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type,
|
||||
* Extract the description of a new key from userspace and either add it as a
|
||||
* new key to the specified keyring or update a matching key in that keyring.
|
||||
*
|
||||
* If the description is NULL or an empty string, the key type is asked to
|
||||
* generate one from the payload.
|
||||
*
|
||||
* The keyring must be writable so that we can attach the key to it.
|
||||
*
|
||||
* If successful, the new key's serial number is returned, otherwise an error
|
||||
@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
description = strndup_user(_description, PAGE_SIZE);
|
||||
if (IS_ERR(description)) {
|
||||
ret = PTR_ERR(description);
|
||||
goto error;
|
||||
description = NULL;
|
||||
if (_description) {
|
||||
description = strndup_user(_description, PAGE_SIZE);
|
||||
if (IS_ERR(description)) {
|
||||
ret = PTR_ERR(description);
|
||||
goto error;
|
||||
}
|
||||
if (!*description) {
|
||||
kfree(description);
|
||||
description = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* pull the payload in if one was supplied */
|
||||
|
@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc)
|
||||
* operations.
|
||||
*/
|
||||
static int keyring_instantiate(struct key *keyring,
|
||||
const void *data, size_t datalen);
|
||||
struct key_preparsed_payload *prep);
|
||||
static int keyring_match(const struct key *keyring, const void *criterion);
|
||||
static void keyring_revoke(struct key *keyring);
|
||||
static void keyring_destroy(struct key *keyring);
|
||||
@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring)
|
||||
* Returns 0 on success, -EINVAL if given any data.
|
||||
*/
|
||||
static int keyring_instantiate(struct key *keyring,
|
||||
const void *data, size_t datalen)
|
||||
struct key_preparsed_payload *prep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen == 0) {
|
||||
if (prep->datalen == 0) {
|
||||
/* make the keyring available by name if it has one */
|
||||
keyring_publish_name(keyring);
|
||||
ret = 0;
|
||||
|
@@ -19,7 +19,8 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int request_key_auth_instantiate(struct key *, const void *, size_t);
|
||||
static int request_key_auth_instantiate(struct key *,
|
||||
struct key_preparsed_payload *);
|
||||
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 *);
|
||||
@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = {
|
||||
* Instantiate a request-key authorisation key.
|
||||
*/
|
||||
static int request_key_auth_instantiate(struct key *key,
|
||||
const void *data,
|
||||
size_t datalen)
|
||||
struct key_preparsed_payload *prep)
|
||||
{
|
||||
key->payload.data = (struct request_key_auth *) data;
|
||||
key->payload.data = (struct request_key_auth *)prep->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -895,23 +895,24 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
|
||||
*
|
||||
* On success, return 0. Otherwise return errno.
|
||||
*/
|
||||
static int trusted_instantiate(struct key *key, const void *data,
|
||||
size_t datalen)
|
||||
static int trusted_instantiate(struct key *key,
|
||||
struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct trusted_key_payload *payload = NULL;
|
||||
struct trusted_key_options *options = NULL;
|
||||
size_t datalen = prep->datalen;
|
||||
char *datablob;
|
||||
int ret = 0;
|
||||
int key_cmd;
|
||||
size_t key_len;
|
||||
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
return -EINVAL;
|
||||
|
||||
datablob = kmalloc(datalen + 1, GFP_KERNEL);
|
||||
if (!datablob)
|
||||
return -ENOMEM;
|
||||
memcpy(datablob, data, datalen);
|
||||
memcpy(datablob, prep->data, datalen);
|
||||
datablob[datalen] = '\0';
|
||||
|
||||
options = trusted_options_alloc();
|
||||
@@ -981,17 +982,18 @@ static void trusted_rcu_free(struct rcu_head *rcu)
|
||||
/*
|
||||
* trusted_update - reseal an existing key with new PCR values
|
||||
*/
|
||||
static int trusted_update(struct key *key, const void *data, size_t datalen)
|
||||
static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct trusted_key_payload *p = key->payload.data;
|
||||
struct trusted_key_payload *new_p;
|
||||
struct trusted_key_options *new_o;
|
||||
size_t datalen = prep->datalen;
|
||||
char *datablob;
|
||||
int ret = 0;
|
||||
|
||||
if (!p->migratable)
|
||||
return -EPERM;
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
return -EINVAL;
|
||||
|
||||
datablob = kmalloc(datalen + 1, GFP_KERNEL);
|
||||
@@ -1008,7 +1010,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen)
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(datablob, data, datalen);
|
||||
memcpy(datablob, prep->data, datalen);
|
||||
datablob[datalen] = '\0';
|
||||
ret = datablob_parse(datablob, new_p, new_o);
|
||||
if (ret != Opt_update) {
|
||||
|
@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon);
|
||||
/*
|
||||
* instantiate a user defined key
|
||||
*/
|
||||
int user_instantiate(struct key *key, const void *data, size_t datalen)
|
||||
int user_instantiate(struct key *key, struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct user_key_payload *upayload;
|
||||
size_t datalen = prep->datalen;
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
goto error;
|
||||
|
||||
ret = key_payload_reserve(key, datalen);
|
||||
@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen)
|
||||
|
||||
/* attach the data */
|
||||
upayload->datalen = datalen;
|
||||
memcpy(upayload->data, data, datalen);
|
||||
memcpy(upayload->data, prep->data, datalen);
|
||||
rcu_assign_keypointer(key, upayload);
|
||||
ret = 0;
|
||||
|
||||
@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate);
|
||||
* update a user defined key
|
||||
* - the key's semaphore is write-locked
|
||||
*/
|
||||
int user_update(struct key *key, const void *data, size_t datalen)
|
||||
int user_update(struct key *key, struct key_preparsed_payload *prep)
|
||||
{
|
||||
struct user_key_payload *upayload, *zap;
|
||||
size_t datalen = prep->datalen;
|
||||
int ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (datalen <= 0 || datalen > 32767 || !data)
|
||||
if (datalen <= 0 || datalen > 32767 || !prep->data)
|
||||
goto error;
|
||||
|
||||
/* construct a replacement payload */
|
||||
@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
|
||||
goto error;
|
||||
|
||||
upayload->datalen = datalen;
|
||||
memcpy(upayload->data, data, datalen);
|
||||
memcpy(upayload->data, prep->data, datalen);
|
||||
|
||||
/* check the quota and attach the new data */
|
||||
zap = upayload;
|
||||
|
Reference in New Issue
Block a user