Branch data Line data Source code
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 : 0 : static int __init ca_keys_setup(char *str)
25 : : {
26 [ # # ]: 0 : if (!str) /* default system keyring */
27 : : return 1;
28 : :
29 [ # # ]: 0 : if (strncmp(str, "id:", 3) == 0) {
30 : : struct asymmetric_key_id *p = &cakey.id;
31 : 0 : size_t hexlen = (strlen(str) - 3) / 2;
32 : : int ret;
33 : :
34 [ # # ]: 0 : if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
35 : 0 : pr_err("Missing or invalid ca_keys id\n");
36 : 0 : return 1;
37 : : }
38 : :
39 : 0 : ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
40 [ # # ]: 0 : if (ret < 0)
41 : 0 : pr_err("Unparsable ca_keys id hex string\n");
42 : : else
43 : 0 : ca_keyid = p; /* owner key 'id:xxxxxx' */
44 [ # # ]: 0 : } else if (strcmp(str, "builtin") == 0) {
45 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (!trust_keyring)
82 : : return -ENOKEY;
83 : :
84 [ # # ]: 0 : if (type != &key_type_asymmetric)
85 : : return -EOPNOTSUPP;
86 : :
87 : 0 : sig = payload->data[asym_auth];
88 [ # # ]: 0 : if (!sig)
89 : : return -ENOPKG;
90 [ # # # # ]: 0 : if (!sig->auth_ids[0] && !sig->auth_ids[1])
91 : : return -ENOKEY;
92 : :
93 [ # # # # ]: 0 : if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
94 : : return -EPERM;
95 : :
96 : : /* See if we have a key that signed this one. */
97 : 0 : key = find_asymmetric_key(trust_keyring,
98 : 0 : sig->auth_ids[0], sig->auth_ids[1],
99 : : false);
100 [ # # ]: 0 : if (IS_ERR(key))
101 : : return -ENOKEY;
102 : :
103 [ # # # # ]: 0 : if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
104 : : ret = -ENOKEY;
105 : : else
106 : 0 : ret = verify_signature(key, sig);
107 : 0 : key_put(key);
108 : 0 : return ret;
109 : : }
110 : :
111 : 0 : static bool match_either_id(const struct asymmetric_key_ids *pair,
112 : : const struct asymmetric_key_id *single)
113 : : {
114 [ # # # # ]: 0 : return (asymmetric_key_id_same(pair->id[0], single) ||
115 : 0 : asymmetric_key_id_same(pair->id[1], single));
116 : : }
117 : :
118 : 0 : static int key_or_keyring_common(struct key *dest_keyring,
119 : : const struct key_type *type,
120 : : const union key_payload *payload,
121 : : struct key *trusted, bool check_dest)
122 : : {
123 : : const struct public_key_signature *sig;
124 : : struct key *key = NULL;
125 : : int ret;
126 : :
127 : : pr_devel("==>%s()\n", __func__);
128 : :
129 [ # # ]: 0 : if (!dest_keyring)
130 : : return -ENOKEY;
131 [ # # ]: 0 : else if (dest_keyring->type != &key_type_keyring)
132 : : return -EOPNOTSUPP;
133 : :
134 [ # # ]: 0 : if (!trusted && !check_dest)
135 : : return -ENOKEY;
136 : :
137 [ # # ]: 0 : if (type != &key_type_asymmetric)
138 : : return -EOPNOTSUPP;
139 : :
140 : 0 : sig = payload->data[asym_auth];
141 [ # # ]: 0 : if (!sig)
142 : : return -ENOPKG;
143 [ # # # # ]: 0 : if (!sig->auth_ids[0] && !sig->auth_ids[1])
144 : : return -ENOKEY;
145 : :
146 [ # # ]: 0 : if (trusted) {
147 [ # # ]: 0 : if (trusted->type == &key_type_keyring) {
148 : : /* See if we have a key that signed this one. */
149 : 0 : key = find_asymmetric_key(trusted, sig->auth_ids[0],
150 : 0 : sig->auth_ids[1], false);
151 [ # # ]: 0 : if (IS_ERR(key))
152 : : key = NULL;
153 [ # # ]: 0 : } else if (trusted->type == &key_type_asymmetric) {
154 : : const struct asymmetric_key_ids *signer_ids;
155 : :
156 : : signer_ids = asymmetric_key_ids(trusted);
157 : :
158 : : /*
159 : : * The auth_ids come from the candidate key (the
160 : : * one that is being considered for addition to
161 : : * dest_keyring) and identify the key that was
162 : : * used to sign.
163 : : *
164 : : * The signer_ids are identifiers for the
165 : : * signing key specified for dest_keyring.
166 : : *
167 : : * The first auth_id is the preferred id, and
168 : : * the second is the fallback. If only one
169 : : * auth_id is present, it may match against
170 : : * either signer_id. If two auth_ids are
171 : : * present, the first auth_id must match one
172 : : * signer_id and the second auth_id must match
173 : : * the second signer_id.
174 : : */
175 [ # # # # ]: 0 : if (!sig->auth_ids[0] || !sig->auth_ids[1]) {
176 : : const struct asymmetric_key_id *auth_id;
177 : :
178 [ # # ]: 0 : auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];
179 [ # # ]: 0 : if (match_either_id(signer_ids, auth_id))
180 : : key = __key_get(trusted);
181 : :
182 [ # # ]: 0 : } else if (asymmetric_key_id_same(signer_ids->id[1],
183 [ # # ]: 0 : sig->auth_ids[1]) &&
184 : 0 : match_either_id(signer_ids,
185 : 0 : sig->auth_ids[0])) {
186 : : key = __key_get(trusted);
187 : : }
188 : : } else {
189 : : return -EOPNOTSUPP;
190 : : }
191 : : }
192 : :
193 [ # # ]: 0 : if (check_dest && !key) {
194 : : /* See if the destination has a key that signed this one. */
195 : 0 : key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],
196 : 0 : sig->auth_ids[1], false);
197 [ # # ]: 0 : if (IS_ERR(key))
198 : : key = NULL;
199 : : }
200 : :
201 [ # # ]: 0 : if (!key)
202 : : return -ENOKEY;
203 : :
204 : 0 : ret = key_validate(key);
205 [ # # ]: 0 : if (ret == 0)
206 : 0 : ret = verify_signature(key, sig);
207 : :
208 : 0 : key_put(key);
209 : 0 : return ret;
210 : : }
211 : :
212 : : /**
213 : : * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
214 : : * keys using the restrict_key information stored in the ring.
215 : : * @dest_keyring: Keyring being linked to.
216 : : * @type: The type of key being added.
217 : : * @payload: The payload of the new key.
218 : : * @trusted: A key or ring of keys that can be used to vouch for the new cert.
219 : : *
220 : : * Check the new certificate only against the key or keys passed in the data
221 : : * parameter. If one of those is the signing key and validates the new
222 : : * certificate, then mark the new certificate as being ok to link.
223 : : *
224 : : * Returns 0 if the new certificate was accepted, -ENOKEY if we
225 : : * couldn't find a matching parent certificate in the trusted list,
226 : : * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
227 : : * unsupported crypto, or some other error if there is a matching certificate
228 : : * but the signature check cannot be performed.
229 : : */
230 : 0 : int restrict_link_by_key_or_keyring(struct key *dest_keyring,
231 : : const struct key_type *type,
232 : : const union key_payload *payload,
233 : : struct key *trusted)
234 : : {
235 : 0 : return key_or_keyring_common(dest_keyring, type, payload, trusted,
236 : : false);
237 : : }
238 : :
239 : : /**
240 : : * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of
241 : : * public keys using the restrict_key information stored in the ring.
242 : : * @dest_keyring: Keyring being linked to.
243 : : * @type: The type of key being added.
244 : : * @payload: The payload of the new key.
245 : : * @trusted: A key or ring of keys that can be used to vouch for the new cert.
246 : : *
247 : : * Check the new certificate only against the key or keys passed in the data
248 : : * parameter. If one of those is the signing key and validates the new
249 : : * certificate, then mark the new certificate as being ok to link.
250 : : *
251 : : * Returns 0 if the new certificate was accepted, -ENOKEY if we
252 : : * couldn't find a matching parent certificate in the trusted list,
253 : : * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
254 : : * unsupported crypto, or some other error if there is a matching certificate
255 : : * but the signature check cannot be performed.
256 : : */
257 : 0 : int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,
258 : : const struct key_type *type,
259 : : const union key_payload *payload,
260 : : struct key *trusted)
261 : : {
262 : 0 : return key_or_keyring_common(dest_keyring, type, payload, trusted,
263 : : true);
264 : : }
|