aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2014-10-06 10:21:05 -0400
committerDavid Howells <dhowells@redhat.com>2014-10-06 10:21:05 -0400
commitf1b731dbc2530cab93fcfc5fcb18c9f3a100feeb (patch)
treeb5b02c3fd51b13e11a5212e4b726f5e2df653f8a /crypto/asymmetric_keys
parentdd2f6c4481debfa389c1f2b2b1d5bd6449c42611 (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.h3
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c70
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c9
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c18
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
12extern bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids,
13 const struct asymmetric_key_id *match_id);
14
15extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); 12extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
16 13
17static inline 14static 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,
66EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 66EXPORT_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 */
73bool 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}
83EXPORT_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 */
73bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, 91static 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}
84EXPORT_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 */
118static bool asymmetric_key_cmp(const struct key *key, 139static 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 */
152static 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 */
61struct key *x509_request_asymmetric_key(struct key *keyring, 62struct 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))