Blame view

certs/system_keyring.c 8.74 KB
b4d0d230c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
b56e5a17b   David Howells   KEYS: Separate th...
2
3
4
5
  /* System trusted keyring for trusted public keys
   *
   * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
b56e5a17b   David Howells   KEYS: Separate th...
6
7
8
9
10
11
12
   */
  
  #include <linux/export.h>
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/cred.h>
  #include <linux/err.h>
2b6aa412f   Mat Martineau   KEYS: Use structu...
13
  #include <linux/slab.h>
817aef260   Yannik Sembritzki   Replace magic for...
14
  #include <linux/verification.h>
b56e5a17b   David Howells   KEYS: Separate th...
15
16
  #include <keys/asymmetric-type.h>
  #include <keys/system_keyring.h>
091f6e26e   David Howells   MODSIGN: Extract ...
17
  #include <crypto/pkcs7.h>
b56e5a17b   David Howells   KEYS: Separate th...
18

d3bfe8412   David Howells   certs: Add a seco...
19
20
21
22
  static struct key *builtin_trusted_keys;
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  static struct key *secondary_trusted_keys;
  #endif
219a3e867   Kairui Song   integrity, KEYS: ...
23
24
25
  #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
  static struct key *platform_trusted_keys;
  #endif
b56e5a17b   David Howells   KEYS: Separate th...
26
27
  
  extern __initconst const u8 system_certificate_list[];
62226983d   Hendrik Brueckner   KEYS: correct ali...
28
  extern __initconst const unsigned long system_certificate_list_size;
b56e5a17b   David Howells   KEYS: Separate th...
29

a511e1af8   David Howells   KEYS: Move the po...
30
  /**
d3bfe8412   David Howells   certs: Add a seco...
31
   * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
a511e1af8   David Howells   KEYS: Move the po...
32
33
   *
   * Restrict the addition of keys into a keyring based on the key-to-be-added
d3bfe8412   David Howells   certs: Add a seco...
34
   * being vouched for by a key in the built in system keyring.
a511e1af8   David Howells   KEYS: Move the po...
35
   */
aaf66c883   Mat Martineau   KEYS: Split role ...
36
  int restrict_link_by_builtin_trusted(struct key *dest_keyring,
a511e1af8   David Howells   KEYS: Move the po...
37
  				     const struct key_type *type,
aaf66c883   Mat Martineau   KEYS: Split role ...
38
39
  				     const union key_payload *payload,
  				     struct key *restriction_key)
a511e1af8   David Howells   KEYS: Move the po...
40
  {
aaf66c883   Mat Martineau   KEYS: Split role ...
41
42
  	return restrict_link_by_signature(dest_keyring, type, payload,
  					  builtin_trusted_keys);
a511e1af8   David Howells   KEYS: Move the po...
43
  }
d3bfe8412   David Howells   certs: Add a seco...
44
45
46
47
48
49
50
51
52
53
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  /**
   * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
   *   addition by both builtin and secondary keyrings
   *
   * Restrict the addition of keys into a keyring based on the key-to-be-added
   * being vouched for by a key in either the built-in or the secondary system
   * keyrings.
   */
  int restrict_link_by_builtin_and_secondary_trusted(
aaf66c883   Mat Martineau   KEYS: Split role ...
54
  	struct key *dest_keyring,
d3bfe8412   David Howells   certs: Add a seco...
55
  	const struct key_type *type,
aaf66c883   Mat Martineau   KEYS: Split role ...
56
57
  	const union key_payload *payload,
  	struct key *restrict_key)
d3bfe8412   David Howells   certs: Add a seco...
58
59
60
61
62
  {
  	/* If we have a secondary trusted keyring, then that contains a link
  	 * through to the builtin keyring and the search will follow that link.
  	 */
  	if (type == &key_type_keyring &&
aaf66c883   Mat Martineau   KEYS: Split role ...
63
  	    dest_keyring == secondary_trusted_keys &&
d3bfe8412   David Howells   certs: Add a seco...
64
65
66
  	    payload == &builtin_trusted_keys->payload)
  		/* Allow the builtin keyring to be added to the secondary */
  		return 0;
aaf66c883   Mat Martineau   KEYS: Split role ...
67
68
  	return restrict_link_by_signature(dest_keyring, type, payload,
  					  secondary_trusted_keys);
d3bfe8412   David Howells   certs: Add a seco...
69
  }
2b6aa412f   Mat Martineau   KEYS: Use structu...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  
  /**
   * Allocate a struct key_restriction for the "builtin and secondary trust"
   * keyring. Only for use in system_trusted_keyring_init().
   */
  static __init struct key_restriction *get_builtin_and_secondary_restriction(void)
  {
  	struct key_restriction *restriction;
  
  	restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
  
  	if (!restriction)
  		panic("Can't allocate secondary trusted keyring restriction
  ");
  
  	restriction->check = restrict_link_by_builtin_and_secondary_trusted;
  
  	return restriction;
  }
d3bfe8412   David Howells   certs: Add a seco...
89
  #endif
b56e5a17b   David Howells   KEYS: Separate th...
90
  /*
d3bfe8412   David Howells   certs: Add a seco...
91
   * Create the trusted keyrings
b56e5a17b   David Howells   KEYS: Separate th...
92
93
94
   */
  static __init int system_trusted_keyring_init(void)
  {
d3bfe8412   David Howells   certs: Add a seco...
95
96
  	pr_notice("Initialise system trusted keyrings
  ");
b56e5a17b   David Howells   KEYS: Separate th...
97

d3bfe8412   David Howells   certs: Add a seco...
98
99
  	builtin_trusted_keys =
  		keyring_alloc(".builtin_trusted_keys",
b56e5a17b   David Howells   KEYS: Separate th...
100
  			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
028db3e29   Linus Torvalds   Revert "Merge tag...
101
102
103
  			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
  			      KEY_ALLOC_NOT_IN_QUOTA,
d3bfe8412   David Howells   certs: Add a seco...
104
105
106
107
108
109
110
111
112
  			      NULL, NULL);
  	if (IS_ERR(builtin_trusted_keys))
  		panic("Can't allocate builtin trusted keyring
  ");
  
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  	secondary_trusted_keys =
  		keyring_alloc(".secondary_trusted_keys",
  			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
028db3e29   Linus Torvalds   Revert "Merge tag...
113
114
115
116
  			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
  			       KEY_USR_WRITE),
  			      KEY_ALLOC_NOT_IN_QUOTA,
2b6aa412f   Mat Martineau   KEYS: Use structu...
117
  			      get_builtin_and_secondary_restriction(),
d3bfe8412   David Howells   certs: Add a seco...
118
119
120
121
122
123
124
125
126
  			      NULL);
  	if (IS_ERR(secondary_trusted_keys))
  		panic("Can't allocate secondary trusted keyring
  ");
  
  	if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0)
  		panic("Can't link trusted keyrings
  ");
  #endif
b56e5a17b   David Howells   KEYS: Separate th...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  	return 0;
  }
  
  /*
   * Must be initialised before we try and load the keys into the keyring.
   */
  device_initcall(system_trusted_keyring_init);
  
  /*
   * Load the compiled-in list of X.509 certificates.
   */
  static __init int load_system_certificate_list(void)
  {
  	key_ref_t key;
  	const u8 *p, *end;
  	size_t plen;
  
  	pr_notice("Loading compiled-in X.509 certificates
  ");
b56e5a17b   David Howells   KEYS: Separate th...
146
  	p = system_certificate_list;
62226983d   Hendrik Brueckner   KEYS: correct ali...
147
  	end = p + system_certificate_list_size;
b56e5a17b   David Howells   KEYS: Separate th...
148
149
150
151
152
153
154
155
156
157
158
159
160
  	while (p < end) {
  		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
  		 * than 256 bytes in size.
  		 */
  		if (end - p < 4)
  			goto dodgy_cert;
  		if (p[0] != 0x30 &&
  		    p[1] != 0x82)
  			goto dodgy_cert;
  		plen = (p[2] << 8) | p[3];
  		plen += 4;
  		if (plen > end - p)
  			goto dodgy_cert;
d3bfe8412   David Howells   certs: Add a seco...
161
  		key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
b56e5a17b   David Howells   KEYS: Separate th...
162
163
164
165
  					   "asymmetric",
  					   NULL,
  					   p,
  					   plen,
028db3e29   Linus Torvalds   Revert "Merge tag...
166
167
  					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  					   KEY_USR_VIEW | KEY_USR_READ),
008643b86   David Howells   KEYS: Add a 'trus...
168
  					   KEY_ALLOC_NOT_IN_QUOTA |
5ac7eace2   David Howells   KEYS: Add a facil...
169
170
  					   KEY_ALLOC_BUILT_IN |
  					   KEY_ALLOC_BYPASS_RESTRICTION);
b56e5a17b   David Howells   KEYS: Separate th...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  		if (IS_ERR(key)) {
  			pr_err("Problem loading in-kernel X.509 certificate (%ld)
  ",
  			       PTR_ERR(key));
  		} else {
  			pr_notice("Loaded X.509 cert '%s'
  ",
  				  key_ref_to_ptr(key)->description);
  			key_ref_put(key);
  		}
  		p += plen;
  	}
  
  	return 0;
  
  dodgy_cert:
  	pr_err("Problem parsing in-kernel X.509 certificate list
  ");
  	return 0;
  }
  late_initcall(load_system_certificate_list);
091f6e26e   David Howells   MODSIGN: Extract ...
192
193
194
195
  
  #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
  
  /**
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
196
   * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
e68503bd6   David Howells   KEYS: Generalise ...
197
   * @data: The data to be verified (NULL if expecting internal data).
091f6e26e   David Howells   MODSIGN: Extract ...
198
   * @len: Size of @data.
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
199
   * @pkcs7: The PKCS#7 message that is the signature.
d3bfe8412   David Howells   certs: Add a seco...
200
201
   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
   *					(void *)1UL for all trusted keys).
99db44350   David Howells   PKCS#7: Appropria...
202
   * @usage: The use to which the key is being put.
e68503bd6   David Howells   KEYS: Generalise ...
203
204
   * @view_content: Callback to gain access to content.
   * @ctx: Context for callback.
091f6e26e   David Howells   MODSIGN: Extract ...
205
   */
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
206
207
208
209
210
211
212
213
  int verify_pkcs7_message_sig(const void *data, size_t len,
  			     struct pkcs7_message *pkcs7,
  			     struct key *trusted_keys,
  			     enum key_being_used_for usage,
  			     int (*view_content)(void *ctx,
  						 const void *data, size_t len,
  						 size_t asn1hdrlen),
  			     void *ctx)
091f6e26e   David Howells   MODSIGN: Extract ...
214
  {
091f6e26e   David Howells   MODSIGN: Extract ...
215
  	int ret;
091f6e26e   David Howells   MODSIGN: Extract ...
216
  	/* The data should be detached - so we need to supply it. */
e68503bd6   David Howells   KEYS: Generalise ...
217
  	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
091f6e26e   David Howells   MODSIGN: Extract ...
218
219
220
221
222
  		pr_err("PKCS#7 signature with non-detached data
  ");
  		ret = -EBADMSG;
  		goto error;
  	}
99db44350   David Howells   PKCS#7: Appropria...
223
  	ret = pkcs7_verify(pkcs7, usage);
091f6e26e   David Howells   MODSIGN: Extract ...
224
225
  	if (ret < 0)
  		goto error;
d3bfe8412   David Howells   certs: Add a seco...
226
227
  	if (!trusted_keys) {
  		trusted_keys = builtin_trusted_keys;
817aef260   Yannik Sembritzki   Replace magic for...
228
  	} else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) {
d3bfe8412   David Howells   certs: Add a seco...
229
230
231
232
233
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  		trusted_keys = secondary_trusted_keys;
  #else
  		trusted_keys = builtin_trusted_keys;
  #endif
278311e41   Kairui Song   kexec, KEYS: Make...
234
235
236
237
238
239
240
241
242
243
244
245
  	} else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
  #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
  		trusted_keys = platform_trusted_keys;
  #else
  		trusted_keys = NULL;
  #endif
  		if (!trusted_keys) {
  			ret = -ENOKEY;
  			pr_devel("PKCS#7 platform keyring is not available
  ");
  			goto error;
  		}
d3bfe8412   David Howells   certs: Add a seco...
246
  	}
bda850cd2   David Howells   PKCS#7: Make trus...
247
248
249
  	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
  	if (ret < 0) {
  		if (ret == -ENOKEY)
278311e41   Kairui Song   kexec, KEYS: Make...
250
251
  			pr_devel("PKCS#7 signature not signed with a trusted key
  ");
e68503bd6   David Howells   KEYS: Generalise ...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  		goto error;
  	}
  
  	if (view_content) {
  		size_t asn1hdrlen;
  
  		ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
  		if (ret < 0) {
  			if (ret == -ENODATA)
  				pr_devel("PKCS#7 message does not contain data
  ");
  			goto error;
  		}
  
  		ret = view_content(ctx, data, len, asn1hdrlen);
091f6e26e   David Howells   MODSIGN: Extract ...
267
268
269
  	}
  
  error:
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  	pr_devel("<==%s() = %d
  ", __func__, ret);
  	return ret;
  }
  
  /**
   * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
   * @data: The data to be verified (NULL if expecting internal data).
   * @len: Size of @data.
   * @raw_pkcs7: The PKCS#7 message that is the signature.
   * @pkcs7_len: The size of @raw_pkcs7.
   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
   *					(void *)1UL for all trusted keys).
   * @usage: The use to which the key is being put.
   * @view_content: Callback to gain access to content.
   * @ctx: Context for callback.
   */
  int verify_pkcs7_signature(const void *data, size_t len,
  			   const void *raw_pkcs7, size_t pkcs7_len,
  			   struct key *trusted_keys,
  			   enum key_being_used_for usage,
  			   int (*view_content)(void *ctx,
  					       const void *data, size_t len,
  					       size_t asn1hdrlen),
  			   void *ctx)
  {
  	struct pkcs7_message *pkcs7;
  	int ret;
  
  	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
  	if (IS_ERR(pkcs7))
  		return PTR_ERR(pkcs7);
  
  	ret = verify_pkcs7_message_sig(data, len, pkcs7, trusted_keys, usage,
  				       view_content, ctx);
091f6e26e   David Howells   MODSIGN: Extract ...
305
306
307
308
309
  	pkcs7_free_message(pkcs7);
  	pr_devel("<==%s() = %d
  ", __func__, ret);
  	return ret;
  }
e68503bd6   David Howells   KEYS: Generalise ...
310
  EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
091f6e26e   David Howells   MODSIGN: Extract ...
311
312
  
  #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
219a3e867   Kairui Song   integrity, KEYS: ...
313
314
315
316
317
318
319
  
  #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
  void __init set_platform_trusted_keys(struct key *keyring)
  {
  	platform_trusted_keys = keyring;
  }
  #endif