1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* Instantiate a public key crypto key from an X.509 Certificate |
3 | * |
4 | * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. |
5 | * Written by David Howells (dhowells@redhat.com) |
6 | */ |
7 | |
8 | #define pr_fmt(fmt) "ASYM: "fmt |
9 | #include <linux/module.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/err.h> |
12 | #include <crypto/public_key.h> |
13 | #include "asymmetric_keys.h" |
14 | |
15 | static bool use_builtin_keys; |
16 | static struct asymmetric_key_id *ca_keyid; |
17 | |
18 | #ifndef MODULE |
19 | static struct { |
20 | struct asymmetric_key_id id; |
21 | unsigned char data[10]; |
22 | } cakey; |
23 | |
24 | static int __init ca_keys_setup(char *str) |
25 | { |
26 | if (!str) /* default system keyring */ |
27 | return 1; |
28 | |
29 | if (strncmp(str, "id:" , 3) == 0) { |
30 | struct asymmetric_key_id *p = &cakey.id; |
31 | size_t hexlen = (strlen(str) - 3) / 2; |
32 | int ret; |
33 | |
34 | if (hexlen == 0 || hexlen > sizeof(cakey.data)) { |
35 | pr_err("Missing or invalid ca_keys id\n" ); |
36 | return 1; |
37 | } |
38 | |
39 | ret = __asymmetric_key_hex_to_key_id(id: str + 3, match_id: p, hexlen); |
40 | if (ret < 0) |
41 | pr_err("Unparsable ca_keys id hex string\n" ); |
42 | else |
43 | ca_keyid = p; /* owner key 'id:xxxxxx' */ |
44 | } else if (strcmp(str, "builtin" ) == 0) { |
45 | use_builtin_keys = true; |
46 | } |
47 | |
48 | return 1; |
49 | } |
50 | __setup("ca_keys=" , ca_keys_setup); |
51 | #endif |
52 | |
53 | /** |
54 | * restrict_link_by_signature - Restrict additions to a ring of public keys |
55 | * @dest_keyring: Keyring being linked to. |
56 | * @type: The type of key being added. |
57 | * @payload: The payload of the new key. |
58 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. |
59 | * |
60 | * Check the new certificate against the ones in the trust keyring. If one of |
61 | * those is the signing key and validates the new certificate, then mark the |
62 | * new certificate as being trusted. |
63 | * |
64 | * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a |
65 | * matching parent certificate in the trusted list, -EKEYREJECTED if the |
66 | * signature check fails or the key is blacklisted, -ENOPKG if the signature |
67 | * uses unsupported crypto, or some other error if there is a matching |
68 | * certificate but the signature check cannot be performed. |
69 | */ |
70 | int restrict_link_by_signature(struct key *dest_keyring, |
71 | const struct key_type *type, |
72 | const union key_payload *payload, |
73 | struct key *trust_keyring) |
74 | { |
75 | const struct public_key_signature *sig; |
76 | struct key *key; |
77 | int ret; |
78 | |
79 | pr_devel("==>%s()\n" , __func__); |
80 | |
81 | if (!trust_keyring) |
82 | return -ENOKEY; |
83 | |
84 | if (type != &key_type_asymmetric) |
85 | return -EOPNOTSUPP; |
86 | |
87 | sig = payload->data[asym_auth]; |
88 | if (!sig) |
89 | return -ENOPKG; |
90 | if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2]) |
91 | return -ENOKEY; |
92 | |
93 | if (ca_keyid && !asymmetric_key_id_partial(kid1: sig->auth_ids[1], kid2: ca_keyid)) |
94 | return -EPERM; |
95 | |
96 | /* See if we have a key that signed this one. */ |
97 | key = find_asymmetric_key(keyring: trust_keyring, |
98 | id_0: sig->auth_ids[0], id_1: sig->auth_ids[1], |
99 | id_2: sig->auth_ids[2], partial: false); |
100 | if (IS_ERR(ptr: key)) |
101 | return -ENOKEY; |
102 | |
103 | if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) |
104 | ret = -ENOKEY; |
105 | else if (IS_BUILTIN(CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN) && |
106 | !strcmp(dest_keyring->description, ".secondary_trusted_keys" ) && |
107 | !test_bit(KEY_FLAG_BUILTIN, &key->flags)) |
108 | ret = -ENOKEY; |
109 | else |
110 | ret = verify_signature(key, sig); |
111 | key_put(key); |
112 | return ret; |
113 | } |
114 | |
115 | /** |
116 | * restrict_link_by_ca - Restrict additions to a ring of CA keys |
117 | * @dest_keyring: Keyring being linked to. |
118 | * @type: The type of key being added. |
119 | * @payload: The payload of the new key. |
120 | * @trust_keyring: Unused. |
121 | * |
122 | * Check if the new certificate is a CA. If it is a CA, then mark the new |
123 | * certificate as being ok to link. |
124 | * |
125 | * Returns 0 if the new certificate was accepted, -ENOKEY if the |
126 | * certificate is not a CA. -ENOPKG if the signature uses unsupported |
127 | * crypto, or some other error if there is a matching certificate but |
128 | * the signature check cannot be performed. |
129 | */ |
130 | int restrict_link_by_ca(struct key *dest_keyring, |
131 | const struct key_type *type, |
132 | const union key_payload *payload, |
133 | struct key *trust_keyring) |
134 | { |
135 | const struct public_key *pkey; |
136 | |
137 | if (type != &key_type_asymmetric) |
138 | return -EOPNOTSUPP; |
139 | |
140 | pkey = payload->data[asym_crypto]; |
141 | if (!pkey) |
142 | return -ENOPKG; |
143 | if (!test_bit(KEY_EFLAG_CA, &pkey->key_eflags)) |
144 | return -ENOKEY; |
145 | if (!test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags)) |
146 | return -ENOKEY; |
147 | if (!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX)) |
148 | return 0; |
149 | if (test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags)) |
150 | return -ENOKEY; |
151 | |
152 | return 0; |
153 | } |
154 | |
155 | /** |
156 | * restrict_link_by_digsig - Restrict additions to a ring of digsig keys |
157 | * @dest_keyring: Keyring being linked to. |
158 | * @type: The type of key being added. |
159 | * @payload: The payload of the new key. |
160 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. |
161 | * |
162 | * Check if the new certificate has digitalSignature usage set. If it is, |
163 | * then mark the new certificate as being ok to link. Afterwards verify |
164 | * the new certificate against the ones in the trust_keyring. |
165 | * |
166 | * Returns 0 if the new certificate was accepted, -ENOKEY if the |
167 | * certificate is not a digsig. -ENOPKG if the signature uses unsupported |
168 | * crypto, or some other error if there is a matching certificate but |
169 | * the signature check cannot be performed. |
170 | */ |
171 | int restrict_link_by_digsig(struct key *dest_keyring, |
172 | const struct key_type *type, |
173 | const union key_payload *payload, |
174 | struct key *trust_keyring) |
175 | { |
176 | const struct public_key *pkey; |
177 | |
178 | if (type != &key_type_asymmetric) |
179 | return -EOPNOTSUPP; |
180 | |
181 | pkey = payload->data[asym_crypto]; |
182 | |
183 | if (!pkey) |
184 | return -ENOPKG; |
185 | |
186 | if (!test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags)) |
187 | return -ENOKEY; |
188 | |
189 | if (test_bit(KEY_EFLAG_CA, &pkey->key_eflags)) |
190 | return -ENOKEY; |
191 | |
192 | if (test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags)) |
193 | return -ENOKEY; |
194 | |
195 | return restrict_link_by_signature(dest_keyring, type, payload, |
196 | trust_keyring); |
197 | } |
198 | |
199 | static bool match_either_id(const struct asymmetric_key_id **pair, |
200 | const struct asymmetric_key_id *single) |
201 | { |
202 | return (asymmetric_key_id_same(kid1: pair[0], kid2: single) || |
203 | asymmetric_key_id_same(kid1: pair[1], kid2: single)); |
204 | } |
205 | |
206 | static int key_or_keyring_common(struct key *dest_keyring, |
207 | const struct key_type *type, |
208 | const union key_payload *payload, |
209 | struct key *trusted, bool check_dest) |
210 | { |
211 | const struct public_key_signature *sig; |
212 | struct key *key = NULL; |
213 | int ret; |
214 | |
215 | pr_devel("==>%s()\n" , __func__); |
216 | |
217 | if (!dest_keyring) |
218 | return -ENOKEY; |
219 | else if (dest_keyring->type != &key_type_keyring) |
220 | return -EOPNOTSUPP; |
221 | |
222 | if (!trusted && !check_dest) |
223 | return -ENOKEY; |
224 | |
225 | if (type != &key_type_asymmetric) |
226 | return -EOPNOTSUPP; |
227 | |
228 | sig = payload->data[asym_auth]; |
229 | if (!sig) |
230 | return -ENOPKG; |
231 | if (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2]) |
232 | return -ENOKEY; |
233 | |
234 | if (trusted) { |
235 | if (trusted->type == &key_type_keyring) { |
236 | /* See if we have a key that signed this one. */ |
237 | key = find_asymmetric_key(keyring: trusted, id_0: sig->auth_ids[0], |
238 | id_1: sig->auth_ids[1], |
239 | id_2: sig->auth_ids[2], partial: false); |
240 | if (IS_ERR(ptr: key)) |
241 | key = NULL; |
242 | } else if (trusted->type == &key_type_asymmetric) { |
243 | const struct asymmetric_key_id **signer_ids; |
244 | |
245 | signer_ids = (const struct asymmetric_key_id **) |
246 | asymmetric_key_ids(key: trusted)->id; |
247 | |
248 | /* |
249 | * The auth_ids come from the candidate key (the |
250 | * one that is being considered for addition to |
251 | * dest_keyring) and identify the key that was |
252 | * used to sign. |
253 | * |
254 | * The signer_ids are identifiers for the |
255 | * signing key specified for dest_keyring. |
256 | * |
257 | * The first auth_id is the preferred id, 2nd and |
258 | * 3rd are the fallbacks. If exactly one of |
259 | * auth_ids[0] and auth_ids[1] is present, it may |
260 | * match either signer_ids[0] or signed_ids[1]. |
261 | * If both are present the first one may match |
262 | * either signed_id but the second one must match |
263 | * the second signer_id. If neither of them is |
264 | * available, auth_ids[2] is matched against |
265 | * signer_ids[2] as a fallback. |
266 | */ |
267 | if (!sig->auth_ids[0] && !sig->auth_ids[1]) { |
268 | if (asymmetric_key_id_same(kid1: signer_ids[2], |
269 | kid2: sig->auth_ids[2])) |
270 | key = __key_get(key: trusted); |
271 | |
272 | } else if (!sig->auth_ids[0] || !sig->auth_ids[1]) { |
273 | const struct asymmetric_key_id *auth_id; |
274 | |
275 | auth_id = sig->auth_ids[0] ?: sig->auth_ids[1]; |
276 | if (match_either_id(pair: signer_ids, single: auth_id)) |
277 | key = __key_get(key: trusted); |
278 | |
279 | } else if (asymmetric_key_id_same(kid1: signer_ids[1], |
280 | kid2: sig->auth_ids[1]) && |
281 | match_either_id(pair: signer_ids, |
282 | single: sig->auth_ids[0])) { |
283 | key = __key_get(key: trusted); |
284 | } |
285 | } else { |
286 | return -EOPNOTSUPP; |
287 | } |
288 | } |
289 | |
290 | if (check_dest && !key) { |
291 | /* See if the destination has a key that signed this one. */ |
292 | key = find_asymmetric_key(keyring: dest_keyring, id_0: sig->auth_ids[0], |
293 | id_1: sig->auth_ids[1], id_2: sig->auth_ids[2], |
294 | partial: false); |
295 | if (IS_ERR(ptr: key)) |
296 | key = NULL; |
297 | } |
298 | |
299 | if (!key) |
300 | return -ENOKEY; |
301 | |
302 | ret = key_validate(key); |
303 | if (ret == 0) |
304 | ret = verify_signature(key, sig); |
305 | |
306 | key_put(key); |
307 | return ret; |
308 | } |
309 | |
310 | /** |
311 | * restrict_link_by_key_or_keyring - Restrict additions to a ring of public |
312 | * keys using the restrict_key information stored in the ring. |
313 | * @dest_keyring: Keyring being linked to. |
314 | * @type: The type of key being added. |
315 | * @payload: The payload of the new key. |
316 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. |
317 | * |
318 | * Check the new certificate only against the key or keys passed in the data |
319 | * parameter. If one of those is the signing key and validates the new |
320 | * certificate, then mark the new certificate as being ok to link. |
321 | * |
322 | * Returns 0 if the new certificate was accepted, -ENOKEY if we |
323 | * couldn't find a matching parent certificate in the trusted list, |
324 | * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses |
325 | * unsupported crypto, or some other error if there is a matching certificate |
326 | * but the signature check cannot be performed. |
327 | */ |
328 | int restrict_link_by_key_or_keyring(struct key *dest_keyring, |
329 | const struct key_type *type, |
330 | const union key_payload *payload, |
331 | struct key *trusted) |
332 | { |
333 | return key_or_keyring_common(dest_keyring, type, payload, trusted, |
334 | check_dest: false); |
335 | } |
336 | |
337 | /** |
338 | * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of |
339 | * public keys using the restrict_key information stored in the ring. |
340 | * @dest_keyring: Keyring being linked to. |
341 | * @type: The type of key being added. |
342 | * @payload: The payload of the new key. |
343 | * @trusted: A key or ring of keys that can be used to vouch for the new cert. |
344 | * |
345 | * Check the new certificate against the key or keys passed in the data |
346 | * parameter and against the keys already linked to the destination keyring. If |
347 | * one of those is the signing key and validates the new certificate, then mark |
348 | * the new certificate as being ok to link. |
349 | * |
350 | * Returns 0 if the new certificate was accepted, -ENOKEY if we |
351 | * couldn't find a matching parent certificate in the trusted list, |
352 | * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses |
353 | * unsupported crypto, or some other error if there is a matching certificate |
354 | * but the signature check cannot be performed. |
355 | */ |
356 | int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, |
357 | const struct key_type *type, |
358 | const union key_payload *payload, |
359 | struct key *trusted) |
360 | { |
361 | return key_or_keyring_common(dest_keyring, type, payload, trusted, |
362 | check_dest: true); |
363 | } |
364 | |