Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KEYS: Asymmetric key pluggable data parsers

The instantiation data passed to the asymmetric key type are expected to be
formatted in some way, and there are several possible standard ways to format
the data.

The two obvious standards are OpenPGP keys and X.509 certificates. The latter
is especially useful when dealing with UEFI, and the former might be useful
when dealing with, say, eCryptfs.

Further, it might be desirable to provide formatted blobs that indicate
hardware is to be accessed to retrieve the keys or that the keys live
unretrievably in a hardware store, but that the keys can be used by means of
the hardware.

From userspace, the keys can be loaded using the keyctl command, for example,
an X.509 binary certificate:

keyctl padd asymmetric foo @s <dhowells.pem

or a PGP key:

keyctl padd asymmetric bar @s <dhowells.pub

or a pointer into the contents of the TPM:

keyctl add asymmetric zebra "TPM:04982390582905f8" @s

Inside the kernel, pluggable parsers register themselves and then get to
examine the payload data to see if they can handle it. If they can, they get
to:

(1) Propose a name for the key, to be used it the name is "" or NULL.

(2) Specify the key subtype.

(3) Provide the data for the subtype.

The key type asks the parser to do its stuff before a key is allocated and thus
before the name is set. If successful, the parser stores the suggested data
into the key_preparsed_payload struct, which will be either used (if the key is
successfully created and instantiated or updated) or discarded.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

David Howells and committed by
Rusty Russell
46c6f177 964f3b3b

+156 -1
+119 -1
crypto/asymmetric_keys/asymmetric_type.c
··· 11 11 * 2 of the Licence, or (at your option) any later version. 12 12 */ 13 13 #include <keys/asymmetric-subtype.h> 14 + #include <keys/asymmetric-parser.h> 14 15 #include <linux/seq_file.h> 15 16 #include <linux/module.h> 16 17 #include <linux/slab.h> 17 18 #include "asymmetric_keys.h" 18 19 19 20 MODULE_LICENSE("GPL"); 21 + 22 + static LIST_HEAD(asymmetric_key_parsers); 23 + static DECLARE_RWSEM(asymmetric_key_parsers_sem); 20 24 21 25 /* 22 26 * Match asymmetric keys on (part of) their name ··· 111 107 } 112 108 113 109 /* 110 + * Preparse a asymmetric payload to get format the contents appropriately for the 111 + * internal payload to cut down on the number of scans of the data performed. 112 + * 113 + * We also generate a proposed description from the contents of the key that 114 + * can be used to name the key if the user doesn't want to provide one. 115 + */ 116 + static int asymmetric_key_preparse(struct key_preparsed_payload *prep) 117 + { 118 + struct asymmetric_key_parser *parser; 119 + int ret; 120 + 121 + pr_devel("==>%s()\n", __func__); 122 + 123 + if (prep->datalen == 0) 124 + return -EINVAL; 125 + 126 + down_read(&asymmetric_key_parsers_sem); 127 + 128 + ret = -EBADMSG; 129 + list_for_each_entry(parser, &asymmetric_key_parsers, link) { 130 + pr_debug("Trying parser '%s'\n", parser->name); 131 + 132 + ret = parser->parse(prep); 133 + if (ret != -EBADMSG) { 134 + pr_debug("Parser recognised the format (ret %d)\n", 135 + ret); 136 + break; 137 + } 138 + } 139 + 140 + up_read(&asymmetric_key_parsers_sem); 141 + pr_devel("<==%s() = %d\n", __func__, ret); 142 + return ret; 143 + } 144 + 145 + /* 146 + * Clean up the preparse data 147 + */ 148 + static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) 149 + { 150 + struct asymmetric_key_subtype *subtype = prep->type_data[0]; 151 + 152 + pr_devel("==>%s()\n", __func__); 153 + 154 + if (subtype) { 155 + subtype->destroy(prep->payload); 156 + module_put(subtype->owner); 157 + } 158 + kfree(prep->type_data[1]); 159 + kfree(prep->description); 160 + } 161 + 162 + /* 114 163 * Instantiate a asymmetric_key defined key. The key was preparsed, so we just 115 164 * have to transfer the data here. 116 165 */ 117 166 static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) 118 167 { 119 - return -EOPNOTSUPP; 168 + int ret; 169 + 170 + pr_devel("==>%s()\n", __func__); 171 + 172 + ret = key_payload_reserve(key, prep->quotalen); 173 + if (ret == 0) { 174 + key->type_data.p[0] = prep->type_data[0]; 175 + key->type_data.p[1] = prep->type_data[1]; 176 + key->payload.data = prep->payload; 177 + prep->type_data[0] = NULL; 178 + prep->type_data[1] = NULL; 179 + prep->payload = NULL; 180 + } 181 + pr_devel("<==%s() = %d\n", __func__, ret); 182 + return ret; 120 183 } 121 184 122 185 /* ··· 203 132 204 133 struct key_type key_type_asymmetric = { 205 134 .name = "asymmetric", 135 + .preparse = asymmetric_key_preparse, 136 + .free_preparse = asymmetric_key_free_preparse, 206 137 .instantiate = asymmetric_key_instantiate, 207 138 .match = asymmetric_key_match, 208 139 .destroy = asymmetric_key_destroy, 209 140 .describe = asymmetric_key_describe, 210 141 }; 211 142 EXPORT_SYMBOL_GPL(key_type_asymmetric); 143 + 144 + /** 145 + * register_asymmetric_key_parser - Register a asymmetric key blob parser 146 + * @parser: The parser to register 147 + */ 148 + int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) 149 + { 150 + struct asymmetric_key_parser *cursor; 151 + int ret; 152 + 153 + down_write(&asymmetric_key_parsers_sem); 154 + 155 + list_for_each_entry(cursor, &asymmetric_key_parsers, link) { 156 + if (strcmp(cursor->name, parser->name) == 0) { 157 + pr_err("Asymmetric key parser '%s' already registered\n", 158 + parser->name); 159 + ret = -EEXIST; 160 + goto out; 161 + } 162 + } 163 + 164 + list_add_tail(&parser->link, &asymmetric_key_parsers); 165 + 166 + pr_notice("Asymmetric key parser '%s' registered\n", parser->name); 167 + ret = 0; 168 + 169 + out: 170 + up_write(&asymmetric_key_parsers_sem); 171 + return ret; 172 + } 173 + EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); 174 + 175 + /** 176 + * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser 177 + * @parser: The parser to unregister 178 + */ 179 + void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) 180 + { 181 + down_write(&asymmetric_key_parsers_sem); 182 + list_del(&parser->link); 183 + up_write(&asymmetric_key_parsers_sem); 184 + 185 + pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); 186 + } 187 + EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); 212 188 213 189 /* 214 190 * Module stuff
+37
include/keys/asymmetric-parser.h
··· 1 + /* Asymmetric public-key cryptography data parser 2 + * 3 + * See Documentation/crypto/asymmetric-keys.txt 4 + * 5 + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 6 + * Written by David Howells (dhowells@redhat.com) 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public Licence 10 + * as published by the Free Software Foundation; either version 11 + * 2 of the Licence, or (at your option) any later version. 12 + */ 13 + 14 + #ifndef _KEYS_ASYMMETRIC_PARSER_H 15 + #define _KEYS_ASYMMETRIC_PARSER_H 16 + 17 + /* 18 + * Key data parser. Called during key instantiation. 19 + */ 20 + struct asymmetric_key_parser { 21 + struct list_head link; 22 + struct module *owner; 23 + const char *name; 24 + 25 + /* Attempt to parse a key from the data blob passed to add_key() or 26 + * keyctl_instantiate(). Should also generate a proposed description 27 + * that the caller can optionally use for the key. 28 + * 29 + * Return EBADMSG if not recognised. 30 + */ 31 + int (*parse)(struct key_preparsed_payload *prep); 32 + }; 33 + 34 + extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); 35 + extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); 36 + 37 + #endif /* _KEYS_ASYMMETRIC_PARSER_H */