summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys/asymmetric_type.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-09-16 17:36:13 +0100
committerDavid Howells <dhowells@redhat.com>2014-09-16 17:36:13 +0100
commit46963b774d441c833afc1535f6d84b3df2a94204 (patch)
tree335cbd163ef2581b72d462f49984a6809609a58b /crypto/asymmetric_keys/asymmetric_type.c
parent7901c1a8effbe5f89673bfc09d6e37b8f334f1a7 (diff)
KEYS: Overhaul key identification when searching for asymmetric keys
Make use of the new match string preparsing to overhaul key identification when searching for asymmetric keys. The following changes are made: (1) Use the previously created asymmetric_key_id struct to hold the following key IDs derived from the X.509 certificate or PKCS#7 message: id: serial number + issuer skid: subjKeyId + subject authority: authKeyId + issuer (2) Replace the hex fingerprint attached to key->type_data[1] with an asymmetric_key_ids struct containing the id and the skid (if present). (3) Make the asymmetric_type match data preparse select one of two searches: (a) An iterative search for the key ID given if prefixed with "id:". The prefix is expected to be followed by a hex string giving the ID to search for. The criterion key ID is checked against all key IDs recorded on the key. (b) A direct search if the key ID is not prefixed with "id:". This will look for an exact match on the key description. (4) Make x509_request_asymmetric_key() take a key ID. This is then converted into "id:<hex>" and passed into keyring_search() where match preparsing will turn it back into a binary ID. (5) X.509 certificate verification then takes the authority key ID and looks up a key that matches it to find the public key for the certificate signature. (6) PKCS#7 certificate verification then takes the id key ID and looks up a key that matches it to find the public key for the signed information block signature. Additional changes: (1) Multiple subjKeyId and authKeyId values on an X.509 certificate cause the cert to be rejected with -EBADMSG. (2) The 'fingerprint' ID is gone. This was primarily intended to convey PGP public key fingerprints. If PGP is supported in future, this should generate a key ID that carries the fingerprint. (3) Th ca_keyid= kernel command line option is now converted to a key ID and used to match the authority key ID. Possibly this should only match the actual authKeyId part and not the issuer as well. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'crypto/asymmetric_keys/asymmetric_type.c')
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c133
1 files changed, 56 insertions, 77 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 92bfc438dd1d..718e779a010e 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -112,76 +112,15 @@ struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
}
/*
- * Match asymmetric key id with partial match
- * @id: key id to match in a form "id:<id>"
- */
-int asymmetric_keyid_match(const char *kid, const char *id)
-{
- size_t idlen, kidlen;
-
- if (!kid || !id)
- return 0;
-
- /* make it possible to use id as in the request: "id:<id>" */
- if (strncmp(id, "id:", 3) == 0)
- id += 3;
-
- /* Anything after here requires a partial match on the ID string */
- idlen = strlen(id);
- kidlen = strlen(kid);
- if (idlen > kidlen)
- return 0;
-
- kid += kidlen - idlen;
- if (strcasecmp(id, kid) != 0)
- return 0;
-
- return 1;
-}
-EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
-
-/*
- * Match asymmetric keys on (part of) their name
- * We have some shorthand methods for matching keys. We allow:
- *
- * "<desc>" - request a key by description
- * "id:<id>" - request a key matching the ID
- * "<subtype>:<id>" - request a key of a subtype
+ * Match asymmetric keys by ID.
*/
static bool asymmetric_key_cmp(const struct key *key,
const struct key_match_data *match_data)
{
- const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
- const char *description = match_data->raw_data;
- const char *spec = description;
- const char *id;
- ptrdiff_t speclen;
-
- if (!subtype || !spec || !*spec)
- return 0;
-
- /* See if the full key description matches as is */
- if (key->description && strcmp(key->description, description) == 0)
- return 1;
-
- /* All tests from here on break the criterion description into a
- * specifier, a colon and then an identifier.
- */
- id = strchr(spec, ':');
- if (!id)
- return 0;
-
- speclen = id - spec;
- id++;
-
- if (speclen == 2 && memcmp(spec, "id", 2) == 0)
- return asymmetric_keyid_match(asymmetric_key_id(key), id);
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *match_id = match_data->preparsed;
- if (speclen == subtype->name_len &&
- memcmp(spec, subtype->name, speclen) == 0)
- return 1;
-
- return 0;
+ return asymmetric_match_key_ids(kids, match_id);
}
/*
@@ -198,8 +137,30 @@ static bool asymmetric_key_cmp(const struct key *key,
*/
static int asymmetric_key_match_preparse(struct key_match_data *match_data)
{
- match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
+ struct asymmetric_key_id *match_id;
+ const char *spec = match_data->raw_data;
+ const char *id;
+
+ if (!spec || !*spec)
+ return -EINVAL;
+ if (spec[0] == 'i' &&
+ spec[1] == 'd' &&
+ spec[2] == ':') {
+ id = spec + 3;
+ } else {
+ goto default_match;
+ }
+
+ match_id = asymmetric_key_hex_to_key_id(id);
+ if (!match_id)
+ return -ENOMEM;
+
+ match_data->preparsed = match_id;
match_data->cmp = asymmetric_key_cmp;
+ match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
+ return 0;
+
+default_match:
return 0;
}
@@ -208,6 +169,7 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
*/
static void asymmetric_key_match_free(struct key_match_data *match_data)
{
+ kfree(match_data->preparsed);
}
/*
@@ -216,8 +178,10 @@ static void asymmetric_key_match_free(struct key_match_data *match_data)
static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
{
const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
- const char *kid = asymmetric_key_id(key);
- size_t n;
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *kid;
+ const unsigned char *p;
+ int n;
seq_puts(m, key->description);
@@ -225,13 +189,16 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
seq_puts(m, ": ");
subtype->describe(key, m);
- if (kid) {
+ if (kids && kids->id[0]) {
+ kid = kids->id[0];
seq_putc(m, ' ');
- n = strlen(kid);
- if (n <= 8)
- seq_puts(m, kid);
- else
- seq_puts(m, kid + n - 8);
+ n = kid->len;
+ p = kid->data;
+ if (n > 8) {
+ p += n - 8;
+ n = 8;
+ }
+ seq_printf(m, "%*phN", n, p);
}
seq_puts(m, " [");
@@ -282,6 +249,7 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
{
struct asymmetric_key_subtype *subtype = prep->type_data[0];
+ struct asymmetric_key_ids *kids = prep->type_data[1];
pr_devel("==>%s()\n", __func__);
@@ -289,7 +257,11 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
subtype->destroy(prep->payload[0]);
module_put(subtype->owner);
}
- kfree(prep->type_data[1]);
+ if (kids) {
+ kfree(kids->id[0]);
+ kfree(kids->id[1]);
+ kfree(kids);
+ }
kfree(prep->description);
}
@@ -299,13 +271,20 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
static void asymmetric_key_destroy(struct key *key)
{
struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
+ struct asymmetric_key_ids *kids = key->type_data.p[1];
+
if (subtype) {
subtype->destroy(key->payload.data);
module_put(subtype->owner);
key->type_data.p[0] = NULL;
}
- kfree(key->type_data.p[1]);
- key->type_data.p[1] = NULL;
+
+ if (kids) {
+ kfree(kids->id[0]);
+ kfree(kids->id[1]);
+ kfree(kids);
+ key->type_data.p[1] = NULL;
+ }
}
struct key_type key_type_asymmetric = {