From f1b731dbc2530cab93fcfc5fcb18c9f3a100feeb Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Mon, 6 Oct 2014 15:21:05 +0100 Subject: KEYS: Restore partial ID matching functionality for asymmetric keys Bring back the functionality whereby an asymmetric key can be matched with a partial match on one of its IDs. Whilst we're at it, allow for the possibility of having an increased number of IDs. Reported-by: Dmitry Kasatkin Signed-off-by: Dmitry Kasatkin Signed-off-by: David Howells --- crypto/asymmetric_keys/asymmetric_type.c | 70 ++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) (limited to 'crypto/asymmetric_keys/asymmetric_type.c') diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index 29983cbb658d..052e944bb109 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -65,23 +65,44 @@ bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, } EXPORT_SYMBOL_GPL(asymmetric_key_id_same); +/** + * asymmetric_key_id_partial - Return true if two asymmetric keys IDs + * partially match + * @kid_1, @kid_2: The key IDs to compare + */ +bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1, + const struct asymmetric_key_id *kid2) +{ + if (!kid1 || !kid2) + return false; + if (kid1->len < kid2->len) + return false; + return memcmp(kid1->data + (kid1->len - kid2->len), + kid2->data, kid2->len) == 0; +} +EXPORT_SYMBOL_GPL(asymmetric_key_id_partial); + /** * asymmetric_match_key_ids - Search asymmetric key IDs * @kids: The list of key IDs to check * @match_id: The key ID we're looking for + * @match: The match function to use */ -bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, - const struct asymmetric_key_id *match_id) +static bool asymmetric_match_key_ids( + const struct asymmetric_key_ids *kids, + const struct asymmetric_key_id *match_id, + bool (*match)(const struct asymmetric_key_id *kid1, + const struct asymmetric_key_id *kid2)) { + int i; + if (!kids || !match_id) return false; - if (asymmetric_key_id_same(kids->id[0], match_id)) - return true; - if (asymmetric_key_id_same(kids->id[1], match_id)) - return true; + for (i = 0; i < ARRAY_SIZE(kids->id); i++) + if (match(kids->id[i], match_id)) + return true; return false; } -EXPORT_SYMBOL_GPL(asymmetric_match_key_ids); /** * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. @@ -113,7 +134,7 @@ struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id) } /* - * Match asymmetric keys by ID. + * Match asymmetric keys by an exact match on an ID. */ static bool asymmetric_key_cmp(const struct key *key, const struct key_match_data *match_data) @@ -121,7 +142,21 @@ static bool asymmetric_key_cmp(const struct key *key, const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); const struct asymmetric_key_id *match_id = match_data->preparsed; - return asymmetric_match_key_ids(kids, match_id); + return asymmetric_match_key_ids(kids, match_id, + asymmetric_key_id_same); +} + +/* + * Match asymmetric keys by a partial match on an IDs. + */ +static bool asymmetric_key_cmp_partial(const struct key *key, + const struct key_match_data *match_data) +{ + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); + const struct asymmetric_key_id *match_id = match_data->preparsed; + + return asymmetric_match_key_ids(kids, match_id, + asymmetric_key_id_partial); } /* @@ -131,7 +166,8 @@ static bool asymmetric_key_cmp(const struct key *key, * There are some specifiers for matching key IDs rather than by the key * description: * - * "id:" - request a key by any available ID + * "id:" - find a key by partial match on any available ID + * "ex:" - find a key by exact match on any available ID * * These have to be searched by iteration rather than by direct lookup because * the key is hashed according to its description. @@ -141,6 +177,8 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) struct asymmetric_key_id *match_id; const char *spec = match_data->raw_data; const char *id; + bool (*cmp)(const struct key *, const struct key_match_data *) = + asymmetric_key_cmp; if (!spec || !*spec) return -EINVAL; @@ -148,6 +186,11 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) spec[1] == 'd' && spec[2] == ':') { id = spec + 3; + cmp = asymmetric_key_cmp_partial; + } else if (spec[0] == 'e' && + spec[1] == 'x' && + spec[2] == ':') { + id = spec + 3; } else { goto default_match; } @@ -157,7 +200,7 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) return PTR_ERR(match_id); match_data->preparsed = match_id; - match_data->cmp = asymmetric_key_cmp; + match_data->cmp = cmp; match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; return 0; @@ -251,6 +294,7 @@ 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]; + int i; pr_devel("==>%s()\n", __func__); @@ -259,8 +303,8 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) module_put(subtype->owner); } if (kids) { - kfree(kids->id[0]); - kfree(kids->id[1]); + for (i = 0; i < ARRAY_SIZE(kids->id); i++) + kfree(kids->id[i]); kfree(kids); } kfree(prep->description); -- cgit v1.2.3