diff options
35 files changed, 690 insertions, 338 deletions
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 8727c194ca16..821c936e1a63 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -888,11 +888,11 @@ payload contents" for more information. | |||
888 | const char *callout_info); | 888 | const char *callout_info); |
889 | 889 | ||
890 | This is used to request a key or keyring with a description that matches | 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 | 891 | the description specified according to the key type's match_preparse() |
892 | permits approximate matching to occur. If callout_string is not NULL, then | 892 | method. This permits approximate matching to occur. If callout_string is |
893 | /sbin/request-key will be invoked in an attempt to obtain the key from | 893 | not NULL, then /sbin/request-key will be invoked in an attempt to obtain |
894 | userspace. In that case, callout_string will be passed as an argument to | 894 | the key from userspace. In that case, callout_string will be passed as an |
895 | the program. | 895 | argument to the program. |
896 | 896 | ||
897 | Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be | 897 | Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be |
898 | returned. | 898 | returned. |
@@ -1170,7 +1170,7 @@ The structure has a number of fields, some of which are mandatory: | |||
1170 | The method should return 0 if successful or a negative error code | 1170 | The method should return 0 if successful or a negative error code |
1171 | otherwise. | 1171 | otherwise. |
1172 | 1172 | ||
1173 | 1173 | ||
1174 | (*) void (*free_preparse)(struct key_preparsed_payload *prep); | 1174 | (*) void (*free_preparse)(struct key_preparsed_payload *prep); |
1175 | 1175 | ||
1176 | This method is only required if the preparse() method is provided, | 1176 | This method is only required if the preparse() method is provided, |
@@ -1225,16 +1225,55 @@ The structure has a number of fields, some of which are mandatory: | |||
1225 | It is safe to sleep in this method. | 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 | |||
1230 | This method is optional. It is called when a key search is about to be | ||
1231 | performed. It is given the following structure: | ||
1229 | 1232 | ||
1230 | This method is called to match a key against a description. It should | 1233 | struct key_match_data { |
1231 | return non-zero if the two match, zero if they don't. | 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 | }; | ||
1232 | 1240 | ||
1233 | This method should not need to lock the key in any way. The type and | 1241 | On entry, raw_data will be pointing to the criteria to be used in matching |
1234 | description can be considered invariant, and the payload should not be | 1242 | a key by the caller and should not be modified. (*cmp)() will be pointing |
1235 | accessed (the key may not yet be instantiated). | 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. | ||
1236 | 1245 | ||
1237 | It is not safe to sleep in this method; the caller may hold spinlocks. | 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 | (*) void (*revoke)(struct key *key); | 1279 | (*) void (*revoke)(struct key *key); |
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h index a63c551c6557..fd21ac28e0a0 100644 --- a/crypto/asymmetric_keys/asymmetric_keys.h +++ b/crypto/asymmetric_keys/asymmetric_keys.h | |||
@@ -9,9 +9,13 @@ | |||
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 | 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 | return key->type_data.p[1]; | 20 | return key->type_data.p[1]; |
17 | } | 21 | } |
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index eb8cd46961a5..f0f2111d2c66 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/ctype.h> | ||
18 | #include "asymmetric_keys.h" | 19 | #include "asymmetric_keys.h" |
19 | 20 | ||
20 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
@@ -22,85 +23,166 @@ MODULE_LICENSE("GPL"); | |||
22 | static LIST_HEAD(asymmetric_key_parsers); | 23 | static LIST_HEAD(asymmetric_key_parsers); |
23 | static DECLARE_RWSEM(asymmetric_key_parsers_sem); | 24 | static DECLARE_RWSEM(asymmetric_key_parsers_sem); |
24 | 25 | ||
25 | /* | 26 | /** |
26 | * Match asymmetric key id with partial match | 27 | * asymmetric_key_generate_id: Construct an asymmetric key ID |
27 | * @id: key id to match in a form "id:<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. | ||
34 | */ | ||
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) | ||
39 | { | ||
40 | struct asymmetric_key_id *kid; | ||
41 | |||
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); | ||
52 | |||
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 | ||
28 | */ | 56 | */ |
29 | int asymmetric_keyid_match(const char *kid, const char *id) | 57 | bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1, |
58 | const struct asymmetric_key_id *kid2) | ||
30 | { | 59 | { |
31 | size_t idlen, kidlen; | 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); | ||
32 | 67 | ||
33 | if (!kid || !id) | 68 | /** |
34 | return 0; | 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); | ||
35 | 85 | ||
36 | /* make it possible to use id as in the request: "id:<id>" */ | 86 | /** |
37 | if (strncmp(id, "id:", 3) == 0) | 87 | * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. |
38 | id += 3; | 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; | ||
39 | 95 | ||
40 | /* Anything after here requires a partial match on the ID string */ | 96 | if (!*id) |
41 | idlen = strlen(id); | 97 | return ERR_PTR(-EINVAL); |
42 | kidlen = strlen(kid); | 98 | hexlen = strlen(id); |
43 | if (idlen > kidlen) | 99 | if (hexlen & 1) |
44 | return 0; | 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; | ||
113 | } | ||
45 | 114 | ||
46 | kid += kidlen - idlen; | 115 | /* |
47 | if (strcasecmp(id, kid) != 0) | 116 | * Match asymmetric keys by ID. |
48 | return 0; | 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; | ||
49 | 123 | ||
50 | return 1; | 124 | return asymmetric_match_key_ids(kids, match_id); |
51 | } | 125 | } |
52 | EXPORT_SYMBOL_GPL(asymmetric_keyid_match); | ||
53 | 126 | ||
54 | /* | 127 | /* |
55 | * Match asymmetric keys on (part of) their name | 128 | * Preparse the match criterion. If we don't set lookup_type and cmp, |
56 | * We have some shorthand methods for matching keys. We allow: | 129 | * the default will be an exact match on the key description. |
130 | * | ||
131 | * There are some specifiers for matching key IDs rather than by the key | ||
132 | * description: | ||
57 | * | 133 | * |
58 | * "<desc>" - request a key by description | 134 | * "id:<id>" - request a key by any available ID |
59 | * "id:<id>" - request a key matching the ID | 135 | * |
60 | * "<subtype>:<id>" - request a key of a subtype | 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); | 141 | struct asymmetric_key_id *match_id; |
65 | const char *spec = description; | 142 | const char *spec = match_data->raw_data; |
66 | const char *id; | 143 | const char *id; |
67 | ptrdiff_t speclen; | ||
68 | 144 | ||
69 | if (!subtype || !spec || !*spec) | 145 | if (!spec || !*spec) |
70 | return 0; | 146 | return -EINVAL; |
71 | 147 | if (spec[0] == 'i' && | |
72 | /* See if the full key description matches as is */ | 148 | spec[1] == 'd' && |
73 | if (key->description && strcmp(key->description, description) == 0) | 149 | spec[2] == ':') { |
74 | return 1; | 150 | id = spec + 3; |
75 | 151 | } else { | |
76 | /* All tests from here on break the criterion description into a | 152 | goto default_match; |
77 | * specifier, a colon and then an identifier. | 153 | } |
78 | */ | ||
79 | id = strchr(spec, ':'); | ||
80 | if (!id) | ||
81 | return 0; | ||
82 | |||
83 | speclen = id - spec; | ||
84 | id++; | ||
85 | 154 | ||
86 | if (speclen == 2 && memcmp(spec, "id", 2) == 0) | 155 | match_id = asymmetric_key_hex_to_key_id(id); |
87 | return asymmetric_keyid_match(asymmetric_key_id(key), id); | 156 | if (!match_id) |
157 | return -ENOMEM; | ||
88 | 158 | ||
89 | if (speclen == subtype->name_len && | 159 | match_data->preparsed = match_id; |
90 | memcmp(spec, subtype->name, speclen) == 0) | 160 | match_data->cmp = asymmetric_key_cmp; |
91 | return 1; | 161 | match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; |
162 | return 0; | ||
92 | 163 | ||
164 | default_match: | ||
93 | return 0; | 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 | * Describe the asymmetric key | 177 | * Describe the asymmetric key |
98 | */ | 178 | */ |
99 | static void asymmetric_key_describe(const struct key *key, struct seq_file *m) | 179 | static void asymmetric_key_describe(const struct key *key, struct seq_file *m) |
100 | { | 180 | { |
101 | const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | 181 | const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); |
102 | const char *kid = asymmetric_key_id(key); | 182 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); |
103 | size_t n; | 183 | const struct asymmetric_key_id *kid; |
184 | const unsigned char *p; | ||
185 | int n; | ||
104 | 186 | ||
105 | seq_puts(m, key->description); | 187 | seq_puts(m, key->description); |
106 | 188 | ||
@@ -108,13 +190,16 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m) | |||
108 | seq_puts(m, ": "); | 190 | seq_puts(m, ": "); |
109 | subtype->describe(key, m); | 191 | subtype->describe(key, m); |
110 | 192 | ||
111 | if (kid) { | 193 | if (kids && kids->id[0]) { |
194 | kid = kids->id[0]; | ||
112 | seq_putc(m, ' '); | 195 | seq_putc(m, ' '); |
113 | n = strlen(kid); | 196 | n = kid->len; |
114 | if (n <= 8) | 197 | p = kid->data; |
115 | seq_puts(m, kid); | 198 | if (n > 8) { |
116 | else | 199 | p += n - 8; |
117 | seq_puts(m, kid + n - 8); | 200 | n = 8; |
201 | } | ||
202 | seq_printf(m, "%*phN", n, p); | ||
118 | } | 203 | } |
119 | 204 | ||
120 | seq_puts(m, " ["); | 205 | seq_puts(m, " ["); |
@@ -165,6 +250,7 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep) | |||
165 | static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | 250 | static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) |
166 | { | 251 | { |
167 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; | 252 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; |
253 | struct asymmetric_key_ids *kids = prep->type_data[1]; | ||
168 | 254 | ||
169 | pr_devel("==>%s()\n", __func__); | 255 | pr_devel("==>%s()\n", __func__); |
170 | 256 | ||
@@ -172,7 +258,11 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | |||
172 | subtype->destroy(prep->payload[0]); | 258 | subtype->destroy(prep->payload[0]); |
173 | module_put(subtype->owner); | 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 | kfree(prep->description); | 266 | kfree(prep->description); |
177 | } | 267 | } |
178 | 268 | ||
@@ -182,13 +272,20 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | |||
182 | static void asymmetric_key_destroy(struct key *key) | 272 | static void asymmetric_key_destroy(struct key *key) |
183 | { | 273 | { |
184 | struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | 274 | struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); |
275 | struct asymmetric_key_ids *kids = key->type_data.p[1]; | ||
276 | |||
185 | if (subtype) { | 277 | if (subtype) { |
186 | subtype->destroy(key->payload.data); | 278 | subtype->destroy(key->payload.data); |
187 | module_put(subtype->owner); | 279 | module_put(subtype->owner); |
188 | key->type_data.p[0] = NULL; | 280 | key->type_data.p[0] = NULL; |
189 | } | 281 | } |
190 | kfree(key->type_data.p[1]); | 282 | |
191 | key->type_data.p[1] = NULL; | 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 | struct key_type key_type_asymmetric = { | 291 | struct key_type key_type_asymmetric = { |
@@ -196,10 +293,10 @@ struct key_type key_type_asymmetric = { | |||
196 | .preparse = asymmetric_key_preparse, | 293 | .preparse = asymmetric_key_preparse, |
197 | .free_preparse = asymmetric_key_free_preparse, | 294 | .free_preparse = asymmetric_key_free_preparse, |
198 | .instantiate = generic_key_instantiate, | 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 | .destroy = asymmetric_key_destroy, | 298 | .destroy = asymmetric_key_destroy, |
201 | .describe = asymmetric_key_describe, | 299 | .describe = asymmetric_key_describe, |
202 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE, | ||
203 | }; | 300 | }; |
204 | EXPORT_SYMBOL_GPL(key_type_asymmetric); | 301 | EXPORT_SYMBOL_GPL(key_type_asymmetric); |
205 | 302 | ||
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c index 3de5fb011de0..751f8fd7335d 100644 --- a/crypto/asymmetric_keys/pkcs7_key_type.c +++ b/crypto/asymmetric_keys/pkcs7_key_type.c | |||
@@ -72,11 +72,9 @@ error: | |||
72 | */ | 72 | */ |
73 | static struct key_type key_type_pkcs7 = { | 73 | static struct key_type key_type_pkcs7 = { |
74 | .name = "pkcs7_test", | 74 | .name = "pkcs7_test", |
75 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
76 | .preparse = pkcs7_preparse, | 75 | .preparse = pkcs7_preparse, |
77 | .free_preparse = user_free_preparse, | 76 | .free_preparse = user_free_preparse, |
78 | .instantiate = generic_key_instantiate, | 77 | .instantiate = generic_key_instantiate, |
79 | .match = user_match, | ||
80 | .revoke = user_revoke, | 78 | .revoke = user_revoke, |
81 | .destroy = user_destroy, | 79 | .destroy = user_destroy, |
82 | .describe = user_describe, | 80 | .describe = user_describe, |
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 42e56aa7d277..3bd5a1e4c493 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c | |||
@@ -29,8 +29,25 @@ struct pkcs7_parse_context { | |||
29 | enum OID last_oid; /* Last OID encountered */ | 29 | enum OID last_oid; /* Last OID encountered */ |
30 | unsigned x509_index; | 30 | unsigned x509_index; |
31 | unsigned sinfo_index; | 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 | * pkcs7_free_message - Free a PKCS#7 message | 52 | * pkcs7_free_message - Free a PKCS#7 message |
36 | * @pkcs7: The PKCS#7 message to free | 53 | * @pkcs7: The PKCS#7 message to free |
@@ -54,9 +71,7 @@ void pkcs7_free_message(struct pkcs7_message *pkcs7) | |||
54 | while (pkcs7->signed_infos) { | 71 | while (pkcs7->signed_infos) { |
55 | sinfo = pkcs7->signed_infos; | 72 | sinfo = pkcs7->signed_infos; |
56 | pkcs7->signed_infos = sinfo->next; | 73 | pkcs7->signed_infos = sinfo->next; |
57 | mpi_free(sinfo->sig.mpi[0]); | 74 | pkcs7_free_signed_info(sinfo); |
58 | kfree(sinfo->sig.digest); | ||
59 | kfree(sinfo); | ||
60 | } | 75 | } |
61 | kfree(pkcs7); | 76 | kfree(pkcs7); |
62 | } | 77 | } |
@@ -71,51 +86,46 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message); | |||
71 | struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) | 86 | struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) |
72 | { | 87 | { |
73 | struct pkcs7_parse_context *ctx; | 88 | struct pkcs7_parse_context *ctx; |
74 | struct pkcs7_message *msg; | 89 | struct pkcs7_message *msg = ERR_PTR(-ENOMEM); |
75 | long ret; | 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 | ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); | 92 | ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); |
82 | if (!ctx) | 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 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); | 98 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); |
85 | if (!ctx->sinfo) | 99 | if (!ctx->sinfo) |
86 | goto error_no_sinfo; | 100 | goto out_no_sinfo; |
87 | 101 | ||
88 | ctx->msg = msg; | ||
89 | ctx->data = (unsigned long)data; | 102 | ctx->data = (unsigned long)data; |
90 | ctx->ppcerts = &ctx->certs; | 103 | ctx->ppcerts = &ctx->certs; |
91 | ctx->ppsinfo = &ctx->msg->signed_infos; | 104 | ctx->ppsinfo = &ctx->msg->signed_infos; |
92 | 105 | ||
93 | /* Attempt to decode the signature */ | 106 | /* Attempt to decode the signature */ |
94 | ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); | 107 | ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); |
95 | if (ret < 0) | 108 | if (ret < 0) { |
96 | goto error_decode; | 109 | msg = ERR_PTR(ret); |
110 | goto out; | ||
111 | } | ||
97 | 112 | ||
113 | msg = ctx->msg; | ||
114 | ctx->msg = NULL; | ||
115 | |||
116 | out: | ||
98 | while (ctx->certs) { | 117 | while (ctx->certs) { |
99 | struct x509_certificate *cert = ctx->certs; | 118 | struct x509_certificate *cert = ctx->certs; |
100 | ctx->certs = cert->next; | 119 | ctx->certs = cert->next; |
101 | x509_free_certificate(cert); | 120 | x509_free_certificate(cert); |
102 | } | 121 | } |
103 | mpi_free(ctx->sinfo->sig.mpi[0]); | 122 | pkcs7_free_signed_info(ctx->sinfo); |
104 | kfree(ctx->sinfo->sig.digest); | 123 | out_no_sinfo: |
105 | kfree(ctx->sinfo); | 124 | pkcs7_free_message(ctx->msg); |
125 | out_no_msg: | ||
106 | kfree(ctx); | 126 | kfree(ctx); |
127 | out_no_ctx: | ||
107 | return msg; | 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 | EXPORT_SYMBOL_GPL(pkcs7_parse_message); | 130 | EXPORT_SYMBOL_GPL(pkcs7_parse_message); |
121 | 131 | ||
@@ -246,10 +256,10 @@ int pkcs7_extract_cert(void *context, size_t hdrlen, | |||
246 | if (IS_ERR(x509)) | 256 | if (IS_ERR(x509)) |
247 | return PTR_ERR(x509); | 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 | x509->index = ++ctx->x509_index; | 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 | *ctx->ppcerts = x509; | 263 | *ctx->ppcerts = x509; |
254 | ctx->ppcerts = &x509->next; | 264 | ctx->ppcerts = &x509->next; |
255 | return 0; | 265 | return 0; |
@@ -338,8 +348,8 @@ int pkcs7_sig_note_serial(void *context, size_t hdrlen, | |||
338 | const void *value, size_t vlen) | 348 | const void *value, size_t vlen) |
339 | { | 349 | { |
340 | struct pkcs7_parse_context *ctx = context; | 350 | struct pkcs7_parse_context *ctx = context; |
341 | ctx->sinfo->raw_serial = value; | 351 | ctx->raw_serial = value; |
342 | ctx->sinfo->raw_serial_size = vlen; | 352 | ctx->raw_serial_size = vlen; |
343 | return 0; | 353 | return 0; |
344 | } | 354 | } |
345 | 355 | ||
@@ -351,8 +361,8 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen, | |||
351 | const void *value, size_t vlen) | 361 | const void *value, size_t vlen) |
352 | { | 362 | { |
353 | struct pkcs7_parse_context *ctx = context; | 363 | struct pkcs7_parse_context *ctx = context; |
354 | ctx->sinfo->raw_issuer = value; | 364 | ctx->raw_issuer = value; |
355 | ctx->sinfo->raw_issuer_size = vlen; | 365 | ctx->raw_issuer_size = vlen; |
356 | return 0; | 366 | return 0; |
357 | } | 367 | } |
358 | 368 | ||
@@ -385,10 +395,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen, | |||
385 | const void *value, size_t vlen) | 395 | const void *value, size_t vlen) |
386 | { | 396 | { |
387 | struct pkcs7_parse_context *ctx = context; | 397 | struct pkcs7_parse_context *ctx = context; |
388 | 398 | struct pkcs7_signed_info *sinfo = ctx->sinfo; | |
389 | ctx->sinfo->index = ++ctx->sinfo_index; | 399 | struct asymmetric_key_id *kid; |
390 | *ctx->ppsinfo = ctx->sinfo; | 400 | |
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 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); | 413 | ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); |
393 | if (!ctx->sinfo) | 414 | if (!ctx->sinfo) |
394 | return -ENOMEM; | 415 | return -ENOMEM; |
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index d25f4d15370f..efc7dc9b8f9c 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h | |||
@@ -23,6 +23,7 @@ struct pkcs7_signed_info { | |||
23 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ | 23 | struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ |
24 | unsigned index; | 24 | unsigned index; |
25 | bool trusted; | 25 | bool trusted; |
26 | bool unsupported_crypto; /* T if not usable due to missing crypto */ | ||
26 | 27 | ||
27 | /* Message digest - the digest of the Content Data (or NULL) */ | 28 | /* Message digest - the digest of the Content Data (or NULL) */ |
28 | const void *msgdigest; | 29 | const void *msgdigest; |
@@ -33,10 +34,7 @@ struct pkcs7_signed_info { | |||
33 | const void *authattrs; | 34 | const void *authattrs; |
34 | 35 | ||
35 | /* Issuing cert serial number and issuer's name */ | 36 | /* Issuing cert serial number and issuer's name */ |
36 | const void *raw_serial; | 37 | struct asymmetric_key_id *signing_cert_id; |
37 | unsigned raw_serial_size; | ||
38 | unsigned raw_issuer_size; | ||
39 | const void *raw_issuer; | ||
40 | 38 | ||
41 | /* Message signature. | 39 | /* Message signature. |
42 | * | 40 | * |
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index e666eb011a85..ae47be6128c4 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c | |||
@@ -23,9 +23,9 @@ | |||
23 | /** | 23 | /** |
24 | * Check the trust on one PKCS#7 SignedInfo block. | 24 | * Check the trust on one PKCS#7 SignedInfo block. |
25 | */ | 25 | */ |
26 | int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | 26 | static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, |
27 | struct pkcs7_signed_info *sinfo, | 27 | struct pkcs7_signed_info *sinfo, |
28 | struct key *trust_keyring) | 28 | struct key *trust_keyring) |
29 | { | 29 | { |
30 | struct public_key_signature *sig = &sinfo->sig; | 30 | struct public_key_signature *sig = &sinfo->sig; |
31 | struct x509_certificate *x509, *last = NULL, *p; | 31 | struct x509_certificate *x509, *last = NULL, *p; |
@@ -35,6 +35,11 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
35 | 35 | ||
36 | kenter(",%u,", sinfo->index); | 36 | kenter(",%u,", sinfo->index); |
37 | 37 | ||
38 | if (sinfo->unsupported_crypto) { | ||
39 | kleave(" = -ENOPKG [cached]"); | ||
40 | return -ENOPKG; | ||
41 | } | ||
42 | |||
38 | for (x509 = sinfo->signer; x509; x509 = x509->signer) { | 43 | for (x509 = sinfo->signer; x509; x509 = x509->signer) { |
39 | if (x509->seen) { | 44 | if (x509->seen) { |
40 | if (x509->verified) { | 45 | if (x509->verified) { |
@@ -49,15 +54,17 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
49 | /* Look to see if this certificate is present in the trusted | 54 | /* Look to see if this certificate is present in the trusted |
50 | * keys. | 55 | * keys. |
51 | */ | 56 | */ |
52 | key = x509_request_asymmetric_key(trust_keyring, x509->subject, | 57 | key = x509_request_asymmetric_key(trust_keyring, x509->id); |
53 | x509->fingerprint); | 58 | if (!IS_ERR(key)) { |
54 | if (!IS_ERR(key)) | ||
55 | /* One of the X.509 certificates in the PKCS#7 message | 59 | /* One of the X.509 certificates in the PKCS#7 message |
56 | * is apparently the same as one we already trust. | 60 | * is apparently the same as one we already trust. |
57 | * Verify that the trusted variant can also validate | 61 | * Verify that the trusted variant can also validate |
58 | * the signature on the descendant. | 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 | goto matched; | 66 | goto matched; |
67 | } | ||
61 | if (key == ERR_PTR(-ENOMEM)) | 68 | if (key == ERR_PTR(-ENOMEM)) |
62 | return -ENOMEM; | 69 | return -ENOMEM; |
63 | 70 | ||
@@ -77,16 +84,34 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, | |||
77 | /* No match - see if the root certificate has a signer amongst the | 84 | /* No match - see if the root certificate has a signer amongst the |
78 | * trusted keys. | 85 | * trusted keys. |
79 | */ | 86 | */ |
80 | if (!last || !last->issuer || !last->authority) { | 87 | if (last && last->authority) { |
81 | kleave(" = -ENOKEY [no backref]"); | 88 | key = x509_request_asymmetric_key(trust_keyring, last->authority); |
82 | return -ENOKEY; | 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); | ||
97 | } | ||
98 | |||
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; | ||
83 | } | 109 | } |
110 | if (PTR_ERR(key) != -ENOKEY) | ||
111 | return PTR_ERR(key); | ||
84 | 112 | ||
85 | key = x509_request_asymmetric_key(trust_keyring, last->issuer, | 113 | kleave(" = -ENOKEY [no backref]"); |
86 | last->authority); | 114 | return -ENOKEY; |
87 | if (IS_ERR(key)) | ||
88 | return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY; | ||
89 | x509 = last; | ||
90 | 115 | ||
91 | matched: | 116 | matched: |
92 | ret = verify_signature(key, sig); | 117 | ret = verify_signature(key, sig); |
@@ -100,10 +125,12 @@ matched: | |||
100 | } | 125 | } |
101 | 126 | ||
102 | verified: | 127 | verified: |
103 | x509->verified = true; | 128 | if (x509) { |
104 | for (p = sinfo->signer; p != x509; p = p->signer) { | 129 | x509->verified = true; |
105 | p->verified = true; | 130 | for (p = sinfo->signer; p != x509; p = p->signer) { |
106 | p->trusted = trusted; | 131 | p->verified = true; |
132 | p->trusted = trusted; | ||
133 | } | ||
107 | } | 134 | } |
108 | sinfo->trusted = trusted; | 135 | sinfo->trusted = trusted; |
109 | kleave(" = 0"); | 136 | kleave(" = 0"); |
@@ -141,24 +168,28 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, | |||
141 | { | 168 | { |
142 | struct pkcs7_signed_info *sinfo; | 169 | struct pkcs7_signed_info *sinfo; |
143 | struct x509_certificate *p; | 170 | struct x509_certificate *p; |
144 | int cached_ret = 0, ret; | 171 | int cached_ret = -ENOKEY; |
172 | int ret; | ||
145 | 173 | ||
146 | for (p = pkcs7->certs; p; p = p->next) | 174 | for (p = pkcs7->certs; p; p = p->next) |
147 | p->seen = false; | 175 | p->seen = false; |
148 | 176 | ||
149 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { | 177 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { |
150 | ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring); | 178 | ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring); |
151 | if (ret < 0) { | 179 | switch (ret) { |
152 | if (ret == -ENOPKG) { | 180 | case -ENOKEY: |
181 | continue; | ||
182 | case -ENOPKG: | ||
183 | if (cached_ret == -ENOKEY) | ||
153 | cached_ret = -ENOPKG; | 184 | cached_ret = -ENOPKG; |
154 | } else if (ret == -ENOKEY) { | 185 | continue; |
155 | if (cached_ret == 0) | 186 | case 0: |
156 | cached_ret = -ENOKEY; | 187 | *_trusted |= sinfo->trusted; |
157 | } else { | 188 | cached_ret = 0; |
158 | return ret; | 189 | continue; |
159 | } | 190 | default: |
191 | return ret; | ||
160 | } | 192 | } |
161 | *_trusted |= sinfo->trusted; | ||
162 | } | 193 | } |
163 | 194 | ||
164 | return cached_ret; | 195 | return cached_ret; |
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index c62cf8006e1f..cd455450b069 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c | |||
@@ -131,8 +131,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, | |||
131 | struct x509_certificate *x509; | 131 | struct x509_certificate *x509; |
132 | unsigned certix = 1; | 132 | unsigned certix = 1; |
133 | 133 | ||
134 | kenter("%u,%u,%u", | 134 | kenter("%u", sinfo->index); |
135 | sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size); | ||
136 | 135 | ||
137 | for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { | 136 | for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { |
138 | /* I'm _assuming_ that the generator of the PKCS#7 message will | 137 | /* I'm _assuming_ that the generator of the PKCS#7 message will |
@@ -140,21 +139,11 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, | |||
140 | * PKCS#7 message - but I can't be 100% sure of that. It's | 139 | * PKCS#7 message - but I can't be 100% sure of that. It's |
141 | * possible this will need element-by-element comparison. | 140 | * possible this will need element-by-element comparison. |
142 | */ | 141 | */ |
143 | if (x509->raw_serial_size != sinfo->raw_serial_size || | 142 | if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id)) |
144 | memcmp(x509->raw_serial, sinfo->raw_serial, | ||
145 | sinfo->raw_serial_size) != 0) | ||
146 | continue; | 143 | continue; |
147 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", | 144 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", |
148 | sinfo->index, certix); | 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 | if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { | 147 | if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { |
159 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", | 148 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", |
160 | sinfo->index); | 149 | sinfo->index); |
@@ -164,9 +153,14 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, | |||
164 | sinfo->signer = x509; | 153 | sinfo->signer = x509; |
165 | return 0; | 154 | return 0; |
166 | } | 155 | } |
167 | pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n", | 156 | |
168 | sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial); | 157 | /* The relevant X.509 cert isn't found here, but it might be found in |
169 | return -ENOKEY; | 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 | /* |
@@ -184,15 +178,18 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
184 | p->seen = false; | 178 | p->seen = false; |
185 | 179 | ||
186 | for (;;) { | 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 | x509->seen = true; | 184 | x509->seen = true; |
189 | ret = x509_get_sig_params(x509); | 185 | ret = x509_get_sig_params(x509); |
190 | if (ret < 0) | 186 | if (ret < 0) |
191 | return ret; | 187 | goto maybe_missing_crypto_in_x509; |
192 | 188 | ||
193 | pr_debug("- issuer %s\n", x509->issuer); | 189 | pr_debug("- issuer %s\n", x509->issuer); |
194 | if (x509->authority) | 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 | if (!x509->authority || | 194 | if (!x509->authority || |
198 | strcmp(x509->subject, x509->issuer) == 0) { | 195 | strcmp(x509->subject, x509->issuer) == 0) { |
@@ -209,7 +206,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
209 | 206 | ||
210 | ret = x509_check_signature(x509->pub, x509); | 207 | ret = x509_check_signature(x509->pub, x509); |
211 | if (ret < 0) | 208 | if (ret < 0) |
212 | return ret; | 209 | goto maybe_missing_crypto_in_x509; |
213 | x509->signer = x509; | 210 | x509->signer = x509; |
214 | pr_debug("- self-signed\n"); | 211 | pr_debug("- self-signed\n"); |
215 | return 0; | 212 | return 0; |
@@ -218,13 +215,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
218 | /* Look through the X.509 certificates in the PKCS#7 message's | 215 | /* Look through the X.509 certificates in the PKCS#7 message's |
219 | * list to see if the next one is there. | 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 | for (p = pkcs7->certs; p; p = p->next) { | 220 | for (p = pkcs7->certs; p; p = p->next) { |
223 | pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint); | 221 | if (!p->skid) |
224 | if (p->raw_subject_size == x509->raw_issuer_size && | 222 | continue; |
225 | strcmp(p->fingerprint, x509->authority) == 0 && | 223 | pr_debug("- cmp [%u] %*phN\n", |
226 | memcmp(p->raw_subject, x509->raw_issuer, | 224 | p->index, p->skid->len, p->skid->data); |
227 | x509->raw_issuer_size) == 0) | 225 | if (asymmetric_key_id_same(p->skid, x509->authority)) |
228 | goto found_issuer; | 226 | goto found_issuer; |
229 | } | 227 | } |
230 | 228 | ||
@@ -233,7 +231,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
233 | return 0; | 231 | return 0; |
234 | 232 | ||
235 | found_issuer: | 233 | found_issuer: |
236 | pr_debug("- issuer %s\n", p->subject); | 234 | pr_debug("- subject %s\n", p->subject); |
237 | if (p->seen) { | 235 | if (p->seen) { |
238 | pr_warn("Sig %u: X.509 chain contains loop\n", | 236 | pr_warn("Sig %u: X.509 chain contains loop\n", |
239 | sinfo->index); | 237 | sinfo->index); |
@@ -250,6 +248,17 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, | |||
250 | x509 = p; | 248 | x509 = p; |
251 | might_sleep(); | 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 | /* |
@@ -269,11 +278,14 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | |||
269 | if (ret < 0) | 278 | if (ret < 0) |
270 | return ret; | 279 | return ret; |
271 | 280 | ||
272 | /* Find the key for the signature */ | 281 | /* Find the key for the signature if there is one */ |
273 | ret = pkcs7_find_key(pkcs7, sinfo); | 282 | ret = pkcs7_find_key(pkcs7, sinfo); |
274 | if (ret < 0) | 283 | if (ret < 0) |
275 | return ret; | 284 | return ret; |
276 | 285 | ||
286 | if (!sinfo->signer) | ||
287 | return 0; | ||
288 | |||
277 | pr_devel("Using X.509[%u] for sig %u\n", | 289 | pr_devel("Using X.509[%u] for sig %u\n", |
278 | sinfo->signer->index, sinfo->index); | 290 | sinfo->signer->index, sinfo->index); |
279 | 291 | ||
@@ -291,11 +303,33 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, | |||
291 | /** | 303 | /** |
292 | * pkcs7_verify - Verify a PKCS#7 message | 304 | * pkcs7_verify - Verify a PKCS#7 message |
293 | * @pkcs7: The PKCS#7 message to be verified | 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 | int pkcs7_verify(struct pkcs7_message *pkcs7) | 328 | int pkcs7_verify(struct pkcs7_message *pkcs7) |
296 | { | 329 | { |
297 | struct pkcs7_signed_info *sinfo; | 330 | struct pkcs7_signed_info *sinfo; |
298 | struct x509_certificate *x509; | 331 | struct x509_certificate *x509; |
332 | int enopkg = -ENOPKG; | ||
299 | int ret, n; | 333 | int ret, n; |
300 | 334 | ||
301 | kenter(""); | 335 | kenter(""); |
@@ -304,18 +338,24 @@ int pkcs7_verify(struct pkcs7_message *pkcs7) | |||
304 | ret = x509_get_sig_params(x509); | 338 | ret = x509_get_sig_params(x509); |
305 | if (ret < 0) | 339 | if (ret < 0) |
306 | return ret; | 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 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { | 345 | for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { |
311 | ret = pkcs7_verify_one(pkcs7, sinfo); | 346 | ret = pkcs7_verify_one(pkcs7, sinfo); |
312 | if (ret < 0) { | 347 | if (ret < 0) { |
348 | if (ret == -ENOPKG) { | ||
349 | sinfo->unsupported_crypto = true; | ||
350 | continue; | ||
351 | } | ||
313 | kleave(" = %d", ret); | 352 | kleave(" = %d", ret); |
314 | return ret; | 353 | return ret; |
315 | } | 354 | } |
355 | enopkg = 0; | ||
316 | } | 356 | } |
317 | 357 | ||
318 | kleave(" = 0"); | 358 | kleave(" = %d", enopkg); |
319 | return 0; | 359 | return enopkg; |
320 | } | 360 | } |
321 | EXPORT_SYMBOL_GPL(pkcs7_verify); | 361 | EXPORT_SYMBOL_GPL(pkcs7_verify); |
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index ac72348c186a..96151b2b91a2 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c | |||
@@ -46,7 +46,8 @@ void x509_free_certificate(struct x509_certificate *cert) | |||
46 | public_key_destroy(cert->pub); | 46 | public_key_destroy(cert->pub); |
47 | kfree(cert->issuer); | 47 | kfree(cert->issuer); |
48 | kfree(cert->subject); | 48 | kfree(cert->subject); |
49 | kfree(cert->fingerprint); | 49 | kfree(cert->id); |
50 | kfree(cert->skid); | ||
50 | kfree(cert->authority); | 51 | kfree(cert->authority); |
51 | kfree(cert->sig.digest); | 52 | kfree(cert->sig.digest); |
52 | mpi_free(cert->sig.rsa.s); | 53 | mpi_free(cert->sig.rsa.s); |
@@ -62,6 +63,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) | |||
62 | { | 63 | { |
63 | struct x509_certificate *cert; | 64 | struct x509_certificate *cert; |
64 | struct x509_parse_context *ctx; | 65 | struct x509_parse_context *ctx; |
66 | struct asymmetric_key_id *kid; | ||
65 | long ret; | 67 | long ret; |
66 | 68 | ||
67 | ret = -ENOMEM; | 69 | ret = -ENOMEM; |
@@ -89,6 +91,17 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) | |||
89 | if (ret < 0) | 91 | if (ret < 0) |
90 | goto error_decode; | 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 | kfree(ctx); | 105 | kfree(ctx); |
93 | return cert; | 106 | return cert; |
94 | 107 | ||
@@ -407,36 +420,34 @@ int x509_process_extension(void *context, size_t hdrlen, | |||
407 | const void *value, size_t vlen) | 420 | const void *value, size_t vlen) |
408 | { | 421 | { |
409 | struct x509_parse_context *ctx = context; | 422 | struct x509_parse_context *ctx = context; |
423 | struct asymmetric_key_id *kid; | ||
410 | const unsigned char *v = value; | 424 | const unsigned char *v = value; |
411 | char *f; | ||
412 | int i; | 425 | int i; |
413 | 426 | ||
414 | pr_debug("Extension: %u\n", ctx->last_oid); | 427 | pr_debug("Extension: %u\n", ctx->last_oid); |
415 | 428 | ||
416 | if (ctx->last_oid == OID_subjectKeyIdentifier) { | 429 | if (ctx->last_oid == OID_subjectKeyIdentifier) { |
417 | /* Get hold of the key fingerprint */ | 430 | /* Get hold of the key fingerprint */ |
418 | if (vlen < 3) | 431 | if (ctx->cert->skid || vlen < 3) |
419 | return -EBADMSG; | 432 | return -EBADMSG; |
420 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) | 433 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) |
421 | return -EBADMSG; | 434 | return -EBADMSG; |
422 | v += 2; | 435 | v += 2; |
423 | vlen -= 2; | 436 | vlen -= 2; |
424 | 437 | ||
425 | f = kmalloc(vlen * 2 + 1, GFP_KERNEL); | 438 | kid = asymmetric_key_generate_id(v, vlen, |
426 | if (!f) | 439 | ctx->cert->raw_subject, |
427 | return -ENOMEM; | 440 | ctx->cert->raw_subject_size); |
428 | for (i = 0; i < vlen; i++) | 441 | if (IS_ERR(kid)) |
429 | sprintf(f + i * 2, "%02x", v[i]); | 442 | return PTR_ERR(kid); |
430 | pr_debug("fingerprint %s\n", f); | 443 | ctx->cert->skid = kid; |
431 | ctx->cert->fingerprint = f; | 444 | pr_debug("subjkeyid %*phN\n", kid->len, kid->data); |
432 | return 0; | 445 | return 0; |
433 | } | 446 | } |
434 | 447 | ||
435 | if (ctx->last_oid == OID_authorityKeyIdentifier) { | 448 | if (ctx->last_oid == OID_authorityKeyIdentifier) { |
436 | size_t key_len; | ||
437 | |||
438 | /* Get hold of the CA key fingerprint */ | 449 | /* Get hold of the CA key fingerprint */ |
439 | if (vlen < 5) | 450 | if (ctx->cert->authority || vlen < 5) |
440 | return -EBADMSG; | 451 | return -EBADMSG; |
441 | 452 | ||
442 | /* Authority Key Identifier must be a Constructed SEQUENCE */ | 453 | /* Authority Key Identifier must be a Constructed SEQUENCE */ |
@@ -454,7 +465,7 @@ int x509_process_extension(void *context, size_t hdrlen, | |||
454 | v[3] > vlen - 4) | 465 | v[3] > vlen - 4) |
455 | return -EBADMSG; | 466 | return -EBADMSG; |
456 | 467 | ||
457 | key_len = v[3]; | 468 | vlen = v[3]; |
458 | v += 4; | 469 | v += 4; |
459 | } else { | 470 | } else { |
460 | /* Long Form length */ | 471 | /* Long Form length */ |
@@ -476,17 +487,17 @@ int x509_process_extension(void *context, size_t hdrlen, | |||
476 | v[sub + 1] > vlen - 4 - sub) | 487 | v[sub + 1] > vlen - 4 - sub) |
477 | return -EBADMSG; | 488 | return -EBADMSG; |
478 | 489 | ||
479 | key_len = v[sub + 1]; | 490 | vlen = v[sub + 1]; |
480 | v += (sub + 2); | 491 | v += (sub + 2); |
481 | } | 492 | } |
482 | 493 | ||
483 | f = kmalloc(key_len * 2 + 1, GFP_KERNEL); | 494 | kid = asymmetric_key_generate_id(v, vlen, |
484 | if (!f) | 495 | ctx->cert->raw_issuer, |
485 | return -ENOMEM; | 496 | ctx->cert->raw_issuer_size); |
486 | for (i = 0; i < key_len; i++) | 497 | if (IS_ERR(kid)) |
487 | sprintf(f + i * 2, "%02x", v[i]); | 498 | return PTR_ERR(kid); |
488 | pr_debug("authority %s\n", f); | 499 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); |
489 | ctx->cert->authority = f; | 500 | ctx->cert->authority = kid; |
490 | return 0; | 501 | return 0; |
491 | } | 502 | } |
492 | 503 | ||
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 1b76f207c1f3..4e1a384901ed 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h | |||
@@ -19,8 +19,9 @@ struct x509_certificate { | |||
19 | struct public_key_signature sig; /* Signature parameters */ | 19 | struct public_key_signature sig; /* Signature parameters */ |
20 | char *issuer; /* Name of certificate issuer */ | 20 | char *issuer; /* Name of certificate issuer */ |
21 | char *subject; /* Name of certificate subject */ | 21 | char *subject; /* Name of certificate subject */ |
22 | char *fingerprint; /* Key fingerprint as hex */ | 22 | struct asymmetric_key_id *id; /* Issuer + serial number */ |
23 | char *authority; /* Authority key fingerprint as hex */ | 23 | struct asymmetric_key_id *skid; /* Subject key identifier */ |
24 | struct asymmetric_key_id *authority; /* Authority key identifier */ | ||
24 | struct tm valid_from; | 25 | struct tm valid_from; |
25 | struct tm valid_to; | 26 | struct tm valid_to; |
26 | const void *tbs; /* Signed data */ | 27 | const void *tbs; /* Signed data */ |
@@ -37,6 +38,7 @@ struct x509_certificate { | |||
37 | bool seen; /* Infinite recursion prevention */ | 38 | bool seen; /* Infinite recursion prevention */ |
38 | bool verified; | 39 | bool verified; |
39 | bool trusted; | 40 | bool trusted; |
41 | bool unsupported_crypto; /* T if can't be verified due to missing crypto */ | ||
40 | }; | 42 | }; |
41 | 43 | ||
42 | /* | 44 | /* |
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index f3d62307e6ee..1d9a4c555376 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include "x509_parser.h" | 25 | #include "x509_parser.h" |
26 | 26 | ||
27 | static bool use_builtin_keys; | 27 | static bool use_builtin_keys; |
28 | static char *ca_keyid; | 28 | static struct asymmetric_key_id *ca_keyid; |
29 | 29 | ||
30 | #ifndef MODULE | 30 | #ifndef MODULE |
31 | static int __init ca_keys_setup(char *str) | 31 | static int __init ca_keys_setup(char *str) |
@@ -33,10 +33,16 @@ static int __init ca_keys_setup(char *str) | |||
33 | if (!str) /* default system keyring */ | 33 | if (!str) /* default system keyring */ |
34 | return 1; | 34 | return 1; |
35 | 35 | ||
36 | if (strncmp(str, "id:", 3) == 0) | 36 | if (strncmp(str, "id:", 3) == 0) { |
37 | ca_keyid = str; /* owner key 'id:xxxxxx' */ | 37 | struct asymmetric_key_id *p; |
38 | else if (strcmp(str, "builtin") == 0) | 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 | use_builtin_keys = true; | 44 | use_builtin_keys = true; |
45 | } | ||
40 | 46 | ||
41 | return 1; | 47 | return 1; |
42 | } | 48 | } |
@@ -46,31 +52,28 @@ __setup("ca_keys=", ca_keys_setup); | |||
46 | /** | 52 | /** |
47 | * 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. |
48 | * @keyring: The keys to search. | 54 | * @keyring: The keys to search. |
49 | * @subject: The name of the subject to whom the key belongs. | 55 | * @kid: The key ID. |
50 | * @key_id: The subject key ID as a hex string. | ||
51 | * | 56 | * |
52 | * Find a key in the given keyring by subject name and key ID. These might, | 57 | * Find a key in the given keyring by subject name and key ID. These might, |
53 | * for instance, be the issuer name and the authority key ID of an X.509 | 58 | * for instance, be the issuer name and the authority key ID of an X.509 |
54 | * certificate that needs to be verified. | 59 | * certificate that needs to be verified. |
55 | */ | 60 | */ |
56 | struct key *x509_request_asymmetric_key(struct key *keyring, | 61 | struct key *x509_request_asymmetric_key(struct key *keyring, |
57 | const char *subject, | 62 | const struct asymmetric_key_id *kid) |
58 | const char *key_id) | ||
59 | { | 63 | { |
60 | key_ref_t key; | 64 | key_ref_t key; |
61 | size_t subject_len = strlen(subject), key_id_len = strlen(key_id); | 65 | char *id, *p; |
62 | char *id; | ||
63 | 66 | ||
64 | /* Construct an identifier "<subjname>:<keyid>". */ | 67 | /* Construct an identifier "id:<keyid>". */ |
65 | id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL); | 68 | p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); |
66 | if (!id) | 69 | if (!id) |
67 | return ERR_PTR(-ENOMEM); | 70 | return ERR_PTR(-ENOMEM); |
68 | 71 | ||
69 | memcpy(id, subject, subject_len); | 72 | *p++ = 'i'; |
70 | id[subject_len + 0] = ':'; | 73 | *p++ = 'd'; |
71 | id[subject_len + 1] = ' '; | 74 | *p++ = ':'; |
72 | memcpy(id + subject_len + 2, key_id, key_id_len); | 75 | p = bin2hex(p, kid->data, kid->len); |
73 | id[subject_len + 2 + key_id_len] = 0; | 76 | *p = 0; |
74 | 77 | ||
75 | pr_debug("Look up: \"%s\"\n", id); | 78 | pr_debug("Look up: \"%s\"\n", id); |
76 | 79 | ||
@@ -112,6 +115,8 @@ int x509_get_sig_params(struct x509_certificate *cert) | |||
112 | 115 | ||
113 | pr_devel("==>%s()\n", __func__); | 116 | pr_devel("==>%s()\n", __func__); |
114 | 117 | ||
118 | if (cert->unsupported_crypto) | ||
119 | return -ENOPKG; | ||
115 | if (cert->sig.rsa.s) | 120 | if (cert->sig.rsa.s) |
116 | return 0; | 121 | return 0; |
117 | 122 | ||
@@ -124,8 +129,13 @@ int x509_get_sig_params(struct x509_certificate *cert) | |||
124 | * big the hash operational data will be. | 129 | * big the hash operational data will be. |
125 | */ | 130 | */ |
126 | tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); | 131 | tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); |
127 | if (IS_ERR(tfm)) | 132 | if (IS_ERR(tfm)) { |
128 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_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 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); | 140 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); |
131 | digest_size = crypto_shash_digestsize(tfm); | 141 | digest_size = crypto_shash_digestsize(tfm); |
@@ -172,6 +182,8 @@ int x509_check_signature(const struct public_key *pub, | |||
172 | return ret; | 182 | return ret; |
173 | 183 | ||
174 | ret = public_key_verify_signature(pub, &cert->sig); | 184 | ret = public_key_verify_signature(pub, &cert->sig); |
185 | if (ret == -ENOPKG) | ||
186 | cert->unsupported_crypto = true; | ||
175 | pr_debug("Cert Verification: %d\n", ret); | 187 | pr_debug("Cert Verification: %d\n", ret); |
176 | return ret; | 188 | return ret; |
177 | } | 189 | } |
@@ -195,11 +207,10 @@ static int x509_validate_trust(struct x509_certificate *cert, | |||
195 | if (!trust_keyring) | 207 | if (!trust_keyring) |
196 | return -EOPNOTSUPP; | 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 | return -EPERM; | 211 | return -EPERM; |
200 | 212 | ||
201 | key = x509_request_asymmetric_key(trust_keyring, | 213 | key = x509_request_asymmetric_key(trust_keyring, cert->authority); |
202 | cert->issuer, cert->authority); | ||
203 | if (!IS_ERR(key)) { | 214 | if (!IS_ERR(key)) { |
204 | if (!use_builtin_keys | 215 | if (!use_builtin_keys |
205 | || test_bit(KEY_FLAG_BUILTIN, &key->flags)) | 216 | || test_bit(KEY_FLAG_BUILTIN, &key->flags)) |
@@ -214,9 +225,11 @@ static int x509_validate_trust(struct x509_certificate *cert, | |||
214 | */ | 225 | */ |
215 | static int x509_key_preparse(struct key_preparsed_payload *prep) | 226 | static int x509_key_preparse(struct key_preparsed_payload *prep) |
216 | { | 227 | { |
228 | struct asymmetric_key_ids *kids; | ||
217 | struct x509_certificate *cert; | 229 | struct x509_certificate *cert; |
230 | const char *q; | ||
218 | size_t srlen, sulen; | 231 | size_t srlen, sulen; |
219 | char *desc = NULL; | 232 | char *desc = NULL, *p; |
220 | int ret; | 233 | int ret; |
221 | 234 | ||
222 | cert = x509_cert_parse(prep->data, prep->datalen); | 235 | cert = x509_cert_parse(prep->data, prep->datalen); |
@@ -249,19 +262,12 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
249 | pkey_algo_name[cert->sig.pkey_algo], | 262 | pkey_algo_name[cert->sig.pkey_algo], |
250 | hash_algo_name[cert->sig.pkey_hash_algo]); | 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 | cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; | 265 | cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; |
260 | cert->pub->id_type = PKEY_ID_X509; | 266 | cert->pub->id_type = PKEY_ID_X509; |
261 | 267 | ||
262 | /* Check the signature on the key if it appears to be self-signed */ | 268 | /* Check the signature on the key if it appears to be self-signed */ |
263 | if (!cert->authority || | 269 | if (!cert->authority || |
264 | strcmp(cert->fingerprint, cert->authority) == 0) { | 270 | asymmetric_key_id_same(cert->skid, cert->authority)) { |
265 | ret = x509_check_signature(cert->pub, cert); /* self-signed */ | 271 | ret = x509_check_signature(cert->pub, cert); /* self-signed */ |
266 | if (ret < 0) | 272 | if (ret < 0) |
267 | goto error_free_cert; | 273 | goto error_free_cert; |
@@ -273,31 +279,47 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
273 | 279 | ||
274 | /* Propose a description */ | 280 | /* Propose a description */ |
275 | sulen = strlen(cert->subject); | 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 | ret = -ENOMEM; | 289 | ret = -ENOMEM; |
278 | desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); | 290 | desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); |
279 | if (!desc) | 291 | if (!desc) |
280 | goto error_free_cert; | 292 | goto error_free_cert; |
281 | memcpy(desc, cert->subject, sulen); | 293 | p = memcpy(desc, cert->subject, sulen); |
282 | desc[sulen] = ':'; | 294 | p += sulen; |
283 | desc[sulen + 1] = ' '; | 295 | *p++ = ':'; |
284 | memcpy(desc + sulen + 2, cert->fingerprint, srlen); | 296 | *p++ = ' '; |
285 | desc[sulen + 2 + srlen] = 0; | 297 | p = bin2hex(p, q, srlen); |
298 | *p = 0; | ||
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; | ||
286 | 305 | ||
287 | /* We're pinning the module by being linked against it */ | 306 | /* We're pinning the module by being linked against it */ |
288 | __module_get(public_key_subtype.owner); | 307 | __module_get(public_key_subtype.owner); |
289 | prep->type_data[0] = &public_key_subtype; | 308 | prep->type_data[0] = &public_key_subtype; |
290 | prep->type_data[1] = cert->fingerprint; | 309 | prep->type_data[1] = kids; |
291 | prep->payload[0] = cert->pub; | 310 | prep->payload[0] = cert->pub; |
292 | prep->description = desc; | 311 | prep->description = desc; |
293 | prep->quotalen = 100; | 312 | prep->quotalen = 100; |
294 | 313 | ||
295 | /* We've finished with the certificate */ | 314 | /* We've finished with the certificate */ |
296 | cert->pub = NULL; | 315 | cert->pub = NULL; |
297 | cert->fingerprint = NULL; | 316 | cert->id = NULL; |
317 | cert->skid = NULL; | ||
298 | desc = NULL; | 318 | desc = NULL; |
299 | ret = 0; | 319 | ret = 0; |
300 | 320 | ||
321 | error_free_desc: | ||
322 | kfree(desc); | ||
301 | error_free_cert: | 323 | error_free_cert: |
302 | x509_free_certificate(cert); | 324 | x509_free_certificate(cert); |
303 | return ret; | 325 | return ret; |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index a3e932547617..f4cf200b3c76 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -62,7 +62,6 @@ cifs_spnego_key_destroy(struct key *key) | |||
62 | struct key_type cifs_spnego_key_type = { | 62 | struct key_type cifs_spnego_key_type = { |
63 | .name = "cifs.spnego", | 63 | .name = "cifs.spnego", |
64 | .instantiate = cifs_spnego_key_instantiate, | 64 | .instantiate = cifs_spnego_key_instantiate, |
65 | .match = user_match, | ||
66 | .destroy = cifs_spnego_key_destroy, | 65 | .destroy = cifs_spnego_key_destroy, |
67 | .describe = user_describe, | 66 | .describe = user_describe, |
68 | }; | 67 | }; |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 7ff866dbb89e..6d00c419cbae 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -84,7 +84,6 @@ static struct key_type cifs_idmap_key_type = { | |||
84 | .instantiate = cifs_idmap_key_instantiate, | 84 | .instantiate = cifs_idmap_key_instantiate, |
85 | .destroy = cifs_idmap_key_destroy, | 85 | .destroy = cifs_idmap_key_destroy, |
86 | .describe = user_describe, | 86 | .describe = user_describe, |
87 | .match = user_match, | ||
88 | }; | 87 | }; |
89 | 88 | ||
90 | static char * | 89 | static char * |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 7dd55b745c4d..2f5db844c172 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -177,7 +177,6 @@ static struct key_type key_type_id_resolver = { | |||
177 | .preparse = user_preparse, | 177 | .preparse = user_preparse, |
178 | .free_preparse = user_free_preparse, | 178 | .free_preparse = user_free_preparse, |
179 | .instantiate = generic_key_instantiate, | 179 | .instantiate = generic_key_instantiate, |
180 | .match = user_match, | ||
181 | .revoke = user_revoke, | 180 | .revoke = user_revoke, |
182 | .destroy = user_destroy, | 181 | .destroy = user_destroy, |
183 | .describe = user_describe, | 182 | .describe = user_describe, |
@@ -401,7 +400,6 @@ static struct key_type key_type_id_resolver_legacy = { | |||
401 | .preparse = user_preparse, | 400 | .preparse = user_preparse, |
402 | .free_preparse = user_free_preparse, | 401 | .free_preparse = user_free_preparse, |
403 | .instantiate = generic_key_instantiate, | 402 | .instantiate = generic_key_instantiate, |
404 | .match = user_match, | ||
405 | .revoke = user_revoke, | 403 | .revoke = user_revoke, |
406 | .destroy = user_destroy, | 404 | .destroy = user_destroy, |
407 | .describe = user_describe, | 405 | .describe = user_describe, |
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 0d164c6af539..fa73a6fd536c 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define _LINUX_PUBLIC_KEY_H | 15 | #define _LINUX_PUBLIC_KEY_H |
16 | 16 | ||
17 | #include <linux/mpi.h> | 17 | #include <linux/mpi.h> |
18 | #include <keys/asymmetric-type.h> | ||
18 | #include <crypto/hash_info.h> | 19 | #include <crypto/hash_info.h> |
19 | 20 | ||
20 | enum pkey_algo { | 21 | enum pkey_algo { |
@@ -98,8 +99,8 @@ struct key; | |||
98 | extern int verify_signature(const struct key *key, | 99 | extern int verify_signature(const struct key *key, |
99 | const struct public_key_signature *sig); | 100 | const struct public_key_signature *sig); |
100 | 101 | ||
102 | struct asymmetric_key_id; | ||
101 | extern struct key *x509_request_asymmetric_key(struct key *keyring, | 103 | extern struct key *x509_request_asymmetric_key(struct key *keyring, |
102 | const char *issuer, | 104 | const struct asymmetric_key_id *kid); |
103 | const char *key_id); | ||
104 | 105 | ||
105 | #endif /* _LINUX_PUBLIC_KEY_H */ | 106 | #endif /* _LINUX_PUBLIC_KEY_H */ |
diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 7dd473496180..044ab0d3aa45 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h | |||
@@ -19,6 +19,44 @@ | |||
19 | extern struct key_type key_type_asymmetric; | 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 | * The payload is at the discretion of the subtype. | 60 | * The payload is at the discretion of the subtype. |
23 | */ | 61 | */ |
24 | 62 | ||
diff --git a/include/keys/user-type.h b/include/keys/user-type.h index 3ab1873a4bfa..cebefb069c44 100644 --- a/include/keys/user-type.h +++ b/include/keys/user-type.h | |||
@@ -40,7 +40,6 @@ struct key_preparsed_payload; | |||
40 | extern int user_preparse(struct key_preparsed_payload *prep); | 40 | extern int user_preparse(struct key_preparsed_payload *prep); |
41 | extern void user_free_preparse(struct key_preparsed_payload *prep); | 41 | extern void user_free_preparse(struct key_preparsed_payload *prep); |
42 | extern int user_update(struct key *key, struct key_preparsed_payload *prep); | 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 | extern void user_revoke(struct key *key); | 43 | extern void user_revoke(struct key *key); |
45 | extern void user_destroy(struct key *key); | 44 | extern void user_destroy(struct key *key); |
46 | extern void user_describe(const struct key *user, struct seq_file *m); | 45 | extern void user_describe(const struct key *user, struct seq_file *m); |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4c52907a6d8b..89a0b8e5a952 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -500,6 +500,7 @@ static inline char * __deprecated pack_hex_byte(char *buf, u8 byte) | |||
500 | 500 | ||
501 | extern int hex_to_bin(char ch); | 501 | extern int hex_to_bin(char ch); |
502 | extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); | 502 | extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); |
503 | extern char *bin2hex(char *dst, const void *src, size_t count); | ||
503 | 504 | ||
504 | int mac_pton(const char *s, u8 *mac); | 505 | int mac_pton(const char *s, u8 *mac); |
505 | 506 | ||
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 44792ee649de..ff9f1d394235 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h | |||
@@ -53,6 +53,24 @@ typedef int (*request_key_actor_t)(struct key_construction *key, | |||
53 | const char *op, void *aux); | 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 | * kernel managed key type definition | 74 | * kernel managed key type definition |
57 | */ | 75 | */ |
58 | struct key_type { | 76 | struct key_type { |
@@ -65,11 +83,6 @@ struct key_type { | |||
65 | */ | 83 | */ |
66 | size_t def_datalen; | 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 | /* vet a description */ | 86 | /* vet a description */ |
74 | int (*vet_description)(const char *description); | 87 | int (*vet_description)(const char *description); |
75 | 88 | ||
@@ -96,8 +109,15 @@ struct key_type { | |||
96 | */ | 109 | */ |
97 | int (*update)(struct key *key, struct key_preparsed_payload *prep); | 110 | int (*update)(struct key *key, struct key_preparsed_payload *prep); |
98 | 111 | ||
99 | /* match a key against a description */ | 112 | /* Preparse the data supplied to ->match() (optional). The |
100 | int (*match)(const struct key *key, const void *desc); | 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 | /* clear some of the data from a key on revokation (optional) | 122 | /* clear some of the data from a key on revokation (optional) |
103 | * - the key's semaphore will be write-locked by the caller | 123 | * - the key's semaphore will be write-locked by the caller |
diff --git a/lib/hexdump.c b/lib/hexdump.c index 8499c810909a..270773b91923 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c | |||
@@ -59,6 +59,22 @@ int hex2bin(u8 *dst, const char *src, size_t count) | |||
59 | EXPORT_SYMBOL(hex2bin); | 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 | * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory | 78 | * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory |
63 | * @buf: data blob to dump | 79 | * @buf: data blob to dump |
64 | * @len: number of bytes in the @buf | 80 | * @len: number of bytes in the @buf |
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index ffeba8f9dda9..62fc5e7a9acf 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -476,7 +476,6 @@ struct key_type key_type_ceph = { | |||
476 | .preparse = ceph_key_preparse, | 476 | .preparse = ceph_key_preparse, |
477 | .free_preparse = ceph_key_free_preparse, | 477 | .free_preparse = ceph_key_free_preparse, |
478 | .instantiate = generic_key_instantiate, | 478 | .instantiate = generic_key_instantiate, |
479 | .match = user_match, | ||
480 | .destroy = ceph_key_destroy, | 479 | .destroy = ceph_key_destroy, |
481 | }; | 480 | }; |
482 | 481 | ||
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index f380b2c58178..31cd4fd75486 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -176,11 +176,11 @@ static void dns_resolver_free_preparse(struct key_preparsed_payload *prep) | |||
176 | * The domain name may be a simple name or an absolute domain name (which | 176 | * The domain name may be a simple name or an absolute domain name (which |
177 | * should end with a period). The domain name is case-independent. | 177 | * should end with a period). The domain name is case-independent. |
178 | */ | 178 | */ |
179 | static int | 179 | static bool dns_resolver_cmp(const struct key *key, |
180 | dns_resolver_match(const struct key *key, const void *description) | 180 | const struct key_match_data *match_data) |
181 | { | 181 | { |
182 | int slen, dlen, ret = 0; | 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 | kenter("%s,%s", src, dsp); | 185 | kenter("%s,%s", src, dsp); |
186 | 186 | ||
@@ -209,6 +209,16 @@ no_match: | |||
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 | * Describe a DNS key | 222 | * Describe a DNS key |
213 | */ | 223 | */ |
214 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) | 224 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) |
@@ -242,7 +252,7 @@ struct key_type key_type_dns_resolver = { | |||
242 | .preparse = dns_resolver_preparse, | 252 | .preparse = dns_resolver_preparse, |
243 | .free_preparse = dns_resolver_free_preparse, | 253 | .free_preparse = dns_resolver_free_preparse, |
244 | .instantiate = generic_key_instantiate, | 254 | .instantiate = generic_key_instantiate, |
245 | .match = dns_resolver_match, | 255 | .match_preparse = dns_resolver_match_preparse, |
246 | .revoke = user_revoke, | 256 | .revoke = user_revoke, |
247 | .destroy = user_destroy, | 257 | .destroy = user_destroy, |
248 | .describe = dns_resolver_describe, | 258 | .describe = dns_resolver_describe, |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 3907add75932..10c6cb694b43 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -44,7 +44,6 @@ struct key_type key_type_rxrpc = { | |||
44 | .preparse = rxrpc_preparse, | 44 | .preparse = rxrpc_preparse, |
45 | .free_preparse = rxrpc_free_preparse, | 45 | .free_preparse = rxrpc_free_preparse, |
46 | .instantiate = generic_key_instantiate, | 46 | .instantiate = generic_key_instantiate, |
47 | .match = user_match, | ||
48 | .destroy = rxrpc_destroy, | 47 | .destroy = rxrpc_destroy, |
49 | .describe = rxrpc_describe, | 48 | .describe = rxrpc_describe, |
50 | .read = rxrpc_read, | 49 | .read = rxrpc_read, |
@@ -61,7 +60,6 @@ struct key_type key_type_rxrpc_s = { | |||
61 | .preparse = rxrpc_preparse_s, | 60 | .preparse = rxrpc_preparse_s, |
62 | .free_preparse = rxrpc_free_preparse_s, | 61 | .free_preparse = rxrpc_free_preparse_s, |
63 | .instantiate = generic_key_instantiate, | 62 | .instantiate = generic_key_instantiate, |
64 | .match = user_match, | ||
65 | .destroy = rxrpc_destroy_s, | 63 | .destroy = rxrpc_destroy_s, |
66 | .describe = rxrpc_describe, | 64 | .describe = rxrpc_describe, |
67 | }; | 65 | }; |
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index c2f91a0cf889..b6adb94f6d52 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c | |||
@@ -33,11 +33,9 @@ MODULE_LICENSE("GPL"); | |||
33 | */ | 33 | */ |
34 | struct key_type key_type_big_key = { | 34 | struct key_type key_type_big_key = { |
35 | .name = "big_key", | 35 | .name = "big_key", |
36 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
37 | .preparse = big_key_preparse, | 36 | .preparse = big_key_preparse, |
38 | .free_preparse = big_key_free_preparse, | 37 | .free_preparse = big_key_free_preparse, |
39 | .instantiate = generic_key_instantiate, | 38 | .instantiate = generic_key_instantiate, |
40 | .match = user_match, | ||
41 | .revoke = big_key_revoke, | 39 | .revoke = big_key_revoke, |
42 | .destroy = big_key_destroy, | 40 | .destroy = big_key_destroy, |
43 | .describe = big_key_describe, | 41 | .describe = big_key_describe, |
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 5fe443d120af..db9675db1026 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -970,7 +970,6 @@ struct key_type key_type_encrypted = { | |||
970 | .name = "encrypted", | 970 | .name = "encrypted", |
971 | .instantiate = encrypted_instantiate, | 971 | .instantiate = encrypted_instantiate, |
972 | .update = encrypted_update, | 972 | .update = encrypted_update, |
973 | .match = user_match, | ||
974 | .destroy = encrypted_destroy, | 973 | .destroy = encrypted_destroy, |
975 | .describe = user_describe, | 974 | .describe = user_describe, |
976 | .read = encrypted_read, | 975 | .read = encrypted_read, |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 5f20da01fd8d..b8960c4959a5 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -107,20 +107,16 @@ extern int iterate_over_keyring(const struct key *keyring, | |||
107 | int (*func)(const struct key *key, void *data), | 107 | int (*func)(const struct key *key, void *data), |
108 | void *data); | 108 | void *data); |
109 | 109 | ||
110 | typedef int (*key_match_func_t)(const struct key *, const void *); | ||
111 | |||
112 | struct keyring_search_context { | 110 | struct keyring_search_context { |
113 | struct keyring_index_key index_key; | 111 | struct keyring_index_key index_key; |
114 | const struct cred *cred; | 112 | const struct cred *cred; |
115 | key_match_func_t match; | 113 | struct key_match_data match_data; |
116 | const void *match_data; | ||
117 | unsigned flags; | 114 | unsigned flags; |
118 | #define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ | 115 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0001 /* Skip state checks */ |
119 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ | 116 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0002 /* Override NO_STATE_CHECK */ |
120 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */ | 117 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0004 /* Don't update times */ |
121 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */ | 118 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ |
122 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ | 119 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ |
123 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ | ||
124 | 120 | ||
125 | int (*iterator)(const void *object, void *iterator_data); | 121 | int (*iterator)(const void *object, void *iterator_data); |
126 | 122 | ||
@@ -131,6 +127,8 @@ struct keyring_search_context { | |||
131 | struct timespec now; | 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 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 132 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
135 | struct keyring_search_context *ctx); | 133 | struct keyring_search_context *ctx); |
136 | 134 | ||
@@ -152,7 +150,8 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
152 | struct key *dest_keyring, | 150 | struct key *dest_keyring, |
153 | unsigned long flags); | 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 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | 155 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, |
157 | key_perm_t perm); | 156 | key_perm_t perm); |
158 | #define KEY_LOOKUP_CREATE 0x01 | 157 | #define KEY_LOOKUP_CREATE 0x01 |
diff --git a/security/keys/key.c b/security/keys/key.c index b90a68c4e2c4..8c0092ca0443 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -799,7 +799,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
799 | } | 799 | } |
800 | 800 | ||
801 | key_ref = ERR_PTR(-EINVAL); | 801 | key_ref = ERR_PTR(-EINVAL); |
802 | if (!index_key.type->match || !index_key.type->instantiate || | 802 | if (!index_key.type->instantiate || |
803 | (!index_key.description && !index_key.type->preparse)) | 803 | (!index_key.description && !index_key.type->preparse)) |
804 | goto error_put_type; | 804 | goto error_put_type; |
805 | 805 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index e26f860e5f2e..eff88a5f5d40 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -37,6 +37,8 @@ static int key_get_type_from_user(char *type, | |||
37 | return ret; | 37 | return ret; |
38 | if (ret == 0 || ret >= len) | 38 | if (ret == 0 || ret >= len) |
39 | return -EINVAL; | 39 | return -EINVAL; |
40 | if (type[0] == '.') | ||
41 | return -EPERM; | ||
40 | type[len - 1] = '\0'; | 42 | type[len - 1] = '\0'; |
41 | return 0; | 43 | return 0; |
42 | } | 44 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 8314a7d2104d..8177010174f7 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -89,7 +89,6 @@ struct key_type key_type_keyring = { | |||
89 | .preparse = keyring_preparse, | 89 | .preparse = keyring_preparse, |
90 | .free_preparse = keyring_free_preparse, | 90 | .free_preparse = keyring_free_preparse, |
91 | .instantiate = keyring_instantiate, | 91 | .instantiate = keyring_instantiate, |
92 | .match = user_match, | ||
93 | .revoke = keyring_revoke, | 92 | .revoke = keyring_revoke, |
94 | .destroy = keyring_destroy, | 93 | .destroy = keyring_destroy, |
95 | .describe = keyring_describe, | 94 | .describe = keyring_describe, |
@@ -512,6 +511,15 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
512 | EXPORT_SYMBOL(keyring_alloc); | 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 | * Iteration function to consider each key found. | 523 | * Iteration function to consider each key found. |
516 | */ | 524 | */ |
517 | static int keyring_search_iterator(const void *object, void *iterator_data) | 525 | static int keyring_search_iterator(const void *object, void *iterator_data) |
@@ -545,7 +553,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) | |||
545 | } | 553 | } |
546 | 554 | ||
547 | /* keys that don't match */ | 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 | kleave(" = 0 [!match]"); | 557 | kleave(" = 0 [!match]"); |
550 | return 0; | 558 | return 0; |
551 | } | 559 | } |
@@ -585,8 +593,7 @@ skipped: | |||
585 | */ | 593 | */ |
586 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) | 594 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) |
587 | { | 595 | { |
588 | if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == | 596 | if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) { |
589 | KEYRING_SEARCH_LOOKUP_DIRECT) { | ||
590 | const void *object; | 597 | const void *object; |
591 | 598 | ||
592 | object = assoc_array_find(&keyring->keys, | 599 | object = assoc_array_find(&keyring->keys, |
@@ -627,7 +634,7 @@ static bool search_nested_keyrings(struct key *keyring, | |||
627 | /* Check to see if this top-level keyring is what we are looking for | 634 | /* Check to see if this top-level keyring is what we are looking for |
628 | * and whether it is valid or not. | 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 | keyring_compare_object(keyring, &ctx->index_key)) { | 638 | keyring_compare_object(keyring, &ctx->index_key)) { |
632 | ctx->skipped_ret = 2; | 639 | ctx->skipped_ret = 2; |
633 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; | 640 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; |
@@ -885,16 +892,25 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
885 | .index_key.type = type, | 892 | .index_key.type = type, |
886 | .index_key.description = description, | 893 | .index_key.description = description, |
887 | .cred = current_cred(), | 894 | .cred = current_cred(), |
888 | .match = type->match, | 895 | .match_data.cmp = key_default_cmp, |
889 | .match_data = description, | 896 | .match_data.raw_data = description, |
890 | .flags = (type->def_lookup_type | | 897 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
891 | KEYRING_SEARCH_DO_STATE_CHECK), | 898 | .flags = KEYRING_SEARCH_DO_STATE_CHECK, |
892 | }; | 899 | }; |
900 | key_ref_t key; | ||
901 | int ret; | ||
893 | 902 | ||
894 | if (!ctx.match) | 903 | if (type->match_preparse) { |
895 | return ERR_PTR(-ENOKEY); | 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 | EXPORT_SYMBOL(keyring_search); | 915 | EXPORT_SYMBOL(keyring_search); |
900 | 916 | ||
@@ -1014,7 +1030,7 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
1014 | 1030 | ||
1015 | /* We might get a keyring with matching index-key that is nonetheless a | 1031 | /* We might get a keyring with matching index-key that is nonetheless a |
1016 | * different keyring. */ | 1032 | * different keyring. */ |
1017 | if (key != ctx->match_data) | 1033 | if (key != ctx->match_data.raw_data) |
1018 | return 0; | 1034 | return 0; |
1019 | 1035 | ||
1020 | ctx->result = ERR_PTR(-EDEADLK); | 1036 | ctx->result = ERR_PTR(-EDEADLK); |
@@ -1031,14 +1047,14 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
1031 | static int keyring_detect_cycle(struct key *A, struct key *B) | 1047 | static int keyring_detect_cycle(struct key *A, struct key *B) |
1032 | { | 1048 | { |
1033 | struct keyring_search_context ctx = { | 1049 | struct keyring_search_context ctx = { |
1034 | .index_key = A->index_key, | 1050 | .index_key = A->index_key, |
1035 | .match_data = A, | 1051 | .match_data.raw_data = A, |
1036 | .iterator = keyring_detect_cycle_iterator, | 1052 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
1037 | .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | | 1053 | .iterator = keyring_detect_cycle_iterator, |
1038 | KEYRING_SEARCH_NO_STATE_CHECK | | 1054 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
1039 | KEYRING_SEARCH_NO_UPDATE_TIME | | 1055 | KEYRING_SEARCH_NO_UPDATE_TIME | |
1040 | KEYRING_SEARCH_NO_CHECK_PERM | | 1056 | KEYRING_SEARCH_NO_CHECK_PERM | |
1041 | KEYRING_SEARCH_DETECT_TOO_DEEP), | 1057 | KEYRING_SEARCH_DETECT_TOO_DEEP), |
1042 | }; | 1058 | }; |
1043 | 1059 | ||
1044 | rcu_read_lock(); | 1060 | rcu_read_lock(); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index d3f6f2fd21db..972eeb336b81 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -194,10 +194,10 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
194 | .index_key.type = key->type, | 194 | .index_key.type = key->type, |
195 | .index_key.description = key->description, | 195 | .index_key.description = key->description, |
196 | .cred = current_cred(), | 196 | .cred = current_cred(), |
197 | .match = lookup_user_key_possessed, | 197 | .match_data.cmp = lookup_user_key_possessed, |
198 | .match_data = key, | 198 | .match_data.raw_data = key, |
199 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 199 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
200 | KEYRING_SEARCH_LOOKUP_DIRECT), | 200 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | key_ref = make_key_ref(key, 0); | 203 | key_ref = make_key_ref(key, 0); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 0cf8a130a267..bd536cb221e2 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -489,9 +489,10 @@ found: | |||
489 | /* | 489 | /* |
490 | * See if the key we're looking at is the target key. | 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 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | |||
516 | key_perm_t perm) | 517 | key_perm_t perm) |
517 | { | 518 | { |
518 | struct keyring_search_context ctx = { | 519 | struct keyring_search_context ctx = { |
519 | .match = lookup_user_key_possessed, | 520 | .match_data.cmp = lookup_user_key_possessed, |
520 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 521 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
521 | KEYRING_SEARCH_LOOKUP_DIRECT), | 522 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
522 | }; | 523 | }; |
523 | struct request_key_auth *rka; | 524 | struct request_key_auth *rka; |
524 | struct key *key; | 525 | struct key *key; |
@@ -673,7 +674,7 @@ try_again: | |||
673 | ctx.index_key.type = key->type; | 674 | ctx.index_key.type = key->type; |
674 | ctx.index_key.description = key->description; | 675 | ctx.index_key.description = key->description; |
675 | ctx.index_key.desc_len = strlen(key->description); | 676 | ctx.index_key.desc_len = strlen(key->description); |
676 | ctx.match_data = key; | 677 | ctx.match_data.raw_data = key; |
677 | kdebug("check possessed"); | 678 | kdebug("check possessed"); |
678 | skey_ref = search_process_keyrings(&ctx); | 679 | skey_ref = search_process_keyrings(&ctx); |
679 | kdebug("possessed=%p", skey_ref); | 680 | kdebug("possessed=%p", skey_ref); |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 381411941cc1..dc6ed32b7844 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -531,9 +531,9 @@ struct key *request_key_and_link(struct key_type *type, | |||
531 | .index_key.type = type, | 531 | .index_key.type = type, |
532 | .index_key.description = description, | 532 | .index_key.description = description, |
533 | .cred = current_cred(), | 533 | .cred = current_cred(), |
534 | .match = type->match, | 534 | .match_data.cmp = key_default_cmp, |
535 | .match_data = description, | 535 | .match_data.raw_data = description, |
536 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 536 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
537 | }; | 537 | }; |
538 | struct key *key; | 538 | struct key *key; |
539 | key_ref_t key_ref; | 539 | key_ref_t key_ref; |
@@ -543,6 +543,14 @@ struct key *request_key_and_link(struct key_type *type, | |||
543 | ctx.index_key.type->name, ctx.index_key.description, | 543 | ctx.index_key.type->name, ctx.index_key.description, |
544 | callout_info, callout_len, aux, dest_keyring, flags); | 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 | /* search all the process keyrings for a key */ | 554 | /* search all the process keyrings for a key */ |
547 | key_ref = search_process_keyrings(&ctx); | 555 | key_ref = search_process_keyrings(&ctx); |
548 | 556 | ||
@@ -555,7 +563,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
555 | if (ret < 0) { | 563 | if (ret < 0) { |
556 | key_put(key); | 564 | key_put(key); |
557 | key = ERR_PTR(ret); | 565 | key = ERR_PTR(ret); |
558 | goto error; | 566 | goto error_free; |
559 | } | 567 | } |
560 | } | 568 | } |
561 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 569 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
@@ -565,12 +573,15 @@ struct key *request_key_and_link(struct key_type *type, | |||
565 | * should consult userspace if we can */ | 573 | * should consult userspace if we can */ |
566 | key = ERR_PTR(-ENOKEY); | 574 | key = ERR_PTR(-ENOKEY); |
567 | if (!callout_info) | 575 | if (!callout_info) |
568 | goto error; | 576 | goto error_free; |
569 | 577 | ||
570 | key = construct_key_and_link(&ctx, callout_info, callout_len, | 578 | key = construct_key_and_link(&ctx, callout_info, callout_len, |
571 | aux, dest_keyring, flags); | 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 | error: | 585 | error: |
575 | kleave(" = %p", key); | 586 | kleave(" = %p", key); |
576 | return key; | 587 | return key; |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 842e6f410d50..6639e2cb8853 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -44,12 +44,12 @@ struct key_type key_type_request_key_auth = { | |||
44 | .read = request_key_auth_read, | 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 | return 0; | 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 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
246 | .index_key.type = &key_type_request_key_auth, | 246 | .index_key.type = &key_type_request_key_auth, |
247 | .index_key.description = description, | 247 | .index_key.description = description, |
248 | .cred = current_cred(), | 248 | .cred = current_cred(), |
249 | .match = user_match, | 249 | .match_data.cmp = key_default_cmp, |
250 | .match_data = description, | 250 | .match_data.raw_data = description, |
251 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 251 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
252 | }; | 252 | }; |
253 | struct key *authkey; | 253 | struct key *authkey; |
254 | key_ref_t authkey_ref; | 254 | key_ref_t authkey_ref; |
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 6b804aa4529a..c0594cb07ada 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -1096,7 +1096,6 @@ struct key_type key_type_trusted = { | |||
1096 | .name = "trusted", | 1096 | .name = "trusted", |
1097 | .instantiate = trusted_instantiate, | 1097 | .instantiate = trusted_instantiate, |
1098 | .update = trusted_update, | 1098 | .update = trusted_update, |
1099 | .match = user_match, | ||
1100 | .destroy = trusted_destroy, | 1099 | .destroy = trusted_destroy, |
1101 | .describe = user_describe, | 1100 | .describe = user_describe, |
1102 | .read = trusted_read, | 1101 | .read = trusted_read, |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index eee340011f2b..36b47bbd3d8c 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -26,12 +26,10 @@ static int logon_vet_description(const char *desc); | |||
26 | */ | 26 | */ |
27 | struct key_type key_type_user = { | 27 | struct key_type key_type_user = { |
28 | .name = "user", | 28 | .name = "user", |
29 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
30 | .preparse = user_preparse, | 29 | .preparse = user_preparse, |
31 | .free_preparse = user_free_preparse, | 30 | .free_preparse = user_free_preparse, |
32 | .instantiate = generic_key_instantiate, | 31 | .instantiate = generic_key_instantiate, |
33 | .update = user_update, | 32 | .update = user_update, |
34 | .match = user_match, | ||
35 | .revoke = user_revoke, | 33 | .revoke = user_revoke, |
36 | .destroy = user_destroy, | 34 | .destroy = user_destroy, |
37 | .describe = user_describe, | 35 | .describe = user_describe, |
@@ -48,12 +46,10 @@ EXPORT_SYMBOL_GPL(key_type_user); | |||
48 | */ | 46 | */ |
49 | struct key_type key_type_logon = { | 47 | struct key_type key_type_logon = { |
50 | .name = "logon", | 48 | .name = "logon", |
51 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
52 | .preparse = user_preparse, | 49 | .preparse = user_preparse, |
53 | .free_preparse = user_free_preparse, | 50 | .free_preparse = user_free_preparse, |
54 | .instantiate = generic_key_instantiate, | 51 | .instantiate = generic_key_instantiate, |
55 | .update = user_update, | 52 | .update = user_update, |
56 | .match = user_match, | ||
57 | .revoke = user_revoke, | 53 | .revoke = user_revoke, |
58 | .destroy = user_destroy, | 54 | .destroy = user_destroy, |
59 | .describe = user_describe, | 55 | .describe = user_describe, |
@@ -139,16 +135,6 @@ error: | |||
139 | EXPORT_SYMBOL_GPL(user_update); | 135 | EXPORT_SYMBOL_GPL(user_update); |
140 | 136 | ||
141 | /* | 137 | /* |
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 | |||
151 | /* | ||
152 | * dispose of the links from a revoked keyring | 138 | * dispose of the links from a revoked keyring |
153 | * - called with the key sem write-locked | 139 | * - called with the key sem write-locked |
154 | */ | 140 | */ |