Blame view

crypto/asymmetric_keys/restrict.c 7.88 KB
b4d0d230c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
cfb664ff2   David Howells   X.509: Move the t...
2
3
  /* Instantiate a public key crypto key from an X.509 Certificate
   *
a511e1af8   David Howells   KEYS: Move the po...
4
   * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
cfb664ff2   David Howells   X.509: Move the t...
5
   * Written by David Howells (dhowells@redhat.com)
cfb664ff2   David Howells   X.509: Move the t...
6
   */
a511e1af8   David Howells   KEYS: Move the po...
7
  #define pr_fmt(fmt) "ASYM: "fmt
cfb664ff2   David Howells   X.509: Move the t...
8
9
  #include <linux/module.h>
  #include <linux/kernel.h>
cfb664ff2   David Howells   X.509: Move the t...
10
  #include <linux/err.h>
cfb664ff2   David Howells   X.509: Move the t...
11
12
  #include <crypto/public_key.h>
  #include "asymmetric_keys.h"
cfb664ff2   David Howells   X.509: Move the t...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  
  static bool use_builtin_keys;
  static struct asymmetric_key_id *ca_keyid;
  
  #ifndef MODULE
  static struct {
  	struct asymmetric_key_id id;
  	unsigned char data[10];
  } cakey;
  
  static int __init ca_keys_setup(char *str)
  {
  	if (!str)		/* default system keyring */
  		return 1;
  
  	if (strncmp(str, "id:", 3) == 0) {
  		struct asymmetric_key_id *p = &cakey.id;
  		size_t hexlen = (strlen(str) - 3) / 2;
  		int ret;
  
  		if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
  			pr_err("Missing or invalid ca_keys id
  ");
  			return 1;
  		}
  
  		ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
  		if (ret < 0)
  			pr_err("Unparsable ca_keys id hex string
  ");
  		else
  			ca_keyid = p;	/* owner key 'id:xxxxxx' */
  	} else if (strcmp(str, "builtin") == 0) {
  		use_builtin_keys = true;
  	}
  
  	return 1;
  }
  __setup("ca_keys=", ca_keys_setup);
  #endif
a511e1af8   David Howells   KEYS: Move the po...
53
54
  /**
   * restrict_link_by_signature - Restrict additions to a ring of public keys
aaf66c883   Mat Martineau   KEYS: Split role ...
55
   * @dest_keyring: Keyring being linked to.
a511e1af8   David Howells   KEYS: Move the po...
56
57
   * @type: The type of key being added.
   * @payload: The payload of the new key.
aaf66c883   Mat Martineau   KEYS: Split role ...
58
   * @trust_keyring: A ring of keys that can be used to vouch for the new cert.
a511e1af8   David Howells   KEYS: Move the po...
59
   *
cfb664ff2   David Howells   X.509: Move the t...
60
61
62
63
   * Check the new certificate against the ones in the trust keyring.  If one of
   * those is the signing key and validates the new certificate, then mark the
   * new certificate as being trusted.
   *
a511e1af8   David Howells   KEYS: Move the po...
64
65
   * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a
   * matching parent certificate in the trusted list, -EKEYREJECTED if the
4b34968e7   Eric Biggers   X.509: fix NULL d...
66
67
68
   * signature check fails or the key is blacklisted, -ENOPKG if the signature
   * uses unsupported crypto, or some other error if there is a matching
   * certificate but the signature check cannot be performed.
cfb664ff2   David Howells   X.509: Move the t...
69
   */
aaf66c883   Mat Martineau   KEYS: Split role ...
70
  int restrict_link_by_signature(struct key *dest_keyring,
a511e1af8   David Howells   KEYS: Move the po...
71
  			       const struct key_type *type,
aaf66c883   Mat Martineau   KEYS: Split role ...
72
73
  			       const union key_payload *payload,
  			       struct key *trust_keyring)
cfb664ff2   David Howells   X.509: Move the t...
74
  {
a511e1af8   David Howells   KEYS: Move the po...
75
  	const struct public_key_signature *sig;
cfb664ff2   David Howells   X.509: Move the t...
76
  	struct key *key;
a511e1af8   David Howells   KEYS: Move the po...
77
  	int ret;
cfb664ff2   David Howells   X.509: Move the t...
78

a511e1af8   David Howells   KEYS: Move the po...
79
80
  	pr_devel("==>%s()
  ", __func__);
cfb664ff2   David Howells   X.509: Move the t...
81
82
  
  	if (!trust_keyring)
a511e1af8   David Howells   KEYS: Move the po...
83
84
85
  		return -ENOKEY;
  
  	if (type != &key_type_asymmetric)
cfb664ff2   David Howells   X.509: Move the t...
86
  		return -EOPNOTSUPP;
a511e1af8   David Howells   KEYS: Move the po...
87
88
  
  	sig = payload->data[asym_auth];
4b34968e7   Eric Biggers   X.509: fix NULL d...
89
90
  	if (!sig)
  		return -ENOPKG;
a511e1af8   David Howells   KEYS: Move the po...
91
  	if (!sig->auth_ids[0] && !sig->auth_ids[1])
acddc7201   Mat Martineau   KEYS: Fix for err...
92
  		return -ENOKEY;
a511e1af8   David Howells   KEYS: Move the po...
93

cfb664ff2   David Howells   X.509: Move the t...
94
95
  	if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
  		return -EPERM;
cfb664ff2   David Howells   X.509: Move the t...
96

a511e1af8   David Howells   KEYS: Move the po...
97
  	/* See if we have a key that signed this one. */
cfb664ff2   David Howells   X.509: Move the t...
98
99
100
101
  	key = find_asymmetric_key(trust_keyring,
  				  sig->auth_ids[0], sig->auth_ids[1],
  				  false);
  	if (IS_ERR(key))
a511e1af8   David Howells   KEYS: Move the po...
102
  		return -ENOKEY;
cfb664ff2   David Howells   X.509: Move the t...
103

a511e1af8   David Howells   KEYS: Move the po...
104
105
106
107
  	if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
  		ret = -ENOKEY;
  	else
  		ret = verify_signature(key, sig);
cfb664ff2   David Howells   X.509: Move the t...
108
109
110
  	key_put(key);
  	return ret;
  }
7e3c4d220   Mat Martineau   KEYS: Restrict as...
111

8e323a02e   Mat Martineau   KEYS: Keyring asy...
112
113
114
115
116
117
118
119
120
121
122
  static bool match_either_id(const struct asymmetric_key_ids *pair,
  			    const struct asymmetric_key_id *single)
  {
  	return (asymmetric_key_id_same(pair->id[0], single) ||
  		asymmetric_key_id_same(pair->id[1], single));
  }
  
  static int key_or_keyring_common(struct key *dest_keyring,
  				 const struct key_type *type,
  				 const union key_payload *payload,
  				 struct key *trusted, bool check_dest)
7e3c4d220   Mat Martineau   KEYS: Restrict as...
123
124
  {
  	const struct public_key_signature *sig;
8e323a02e   Mat Martineau   KEYS: Keyring asy...
125
  	struct key *key = NULL;
7e3c4d220   Mat Martineau   KEYS: Restrict as...
126
127
128
129
130
131
132
133
134
  	int ret;
  
  	pr_devel("==>%s()
  ", __func__);
  
  	if (!dest_keyring)
  		return -ENOKEY;
  	else if (dest_keyring->type != &key_type_keyring)
  		return -EOPNOTSUPP;
8e323a02e   Mat Martineau   KEYS: Keyring asy...
135
  	if (!trusted && !check_dest)
7e3c4d220   Mat Martineau   KEYS: Restrict as...
136
137
138
139
140
141
  		return -ENOKEY;
  
  	if (type != &key_type_asymmetric)
  		return -EOPNOTSUPP;
  
  	sig = payload->data[asym_auth];
4b34968e7   Eric Biggers   X.509: fix NULL d...
142
143
  	if (!sig)
  		return -ENOPKG;
7e3c4d220   Mat Martineau   KEYS: Restrict as...
144
145
  	if (!sig->auth_ids[0] && !sig->auth_ids[1])
  		return -ENOKEY;
8e323a02e   Mat Martineau   KEYS: Keyring asy...
146
147
148
149
150
151
152
153
154
  	if (trusted) {
  		if (trusted->type == &key_type_keyring) {
  			/* See if we have a key that signed this one. */
  			key = find_asymmetric_key(trusted, sig->auth_ids[0],
  						  sig->auth_ids[1], false);
  			if (IS_ERR(key))
  				key = NULL;
  		} else if (trusted->type == &key_type_asymmetric) {
  			const struct asymmetric_key_ids *signer_ids;
7e3c4d220   Mat Martineau   KEYS: Restrict as...
155

8e323a02e   Mat Martineau   KEYS: Keyring asy...
156
  			signer_ids = asymmetric_key_ids(trusted);
7e3c4d220   Mat Martineau   KEYS: Restrict as...
157

8e323a02e   Mat Martineau   KEYS: Keyring asy...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  			/*
  			 * The auth_ids come from the candidate key (the
  			 * one that is being considered for addition to
  			 * dest_keyring) and identify the key that was
  			 * used to sign.
  			 *
  			 * The signer_ids are identifiers for the
  			 * signing key specified for dest_keyring.
  			 *
  			 * The first auth_id is the preferred id, and
  			 * the second is the fallback. If only one
  			 * auth_id is present, it may match against
  			 * either signer_id. If two auth_ids are
  			 * present, the first auth_id must match one
  			 * signer_id and the second auth_id must match
  			 * the second signer_id.
  			 */
  			if (!sig->auth_ids[0] || !sig->auth_ids[1]) {
  				const struct asymmetric_key_id *auth_id;
7e3c4d220   Mat Martineau   KEYS: Restrict as...
177

8e323a02e   Mat Martineau   KEYS: Keyring asy...
178
179
180
181
182
183
184
185
186
187
188
189
190
  				auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];
  				if (match_either_id(signer_ids, auth_id))
  					key = __key_get(trusted);
  
  			} else if (asymmetric_key_id_same(signer_ids->id[1],
  							  sig->auth_ids[1]) &&
  				   match_either_id(signer_ids,
  						   sig->auth_ids[0])) {
  				key = __key_get(trusted);
  			}
  		} else {
  			return -EOPNOTSUPP;
  		}
7e3c4d220   Mat Martineau   KEYS: Restrict as...
191
  	}
8e323a02e   Mat Martineau   KEYS: Keyring asy...
192
193
194
195
196
197
198
199
200
201
  	if (check_dest && !key) {
  		/* See if the destination has a key that signed this one. */
  		key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],
  					  sig->auth_ids[1], false);
  		if (IS_ERR(key))
  			key = NULL;
  	}
  
  	if (!key)
  		return -ENOKEY;
7e3c4d220   Mat Martineau   KEYS: Restrict as...
202
203
204
205
206
207
208
  	ret = key_validate(key);
  	if (ret == 0)
  		ret = verify_signature(key, sig);
  
  	key_put(key);
  	return ret;
  }
8e323a02e   Mat Martineau   KEYS: Keyring asy...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  
  /**
   * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
   * keys using the restrict_key information stored in the ring.
   * @dest_keyring: Keyring being linked to.
   * @type: The type of key being added.
   * @payload: The payload of the new key.
   * @trusted: A key or ring of keys that can be used to vouch for the new cert.
   *
   * Check the new certificate only against the key or keys passed in the data
   * parameter. If one of those is the signing key and validates the new
   * certificate, then mark the new certificate as being ok to link.
   *
   * Returns 0 if the new certificate was accepted, -ENOKEY if we
   * couldn't find a matching parent certificate in the trusted list,
4b34968e7   Eric Biggers   X.509: fix NULL d...
224
225
226
   * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
   * unsupported crypto, or some other error if there is a matching certificate
   * but the signature check cannot be performed.
8e323a02e   Mat Martineau   KEYS: Keyring asy...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
   */
  int restrict_link_by_key_or_keyring(struct key *dest_keyring,
  				    const struct key_type *type,
  				    const union key_payload *payload,
  				    struct key *trusted)
  {
  	return key_or_keyring_common(dest_keyring, type, payload, trusted,
  				     false);
  }
  
  /**
   * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of
   * public keys using the restrict_key information stored in the ring.
   * @dest_keyring: Keyring being linked to.
   * @type: The type of key being added.
   * @payload: The payload of the new key.
   * @trusted: A key or ring of keys that can be used to vouch for the new cert.
   *
40d32b59e   Andrew Zaborowski   keys: Update comm...
245
246
247
248
   * Check the new certificate against the key or keys passed in the data
   * parameter and against the keys already linked to the destination keyring. If
   * one of those is the signing key and validates the new certificate, then mark
   * the new certificate as being ok to link.
8e323a02e   Mat Martineau   KEYS: Keyring asy...
249
250
251
   *
   * Returns 0 if the new certificate was accepted, -ENOKEY if we
   * couldn't find a matching parent certificate in the trusted list,
4b34968e7   Eric Biggers   X.509: fix NULL d...
252
253
254
   * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
   * unsupported crypto, or some other error if there is a matching certificate
   * but the signature check cannot be performed.
8e323a02e   Mat Martineau   KEYS: Keyring asy...
255
256
257
258
259
260
261
262
263
   */
  int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,
  					  const struct key_type *type,
  					  const union key_payload *payload,
  					  struct key *trusted)
  {
  	return key_or_keyring_common(dest_keyring, type, payload, trusted,
  				     true);
  }