Blame view

certs/system_keyring.c 8.49 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>
a6cb0ab7d   Mickaël Salaün   certs: Replace K{...
14
  #include <linux/uidgid.h>
817aef260   Yannik Sembritzki   Replace magic for...
15
  #include <linux/verification.h>
b56e5a17b   David Howells   KEYS: Separate th...
16
17
  #include <keys/asymmetric-type.h>
  #include <keys/system_keyring.h>
091f6e26e   David Howells   MODSIGN: Extract ...
18
  #include <crypto/pkcs7.h>
2565ca7f5   Eric Snowberg   certs: Move load_...
19
  #include "common.h"
b56e5a17b   David Howells   KEYS: Separate th...
20

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

a511e1af8   David Howells   KEYS: Move the po...
33
  /**
d3bfe8412   David Howells   certs: Add a seco...
34
   * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
a511e1af8   David Howells   KEYS: Move the po...
35
36
   *
   * Restrict the addition of keys into a keyring based on the key-to-be-added
d3bfe8412   David Howells   certs: Add a seco...
37
   * being vouched for by a key in the built in system keyring.
a511e1af8   David Howells   KEYS: Move the po...
38
   */
aaf66c883   Mat Martineau   KEYS: Split role ...
39
  int restrict_link_by_builtin_trusted(struct key *dest_keyring,
a511e1af8   David Howells   KEYS: Move the po...
40
  				     const struct key_type *type,
aaf66c883   Mat Martineau   KEYS: Split role ...
41
42
  				     const union key_payload *payload,
  				     struct key *restriction_key)
a511e1af8   David Howells   KEYS: Move the po...
43
  {
aaf66c883   Mat Martineau   KEYS: Split role ...
44
45
  	return restrict_link_by_signature(dest_keyring, type, payload,
  					  builtin_trusted_keys);
a511e1af8   David Howells   KEYS: Move the po...
46
  }
d3bfe8412   David Howells   certs: Add a seco...
47
48
49
50
51
52
53
54
55
56
  #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 ...
57
  	struct key *dest_keyring,
d3bfe8412   David Howells   certs: Add a seco...
58
  	const struct key_type *type,
aaf66c883   Mat Martineau   KEYS: Split role ...
59
60
  	const union key_payload *payload,
  	struct key *restrict_key)
d3bfe8412   David Howells   certs: Add a seco...
61
62
63
64
65
  {
  	/* 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 ...
66
  	    dest_keyring == secondary_trusted_keys &&
d3bfe8412   David Howells   certs: Add a seco...
67
68
69
  	    payload == &builtin_trusted_keys->payload)
  		/* Allow the builtin keyring to be added to the secondary */
  		return 0;
aaf66c883   Mat Martineau   KEYS: Split role ...
70
71
  	return restrict_link_by_signature(dest_keyring, type, payload,
  					  secondary_trusted_keys);
d3bfe8412   David Howells   certs: Add a seco...
72
  }
2b6aa412f   Mat Martineau   KEYS: Use structu...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  
  /**
   * 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...
92
  #endif
b56e5a17b   David Howells   KEYS: Separate th...
93
  /*
d3bfe8412   David Howells   certs: Add a seco...
94
   * Create the trusted keyrings
b56e5a17b   David Howells   KEYS: Separate th...
95
96
97
   */
  static __init int system_trusted_keyring_init(void)
  {
d3bfe8412   David Howells   certs: Add a seco...
98
99
  	pr_notice("Initialise system trusted keyrings
  ");
b56e5a17b   David Howells   KEYS: Separate th...
100

d3bfe8412   David Howells   certs: Add a seco...
101
102
  	builtin_trusted_keys =
  		keyring_alloc(".builtin_trusted_keys",
a6cb0ab7d   Mickaël Salaün   certs: Replace K{...
103
  			      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
028db3e29   Linus Torvalds   Revert "Merge tag...
104
105
106
  			      ((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...
107
108
109
110
111
112
113
114
  			      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",
a6cb0ab7d   Mickaël Salaün   certs: Replace K{...
115
  			      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
028db3e29   Linus Torvalds   Revert "Merge tag...
116
117
118
119
  			      ((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...
120
  			      get_builtin_and_secondary_restriction(),
d3bfe8412   David Howells   certs: Add a seco...
121
122
123
124
125
126
127
128
129
  			      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...
130
131
132
133
134
135
136
  	return 0;
  }
  
  /*
   * Must be initialised before we try and load the keys into the keyring.
   */
  device_initcall(system_trusted_keyring_init);
6cbdfb3d9   Nayna Jain   ima: enable loadi...
137
138
  __init int load_module_cert(struct key *keyring)
  {
6cbdfb3d9   Nayna Jain   ima: enable loadi...
139
140
141
142
143
  	if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG))
  		return 0;
  
  	pr_notice("Loading compiled-in module X.509 certificates
  ");
e6f0bf09f   Linus Torvalds   Merge tag 'integr...
144
  	return load_certificate_list(system_certificate_list, module_cert_size, keyring);
6cbdfb3d9   Nayna Jain   ima: enable loadi...
145
  }
b56e5a17b   David Howells   KEYS: Separate th...
146
147
148
149
150
  /*
   * Load the compiled-in list of X.509 certificates.
   */
  static __init int load_system_certificate_list(void)
  {
e6f0bf09f   Linus Torvalds   Merge tag 'integr...
151
  	const u8 *p;
6cbdfb3d9   Nayna Jain   ima: enable loadi...
152
  	unsigned long size;
b56e5a17b   David Howells   KEYS: Separate th...
153
154
  	pr_notice("Loading compiled-in X.509 certificates
  ");
6cbdfb3d9   Nayna Jain   ima: enable loadi...
155
156
157
158
159
160
161
  #ifdef CONFIG_MODULE_SIG
  	p = system_certificate_list;
  	size = system_certificate_list_size;
  #else
  	p = system_certificate_list + module_cert_size;
  	size = system_certificate_list_size - module_cert_size;
  #endif
e6f0bf09f   Linus Torvalds   Merge tag 'integr...
162
  	return load_certificate_list(p, size, builtin_trusted_keys);
b56e5a17b   David Howells   KEYS: Separate th...
163
164
  }
  late_initcall(load_system_certificate_list);
091f6e26e   David Howells   MODSIGN: Extract ...
165
166
167
168
  
  #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
  
  /**
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
169
   * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
e68503bd6   David Howells   KEYS: Generalise ...
170
   * @data: The data to be verified (NULL if expecting internal data).
091f6e26e   David Howells   MODSIGN: Extract ...
171
   * @len: Size of @data.
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
172
   * @pkcs7: The PKCS#7 message that is the signature.
d3bfe8412   David Howells   certs: Add a seco...
173
174
   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
   *					(void *)1UL for all trusted keys).
99db44350   David Howells   PKCS#7: Appropria...
175
   * @usage: The use to which the key is being put.
e68503bd6   David Howells   KEYS: Generalise ...
176
177
   * @view_content: Callback to gain access to content.
   * @ctx: Context for callback.
091f6e26e   David Howells   MODSIGN: Extract ...
178
   */
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
179
180
181
182
183
184
185
186
  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 ...
187
  {
091f6e26e   David Howells   MODSIGN: Extract ...
188
  	int ret;
091f6e26e   David Howells   MODSIGN: Extract ...
189
  	/* The data should be detached - so we need to supply it. */
e68503bd6   David Howells   KEYS: Generalise ...
190
  	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
091f6e26e   David Howells   MODSIGN: Extract ...
191
192
193
194
195
  		pr_err("PKCS#7 signature with non-detached data
  ");
  		ret = -EBADMSG;
  		goto error;
  	}
99db44350   David Howells   PKCS#7: Appropria...
196
  	ret = pkcs7_verify(pkcs7, usage);
091f6e26e   David Howells   MODSIGN: Extract ...
197
198
  	if (ret < 0)
  		goto error;
d3bfe8412   David Howells   certs: Add a seco...
199
200
  	if (!trusted_keys) {
  		trusted_keys = builtin_trusted_keys;
817aef260   Yannik Sembritzki   Replace magic for...
201
  	} else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) {
d3bfe8412   David Howells   certs: Add a seco...
202
203
204
205
206
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  		trusted_keys = secondary_trusted_keys;
  #else
  		trusted_keys = builtin_trusted_keys;
  #endif
278311e41   Kairui Song   kexec, KEYS: Make...
207
208
209
210
211
212
213
214
215
216
217
218
  	} 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;
  		}
56c581262   Eric Snowberg   certs: Add EFI_CE...
219
220
221
222
223
224
225
  
  		ret = is_key_on_revocation_list(pkcs7);
  		if (ret != -ENOKEY) {
  			pr_devel("PKCS#7 platform key is on revocation list
  ");
  			goto error;
  		}
d3bfe8412   David Howells   certs: Add a seco...
226
  	}
bda850cd2   David Howells   PKCS#7: Make trus...
227
228
229
  	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
  	if (ret < 0) {
  		if (ret == -ENOKEY)
278311e41   Kairui Song   kexec, KEYS: Make...
230
231
  			pr_devel("PKCS#7 signature not signed with a trusted key
  ");
e68503bd6   David Howells   KEYS: Generalise ...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  		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 ...
247
248
249
  	}
  
  error:
2a7bf6711   Thiago Jung Bauermann   PKCS#7: Refactor ...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  	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 ...
285
286
287
288
289
  	pkcs7_free_message(pkcs7);
  	pr_devel("<==%s() = %d
  ", __func__, ret);
  	return ret;
  }
e68503bd6   David Howells   KEYS: Generalise ...
290
  EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
091f6e26e   David Howells   MODSIGN: Extract ...
291
292
  
  #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
219a3e867   Kairui Song   integrity, KEYS: ...
293
294
295
296
297
298
299
  
  #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
  void __init set_platform_trusted_keys(struct key *keyring)
  {
  	platform_trusted_keys = keyring;
  }
  #endif