lkml.org 
[lkml]   [2013]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: [PATCH 6/9] KEYS: Trusted: Use key preparsing
From
Date
On Mon, 2013-11-04 at 16:23 +0000, David Howells wrote:
> Make use of key preparsing in trusted keys so that quota size determination
> can take place prior to keyring locking when a key is being added.
>
> Signed-off-by: David Howells <dhowells@redhat.com>

Cc'ing Dave Safford.

> ---
>
> security/keys/trusted.c | 190 ++++++++++++++++++++++-------------------------
> 1 file changed, 90 insertions(+), 100 deletions(-)
>
> diff --git a/security/keys/trusted.c b/security/keys/trusted.c
> index e13fcf7636f7..ac444e3cfaa7 100644
> --- a/security/keys/trusted.c
> +++ b/security/keys/trusted.c
> @@ -859,52 +859,22 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p,
> return ret;
> }
>
> -static struct trusted_key_options *trusted_options_alloc(void)
> -{
> - struct trusted_key_options *options;
> -
> - options = kzalloc(sizeof *options, GFP_KERNEL);
> - if (options) {
> - /* set any non-zero defaults */
> - options->keytype = SRK_keytype;
> - options->keyhandle = SRKHANDLE;
> - }
> - return options;
> -}
> -
> -static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
> -{
> - struct trusted_key_payload *p = NULL;
> - int ret;
> -
> - ret = key_payload_reserve(key, sizeof *p);
> - if (ret < 0)
> - return p;
> - p = kzalloc(sizeof *p, GFP_KERNEL);
> - if (p)
> - p->migratable = 1; /* migratable by default */
> - return p;
> -}
> -
> /*
> - * trusted_instantiate - create a new trusted key
> + * trusted_preparse - Preparse data for an trusted key
> *
> - * Unseal an existing trusted blob or, for a new key, get a
> - * random key, then seal and create a trusted key-type key,
> - * adding it to the specified keyring.
> + * Decrypt an existing encrypted datablob or create a new encrypted key
> + * based on a kernel random number.

Not sure why the change in terminology from unsealing/trusted blob to
decrypt/encrypted blob.

> * On success, return 0. Otherwise return errno.
> */
> -static int trusted_instantiate(struct key *key,
> - struct key_preparsed_payload *prep)
> +static int trusted_preparse(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;
> + long key_cmd;
> + int ret = -ENOMEM;
>
> if (datalen <= 0 || datalen > 32767 || !prep->data)
> return -EINVAL;
> @@ -915,16 +885,20 @@ static int trusted_instantiate(struct key *key,
> memcpy(datablob, prep->data, datalen);
> datablob[datalen] = '\0';
>
> - options = trusted_options_alloc();
> - if (!options) {
> - ret = -ENOMEM;
> + payload = kzalloc(sizeof(*payload), GFP_KERNEL);
> + if (!payload)
> goto out;
> - }
> - payload = trusted_payload_alloc(key);
> - if (!payload) {
> - ret = -ENOMEM;
> + prep->payload[0] = payload;
> +
> + options = kzalloc(sizeof(*options), GFP_KERNEL);
> + if (!options)
> goto out;
> - }
> + prep->type_data[0] = options;
> +
> + /* set any non-zero defaults */
> + payload->migratable = 1; /* migratable by default */
> + options->keytype = SRK_keytype;
> + options->keyhandle = SRKHANDLE;
>
> key_cmd = datablob_parse(datablob, payload, options);
> if (key_cmd < 0) {
> @@ -932,42 +906,81 @@ static int trusted_instantiate(struct key *key,
> goto out;
> }
>
> + prep->type_data[1] = (void *)key_cmd;
> +
> dump_payload(payload);
> dump_options(options);
> +out:
> + kfree(datablob);
> + return ret;

trusted_preparse() always fails, since ret is initialized to -ENOMEM and
never set.

Mimi

> +}
> +
> +static void trusted_free_preparse(struct key_preparsed_payload *prep)
> +{
> + struct trusted_key_payload *p = prep->payload[0];
> + struct trusted_key_options *o = prep->type_data[0];
> +
> + if (p) {
> + memset(p->key, 0, p->key_len);
> + kfree(p);
> + }
> + kfree(o);
> +}
> +
> +/*
> + * trusted_instantiate - create a new trusted key
> + *
> + * Unseal an existing trusted blob or, for a new key, get a
> + * random key, then seal and create a trusted key-type key,
> + * adding it to the specified keyring.
> + *
> + * On success, return 0. Otherwise return errno.
> + */
> +static int trusted_instantiate(struct key *key,
> + struct key_preparsed_payload *prep)
> +{
> + struct trusted_key_payload *payload = prep->payload[0];
> + struct trusted_key_options *options = prep->type_data[0];
> + long key_cmd = (unsigned long)prep->type_data[1];
> + int ret;
> + size_t key_len;
>
> switch (key_cmd) {
> case Opt_load:
> ret = key_unseal(payload, options);
> dump_payload(payload);
> dump_options(options);
> - if (ret < 0)
> + if (ret < 0) {
> pr_info("trusted_key: key_unseal failed (%d)\n", ret);
> + return ret;
> + }
> break;
> case Opt_new:
> key_len = payload->key_len;
> ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
> if (ret != key_len) {
> pr_info("trusted_key: key_create failed (%d)\n", ret);
> - goto out;
> + return ret;
> }
> ret = key_seal(payload, options);
> - if (ret < 0)
> + if (ret < 0) {
> pr_info("trusted_key: key_seal failed (%d)\n", ret);
> + return ret;
> + }
> break;
> default:
> - ret = -EINVAL;
> - goto out;
> + return -EINVAL;
> }
> - if (!ret && options->pcrlock)
> +
> + if (options->pcrlock) {
> ret = pcrlock(options->pcrlock);
> -out:
> - kfree(datablob);
> - kfree(options);
> - if (!ret)
> - rcu_assign_keypointer(key, payload);
> - else
> - kfree(payload);
> - return ret;
> + if (ret < 0)
> + return ret;
> + }
> +
> + rcu_assign_keypointer(key, prep->payload[0]);
> + prep->payload[0] = NULL;
> + return 0;
> }
>
> static void trusted_rcu_free(struct rcu_head *rcu)
> @@ -985,39 +998,17 @@ 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 *new_p;
> - struct trusted_key_options *new_o;
> - size_t datalen = prep->datalen;
> - char *datablob;
> + struct trusted_key_payload *new_p = prep->payload[0];
> + struct trusted_key_options *new_o = prep->type_data[0];
> + long key_cmd = (unsigned long)prep->type_data[1];
> int ret = 0;
>
> if (!p->migratable)
> return -EPERM;
> - if (datalen <= 0 || datalen > 32767 || !prep->data)
> - return -EINVAL;
>
> - datablob = kmalloc(datalen + 1, GFP_KERNEL);
> - if (!datablob)
> - return -ENOMEM;
> - new_o = trusted_options_alloc();
> - if (!new_o) {
> - ret = -ENOMEM;
> - goto out;
> - }
> - new_p = trusted_payload_alloc(key);
> - if (!new_p) {
> - ret = -ENOMEM;
> - goto out;
> - }
> + if (key_cmd != Opt_update)
> + return -EINVAL;
>
> - memcpy(datablob, prep->data, datalen);
> - datablob[datalen] = '\0';
> - ret = datablob_parse(datablob, new_p, new_o);
> - if (ret != Opt_update) {
> - 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;
> @@ -1028,23 +1019,19 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
> ret = key_seal(new_p, new_o);
> if (ret < 0) {
> pr_info("trusted_key: key_seal failed (%d)\n", ret);
> - kfree(new_p);
> - goto out;
> + return ret;
> }
> if (new_o->pcrlock) {
> ret = pcrlock(new_o->pcrlock);
> if (ret < 0) {
> pr_info("trusted_key: pcrlock failed (%d)\n", ret);
> - kfree(new_p);
> - goto out;
> + return ret;
> }
> }
> rcu_assign_keypointer(key, new_p);
> call_rcu(&p->rcu, trusted_rcu_free);
> -out:
> - kfree(datablob);
> - kfree(new_o);
> - return ret;
> + prep->payload[0] = NULL;
> + return 0;
> }
>
> /*
> @@ -1093,13 +1080,16 @@ static void trusted_destroy(struct key *key)
> }
>
> struct key_type key_type_trusted = {
> - .name = "trusted",
> - .instantiate = trusted_instantiate,
> - .update = trusted_update,
> - .match = user_match,
> - .destroy = trusted_destroy,
> - .describe = user_describe,
> - .read = trusted_read,
> + .name = "trusted",
> + .def_datalen = sizeof(struct trusted_key_payload),
> + .preparse = trusted_preparse,
> + .free_preparse = trusted_free_preparse,
> + .instantiate = trusted_instantiate,
> + .update = trusted_update,
> + .match = user_match,
> + .destroy = trusted_destroy,
> + .describe = user_describe,
> + .read = trusted_read,
> };
>
> EXPORT_SYMBOL_GPL(key_type_trusted);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>




\
 
 \ /
  Last update: 2013-11-13 18:01    [W:1.084 / U:0.116 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site