Commit 35e1efd25a9e7d5cf2884fa23441ab87353849bb
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'keys-next-20140922' of git://git.kernel.org/pub/scm/linux/kernel/git/…
…dhowells/linux-fs into next
Showing 35 changed files Side-by-side Diff
- Documentation/security/keys.txt
- crypto/asymmetric_keys/asymmetric_keys.h
- crypto/asymmetric_keys/asymmetric_type.c
- crypto/asymmetric_keys/pkcs7_key_type.c
- crypto/asymmetric_keys/pkcs7_parser.c
- crypto/asymmetric_keys/pkcs7_parser.h
- crypto/asymmetric_keys/pkcs7_trust.c
- crypto/asymmetric_keys/pkcs7_verify.c
- crypto/asymmetric_keys/x509_cert_parser.c
- crypto/asymmetric_keys/x509_parser.h
- crypto/asymmetric_keys/x509_public_key.c
- fs/cifs/cifs_spnego.c
- fs/cifs/cifsacl.c
- fs/nfs/idmap.c
- include/crypto/public_key.h
- include/keys/asymmetric-type.h
- include/keys/user-type.h
- include/linux/kernel.h
- include/linux/key-type.h
- lib/hexdump.c
- net/ceph/crypto.c
- net/dns_resolver/dns_key.c
- net/rxrpc/ar-key.c
- security/keys/big_key.c
- security/keys/encrypted-keys/encrypted.c
- security/keys/internal.h
- security/keys/key.c
- security/keys/keyctl.c
- security/keys/keyring.c
- security/keys/proc.c
- security/keys/process_keys.c
- security/keys/request_key.c
- security/keys/request_key_auth.c
- security/keys/trusted.c
- security/keys/user_defined.c
Documentation/security/keys.txt
... | ... | @@ -888,11 +888,11 @@ |
888 | 888 | const char *callout_info); |
889 | 889 | |
890 | 890 | This is used to request a key or keyring with a description that matches |
891 | - the description specified according to the key type's match function. This | |
892 | - permits approximate matching to occur. If callout_string is not NULL, then | |
893 | - /sbin/request-key will be invoked in an attempt to obtain the key from | |
894 | - userspace. In that case, callout_string will be passed as an argument to | |
895 | - the program. | |
891 | + the description specified according to the key type's match_preparse() | |
892 | + method. This permits approximate matching to occur. If callout_string is | |
893 | + not NULL, then /sbin/request-key will be invoked in an attempt to obtain | |
894 | + the key from userspace. In that case, callout_string will be passed as an | |
895 | + argument to the program. | |
896 | 896 | |
897 | 897 | Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be |
898 | 898 | returned. |
... | ... | @@ -1170,7 +1170,7 @@ |
1170 | 1170 | The method should return 0 if successful or a negative error code |
1171 | 1171 | otherwise. |
1172 | 1172 | |
1173 | - | |
1173 | + | |
1174 | 1174 | (*) void (*free_preparse)(struct key_preparsed_payload *prep); |
1175 | 1175 | |
1176 | 1176 | This method is only required if the preparse() method is provided, |
1177 | 1177 | |
1178 | 1178 | |
1179 | 1179 | |
... | ... | @@ -1225,16 +1225,55 @@ |
1225 | 1225 | It is safe to sleep in this method. |
1226 | 1226 | |
1227 | 1227 | |
1228 | - (*) int (*match)(const struct key *key, const void *desc); | |
1228 | + (*) int (*match_preparse)(struct key_match_data *match_data); | |
1229 | 1229 | |
1230 | - This method is called to match a key against a description. It should | |
1231 | - return non-zero if the two match, zero if they don't. | |
1230 | + This method is optional. It is called when a key search is about to be | |
1231 | + performed. It is given the following structure: | |
1232 | 1232 | |
1233 | - This method should not need to lock the key in any way. The type and | |
1234 | - description can be considered invariant, and the payload should not be | |
1235 | - accessed (the key may not yet be instantiated). | |
1233 | + struct key_match_data { | |
1234 | + bool (*cmp)(const struct key *key, | |
1235 | + const struct key_match_data *match_data); | |
1236 | + const void *raw_data; | |
1237 | + void *preparsed; | |
1238 | + unsigned lookup_type; | |
1239 | + }; | |
1236 | 1240 | |
1237 | - It is not safe to sleep in this method; the caller may hold spinlocks. | |
1241 | + On entry, raw_data will be pointing to the criteria to be used in matching | |
1242 | + a key by the caller and should not be modified. (*cmp)() will be pointing | |
1243 | + to the default matcher function (which does an exact description match | |
1244 | + against raw_data) and lookup_type will be set to indicate a direct lookup. | |
1245 | + | |
1246 | + The following lookup_type values are available: | |
1247 | + | |
1248 | + [*] KEYRING_SEARCH_LOOKUP_DIRECT - A direct lookup hashes the type and | |
1249 | + description to narrow down the search to a small number of keys. | |
1250 | + | |
1251 | + [*] KEYRING_SEARCH_LOOKUP_ITERATE - An iterative lookup walks all the | |
1252 | + keys in the keyring until one is matched. This must be used for any | |
1253 | + search that's not doing a simple direct match on the key description. | |
1254 | + | |
1255 | + The method may set cmp to point to a function of its choice that does some | |
1256 | + other form of match, may set lookup_type to KEYRING_SEARCH_LOOKUP_ITERATE | |
1257 | + and may attach something to the preparsed pointer for use by (*cmp)(). | |
1258 | + (*cmp)() should return true if a key matches and false otherwise. | |
1259 | + | |
1260 | + If preparsed is set, it may be necessary to use the match_free() method to | |
1261 | + clean it up. | |
1262 | + | |
1263 | + The method should return 0 if successful or a negative error code | |
1264 | + otherwise. | |
1265 | + | |
1266 | + It is permitted to sleep in this method, but (*cmp)() may not sleep as | |
1267 | + locks will be held over it. | |
1268 | + | |
1269 | + If match_preparse() is not provided, keys of this type will be matched | |
1270 | + exactly by their description. | |
1271 | + | |
1272 | + | |
1273 | + (*) void (*match_free)(struct key_match_data *match_data); | |
1274 | + | |
1275 | + This method is optional. If given, it called to clean up | |
1276 | + match_data->preparsed after a successful call to match_preparse(). | |
1238 | 1277 | |
1239 | 1278 | |
1240 | 1279 | (*) void (*revoke)(struct key *key); |
crypto/asymmetric_keys/asymmetric_keys.h
... | ... | @@ -9,9 +9,13 @@ |
9 | 9 | * 2 of the Licence, or (at your option) any later version. |
10 | 10 | */ |
11 | 11 | |
12 | -int asymmetric_keyid_match(const char *kid, const char *id); | |
12 | +extern bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, | |
13 | + const struct asymmetric_key_id *match_id); | |
13 | 14 | |
14 | -static inline const char *asymmetric_key_id(const struct key *key) | |
15 | +extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); | |
16 | + | |
17 | +static inline | |
18 | +const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) | |
15 | 19 | { |
16 | 20 | return key->type_data.p[1]; |
17 | 21 | } |
crypto/asymmetric_keys/asymmetric_type.c
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #include <linux/seq_file.h> |
16 | 16 | #include <linux/module.h> |
17 | 17 | #include <linux/slab.h> |
18 | +#include <linux/ctype.h> | |
18 | 19 | #include "asymmetric_keys.h" |
19 | 20 | |
20 | 21 | MODULE_LICENSE("GPL"); |
21 | 22 | |
22 | 23 | |
23 | 24 | |
24 | 25 | |
25 | 26 | |
26 | 27 | |
27 | 28 | |
28 | 29 | |
29 | 30 | |
30 | 31 | |
31 | 32 | |
32 | 33 | |
33 | 34 | |
34 | 35 | |
35 | 36 | |
36 | 37 | |
37 | 38 | |
38 | 39 | |
39 | 40 | |
... | ... | @@ -22,85 +23,166 @@ |
22 | 23 | static LIST_HEAD(asymmetric_key_parsers); |
23 | 24 | static DECLARE_RWSEM(asymmetric_key_parsers_sem); |
24 | 25 | |
25 | -/* | |
26 | - * Match asymmetric key id with partial match | |
27 | - * @id: key id to match in a form "id:<id>" | |
26 | +/** | |
27 | + * asymmetric_key_generate_id: Construct an asymmetric key ID | |
28 | + * @val_1: First binary blob | |
29 | + * @len_1: Length of first binary blob | |
30 | + * @val_2: Second binary blob | |
31 | + * @len_2: Length of second binary blob | |
32 | + * | |
33 | + * Construct an asymmetric key ID from a pair of binary blobs. | |
28 | 34 | */ |
29 | -int asymmetric_keyid_match(const char *kid, const char *id) | |
35 | +struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1, | |
36 | + size_t len_1, | |
37 | + const void *val_2, | |
38 | + size_t len_2) | |
30 | 39 | { |
31 | - size_t idlen, kidlen; | |
40 | + struct asymmetric_key_id *kid; | |
32 | 41 | |
33 | - if (!kid || !id) | |
34 | - return 0; | |
42 | + kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2, | |
43 | + GFP_KERNEL); | |
44 | + if (!kid) | |
45 | + return ERR_PTR(-ENOMEM); | |
46 | + kid->len = len_1 + len_2; | |
47 | + memcpy(kid->data, val_1, len_1); | |
48 | + memcpy(kid->data + len_1, val_2, len_2); | |
49 | + return kid; | |
50 | +} | |
51 | +EXPORT_SYMBOL_GPL(asymmetric_key_generate_id); | |
35 | 52 | |
36 | - /* make it possible to use id as in the request: "id:<id>" */ | |
37 | - if (strncmp(id, "id:", 3) == 0) | |
38 | - id += 3; | |
53 | +/** | |
54 | + * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same. | |
55 | + * @kid_1, @kid_2: The key IDs to compare | |
56 | + */ | |
57 | +bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, | |
58 | + const struct asymmetric_key_id *kid2) | |
59 | +{ | |
60 | + if (!kid1 || !kid2) | |
61 | + return false; | |
62 | + if (kid1->len != kid2->len) | |
63 | + return false; | |
64 | + return memcmp(kid1->data, kid2->data, kid1->len) == 0; | |
65 | +} | |
66 | +EXPORT_SYMBOL_GPL(asymmetric_key_id_same); | |
39 | 67 | |
40 | - /* Anything after here requires a partial match on the ID string */ | |
41 | - idlen = strlen(id); | |
42 | - kidlen = strlen(kid); | |
43 | - if (idlen > kidlen) | |
44 | - return 0; | |
68 | +/** | |
69 | + * asymmetric_match_key_ids - Search asymmetric key IDs | |
70 | + * @kids: The list of key IDs to check | |
71 | + * @match_id: The key ID we're looking for | |
72 | + */ | |
73 | +bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids, | |
74 | + const struct asymmetric_key_id *match_id) | |
75 | +{ | |
76 | + if (!kids || !match_id) | |
77 | + return false; | |
78 | + if (asymmetric_key_id_same(kids->id[0], match_id)) | |
79 | + return true; | |
80 | + if (asymmetric_key_id_same(kids->id[1], match_id)) | |
81 | + return true; | |
82 | + return false; | |
83 | +} | |
84 | +EXPORT_SYMBOL_GPL(asymmetric_match_key_ids); | |
45 | 85 | |
46 | - kid += kidlen - idlen; | |
47 | - if (strcasecmp(id, kid) != 0) | |
48 | - return 0; | |
86 | +/** | |
87 | + * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. | |
88 | + * @id: The ID as a hex string. | |
89 | + */ | |
90 | +struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id) | |
91 | +{ | |
92 | + struct asymmetric_key_id *match_id; | |
93 | + size_t hexlen; | |
94 | + int ret; | |
49 | 95 | |
50 | - return 1; | |
96 | + if (!*id) | |
97 | + return ERR_PTR(-EINVAL); | |
98 | + hexlen = strlen(id); | |
99 | + if (hexlen & 1) | |
100 | + return ERR_PTR(-EINVAL); | |
101 | + | |
102 | + match_id = kmalloc(sizeof(struct asymmetric_key_id) + hexlen / 2, | |
103 | + GFP_KERNEL); | |
104 | + if (!match_id) | |
105 | + return ERR_PTR(-ENOMEM); | |
106 | + match_id->len = hexlen / 2; | |
107 | + ret = hex2bin(match_id->data, id, hexlen / 2); | |
108 | + if (ret < 0) { | |
109 | + kfree(match_id); | |
110 | + return ERR_PTR(-EINVAL); | |
111 | + } | |
112 | + return match_id; | |
51 | 113 | } |
52 | -EXPORT_SYMBOL_GPL(asymmetric_keyid_match); | |
53 | 114 | |
54 | 115 | /* |
55 | - * Match asymmetric keys on (part of) their name | |
56 | - * We have some shorthand methods for matching keys. We allow: | |
116 | + * Match asymmetric keys by ID. | |
117 | + */ | |
118 | +static bool asymmetric_key_cmp(const struct key *key, | |
119 | + const struct key_match_data *match_data) | |
120 | +{ | |
121 | + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); | |
122 | + const struct asymmetric_key_id *match_id = match_data->preparsed; | |
123 | + | |
124 | + return asymmetric_match_key_ids(kids, match_id); | |
125 | +} | |
126 | + | |
127 | +/* | |
128 | + * Preparse the match criterion. If we don't set lookup_type and cmp, | |
129 | + * the default will be an exact match on the key description. | |
57 | 130 | * |
58 | - * "<desc>" - request a key by description | |
59 | - * "id:<id>" - request a key matching the ID | |
60 | - * "<subtype>:<id>" - request a key of a subtype | |
131 | + * There are some specifiers for matching key IDs rather than by the key | |
132 | + * description: | |
133 | + * | |
134 | + * "id:<id>" - request a key by any available ID | |
135 | + * | |
136 | + * These have to be searched by iteration rather than by direct lookup because | |
137 | + * the key is hashed according to its description. | |
61 | 138 | */ |
62 | -static int asymmetric_key_match(const struct key *key, const void *description) | |
139 | +static int asymmetric_key_match_preparse(struct key_match_data *match_data) | |
63 | 140 | { |
64 | - const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | |
65 | - const char *spec = description; | |
141 | + struct asymmetric_key_id *match_id; | |
142 | + const char *spec = match_data->raw_data; | |
66 | 143 | const char *id; |
67 | - ptrdiff_t speclen; | |
68 | 144 | |
69 | - if (!subtype || !spec || !*spec) | |
70 | - return 0; | |
145 | + if (!spec || !*spec) | |
146 | + return -EINVAL; | |
147 | + if (spec[0] == 'i' && | |
148 | + spec[1] == 'd' && | |
149 | + spec[2] == ':') { | |
150 | + id = spec + 3; | |
151 | + } else { | |
152 | + goto default_match; | |
153 | + } | |
71 | 154 | |
72 | - /* See if the full key description matches as is */ | |
73 | - if (key->description && strcmp(key->description, description) == 0) | |
74 | - return 1; | |
155 | + match_id = asymmetric_key_hex_to_key_id(id); | |
156 | + if (!match_id) | |
157 | + return -ENOMEM; | |
75 | 158 | |
76 | - /* All tests from here on break the criterion description into a | |
77 | - * specifier, a colon and then an identifier. | |
78 | - */ | |
79 | - id = strchr(spec, ':'); | |
80 | - if (!id) | |
81 | - return 0; | |
159 | + match_data->preparsed = match_id; | |
160 | + match_data->cmp = asymmetric_key_cmp; | |
161 | + match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; | |
162 | + return 0; | |
82 | 163 | |
83 | - speclen = id - spec; | |
84 | - id++; | |
85 | - | |
86 | - if (speclen == 2 && memcmp(spec, "id", 2) == 0) | |
87 | - return asymmetric_keyid_match(asymmetric_key_id(key), id); | |
88 | - | |
89 | - if (speclen == subtype->name_len && | |
90 | - memcmp(spec, subtype->name, speclen) == 0) | |
91 | - return 1; | |
92 | - | |
164 | +default_match: | |
93 | 165 | return 0; |
94 | 166 | } |
95 | 167 | |
96 | 168 | /* |
169 | + * Free the preparsed the match criterion. | |
170 | + */ | |
171 | +static void asymmetric_key_match_free(struct key_match_data *match_data) | |
172 | +{ | |
173 | + kfree(match_data->preparsed); | |
174 | +} | |
175 | + | |
176 | +/* | |
97 | 177 | * Describe the asymmetric key |
98 | 178 | */ |
99 | 179 | static void asymmetric_key_describe(const struct key *key, struct seq_file *m) |
100 | 180 | { |
101 | 181 | const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); |
102 | - const char *kid = asymmetric_key_id(key); | |
103 | - size_t n; | |
182 | + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); | |
183 | + const struct asymmetric_key_id *kid; | |
184 | + const unsigned char *p; | |
185 | + int n; | |
104 | 186 | |
105 | 187 | seq_puts(m, key->description); |
106 | 188 | |
107 | 189 | |
... | ... | @@ -108,13 +190,16 @@ |
108 | 190 | seq_puts(m, ": "); |
109 | 191 | subtype->describe(key, m); |
110 | 192 | |
111 | - if (kid) { | |
193 | + if (kids && kids->id[0]) { | |
194 | + kid = kids->id[0]; | |
112 | 195 | seq_putc(m, ' '); |
113 | - n = strlen(kid); | |
114 | - if (n <= 8) | |
115 | - seq_puts(m, kid); | |
116 | - else | |
117 | - seq_puts(m, kid + n - 8); | |
196 | + n = kid->len; | |
197 | + p = kid->data; | |
198 | + if (n > 8) { | |
199 | + p += n - 8; | |
200 | + n = 8; | |
201 | + } | |
202 | + seq_printf(m, "%*phN", n, p); | |
118 | 203 | } |
119 | 204 | |
120 | 205 | seq_puts(m, " ["); |
... | ... | @@ -165,6 +250,7 @@ |
165 | 250 | static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) |
166 | 251 | { |
167 | 252 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; |
253 | + struct asymmetric_key_ids *kids = prep->type_data[1]; | |
168 | 254 | |
169 | 255 | pr_devel("==>%s()\n", __func__); |
170 | 256 | |
... | ... | @@ -172,7 +258,11 @@ |
172 | 258 | subtype->destroy(prep->payload[0]); |
173 | 259 | module_put(subtype->owner); |
174 | 260 | } |
175 | - kfree(prep->type_data[1]); | |
261 | + if (kids) { | |
262 | + kfree(kids->id[0]); | |
263 | + kfree(kids->id[1]); | |
264 | + kfree(kids); | |
265 | + } | |
176 | 266 | kfree(prep->description); |
177 | 267 | } |
178 | 268 | |
179 | 269 | |
... | ... | @@ -182,13 +272,20 @@ |
182 | 272 | static void asymmetric_key_destroy(struct key *key) |
183 | 273 | { |
184 | 274 | struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); |
275 | + struct asymmetric_key_ids *kids = key->type_data.p[1]; | |
276 | + | |
185 | 277 | if (subtype) { |
186 | 278 | subtype->destroy(key->payload.data); |
187 | 279 | module_put(subtype->owner); |
188 | 280 | key->type_data.p[0] = NULL; |
189 | 281 | } |
190 | - kfree(key->type_data.p[1]); | |
191 | - key->type_data.p[1] = NULL; | |
282 | + | |
283 | + if (kids) { | |
284 | + kfree(kids->id[0]); | |
285 | + kfree(kids->id[1]); | |
286 | + kfree(kids); | |
287 | + key->type_data.p[1] = NULL; | |
288 | + } | |
192 | 289 | } |
193 | 290 | |
194 | 291 | struct key_type key_type_asymmetric = { |
195 | 292 | |
... | ... | @@ -196,10 +293,10 @@ |
196 | 293 | .preparse = asymmetric_key_preparse, |
197 | 294 | .free_preparse = asymmetric_key_free_preparse, |
198 | 295 | .instantiate = generic_key_instantiate, |
199 | - .match = asymmetric_key_match, | |
296 | + .match_preparse = asymmetric_key_match_preparse, | |
297 | + .match_free = asymmetric_key_match_free, | |
200 | 298 | .destroy = asymmetric_key_destroy, |
201 | 299 | .describe = asymmetric_key_describe, |
202 | - .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE, | |
203 | 300 | }; |
204 | 301 | EXPORT_SYMBOL_GPL(key_type_asymmetric); |
205 | 302 |
crypto/asymmetric_keys/pkcs7_key_type.c
... | ... | @@ -72,11 +72,9 @@ |
72 | 72 | */ |
73 | 73 | static struct key_type key_type_pkcs7 = { |
74 | 74 | .name = "pkcs7_test", |
75 | - .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
76 | 75 | .preparse = pkcs7_preparse, |
77 | 76 | .free_preparse = user_free_preparse, |
78 | 77 | .instantiate = generic_key_instantiate, |
79 | - .match = user_match, | |
80 | 78 | .revoke = user_revoke, |
81 | 79 | .destroy = user_destroy, |
82 | 80 | .describe = user_describe, |
crypto/asymmetric_keys/pkcs7_parser.c
... | ... | @@ -29,8 +29,25 @@ |
29 | 29 | enum OID last_oid; /* Last OID encountered */ |
30 | 30 | unsigned x509_index; |
31 | 31 | unsigned sinfo_index; |
32 | + const void *raw_serial; | |
33 | + unsigned raw_serial_size; | |
34 | + unsigned raw_issuer_size; | |
35 | + const void *raw_issuer; | |
32 | 36 | }; |
33 | 37 | |
38 | +/* | |
39 | + * Free a signed information block. | |
40 | + */ | |
41 | +static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) | |
42 | +{ | |
43 | + if (sinfo) { | |
44 | + mpi_free(sinfo->sig.mpi[0]); | |
45 | + kfree(sinfo->sig.digest); | |
46 | + kfree(sinfo->signing_cert_id); | |
47 | + kfree(sinfo); | |
48 | + } | |
49 | +} | |
50 | + | |
34 | 51 | /** |
35 | 52 | * pkcs7_free_message - Free a PKCS#7 message |
36 | 53 | * @pkcs7: The PKCS#7 message to free |
... | ... | @@ -54,9 +71,7 @@ |
54 | 71 | while (pkcs7->signed_infos) { |
55 | 72 | sinfo = pkcs7->signed_infos; |
56 | 73 | pkcs7->signed_infos = sinfo->next; |
57 | - mpi_free(sinfo->sig.mpi[0]); | |
58 | - kfree(sinfo->sig.digest); | |
59 | - kfree(sinfo); | |
74 | + pkcs7_free_signed_info(sinfo); | |
60 | 75 | } |
61 | 76 | kfree(pkcs7); |
62 | 77 | } |
63 | 78 | |
64 | 79 | |
65 | 80 | |
66 | 81 | |
67 | 82 | |
68 | 83 | |
69 | 84 | |
70 | 85 | |
71 | 86 | |
... | ... | @@ -71,51 +86,46 @@ |
71 | 86 | struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) |
72 | 87 | { |
73 | 88 | struct pkcs7_parse_context *ctx; |
74 | - struct pkcs7_message *msg; | |
75 | - long ret; | |
89 | + struct pkcs7_message *msg = ERR_PTR(-ENOMEM); | |
90 | + int ret; | |
76 | 91 | |
77 | - ret = -ENOMEM; | |
78 | - msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL); | |
79 | - if (!msg) | |
80 | - goto error_no_sig; | |
81 | 92 | ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); |
82 | 93 | if (!ctx) |
83 | - goto error_no_ctx; | |
94 | + goto out_no_ctx; | |
95 | + ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL); | |
96 | + if (!ctx->msg) | |
97 | + goto out_no_msg; | |
84 | 98 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); |
85 | 99 | if (!ctx->sinfo) |
86 | - goto error_no_sinfo; | |
100 | + goto out_no_sinfo; | |
87 | 101 | |
88 | - ctx->msg = msg; | |
89 | 102 | ctx->data = (unsigned long)data; |
90 | 103 | ctx->ppcerts = &ctx->certs; |
91 | 104 | ctx->ppsinfo = &ctx->msg->signed_infos; |
92 | 105 | |
93 | 106 | /* Attempt to decode the signature */ |
94 | 107 | ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); |
95 | - if (ret < 0) | |
96 | - goto error_decode; | |
108 | + if (ret < 0) { | |
109 | + msg = ERR_PTR(ret); | |
110 | + goto out; | |
111 | + } | |
97 | 112 | |
113 | + msg = ctx->msg; | |
114 | + ctx->msg = NULL; | |
115 | + | |
116 | +out: | |
98 | 117 | while (ctx->certs) { |
99 | 118 | struct x509_certificate *cert = ctx->certs; |
100 | 119 | ctx->certs = cert->next; |
101 | 120 | x509_free_certificate(cert); |
102 | 121 | } |
103 | - mpi_free(ctx->sinfo->sig.mpi[0]); | |
104 | - kfree(ctx->sinfo->sig.digest); | |
105 | - kfree(ctx->sinfo); | |
122 | + pkcs7_free_signed_info(ctx->sinfo); | |
123 | +out_no_sinfo: | |
124 | + pkcs7_free_message(ctx->msg); | |
125 | +out_no_msg: | |
106 | 126 | kfree(ctx); |
127 | +out_no_ctx: | |
107 | 128 | return msg; |
108 | - | |
109 | -error_decode: | |
110 | - mpi_free(ctx->sinfo->sig.mpi[0]); | |
111 | - kfree(ctx->sinfo->sig.digest); | |
112 | - kfree(ctx->sinfo); | |
113 | -error_no_sinfo: | |
114 | - kfree(ctx); | |
115 | -error_no_ctx: | |
116 | - pkcs7_free_message(msg); | |
117 | -error_no_sig: | |
118 | - return ERR_PTR(ret); | |
119 | 129 | } |
120 | 130 | EXPORT_SYMBOL_GPL(pkcs7_parse_message); |
121 | 131 | |
122 | 132 | |
... | ... | @@ -246,10 +256,10 @@ |
246 | 256 | if (IS_ERR(x509)) |
247 | 257 | return PTR_ERR(x509); |
248 | 258 | |
249 | - pr_debug("Got cert for %s\n", x509->subject); | |
250 | - pr_debug("- fingerprint %s\n", x509->fingerprint); | |
251 | - | |
252 | 259 | x509->index = ++ctx->x509_index; |
260 | + pr_debug("Got cert %u for %s\n", x509->index, x509->subject); | |
261 | + pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data); | |
262 | + | |
253 | 263 | *ctx->ppcerts = x509; |
254 | 264 | ctx->ppcerts = &x509->next; |
255 | 265 | return 0; |
... | ... | @@ -338,8 +348,8 @@ |
338 | 348 | const void *value, size_t vlen) |
339 | 349 | { |
340 | 350 | struct pkcs7_parse_context *ctx = context; |
341 | - ctx->sinfo->raw_serial = value; | |
342 | - ctx->sinfo->raw_serial_size = vlen; | |
351 | + ctx->raw_serial = value; | |
352 | + ctx->raw_serial_size = vlen; | |
343 | 353 | return 0; |
344 | 354 | } |
345 | 355 | |
... | ... | @@ -351,8 +361,8 @@ |
351 | 361 | const void *value, size_t vlen) |
352 | 362 | { |
353 | 363 | struct pkcs7_parse_context *ctx = context; |
354 | - ctx->sinfo->raw_issuer = value; | |
355 | - ctx->sinfo->raw_issuer_size = vlen; | |
364 | + ctx->raw_issuer = value; | |
365 | + ctx->raw_issuer_size = vlen; | |
356 | 366 | return 0; |
357 | 367 | } |
358 | 368 | |
359 | 369 | |
... | ... | @@ -385,10 +395,21 @@ |
385 | 395 | const void *value, size_t vlen) |
386 | 396 | { |
387 | 397 | struct pkcs7_parse_context *ctx = context; |
398 | + struct pkcs7_signed_info *sinfo = ctx->sinfo; | |
399 | + struct asymmetric_key_id *kid; | |
388 | 400 | |
389 | - ctx->sinfo->index = ++ctx->sinfo_index; | |
390 | - *ctx->ppsinfo = ctx->sinfo; | |
391 | - ctx->ppsinfo = &ctx->sinfo->next; | |
401 | + /* Generate cert issuer + serial number key ID */ | |
402 | + kid = asymmetric_key_generate_id(ctx->raw_serial, | |
403 | + ctx->raw_serial_size, | |
404 | + ctx->raw_issuer, | |
405 | + ctx->raw_issuer_size); | |
406 | + if (IS_ERR(kid)) | |
407 | + return PTR_ERR(kid); | |
408 | + | |
409 | + sinfo->signing_cert_id = kid; | |
410 | + sinfo->index = ++ctx->sinfo_index; | |
411 | + *ctx->ppsinfo = sinfo; | |
412 | + ctx->ppsinfo = &sinfo->next; | |
392 | 413 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); |
393 | 414 | if (!ctx->sinfo) |
394 | 415 | return -ENOMEM; |
crypto/asymmetric_keys/pkcs7_parser.h
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ |
24 | 24 | unsigned index; |
25 | 25 | bool trusted; |
26 | + bool unsupported_crypto; /* T if not usable due to missing crypto */ | |
26 | 27 | |
27 | 28 | /* Message digest - the digest of the Content Data (or NULL) */ |
28 | 29 | const void *msgdigest; |
... | ... | @@ -33,10 +34,7 @@ |
33 | 34 | const void *authattrs; |
34 | 35 | |
35 | 36 | /* Issuing cert serial number and issuer's name */ |
36 | - const void *raw_serial; | |
37 | - unsigned raw_serial_size; | |
38 | - unsigned raw_issuer_size; | |
39 | - const void *raw_issuer; | |
37 | + struct asymmetric_key_id *signing_cert_id; | |
40 | 38 | |
41 | 39 | /* Message signature. |
42 | 40 | * |
crypto/asymmetric_keys/pkcs7_trust.c
... | ... | @@ -23,9 +23,9 @@ |
23 | 23 | /** |
24 | 24 | * Check the trust on one PKCS#7 SignedInfo block. |
25 | 25 | */ |
26 | -int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |
27 | - struct pkcs7_signed_info *sinfo, | |
28 | - struct key *trust_keyring) | |
26 | +static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |
27 | + struct pkcs7_signed_info *sinfo, | |
28 | + struct key *trust_keyring) | |
29 | 29 | { |
30 | 30 | struct public_key_signature *sig = &sinfo->sig; |
31 | 31 | struct x509_certificate *x509, *last = NULL, *p; |
... | ... | @@ -35,6 +35,11 @@ |
35 | 35 | |
36 | 36 | kenter(",%u,", sinfo->index); |
37 | 37 | |
38 | + if (sinfo->unsupported_crypto) { | |
39 | + kleave(" = -ENOPKG [cached]"); | |
40 | + return -ENOPKG; | |
41 | + } | |
42 | + | |
38 | 43 | for (x509 = sinfo->signer; x509; x509 = x509->signer) { |
39 | 44 | if (x509->seen) { |
40 | 45 | if (x509->verified) { |
41 | 46 | |
42 | 47 | |
... | ... | @@ -49,15 +54,17 @@ |
49 | 54 | /* Look to see if this certificate is present in the trusted |
50 | 55 | * keys. |
51 | 56 | */ |
52 | - key = x509_request_asymmetric_key(trust_keyring, x509->subject, | |
53 | - x509->fingerprint); | |
54 | - if (!IS_ERR(key)) | |
57 | + key = x509_request_asymmetric_key(trust_keyring, x509->id); | |
58 | + if (!IS_ERR(key)) { | |
55 | 59 | /* One of the X.509 certificates in the PKCS#7 message |
56 | 60 | * is apparently the same as one we already trust. |
57 | 61 | * Verify that the trusted variant can also validate |
58 | 62 | * the signature on the descendant. |
59 | 63 | */ |
64 | + pr_devel("sinfo %u: Cert %u as key %x\n", | |
65 | + sinfo->index, x509->index, key_serial(key)); | |
60 | 66 | goto matched; |
67 | + } | |
61 | 68 | if (key == ERR_PTR(-ENOMEM)) |
62 | 69 | return -ENOMEM; |
63 | 70 | |
64 | 71 | |
65 | 72 | |
... | ... | @@ -77,17 +84,35 @@ |
77 | 84 | /* No match - see if the root certificate has a signer amongst the |
78 | 85 | * trusted keys. |
79 | 86 | */ |
80 | - if (!last || !last->issuer || !last->authority) { | |
81 | - kleave(" = -ENOKEY [no backref]"); | |
82 | - return -ENOKEY; | |
87 | + if (last && last->authority) { | |
88 | + key = x509_request_asymmetric_key(trust_keyring, last->authority); | |
89 | + if (!IS_ERR(key)) { | |
90 | + x509 = last; | |
91 | + pr_devel("sinfo %u: Root cert %u signer is key %x\n", | |
92 | + sinfo->index, x509->index, key_serial(key)); | |
93 | + goto matched; | |
94 | + } | |
95 | + if (PTR_ERR(key) != -ENOKEY) | |
96 | + return PTR_ERR(key); | |
83 | 97 | } |
84 | 98 | |
85 | - key = x509_request_asymmetric_key(trust_keyring, last->issuer, | |
86 | - last->authority); | |
87 | - if (IS_ERR(key)) | |
88 | - return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; | |
89 | - x509 = last; | |
99 | + /* As a last resort, see if we have a trusted public key that matches | |
100 | + * the signed info directly. | |
101 | + */ | |
102 | + key = x509_request_asymmetric_key(trust_keyring, | |
103 | + sinfo->signing_cert_id); | |
104 | + if (!IS_ERR(key)) { | |
105 | + pr_devel("sinfo %u: Direct signer is key %x\n", | |
106 | + sinfo->index, key_serial(key)); | |
107 | + x509 = NULL; | |
108 | + goto matched; | |
109 | + } | |
110 | + if (PTR_ERR(key) != -ENOKEY) | |
111 | + return PTR_ERR(key); | |
90 | 112 | |
113 | + kleave(" = -ENOKEY [no backref]"); | |
114 | + return -ENOKEY; | |
115 | + | |
91 | 116 | matched: |
92 | 117 | ret = verify_signature(key, sig); |
93 | 118 | trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags); |
... | ... | @@ -100,10 +125,12 @@ |
100 | 125 | } |
101 | 126 | |
102 | 127 | verified: |
103 | - x509->verified = true; | |
104 | - for (p = sinfo->signer; p != x509; p = p->signer) { | |
105 | - p->verified = true; | |
106 | - p->trusted = trusted; | |
128 | + if (x509) { | |
129 | + x509->verified = true; | |
130 | + for (p = sinfo->signer; p != x509; p = p->signer) { | |
131 | + p->verified = true; | |
132 | + p->trusted = trusted; | |
133 | + } | |
107 | 134 | } |
108 | 135 | sinfo->trusted = trusted; |
109 | 136 | kleave(" = 0"); |
110 | 137 | |
111 | 138 | |
112 | 139 | |
... | ... | @@ -141,24 +168,28 @@ |
141 | 168 | { |
142 | 169 | struct pkcs7_signed_info *sinfo; |
143 | 170 | struct x509_certificate *p; |
144 | - int cached_ret = 0, ret; | |
171 | + int cached_ret = -ENOKEY; | |
172 | + int ret; | |
145 | 173 | |
146 | 174 | for (p = pkcs7->certs; p; p = p->next) |
147 | 175 | p->seen = false; |
148 | 176 | |
149 | 177 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { |
150 | 178 | ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring); |
151 | - if (ret < 0) { | |
152 | - if (ret == -ENOPKG) { | |
179 | + switch (ret) { | |
180 | + case -ENOKEY: | |
181 | + continue; | |
182 | + case -ENOPKG: | |
183 | + if (cached_ret == -ENOKEY) | |
153 | 184 | cached_ret = -ENOPKG; |
154 | - } else if (ret == -ENOKEY) { | |
155 | - if (cached_ret == 0) | |
156 | - cached_ret = -ENOKEY; | |
157 | - } else { | |
158 | - return ret; | |
159 | - } | |
185 | + continue; | |
186 | + case 0: | |
187 | + *_trusted |= sinfo->trusted; | |
188 | + cached_ret = 0; | |
189 | + continue; | |
190 | + default: | |
191 | + return ret; | |
160 | 192 | } |
161 | - *_trusted |= sinfo->trusted; | |
162 | 193 | } |
163 | 194 | |
164 | 195 | return cached_ret; |
crypto/asymmetric_keys/pkcs7_verify.c
... | ... | @@ -131,8 +131,7 @@ |
131 | 131 | struct x509_certificate *x509; |
132 | 132 | unsigned certix = 1; |
133 | 133 | |
134 | - kenter("%u,%u,%u", | |
135 | - sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size); | |
134 | + kenter("%u", sinfo->index); | |
136 | 135 | |
137 | 136 | for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { |
138 | 137 | /* I'm _assuming_ that the generator of the PKCS#7 message will |
139 | 138 | |
... | ... | @@ -140,21 +139,11 @@ |
140 | 139 | * PKCS#7 message - but I can't be 100% sure of that. It's |
141 | 140 | * possible this will need element-by-element comparison. |
142 | 141 | */ |
143 | - if (x509->raw_serial_size != sinfo->raw_serial_size || | |
144 | - memcmp(x509->raw_serial, sinfo->raw_serial, | |
145 | - sinfo->raw_serial_size) != 0) | |
142 | + if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id)) | |
146 | 143 | continue; |
147 | 144 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", |
148 | 145 | sinfo->index, certix); |
149 | 146 | |
150 | - if (x509->raw_issuer_size != sinfo->raw_issuer_size || | |
151 | - memcmp(x509->raw_issuer, sinfo->raw_issuer, | |
152 | - sinfo->raw_issuer_size) != 0) { | |
153 | - pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n", | |
154 | - sinfo->index); | |
155 | - continue; | |
156 | - } | |
157 | - | |
158 | 147 | if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { |
159 | 148 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", |
160 | 149 | sinfo->index); |
... | ... | @@ -164,9 +153,14 @@ |
164 | 153 | sinfo->signer = x509; |
165 | 154 | return 0; |
166 | 155 | } |
167 | - pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", | |
168 | - sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial); | |
169 | - return -ENOKEY; | |
156 | + | |
157 | + /* The relevant X.509 cert isn't found here, but it might be found in | |
158 | + * the trust keyring. | |
159 | + */ | |
160 | + pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", | |
161 | + sinfo->index, | |
162 | + sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); | |
163 | + return 0; | |
170 | 164 | } |
171 | 165 | |
172 | 166 | /* |
173 | 167 | |
174 | 168 | |
... | ... | @@ -184,15 +178,18 @@ |
184 | 178 | p->seen = false; |
185 | 179 | |
186 | 180 | for (;;) { |
187 | - pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint); | |
181 | + pr_debug("verify %s: %*phN\n", | |
182 | + x509->subject, | |
183 | + x509->raw_serial_size, x509->raw_serial); | |
188 | 184 | x509->seen = true; |
189 | 185 | ret = x509_get_sig_params(x509); |
190 | 186 | if (ret < 0) |
191 | - return ret; | |
187 | + goto maybe_missing_crypto_in_x509; | |
192 | 188 | |
193 | 189 | pr_debug("- issuer %s\n", x509->issuer); |
194 | 190 | if (x509->authority) |
195 | - pr_debug("- authkeyid %s\n", x509->authority); | |
191 | + pr_debug("- authkeyid %*phN\n", | |
192 | + x509->authority->len, x509->authority->data); | |
196 | 193 | |
197 | 194 | if (!x509->authority || |
198 | 195 | strcmp(x509->subject, x509->issuer) == 0) { |
... | ... | @@ -209,7 +206,7 @@ |
209 | 206 | |
210 | 207 | ret = x509_check_signature(x509->pub, x509); |
211 | 208 | if (ret < 0) |
212 | - return ret; | |
209 | + goto maybe_missing_crypto_in_x509; | |
213 | 210 | x509->signer = x509; |
214 | 211 | pr_debug("- self-signed\n"); |
215 | 212 | return 0; |
216 | 213 | |
... | ... | @@ -218,13 +215,14 @@ |
218 | 215 | /* Look through the X.509 certificates in the PKCS#7 message's |
219 | 216 | * list to see if the next one is there. |
220 | 217 | */ |
221 | - pr_debug("- want %s\n", x509->authority); | |
218 | + pr_debug("- want %*phN\n", | |
219 | + x509->authority->len, x509->authority->data); | |
222 | 220 | for (p = pkcs7->certs; p; p = p->next) { |
223 | - pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint); | |
224 | - if (p->raw_subject_size == x509->raw_issuer_size && | |
225 | - strcmp(p->fingerprint, x509->authority) == 0 && | |
226 | - memcmp(p->raw_subject, x509->raw_issuer, | |
227 | - x509->raw_issuer_size) == 0) | |
221 | + if (!p->skid) | |
222 | + continue; | |
223 | + pr_debug("- cmp [%u] %*phN\n", | |
224 | + p->index, p->skid->len, p->skid->data); | |
225 | + if (asymmetric_key_id_same(p->skid, x509->authority)) | |
228 | 226 | goto found_issuer; |
229 | 227 | } |
230 | 228 | |
... | ... | @@ -233,7 +231,7 @@ |
233 | 231 | return 0; |
234 | 232 | |
235 | 233 | found_issuer: |
236 | - pr_debug("- issuer %s\n", p->subject); | |
234 | + pr_debug("- subject %s\n", p->subject); | |
237 | 235 | if (p->seen) { |
238 | 236 | pr_warn("Sig %u: X.509 chain contains loop\n", |
239 | 237 | sinfo->index); |
... | ... | @@ -250,6 +248,17 @@ |
250 | 248 | x509 = p; |
251 | 249 | might_sleep(); |
252 | 250 | } |
251 | + | |
252 | +maybe_missing_crypto_in_x509: | |
253 | + /* Just prune the certificate chain at this point if we lack some | |
254 | + * crypto module to go further. Note, however, we don't want to set | |
255 | + * sinfo->missing_crypto as the signed info block may still be | |
256 | + * validatable against an X.509 cert lower in the chain that we have a | |
257 | + * trusted copy of. | |
258 | + */ | |
259 | + if (ret == -ENOPKG) | |
260 | + return 0; | |
261 | + return ret; | |
253 | 262 | } |
254 | 263 | |
255 | 264 | /* |
256 | 265 | |
... | ... | @@ -269,11 +278,14 @@ |
269 | 278 | if (ret < 0) |
270 | 279 | return ret; |
271 | 280 | |
272 | - /* Find the key for the signature */ | |
281 | + /* Find the key for the signature if there is one */ | |
273 | 282 | ret = pkcs7_find_key(pkcs7, sinfo); |
274 | 283 | if (ret < 0) |
275 | 284 | return ret; |
276 | 285 | |
286 | + if (!sinfo->signer) | |
287 | + return 0; | |
288 | + | |
277 | 289 | pr_devel("Using X.509[%u] for sig %u\n", |
278 | 290 | sinfo->signer->index, sinfo->index); |
279 | 291 | |
280 | 292 | |
... | ... | @@ -291,11 +303,33 @@ |
291 | 303 | /** |
292 | 304 | * pkcs7_verify - Verify a PKCS#7 message |
293 | 305 | * @pkcs7: The PKCS#7 message to be verified |
306 | + * | |
307 | + * Verify a PKCS#7 message is internally consistent - that is, the data digest | |
308 | + * matches the digest in the AuthAttrs and any signature in the message or one | |
309 | + * of the X.509 certificates it carries that matches another X.509 cert in the | |
310 | + * message can be verified. | |
311 | + * | |
312 | + * This does not look to match the contents of the PKCS#7 message against any | |
313 | + * external public keys. | |
314 | + * | |
315 | + * Returns, in order of descending priority: | |
316 | + * | |
317 | + * (*) -EKEYREJECTED if a signature failed to match for which we found an | |
318 | + * appropriate X.509 certificate, or: | |
319 | + * | |
320 | + * (*) -EBADMSG if some part of the message was invalid, or: | |
321 | + * | |
322 | + * (*) -ENOPKG if none of the signature chains are verifiable because suitable | |
323 | + * crypto modules couldn't be found, or: | |
324 | + * | |
325 | + * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified | |
326 | + * (note that a signature chain may be of zero length), or: | |
294 | 327 | */ |
295 | 328 | int pkcs7_verify(struct pkcs7_message *pkcs7) |
296 | 329 | { |
297 | 330 | struct pkcs7_signed_info *sinfo; |
298 | 331 | struct x509_certificate *x509; |
332 | + int enopkg = -ENOPKG; | |
299 | 333 | int ret, n; |
300 | 334 | |
301 | 335 | kenter(""); |
302 | 336 | |
303 | 337 | |
304 | 338 | |
... | ... | @@ -304,19 +338,25 @@ |
304 | 338 | ret = x509_get_sig_params(x509); |
305 | 339 | if (ret < 0) |
306 | 340 | return ret; |
307 | - pr_debug("X.509[%u] %s\n", n, x509->authority); | |
341 | + pr_debug("X.509[%u] %*phN\n", | |
342 | + n, x509->authority->len, x509->authority->data); | |
308 | 343 | } |
309 | 344 | |
310 | 345 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { |
311 | 346 | ret = pkcs7_verify_one(pkcs7, sinfo); |
312 | 347 | if (ret < 0) { |
348 | + if (ret == -ENOPKG) { | |
349 | + sinfo->unsupported_crypto = true; | |
350 | + continue; | |
351 | + } | |
313 | 352 | kleave(" = %d", ret); |
314 | 353 | return ret; |
315 | 354 | } |
355 | + enopkg = 0; | |
316 | 356 | } |
317 | 357 | |
318 | - kleave(" = 0"); | |
319 | - return 0; | |
358 | + kleave(" = %d", enopkg); | |
359 | + return enopkg; | |
320 | 360 | } |
321 | 361 | EXPORT_SYMBOL_GPL(pkcs7_verify); |
crypto/asymmetric_keys/x509_cert_parser.c
... | ... | @@ -46,7 +46,8 @@ |
46 | 46 | public_key_destroy(cert->pub); |
47 | 47 | kfree(cert->issuer); |
48 | 48 | kfree(cert->subject); |
49 | - kfree(cert->fingerprint); | |
49 | + kfree(cert->id); | |
50 | + kfree(cert->skid); | |
50 | 51 | kfree(cert->authority); |
51 | 52 | kfree(cert->sig.digest); |
52 | 53 | mpi_free(cert->sig.rsa.s); |
... | ... | @@ -62,6 +63,7 @@ |
62 | 63 | { |
63 | 64 | struct x509_certificate *cert; |
64 | 65 | struct x509_parse_context *ctx; |
66 | + struct asymmetric_key_id *kid; | |
65 | 67 | long ret; |
66 | 68 | |
67 | 69 | ret = -ENOMEM; |
... | ... | @@ -89,6 +91,17 @@ |
89 | 91 | if (ret < 0) |
90 | 92 | goto error_decode; |
91 | 93 | |
94 | + /* Generate cert issuer + serial number key ID */ | |
95 | + kid = asymmetric_key_generate_id(cert->raw_serial, | |
96 | + cert->raw_serial_size, | |
97 | + cert->raw_issuer, | |
98 | + cert->raw_issuer_size); | |
99 | + if (IS_ERR(kid)) { | |
100 | + ret = PTR_ERR(kid); | |
101 | + goto error_decode; | |
102 | + } | |
103 | + cert->id = kid; | |
104 | + | |
92 | 105 | kfree(ctx); |
93 | 106 | return cert; |
94 | 107 | |
95 | 108 | |
96 | 109 | |
97 | 110 | |
98 | 111 | |
99 | 112 | |
... | ... | @@ -407,36 +420,34 @@ |
407 | 420 | const void *value, size_t vlen) |
408 | 421 | { |
409 | 422 | struct x509_parse_context *ctx = context; |
423 | + struct asymmetric_key_id *kid; | |
410 | 424 | const unsigned char *v = value; |
411 | - char *f; | |
412 | 425 | int i; |
413 | 426 | |
414 | 427 | pr_debug("Extension: %u\n", ctx->last_oid); |
415 | 428 | |
416 | 429 | if (ctx->last_oid == OID_subjectKeyIdentifier) { |
417 | 430 | /* Get hold of the key fingerprint */ |
418 | - if (vlen < 3) | |
431 | + if (ctx->cert->skid || vlen < 3) | |
419 | 432 | return -EBADMSG; |
420 | 433 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) |
421 | 434 | return -EBADMSG; |
422 | 435 | v += 2; |
423 | 436 | vlen -= 2; |
424 | 437 | |
425 | - f = kmalloc(vlen * 2 + 1, GFP_KERNEL); | |
426 | - if (!f) | |
427 | - return -ENOMEM; | |
428 | - for (i = 0; i < vlen; i++) | |
429 | - sprintf(f + i * 2, "%02x", v[i]); | |
430 | - pr_debug("fingerprint %s\n", f); | |
431 | - ctx->cert->fingerprint = f; | |
438 | + kid = asymmetric_key_generate_id(v, vlen, | |
439 | + ctx->cert->raw_subject, | |
440 | + ctx->cert->raw_subject_size); | |
441 | + if (IS_ERR(kid)) | |
442 | + return PTR_ERR(kid); | |
443 | + ctx->cert->skid = kid; | |
444 | + pr_debug("subjkeyid %*phN\n", kid->len, kid->data); | |
432 | 445 | return 0; |
433 | 446 | } |
434 | 447 | |
435 | 448 | if (ctx->last_oid == OID_authorityKeyIdentifier) { |
436 | - size_t key_len; | |
437 | - | |
438 | 449 | /* Get hold of the CA key fingerprint */ |
439 | - if (vlen < 5) | |
450 | + if (ctx->cert->authority || vlen < 5) | |
440 | 451 | return -EBADMSG; |
441 | 452 | |
442 | 453 | /* Authority Key Identifier must be a Constructed SEQUENCE */ |
... | ... | @@ -454,7 +465,7 @@ |
454 | 465 | v[3] > vlen - 4) |
455 | 466 | return -EBADMSG; |
456 | 467 | |
457 | - key_len = v[3]; | |
468 | + vlen = v[3]; | |
458 | 469 | v += 4; |
459 | 470 | } else { |
460 | 471 | /* Long Form length */ |
461 | 472 | |
... | ... | @@ -476,17 +487,17 @@ |
476 | 487 | v[sub + 1] > vlen - 4 - sub) |
477 | 488 | return -EBADMSG; |
478 | 489 | |
479 | - key_len = v[sub + 1]; | |
490 | + vlen = v[sub + 1]; | |
480 | 491 | v += (sub + 2); |
481 | 492 | } |
482 | 493 | |
483 | - f = kmalloc(key_len * 2 + 1, GFP_KERNEL); | |
484 | - if (!f) | |
485 | - return -ENOMEM; | |
486 | - for (i = 0; i < key_len; i++) | |
487 | - sprintf(f + i * 2, "%02x", v[i]); | |
488 | - pr_debug("authority %s\n", f); | |
489 | - ctx->cert->authority = f; | |
494 | + kid = asymmetric_key_generate_id(v, vlen, | |
495 | + ctx->cert->raw_issuer, | |
496 | + ctx->cert->raw_issuer_size); | |
497 | + if (IS_ERR(kid)) | |
498 | + return PTR_ERR(kid); | |
499 | + pr_debug("authkeyid %*phN\n", kid->len, kid->data); | |
500 | + ctx->cert->authority = kid; | |
490 | 501 | return 0; |
491 | 502 | } |
492 | 503 |
crypto/asymmetric_keys/x509_parser.h
... | ... | @@ -19,8 +19,9 @@ |
19 | 19 | struct public_key_signature sig; /* Signature parameters */ |
20 | 20 | char *issuer; /* Name of certificate issuer */ |
21 | 21 | char *subject; /* Name of certificate subject */ |
22 | - char *fingerprint; /* Key fingerprint as hex */ | |
23 | - char *authority; /* Authority key fingerprint as hex */ | |
22 | + struct asymmetric_key_id *id; /* Issuer + serial number */ | |
23 | + struct asymmetric_key_id *skid; /* Subject key identifier */ | |
24 | + struct asymmetric_key_id *authority; /* Authority key identifier */ | |
24 | 25 | struct tm valid_from; |
25 | 26 | struct tm valid_to; |
26 | 27 | const void *tbs; /* Signed data */ |
... | ... | @@ -37,6 +38,7 @@ |
37 | 38 | bool seen; /* Infinite recursion prevention */ |
38 | 39 | bool verified; |
39 | 40 | bool trusted; |
41 | + bool unsupported_crypto; /* T if can't be verified due to missing crypto */ | |
40 | 42 | }; |
41 | 43 | |
42 | 44 | /* |
crypto/asymmetric_keys/x509_public_key.c
... | ... | @@ -25,7 +25,7 @@ |
25 | 25 | #include "x509_parser.h" |
26 | 26 | |
27 | 27 | static bool use_builtin_keys; |
28 | -static char *ca_keyid; | |
28 | +static struct asymmetric_key_id *ca_keyid; | |
29 | 29 | |
30 | 30 | #ifndef MODULE |
31 | 31 | static int __init ca_keys_setup(char *str) |
32 | 32 | |
... | ... | @@ -33,10 +33,16 @@ |
33 | 33 | if (!str) /* default system keyring */ |
34 | 34 | return 1; |
35 | 35 | |
36 | - if (strncmp(str, "id:", 3) == 0) | |
37 | - ca_keyid = str; /* owner key 'id:xxxxxx' */ | |
38 | - else if (strcmp(str, "builtin") == 0) | |
36 | + if (strncmp(str, "id:", 3) == 0) { | |
37 | + struct asymmetric_key_id *p; | |
38 | + p = asymmetric_key_hex_to_key_id(str); | |
39 | + if (p == ERR_PTR(-EINVAL)) | |
40 | + pr_err("Unparsable hex string in ca_keys\n"); | |
41 | + else if (!IS_ERR(p)) | |
42 | + ca_keyid = p; /* owner key 'id:xxxxxx' */ | |
43 | + } else if (strcmp(str, "builtin") == 0) { | |
39 | 44 | use_builtin_keys = true; |
45 | + } | |
40 | 46 | |
41 | 47 | return 1; |
42 | 48 | } |
43 | 49 | |
44 | 50 | |
45 | 51 | |
46 | 52 | |
... | ... | @@ -46,31 +52,28 @@ |
46 | 52 | /** |
47 | 53 | * x509_request_asymmetric_key - Request a key by X.509 certificate params. |
48 | 54 | * @keyring: The keys to search. |
49 | - * @subject: The name of the subject to whom the key belongs. | |
50 | - * @key_id: The subject key ID as a hex string. | |
55 | + * @kid: The key ID. | |
51 | 56 | * |
52 | 57 | * Find a key in the given keyring by subject name and key ID. These might, |
53 | 58 | * for instance, be the issuer name and the authority key ID of an X.509 |
54 | 59 | * certificate that needs to be verified. |
55 | 60 | */ |
56 | 61 | struct key *x509_request_asymmetric_key(struct key *keyring, |
57 | - const char *subject, | |
58 | - const char *key_id) | |
62 | + const struct asymmetric_key_id *kid) | |
59 | 63 | { |
60 | 64 | key_ref_t key; |
61 | - size_t subject_len = strlen(subject), key_id_len = strlen(key_id); | |
62 | - char *id; | |
65 | + char *id, *p; | |
63 | 66 | |
64 | - /* Construct an identifier "<subjname>:<keyid>". */ | |
65 | - id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL); | |
67 | + /* Construct an identifier "id:<keyid>". */ | |
68 | + p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); | |
66 | 69 | if (!id) |
67 | 70 | return ERR_PTR(-ENOMEM); |
68 | 71 | |
69 | - memcpy(id, subject, subject_len); | |
70 | - id[subject_len + 0] = ':'; | |
71 | - id[subject_len + 1] = ' '; | |
72 | - memcpy(id + subject_len + 2, key_id, key_id_len); | |
73 | - id[subject_len + 2 + key_id_len] = 0; | |
72 | + *p++ = 'i'; | |
73 | + *p++ = 'd'; | |
74 | + *p++ = ':'; | |
75 | + p = bin2hex(p, kid->data, kid->len); | |
76 | + *p = 0; | |
74 | 77 | |
75 | 78 | pr_debug("Look up: \"%s\"\n", id); |
76 | 79 | |
... | ... | @@ -112,6 +115,8 @@ |
112 | 115 | |
113 | 116 | pr_devel("==>%s()\n", __func__); |
114 | 117 | |
118 | + if (cert->unsupported_crypto) | |
119 | + return -ENOPKG; | |
115 | 120 | if (cert->sig.rsa.s) |
116 | 121 | return 0; |
117 | 122 | |
... | ... | @@ -124,8 +129,13 @@ |
124 | 129 | * big the hash operational data will be. |
125 | 130 | */ |
126 | 131 | tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); |
127 | - if (IS_ERR(tfm)) | |
128 | - return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); | |
132 | + if (IS_ERR(tfm)) { | |
133 | + if (PTR_ERR(tfm) == -ENOENT) { | |
134 | + cert->unsupported_crypto = true; | |
135 | + return -ENOPKG; | |
136 | + } | |
137 | + return PTR_ERR(tfm); | |
138 | + } | |
129 | 139 | |
130 | 140 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); |
131 | 141 | digest_size = crypto_shash_digestsize(tfm); |
... | ... | @@ -172,6 +182,8 @@ |
172 | 182 | return ret; |
173 | 183 | |
174 | 184 | ret = public_key_verify_signature(pub, &cert->sig); |
185 | + if (ret == -ENOPKG) | |
186 | + cert->unsupported_crypto = true; | |
175 | 187 | pr_debug("Cert Verification: %d\n", ret); |
176 | 188 | return ret; |
177 | 189 | } |
178 | 190 | |
... | ... | @@ -195,11 +207,10 @@ |
195 | 207 | if (!trust_keyring) |
196 | 208 | return -EOPNOTSUPP; |
197 | 209 | |
198 | - if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid)) | |
210 | + if (ca_keyid && !asymmetric_key_id_same(cert->authority, ca_keyid)) | |
199 | 211 | return -EPERM; |
200 | 212 | |
201 | - key = x509_request_asymmetric_key(trust_keyring, | |
202 | - cert->issuer, cert->authority); | |
213 | + key = x509_request_asymmetric_key(trust_keyring, cert->authority); | |
203 | 214 | if (!IS_ERR(key)) { |
204 | 215 | if (!use_builtin_keys |
205 | 216 | || test_bit(KEY_FLAG_BUILTIN, &key->flags)) |
206 | 217 | |
207 | 218 | |
... | ... | @@ -214,9 +225,11 @@ |
214 | 225 | */ |
215 | 226 | static int x509_key_preparse(struct key_preparsed_payload *prep) |
216 | 227 | { |
228 | + struct asymmetric_key_ids *kids; | |
217 | 229 | struct x509_certificate *cert; |
230 | + const char *q; | |
218 | 231 | size_t srlen, sulen; |
219 | - char *desc = NULL; | |
232 | + char *desc = NULL, *p; | |
220 | 233 | int ret; |
221 | 234 | |
222 | 235 | cert = x509_cert_parse(prep->data, prep->datalen); |
223 | 236 | |
... | ... | @@ -249,19 +262,12 @@ |
249 | 262 | pkey_algo_name[cert->sig.pkey_algo], |
250 | 263 | hash_algo_name[cert->sig.pkey_hash_algo]); |
251 | 264 | |
252 | - if (!cert->fingerprint) { | |
253 | - pr_warn("Cert for '%s' must have a SubjKeyId extension\n", | |
254 | - cert->subject); | |
255 | - ret = -EKEYREJECTED; | |
256 | - goto error_free_cert; | |
257 | - } | |
258 | - | |
259 | 265 | cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; |
260 | 266 | cert->pub->id_type = PKEY_ID_X509; |
261 | 267 | |
262 | 268 | /* Check the signature on the key if it appears to be self-signed */ |
263 | 269 | if (!cert->authority || |
264 | - strcmp(cert->fingerprint, cert->authority) == 0) { | |
270 | + asymmetric_key_id_same(cert->skid, cert->authority)) { | |
265 | 271 | ret = x509_check_signature(cert->pub, cert); /* self-signed */ |
266 | 272 | if (ret < 0) |
267 | 273 | goto error_free_cert; |
268 | 274 | |
269 | 275 | |
270 | 276 | |
271 | 277 | |
272 | 278 | |
273 | 279 | |
... | ... | @@ -273,31 +279,47 @@ |
273 | 279 | |
274 | 280 | /* Propose a description */ |
275 | 281 | sulen = strlen(cert->subject); |
276 | - srlen = strlen(cert->fingerprint); | |
282 | + srlen = cert->raw_serial_size; | |
283 | + q = cert->raw_serial; | |
284 | + if (srlen > 1 && *q == 0) { | |
285 | + srlen--; | |
286 | + q++; | |
287 | + } | |
288 | + | |
277 | 289 | ret = -ENOMEM; |
278 | - desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); | |
290 | + desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); | |
279 | 291 | if (!desc) |
280 | 292 | goto error_free_cert; |
281 | - memcpy(desc, cert->subject, sulen); | |
282 | - desc[sulen] = ':'; | |
283 | - desc[sulen + 1] = ' '; | |
284 | - memcpy(desc + sulen + 2, cert->fingerprint, srlen); | |
285 | - desc[sulen + 2 + srlen] = 0; | |
293 | + p = memcpy(desc, cert->subject, sulen); | |
294 | + p += sulen; | |
295 | + *p++ = ':'; | |
296 | + *p++ = ' '; | |
297 | + p = bin2hex(p, q, srlen); | |
298 | + *p = 0; | |
286 | 299 | |
300 | + kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL); | |
301 | + if (!kids) | |
302 | + goto error_free_desc; | |
303 | + kids->id[0] = cert->id; | |
304 | + kids->id[1] = cert->skid; | |
305 | + | |
287 | 306 | /* We're pinning the module by being linked against it */ |
288 | 307 | __module_get(public_key_subtype.owner); |
289 | 308 | prep->type_data[0] = &public_key_subtype; |
290 | - prep->type_data[1] = cert->fingerprint; | |
309 | + prep->type_data[1] = kids; | |
291 | 310 | prep->payload[0] = cert->pub; |
292 | 311 | prep->description = desc; |
293 | 312 | prep->quotalen = 100; |
294 | 313 | |
295 | 314 | /* We've finished with the certificate */ |
296 | 315 | cert->pub = NULL; |
297 | - cert->fingerprint = NULL; | |
316 | + cert->id = NULL; | |
317 | + cert->skid = NULL; | |
298 | 318 | desc = NULL; |
299 | 319 | ret = 0; |
300 | 320 | |
321 | +error_free_desc: | |
322 | + kfree(desc); | |
301 | 323 | error_free_cert: |
302 | 324 | x509_free_certificate(cert); |
303 | 325 | return ret; |
fs/cifs/cifs_spnego.c
fs/cifs/cifsacl.c
fs/nfs/idmap.c
... | ... | @@ -177,7 +177,6 @@ |
177 | 177 | .preparse = user_preparse, |
178 | 178 | .free_preparse = user_free_preparse, |
179 | 179 | .instantiate = generic_key_instantiate, |
180 | - .match = user_match, | |
181 | 180 | .revoke = user_revoke, |
182 | 181 | .destroy = user_destroy, |
183 | 182 | .describe = user_describe, |
... | ... | @@ -401,7 +400,6 @@ |
401 | 400 | .preparse = user_preparse, |
402 | 401 | .free_preparse = user_free_preparse, |
403 | 402 | .instantiate = generic_key_instantiate, |
404 | - .match = user_match, | |
405 | 403 | .revoke = user_revoke, |
406 | 404 | .destroy = user_destroy, |
407 | 405 | .describe = user_describe, |
include/crypto/public_key.h
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #define _LINUX_PUBLIC_KEY_H |
16 | 16 | |
17 | 17 | #include <linux/mpi.h> |
18 | +#include <keys/asymmetric-type.h> | |
18 | 19 | #include <crypto/hash_info.h> |
19 | 20 | |
20 | 21 | enum pkey_algo { |
21 | 22 | |
... | ... | @@ -98,9 +99,9 @@ |
98 | 99 | extern int verify_signature(const struct key *key, |
99 | 100 | const struct public_key_signature *sig); |
100 | 101 | |
102 | +struct asymmetric_key_id; | |
101 | 103 | extern struct key *x509_request_asymmetric_key(struct key *keyring, |
102 | - const char *issuer, | |
103 | - const char *key_id); | |
104 | + const struct asymmetric_key_id *kid); | |
104 | 105 | |
105 | 106 | #endif /* _LINUX_PUBLIC_KEY_H */ |
include/keys/asymmetric-type.h
... | ... | @@ -19,6 +19,44 @@ |
19 | 19 | extern struct key_type key_type_asymmetric; |
20 | 20 | |
21 | 21 | /* |
22 | + * Identifiers for an asymmetric key ID. We have three ways of looking up a | |
23 | + * key derived from an X.509 certificate: | |
24 | + * | |
25 | + * (1) Serial Number & Issuer. Non-optional. This is the only valid way to | |
26 | + * map a PKCS#7 signature to an X.509 certificate. | |
27 | + * | |
28 | + * (2) Issuer & Subject Unique IDs. Optional. These were the original way to | |
29 | + * match X.509 certificates, but have fallen into disuse in favour of (3). | |
30 | + * | |
31 | + * (3) Auth & Subject Key Identifiers. Optional. SKIDs are only provided on | |
32 | + * CA keys that are intended to sign other keys, so don't appear in end | |
33 | + * user certificates unless forced. | |
34 | + * | |
35 | + * We could also support an PGP key identifier, which is just a SHA1 sum of the | |
36 | + * public key and certain parameters, but since we don't support PGP keys at | |
37 | + * the moment, we shall ignore those. | |
38 | + * | |
39 | + * What we actually do is provide a place where binary identifiers can be | |
40 | + * stashed and then compare against them when checking for an id match. | |
41 | + */ | |
42 | +struct asymmetric_key_id { | |
43 | + unsigned short len; | |
44 | + unsigned char data[]; | |
45 | +}; | |
46 | + | |
47 | +struct asymmetric_key_ids { | |
48 | + void *id[2]; | |
49 | +}; | |
50 | + | |
51 | +extern bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, | |
52 | + const struct asymmetric_key_id *kid2); | |
53 | + | |
54 | +extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1, | |
55 | + size_t len_1, | |
56 | + const void *val_2, | |
57 | + size_t len_2); | |
58 | + | |
59 | +/* | |
22 | 60 | * The payload is at the discretion of the subtype. |
23 | 61 | */ |
24 | 62 |
include/keys/user-type.h
... | ... | @@ -40,7 +40,6 @@ |
40 | 40 | extern int user_preparse(struct key_preparsed_payload *prep); |
41 | 41 | extern void user_free_preparse(struct key_preparsed_payload *prep); |
42 | 42 | extern int user_update(struct key *key, struct key_preparsed_payload *prep); |
43 | -extern int user_match(const struct key *key, const void *criterion); | |
44 | 43 | extern void user_revoke(struct key *key); |
45 | 44 | extern void user_destroy(struct key *key); |
46 | 45 | extern void user_describe(const struct key *user, struct seq_file *m); |
include/linux/kernel.h
include/linux/key-type.h
... | ... | @@ -53,6 +53,24 @@ |
53 | 53 | const char *op, void *aux); |
54 | 54 | |
55 | 55 | /* |
56 | + * Preparsed matching criterion. | |
57 | + */ | |
58 | +struct key_match_data { | |
59 | + /* Comparison function, defaults to exact description match, but can be | |
60 | + * overridden by type->match_preparse(). Should return true if a match | |
61 | + * is found and false if not. | |
62 | + */ | |
63 | + bool (*cmp)(const struct key *key, | |
64 | + const struct key_match_data *match_data); | |
65 | + | |
66 | + const void *raw_data; /* Raw match data */ | |
67 | + void *preparsed; /* For ->match_preparse() to stash stuff */ | |
68 | + unsigned lookup_type; /* Type of lookup for this search. */ | |
69 | +#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */ | |
70 | +#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */ | |
71 | +}; | |
72 | + | |
73 | +/* | |
56 | 74 | * kernel managed key type definition |
57 | 75 | */ |
58 | 76 | struct key_type { |
... | ... | @@ -65,11 +83,6 @@ |
65 | 83 | */ |
66 | 84 | size_t def_datalen; |
67 | 85 | |
68 | - /* Default key search algorithm. */ | |
69 | - unsigned def_lookup_type; | |
70 | -#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */ | |
71 | -#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */ | |
72 | - | |
73 | 86 | /* vet a description */ |
74 | 87 | int (*vet_description)(const char *description); |
75 | 88 | |
... | ... | @@ -96,8 +109,15 @@ |
96 | 109 | */ |
97 | 110 | int (*update)(struct key *key, struct key_preparsed_payload *prep); |
98 | 111 | |
99 | - /* match a key against a description */ | |
100 | - int (*match)(const struct key *key, const void *desc); | |
112 | + /* Preparse the data supplied to ->match() (optional). The | |
113 | + * data to be preparsed can be found in match_data->raw_data. | |
114 | + * The lookup type can also be set by this function. | |
115 | + */ | |
116 | + int (*match_preparse)(struct key_match_data *match_data); | |
117 | + | |
118 | + /* Free preparsed match data (optional). This should be supplied it | |
119 | + * ->match_preparse() is supplied. */ | |
120 | + void (*match_free)(struct key_match_data *match_data); | |
101 | 121 | |
102 | 122 | /* clear some of the data from a key on revokation (optional) |
103 | 123 | * - the key's semaphore will be write-locked by the caller |
lib/hexdump.c
... | ... | @@ -59,6 +59,22 @@ |
59 | 59 | EXPORT_SYMBOL(hex2bin); |
60 | 60 | |
61 | 61 | /** |
62 | + * bin2hex - convert binary data to an ascii hexadecimal string | |
63 | + * @dst: ascii hexadecimal result | |
64 | + * @src: binary data | |
65 | + * @count: binary data length | |
66 | + */ | |
67 | +char *bin2hex(char *dst, const void *src, size_t count) | |
68 | +{ | |
69 | + const unsigned char *_src = src; | |
70 | + | |
71 | + while (count--) | |
72 | + dst = hex_byte_pack(dst, *_src++); | |
73 | + return dst; | |
74 | +} | |
75 | +EXPORT_SYMBOL(bin2hex); | |
76 | + | |
77 | +/** | |
62 | 78 | * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory |
63 | 79 | * @buf: data blob to dump |
64 | 80 | * @len: number of bytes in the @buf |
net/ceph/crypto.c
net/dns_resolver/dns_key.c
... | ... | @@ -176,11 +176,11 @@ |
176 | 176 | * The domain name may be a simple name or an absolute domain name (which |
177 | 177 | * should end with a period). The domain name is case-independent. |
178 | 178 | */ |
179 | -static int | |
180 | -dns_resolver_match(const struct key *key, const void *description) | |
179 | +static bool dns_resolver_cmp(const struct key *key, | |
180 | + const struct key_match_data *match_data) | |
181 | 181 | { |
182 | 182 | int slen, dlen, ret = 0; |
183 | - const char *src = key->description, *dsp = description; | |
183 | + const char *src = key->description, *dsp = match_data->raw_data; | |
184 | 184 | |
185 | 185 | kenter("%s,%s", src, dsp); |
186 | 186 | |
... | ... | @@ -209,6 +209,16 @@ |
209 | 209 | } |
210 | 210 | |
211 | 211 | /* |
212 | + * Preparse the match criterion. | |
213 | + */ | |
214 | +static int dns_resolver_match_preparse(struct key_match_data *match_data) | |
215 | +{ | |
216 | + match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; | |
217 | + match_data->cmp = dns_resolver_cmp; | |
218 | + return 0; | |
219 | +} | |
220 | + | |
221 | +/* | |
212 | 222 | * Describe a DNS key |
213 | 223 | */ |
214 | 224 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) |
... | ... | @@ -242,7 +252,7 @@ |
242 | 252 | .preparse = dns_resolver_preparse, |
243 | 253 | .free_preparse = dns_resolver_free_preparse, |
244 | 254 | .instantiate = generic_key_instantiate, |
245 | - .match = dns_resolver_match, | |
255 | + .match_preparse = dns_resolver_match_preparse, | |
246 | 256 | .revoke = user_revoke, |
247 | 257 | .destroy = user_destroy, |
248 | 258 | .describe = dns_resolver_describe, |
net/rxrpc/ar-key.c
... | ... | @@ -44,7 +44,6 @@ |
44 | 44 | .preparse = rxrpc_preparse, |
45 | 45 | .free_preparse = rxrpc_free_preparse, |
46 | 46 | .instantiate = generic_key_instantiate, |
47 | - .match = user_match, | |
48 | 47 | .destroy = rxrpc_destroy, |
49 | 48 | .describe = rxrpc_describe, |
50 | 49 | .read = rxrpc_read, |
... | ... | @@ -61,7 +60,6 @@ |
61 | 60 | .preparse = rxrpc_preparse_s, |
62 | 61 | .free_preparse = rxrpc_free_preparse_s, |
63 | 62 | .instantiate = generic_key_instantiate, |
64 | - .match = user_match, | |
65 | 63 | .destroy = rxrpc_destroy_s, |
66 | 64 | .describe = rxrpc_describe, |
67 | 65 | }; |
security/keys/big_key.c
... | ... | @@ -33,11 +33,9 @@ |
33 | 33 | */ |
34 | 34 | struct key_type key_type_big_key = { |
35 | 35 | .name = "big_key", |
36 | - .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
37 | 36 | .preparse = big_key_preparse, |
38 | 37 | .free_preparse = big_key_free_preparse, |
39 | 38 | .instantiate = generic_key_instantiate, |
40 | - .match = user_match, | |
41 | 39 | .revoke = big_key_revoke, |
42 | 40 | .destroy = big_key_destroy, |
43 | 41 | .describe = big_key_describe, |
security/keys/encrypted-keys/encrypted.c
security/keys/internal.h
... | ... | @@ -107,20 +107,16 @@ |
107 | 107 | int (*func)(const struct key *key, void *data), |
108 | 108 | void *data); |
109 | 109 | |
110 | -typedef int (*key_match_func_t)(const struct key *, const void *); | |
111 | - | |
112 | 110 | struct keyring_search_context { |
113 | 111 | struct keyring_index_key index_key; |
114 | 112 | const struct cred *cred; |
115 | - key_match_func_t match; | |
116 | - const void *match_data; | |
113 | + struct key_match_data match_data; | |
117 | 114 | unsigned flags; |
118 | -#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ | |
119 | -#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ | |
120 | -#define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */ | |
121 | -#define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */ | |
122 | -#define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ | |
123 | -#define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ | |
115 | +#define KEYRING_SEARCH_NO_STATE_CHECK 0x0001 /* Skip state checks */ | |
116 | +#define KEYRING_SEARCH_DO_STATE_CHECK 0x0002 /* Override NO_STATE_CHECK */ | |
117 | +#define KEYRING_SEARCH_NO_UPDATE_TIME 0x0004 /* Don't update times */ | |
118 | +#define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ | |
119 | +#define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ | |
124 | 120 | |
125 | 121 | int (*iterator)(const void *object, void *iterator_data); |
126 | 122 | |
... | ... | @@ -131,6 +127,8 @@ |
131 | 127 | struct timespec now; |
132 | 128 | }; |
133 | 129 | |
130 | +extern bool key_default_cmp(const struct key *key, | |
131 | + const struct key_match_data *match_data); | |
134 | 132 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
135 | 133 | struct keyring_search_context *ctx); |
136 | 134 | |
... | ... | @@ -152,7 +150,8 @@ |
152 | 150 | struct key *dest_keyring, |
153 | 151 | unsigned long flags); |
154 | 152 | |
155 | -extern int lookup_user_key_possessed(const struct key *key, const void *target); | |
153 | +extern bool lookup_user_key_possessed(const struct key *key, | |
154 | + const struct key_match_data *match_data); | |
156 | 155 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, |
157 | 156 | key_perm_t perm); |
158 | 157 | #define KEY_LOOKUP_CREATE 0x01 |
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
... | ... | @@ -89,7 +89,6 @@ |
89 | 89 | .preparse = keyring_preparse, |
90 | 90 | .free_preparse = keyring_free_preparse, |
91 | 91 | .instantiate = keyring_instantiate, |
92 | - .match = user_match, | |
93 | 92 | .revoke = keyring_revoke, |
94 | 93 | .destroy = keyring_destroy, |
95 | 94 | .describe = keyring_describe, |
... | ... | @@ -512,6 +511,15 @@ |
512 | 511 | EXPORT_SYMBOL(keyring_alloc); |
513 | 512 | |
514 | 513 | /* |
514 | + * By default, we keys found by getting an exact match on their descriptions. | |
515 | + */ | |
516 | +bool key_default_cmp(const struct key *key, | |
517 | + const struct key_match_data *match_data) | |
518 | +{ | |
519 | + return strcmp(key->description, match_data->raw_data) == 0; | |
520 | +} | |
521 | + | |
522 | +/* | |
515 | 523 | * Iteration function to consider each key found. |
516 | 524 | */ |
517 | 525 | static int keyring_search_iterator(const void *object, void *iterator_data) |
... | ... | @@ -545,7 +553,7 @@ |
545 | 553 | } |
546 | 554 | |
547 | 555 | /* keys that don't match */ |
548 | - if (!ctx->match(key, ctx->match_data)) { | |
556 | + if (!ctx->match_data.cmp(key, &ctx->match_data)) { | |
549 | 557 | kleave(" = 0 [!match]"); |
550 | 558 | return 0; |
551 | 559 | } |
... | ... | @@ -585,8 +593,7 @@ |
585 | 593 | */ |
586 | 594 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) |
587 | 595 | { |
588 | - if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == | |
589 | - KEYRING_SEARCH_LOOKUP_DIRECT) { | |
596 | + if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) { | |
590 | 597 | const void *object; |
591 | 598 | |
592 | 599 | object = assoc_array_find(&keyring->keys, |
... | ... | @@ -627,7 +634,7 @@ |
627 | 634 | /* Check to see if this top-level keyring is what we are looking for |
628 | 635 | * and whether it is valid or not. |
629 | 636 | */ |
630 | - if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE || | |
637 | + if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_ITERATE || | |
631 | 638 | keyring_compare_object(keyring, &ctx->index_key)) { |
632 | 639 | ctx->skipped_ret = 2; |
633 | 640 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; |
634 | 641 | |
635 | 642 | |
636 | 643 | |
... | ... | @@ -885,16 +892,25 @@ |
885 | 892 | .index_key.type = type, |
886 | 893 | .index_key.description = description, |
887 | 894 | .cred = current_cred(), |
888 | - .match = type->match, | |
889 | - .match_data = description, | |
890 | - .flags = (type->def_lookup_type | | |
891 | - KEYRING_SEARCH_DO_STATE_CHECK), | |
895 | + .match_data.cmp = key_default_cmp, | |
896 | + .match_data.raw_data = description, | |
897 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
898 | + .flags = KEYRING_SEARCH_DO_STATE_CHECK, | |
892 | 899 | }; |
900 | + key_ref_t key; | |
901 | + int ret; | |
893 | 902 | |
894 | - if (!ctx.match) | |
895 | - return ERR_PTR(-ENOKEY); | |
903 | + if (type->match_preparse) { | |
904 | + ret = type->match_preparse(&ctx.match_data); | |
905 | + if (ret < 0) | |
906 | + return ERR_PTR(ret); | |
907 | + } | |
896 | 908 | |
897 | - return keyring_search_aux(keyring, &ctx); | |
909 | + key = keyring_search_aux(keyring, &ctx); | |
910 | + | |
911 | + if (type->match_free) | |
912 | + type->match_free(&ctx.match_data); | |
913 | + return key; | |
898 | 914 | } |
899 | 915 | EXPORT_SYMBOL(keyring_search); |
900 | 916 | |
... | ... | @@ -1014,7 +1030,7 @@ |
1014 | 1030 | |
1015 | 1031 | /* We might get a keyring with matching index-key that is nonetheless a |
1016 | 1032 | * different keyring. */ |
1017 | - if (key != ctx->match_data) | |
1033 | + if (key != ctx->match_data.raw_data) | |
1018 | 1034 | return 0; |
1019 | 1035 | |
1020 | 1036 | ctx->result = ERR_PTR(-EDEADLK); |
... | ... | @@ -1031,14 +1047,14 @@ |
1031 | 1047 | static int keyring_detect_cycle(struct key *A, struct key *B) |
1032 | 1048 | { |
1033 | 1049 | struct keyring_search_context ctx = { |
1034 | - .index_key = A->index_key, | |
1035 | - .match_data = A, | |
1036 | - .iterator = keyring_detect_cycle_iterator, | |
1037 | - .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | | |
1038 | - KEYRING_SEARCH_NO_STATE_CHECK | | |
1039 | - KEYRING_SEARCH_NO_UPDATE_TIME | | |
1040 | - KEYRING_SEARCH_NO_CHECK_PERM | | |
1041 | - KEYRING_SEARCH_DETECT_TOO_DEEP), | |
1050 | + .index_key = A->index_key, | |
1051 | + .match_data.raw_data = A, | |
1052 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
1053 | + .iterator = keyring_detect_cycle_iterator, | |
1054 | + .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | |
1055 | + KEYRING_SEARCH_NO_UPDATE_TIME | | |
1056 | + KEYRING_SEARCH_NO_CHECK_PERM | | |
1057 | + KEYRING_SEARCH_DETECT_TOO_DEEP), | |
1042 | 1058 | }; |
1043 | 1059 | |
1044 | 1060 | rcu_read_lock(); |
security/keys/proc.c
... | ... | @@ -194,10 +194,10 @@ |
194 | 194 | .index_key.type = key->type, |
195 | 195 | .index_key.description = key->description, |
196 | 196 | .cred = current_cred(), |
197 | - .match = lookup_user_key_possessed, | |
198 | - .match_data = key, | |
199 | - .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | |
200 | - KEYRING_SEARCH_LOOKUP_DIRECT), | |
197 | + .match_data.cmp = lookup_user_key_possessed, | |
198 | + .match_data.raw_data = key, | |
199 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
200 | + .flags = KEYRING_SEARCH_NO_STATE_CHECK, | |
201 | 201 | }; |
202 | 202 | |
203 | 203 | key_ref = make_key_ref(key, 0); |
security/keys/process_keys.c
... | ... | @@ -489,9 +489,10 @@ |
489 | 489 | /* |
490 | 490 | * See if the key we're looking at is the target key. |
491 | 491 | */ |
492 | -int lookup_user_key_possessed(const struct key *key, const void *target) | |
492 | +bool lookup_user_key_possessed(const struct key *key, | |
493 | + const struct key_match_data *match_data) | |
493 | 494 | { |
494 | - return key == target; | |
495 | + return key == match_data->raw_data; | |
495 | 496 | } |
496 | 497 | |
497 | 498 | /* |
... | ... | @@ -516,9 +517,9 @@ |
516 | 517 | key_perm_t perm) |
517 | 518 | { |
518 | 519 | struct keyring_search_context ctx = { |
519 | - .match = lookup_user_key_possessed, | |
520 | - .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | |
521 | - KEYRING_SEARCH_LOOKUP_DIRECT), | |
520 | + .match_data.cmp = lookup_user_key_possessed, | |
521 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
522 | + .flags = KEYRING_SEARCH_NO_STATE_CHECK, | |
522 | 523 | }; |
523 | 524 | struct request_key_auth *rka; |
524 | 525 | struct key *key; |
... | ... | @@ -673,7 +674,7 @@ |
673 | 674 | ctx.index_key.type = key->type; |
674 | 675 | ctx.index_key.description = key->description; |
675 | 676 | ctx.index_key.desc_len = strlen(key->description); |
676 | - ctx.match_data = key; | |
677 | + ctx.match_data.raw_data = key; | |
677 | 678 | kdebug("check possessed"); |
678 | 679 | skey_ref = search_process_keyrings(&ctx); |
679 | 680 | kdebug("possessed=%p", skey_ref); |
security/keys/request_key.c
... | ... | @@ -531,9 +531,9 @@ |
531 | 531 | .index_key.type = type, |
532 | 532 | .index_key.description = description, |
533 | 533 | .cred = current_cred(), |
534 | - .match = type->match, | |
535 | - .match_data = description, | |
536 | - .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | |
534 | + .match_data.cmp = key_default_cmp, | |
535 | + .match_data.raw_data = description, | |
536 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
537 | 537 | }; |
538 | 538 | struct key *key; |
539 | 539 | key_ref_t key_ref; |
... | ... | @@ -543,6 +543,14 @@ |
543 | 543 | ctx.index_key.type->name, ctx.index_key.description, |
544 | 544 | callout_info, callout_len, aux, dest_keyring, flags); |
545 | 545 | |
546 | + if (type->match_preparse) { | |
547 | + ret = type->match_preparse(&ctx.match_data); | |
548 | + if (ret < 0) { | |
549 | + key = ERR_PTR(ret); | |
550 | + goto error; | |
551 | + } | |
552 | + } | |
553 | + | |
546 | 554 | /* search all the process keyrings for a key */ |
547 | 555 | key_ref = search_process_keyrings(&ctx); |
548 | 556 | |
... | ... | @@ -555,7 +563,7 @@ |
555 | 563 | if (ret < 0) { |
556 | 564 | key_put(key); |
557 | 565 | key = ERR_PTR(ret); |
558 | - goto error; | |
566 | + goto error_free; | |
559 | 567 | } |
560 | 568 | } |
561 | 569 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
562 | 570 | |
... | ... | @@ -565,12 +573,15 @@ |
565 | 573 | * should consult userspace if we can */ |
566 | 574 | key = ERR_PTR(-ENOKEY); |
567 | 575 | if (!callout_info) |
568 | - goto error; | |
576 | + goto error_free; | |
569 | 577 | |
570 | 578 | key = construct_key_and_link(&ctx, callout_info, callout_len, |
571 | 579 | aux, dest_keyring, flags); |
572 | 580 | } |
573 | 581 | |
582 | +error_free: | |
583 | + if (type->match_free) | |
584 | + type->match_free(&ctx.match_data); | |
574 | 585 | error: |
575 | 586 | kleave(" = %p", key); |
576 | 587 | return key; |
security/keys/request_key_auth.c
... | ... | @@ -44,12 +44,12 @@ |
44 | 44 | .read = request_key_auth_read, |
45 | 45 | }; |
46 | 46 | |
47 | -int request_key_auth_preparse(struct key_preparsed_payload *prep) | |
47 | +static int request_key_auth_preparse(struct key_preparsed_payload *prep) | |
48 | 48 | { |
49 | 49 | return 0; |
50 | 50 | } |
51 | 51 | |
52 | -void request_key_auth_free_preparse(struct key_preparsed_payload *prep) | |
52 | +static void request_key_auth_free_preparse(struct key_preparsed_payload *prep) | |
53 | 53 | { |
54 | 54 | } |
55 | 55 | |
... | ... | @@ -246,9 +246,9 @@ |
246 | 246 | .index_key.type = &key_type_request_key_auth, |
247 | 247 | .index_key.description = description, |
248 | 248 | .cred = current_cred(), |
249 | - .match = user_match, | |
250 | - .match_data = description, | |
251 | - .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | |
249 | + .match_data.cmp = key_default_cmp, | |
250 | + .match_data.raw_data = description, | |
251 | + .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
252 | 252 | }; |
253 | 253 | struct key *authkey; |
254 | 254 | key_ref_t authkey_ref; |
security/keys/trusted.c
security/keys/user_defined.c
... | ... | @@ -26,12 +26,10 @@ |
26 | 26 | */ |
27 | 27 | struct key_type key_type_user = { |
28 | 28 | .name = "user", |
29 | - .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
30 | 29 | .preparse = user_preparse, |
31 | 30 | .free_preparse = user_free_preparse, |
32 | 31 | .instantiate = generic_key_instantiate, |
33 | 32 | .update = user_update, |
34 | - .match = user_match, | |
35 | 33 | .revoke = user_revoke, |
36 | 34 | .destroy = user_destroy, |
37 | 35 | .describe = user_describe, |
38 | 36 | |
... | ... | @@ -48,12 +46,10 @@ |
48 | 46 | */ |
49 | 47 | struct key_type key_type_logon = { |
50 | 48 | .name = "logon", |
51 | - .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
52 | 49 | .preparse = user_preparse, |
53 | 50 | .free_preparse = user_free_preparse, |
54 | 51 | .instantiate = generic_key_instantiate, |
55 | 52 | .update = user_update, |
56 | - .match = user_match, | |
57 | 53 | .revoke = user_revoke, |
58 | 54 | .destroy = user_destroy, |
59 | 55 | .describe = user_describe, |
... | ... | @@ -137,16 +133,6 @@ |
137 | 133 | } |
138 | 134 | |
139 | 135 | EXPORT_SYMBOL_GPL(user_update); |
140 | - | |
141 | -/* | |
142 | - * match users on their name | |
143 | - */ | |
144 | -int user_match(const struct key *key, const void *description) | |
145 | -{ | |
146 | - return strcmp(key->description, description) == 0; | |
147 | -} | |
148 | - | |
149 | -EXPORT_SYMBOL_GPL(user_match); | |
150 | 136 | |
151 | 137 | /* |
152 | 138 | * dispose of the links from a revoked keyring |