diff options
author | Dmitry Kasatkin <d.kasatkin@samsung.com> | 2014-10-06 10:21:05 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-10-06 10:21:05 -0400 |
commit | f1b731dbc2530cab93fcfc5fcb18c9f3a100feeb (patch) | |
tree | b5b02c3fd51b13e11a5212e4b726f5e2df653f8a /crypto/asymmetric_keys | |
parent | dd2f6c4481debfa389c1f2b2b1d5bd6449c42611 (diff) |
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 <d.kasatkin@samsung.com>
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_keys.h | 3 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 70 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_trust.c | 9 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 18 |
4 files changed, 76 insertions, 24 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h index fd21ac28e0a0..f97330886d58 100644 --- a/crypto/asymmetric_keys/asymmetric_keys.h +++ b/crypto/asymmetric_keys/asymmetric_keys.h | |||
@@ -9,9 +9,6 @@ | |||
9 | * 2 of the Licence, or (at your option) any later version. | 9 | * 2 of the Licence, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | extern bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, | ||
13 | const struct asymmetric_key_id *match_id); | ||
14 | |||
15 | extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); | 12 | extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); |
16 | 13 | ||
17 | static inline | 14 | static inline |
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 | |||
@@ -66,22 +66,43 @@ bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, | |||
66 | EXPORT_SYMBOL_GPL(asymmetric_key_id_same); | 66 | EXPORT_SYMBOL_GPL(asymmetric_key_id_same); |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * asymmetric_key_id_partial - Return true if two asymmetric keys IDs | ||
70 | * partially match | ||
71 | * @kid_1, @kid_2: The key IDs to compare | ||
72 | */ | ||
73 | bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1, | ||
74 | const struct asymmetric_key_id *kid2) | ||
75 | { | ||
76 | if (!kid1 || !kid2) | ||
77 | return false; | ||
78 | if (kid1->len < kid2->len) | ||
79 | return false; | ||
80 | return memcmp(kid1->data + (kid1->len - kid2->len), | ||
81 | kid2->data, kid2->len) == 0; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(asymmetric_key_id_partial); | ||
84 | |||
85 | /** | ||
69 | * asymmetric_match_key_ids - Search asymmetric key IDs | 86 | * asymmetric_match_key_ids - Search asymmetric key IDs |
70 | * @kids: The list of key IDs to check | 87 | * @kids: The list of key IDs to check |
71 | * @match_id: The key ID we're looking for | 88 | * @match_id: The key ID we're looking for |
89 | * @match: The match function to use | ||
72 | */ | 90 | */ |
73 | bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, | 91 | static bool asymmetric_match_key_ids( |
74 | const struct asymmetric_key_id *match_id) | 92 | const struct asymmetric_key_ids *kids, |
93 | const struct asymmetric_key_id *match_id, | ||
94 | bool (*match)(const struct asymmetric_key_id *kid1, | ||
95 | const struct asymmetric_key_id *kid2)) | ||
75 | { | 96 | { |
97 | int i; | ||
98 | |||
76 | if (!kids || !match_id) | 99 | if (!kids || !match_id) |
77 | return false; | 100 | return false; |
78 | if (asymmetric_key_id_same(kids->id[0], match_id)) | 101 | for (i = 0; i < ARRAY_SIZE(kids->id); i++) |
79 | return true; | 102 | if (match(kids->id[i], match_id)) |
80 | if (asymmetric_key_id_same(kids->id[1], match_id)) | 103 | return true; |
81 | return true; | ||
82 | return false; | 104 | return false; |
83 | } | 105 | } |
84 | EXPORT_SYMBOL_GPL(asymmetric_match_key_ids); | ||
85 | 106 | ||
86 | /** | 107 | /** |
87 | * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. | 108 | * 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) | |||
113 | } | 134 | } |
114 | 135 | ||
115 | /* | 136 | /* |
116 | * Match asymmetric keys by ID. | 137 | * Match asymmetric keys by an exact match on an ID. |
117 | */ | 138 | */ |
118 | static bool asymmetric_key_cmp(const struct key *key, | 139 | static bool asymmetric_key_cmp(const struct key *key, |
119 | const struct key_match_data *match_data) | 140 | const struct key_match_data *match_data) |
@@ -121,7 +142,21 @@ static bool asymmetric_key_cmp(const struct key *key, | |||
121 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); | 142 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); |
122 | const struct asymmetric_key_id *match_id = match_data->preparsed; | 143 | const struct asymmetric_key_id *match_id = match_data->preparsed; |
123 | 144 | ||
124 | return asymmetric_match_key_ids(kids, match_id); | 145 | return asymmetric_match_key_ids(kids, match_id, |
146 | asymmetric_key_id_same); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Match asymmetric keys by a partial match on an IDs. | ||
151 | */ | ||
152 | static bool asymmetric_key_cmp_partial(const struct key *key, | ||
153 | const struct key_match_data *match_data) | ||
154 | { | ||
155 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); | ||
156 | const struct asymmetric_key_id *match_id = match_data->preparsed; | ||
157 | |||
158 | return asymmetric_match_key_ids(kids, match_id, | ||
159 | asymmetric_key_id_partial); | ||
125 | } | 160 | } |
126 | 161 | ||
127 | /* | 162 | /* |
@@ -131,7 +166,8 @@ static bool asymmetric_key_cmp(const struct key *key, | |||
131 | * There are some specifiers for matching key IDs rather than by the key | 166 | * There are some specifiers for matching key IDs rather than by the key |
132 | * description: | 167 | * description: |
133 | * | 168 | * |
134 | * "id:<id>" - request a key by any available ID | 169 | * "id:<id>" - find a key by partial match on any available ID |
170 | * "ex:<id>" - find a key by exact match on any available ID | ||
135 | * | 171 | * |
136 | * These have to be searched by iteration rather than by direct lookup because | 172 | * These have to be searched by iteration rather than by direct lookup because |
137 | * the key is hashed according to its description. | 173 | * the key is hashed according to its description. |
@@ -141,6 +177,8 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) | |||
141 | struct asymmetric_key_id *match_id; | 177 | struct asymmetric_key_id *match_id; |
142 | const char *spec = match_data->raw_data; | 178 | const char *spec = match_data->raw_data; |
143 | const char *id; | 179 | const char *id; |
180 | bool (*cmp)(const struct key *, const struct key_match_data *) = | ||
181 | asymmetric_key_cmp; | ||
144 | 182 | ||
145 | if (!spec || !*spec) | 183 | if (!spec || !*spec) |
146 | return -EINVAL; | 184 | return -EINVAL; |
@@ -148,6 +186,11 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) | |||
148 | spec[1] == 'd' && | 186 | spec[1] == 'd' && |
149 | spec[2] == ':') { | 187 | spec[2] == ':') { |
150 | id = spec + 3; | 188 | id = spec + 3; |
189 | cmp = asymmetric_key_cmp_partial; | ||
190 | } else if (spec[0] == 'e' && | ||
191 | spec[1] == 'x' && | ||
192 | spec[2] == ':') { | ||
193 | id = spec + 3; | ||
151 | } else { | 194 | } else { |
152 | goto default_match; | 195 | goto default_match; |
153 | } | 196 | } |
@@ -157,7 +200,7 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data) | |||
157 | return PTR_ERR(match_id); | 200 | return PTR_ERR(match_id); |
158 | 201 | ||
159 | match_data->preparsed = match_id; | 202 | match_data->preparsed = match_id; |
160 | match_data->cmp = asymmetric_key_cmp; | 203 | match_data->cmp = cmp; |
161 | match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; | 204 | match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; |
162 | return 0; | 205 | return 0; |
163 | 206 | ||
@@ -251,6 +294,7 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | |||
251 | { | 294 | { |
252 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; | 295 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; |
253 | struct asymmetric_key_ids *kids = prep->type_data[1]; | 296 | struct asymmetric_key_ids *kids = prep->type_data[1]; |
297 | int i; | ||
254 | 298 | ||
255 | pr_devel("==>%s()\n", __func__); | 299 | pr_devel("==>%s()\n", __func__); |
256 | 300 | ||
@@ -259,8 +303,8 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | |||
259 | module_put(subtype->owner); | 303 | module_put(subtype->owner); |
260 | } | 304 | } |
261 | if (kids) { | 305 | if (kids) { |
262 | kfree(kids->id[0]); | 306 | for (i = 0; i < ARRAY_SIZE(kids->id); i++) |
263 | kfree(kids->id[1]); | 307 | kfree(kids->id[i]); |
264 | kfree(kids); | 308 | kfree(kids); |
265 | } | 309 | } |
266 | kfree(prep->description); | 310 | kfree(prep->description); |
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index ae47be6128c4..1d29376072da 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c | |||
@@ -54,7 +54,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
54 | /* Look to see if this certificate is present in the trusted | 54 | /* Look to see if this certificate is present in the trusted |
55 | * keys. | 55 | * keys. |
56 | */ | 56 | */ |
57 | key = x509_request_asymmetric_key(trust_keyring, x509->id); | 57 | key = x509_request_asymmetric_key(trust_keyring, x509->id, |
58 | false); | ||
58 | if (!IS_ERR(key)) { | 59 | if (!IS_ERR(key)) { |
59 | /* One of the X.509 certificates in the PKCS#7 message | 60 | /* One of the X.509 certificates in the PKCS#7 message |
60 | * is apparently the same as one we already trust. | 61 | * is apparently the same as one we already trust. |
@@ -85,7 +86,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
85 | * trusted keys. | 86 | * trusted keys. |
86 | */ | 87 | */ |
87 | if (last && last->authority) { | 88 | if (last && last->authority) { |
88 | key = x509_request_asymmetric_key(trust_keyring, last->authority); | 89 | key = x509_request_asymmetric_key(trust_keyring, last->authority, |
90 | false); | ||
89 | if (!IS_ERR(key)) { | 91 | if (!IS_ERR(key)) { |
90 | x509 = last; | 92 | x509 = last; |
91 | pr_devel("sinfo %u: Root cert %u signer is key %x\n", | 93 | pr_devel("sinfo %u: Root cert %u signer is key %x\n", |
@@ -100,7 +102,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
100 | * the signed info directly. | 102 | * the signed info directly. |
101 | */ | 103 | */ |
102 | key = x509_request_asymmetric_key(trust_keyring, | 104 | key = x509_request_asymmetric_key(trust_keyring, |
103 | sinfo->signing_cert_id); | 105 | sinfo->signing_cert_id, |
106 | false); | ||
104 | if (!IS_ERR(key)) { | 107 | if (!IS_ERR(key)) { |
105 | pr_devel("sinfo %u: Direct signer is key %x\n", | 108 | pr_devel("sinfo %u: Direct signer is key %x\n", |
106 | sinfo->index, key_serial(key)); | 109 | sinfo->index, key_serial(key)); |
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 8bffb06b2683..6ef54495be87 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
@@ -53,13 +53,15 @@ __setup("ca_keys=", ca_keys_setup); | |||
53 | * x509_request_asymmetric_key - Request a key by X.509 certificate params. | 53 | * x509_request_asymmetric_key - Request a key by X.509 certificate params. |
54 | * @keyring: The keys to search. | 54 | * @keyring: The keys to search. |
55 | * @kid: The key ID. | 55 | * @kid: The key ID. |
56 | * @partial: Use partial match if true, exact if false. | ||
56 | * | 57 | * |
57 | * Find a key in the given keyring by subject name and key ID. These might, | 58 | * Find a key in the given keyring by subject name and key ID. These might, |
58 | * for instance, be the issuer name and the authority key ID of an X.509 | 59 | * for instance, be the issuer name and the authority key ID of an X.509 |
59 | * certificate that needs to be verified. | 60 | * certificate that needs to be verified. |
60 | */ | 61 | */ |
61 | struct key *x509_request_asymmetric_key(struct key *keyring, | 62 | struct key *x509_request_asymmetric_key(struct key *keyring, |
62 | const struct asymmetric_key_id *kid) | 63 | const struct asymmetric_key_id *kid, |
64 | bool partial) | ||
63 | { | 65 | { |
64 | key_ref_t key; | 66 | key_ref_t key; |
65 | char *id, *p; | 67 | char *id, *p; |
@@ -69,8 +71,13 @@ struct key *x509_request_asymmetric_key(struct key *keyring, | |||
69 | if (!id) | 71 | if (!id) |
70 | return ERR_PTR(-ENOMEM); | 72 | return ERR_PTR(-ENOMEM); |
71 | 73 | ||
72 | *p++ = 'i'; | 74 | if (partial) { |
73 | *p++ = 'd'; | 75 | *p++ = 'i'; |
76 | *p++ = 'd'; | ||
77 | } else { | ||
78 | *p++ = 'e'; | ||
79 | *p++ = 'x'; | ||
80 | } | ||
74 | *p++ = ':'; | 81 | *p++ = ':'; |
75 | p = bin2hex(p, kid->data, kid->len); | 82 | p = bin2hex(p, kid->data, kid->len); |
76 | *p = 0; | 83 | *p = 0; |
@@ -207,10 +214,11 @@ static int x509_validate_trust(struct x509_certificate *cert, | |||
207 | if (!trust_keyring) | 214 | if (!trust_keyring) |
208 | return -EOPNOTSUPP; | 215 | return -EOPNOTSUPP; |
209 | 216 | ||
210 | if (ca_keyid && !asymmetric_key_id_same(cert->authority, ca_keyid)) | 217 | if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid)) |
211 | return -EPERM; | 218 | return -EPERM; |
212 | 219 | ||
213 | key = x509_request_asymmetric_key(trust_keyring, cert->authority); | 220 | key = x509_request_asymmetric_key(trust_keyring, cert->authority, |
221 | false); | ||
214 | if (!IS_ERR(key)) { | 222 | if (!IS_ERR(key)) { |
215 | if (!use_builtin_keys | 223 | if (!use_builtin_keys |
216 | || test_bit(KEY_FLAG_BUILTIN, &key->flags)) | 224 | || test_bit(KEY_FLAG_BUILTIN, &key->flags)) |