Blame view

certs/system_keyring.c 6.81 KB
b56e5a17b   David Howells   KEYS: Separate th...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /* System trusted keyring for trusted public keys
   *
   * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public Licence
   * as published by the Free Software Foundation; either version
   * 2 of the Licence, or (at your option) any later version.
   */
  
  #include <linux/export.h>
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/cred.h>
  #include <linux/err.h>
  #include <keys/asymmetric-type.h>
  #include <keys/system_keyring.h>
091f6e26e   David Howells   MODSIGN: Extract ...
19
  #include <crypto/pkcs7.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
b56e5a17b   David Howells   KEYS: Separate th...
25
26
  
  extern __initconst const u8 system_certificate_list[];
62226983d   Hendrik Brueckner   KEYS: correct ali...
27
  extern __initconst const unsigned long system_certificate_list_size;
b56e5a17b   David Howells   KEYS: Separate th...
28

a511e1af8   David Howells   KEYS: Move the po...
29
  /**
d3bfe8412   David Howells   certs: Add a seco...
30
   * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
a511e1af8   David Howells   KEYS: Move the po...
31
32
   *
   * Restrict the addition of keys into a keyring based on the key-to-be-added
d3bfe8412   David Howells   certs: Add a seco...
33
   * being vouched for by a key in the built in system keyring.
a511e1af8   David Howells   KEYS: Move the po...
34
35
36
   */
  int restrict_link_by_builtin_trusted(struct key *keyring,
  				     const struct key_type *type,
a511e1af8   David Howells   KEYS: Move the po...
37
38
  				     const union key_payload *payload)
  {
d3bfe8412   David Howells   certs: Add a seco...
39
  	return restrict_link_by_signature(builtin_trusted_keys, type, payload);
a511e1af8   David Howells   KEYS: Move the po...
40
  }
d3bfe8412   David Howells   certs: Add a seco...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  #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(
  	struct key *keyring,
  	const struct key_type *type,
  	const union key_payload *payload)
  {
  	/* 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 &&
  	    keyring == secondary_trusted_keys &&
  	    payload == &builtin_trusted_keys->payload)
  		/* Allow the builtin keyring to be added to the secondary */
  		return 0;
  
  	return restrict_link_by_signature(secondary_trusted_keys, type, payload);
  }
  #endif
b56e5a17b   David Howells   KEYS: Separate th...
67
  /*
d3bfe8412   David Howells   certs: Add a seco...
68
   * Create the trusted keyrings
b56e5a17b   David Howells   KEYS: Separate th...
69
70
71
   */
  static __init int system_trusted_keyring_init(void)
  {
d3bfe8412   David Howells   certs: Add a seco...
72
73
  	pr_notice("Initialise system trusted keyrings
  ");
b56e5a17b   David Howells   KEYS: Separate th...
74

d3bfe8412   David Howells   certs: Add a seco...
75
76
  	builtin_trusted_keys =
  		keyring_alloc(".builtin_trusted_keys",
b56e5a17b   David Howells   KEYS: Separate th...
77
78
  			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
  			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
af34cb0c3   Mimi Zohar   KEYS: Make the sy...
79
  			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
5ac7eace2   David Howells   KEYS: Add a facil...
80
  			      KEY_ALLOC_NOT_IN_QUOTA,
d3bfe8412   David Howells   certs: Add a seco...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  			      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(),
  			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
  			       KEY_USR_WRITE),
  			      KEY_ALLOC_NOT_IN_QUOTA,
  			      restrict_link_by_builtin_and_secondary_trusted,
  			      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...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  	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...
123
  	p = system_certificate_list;
62226983d   Hendrik Brueckner   KEYS: correct ali...
124
  	end = p + system_certificate_list_size;
b56e5a17b   David Howells   KEYS: Separate th...
125
126
127
128
129
130
131
132
133
134
135
136
137
  	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...
138
  		key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
b56e5a17b   David Howells   KEYS: Separate th...
139
140
141
142
  					   "asymmetric",
  					   NULL,
  					   p,
  					   plen,
af34cb0c3   Mimi Zohar   KEYS: Make the sy...
143
144
  					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  					   KEY_USR_VIEW | KEY_USR_READ),
008643b86   David Howells   KEYS: Add a 'trus...
145
  					   KEY_ALLOC_NOT_IN_QUOTA |
5ac7eace2   David Howells   KEYS: Add a facil...
146
147
  					   KEY_ALLOC_BUILT_IN |
  					   KEY_ALLOC_BYPASS_RESTRICTION);
b56e5a17b   David Howells   KEYS: Separate th...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  		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 ...
169
170
171
172
  
  #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
  
  /**
e68503bd6   David Howells   KEYS: Generalise ...
173
174
   * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
   * @data: The data to be verified (NULL if expecting internal data).
091f6e26e   David Howells   MODSIGN: Extract ...
175
176
177
   * @len: Size of @data.
   * @raw_pkcs7: The PKCS#7 message that is the signature.
   * @pkcs7_len: The size of @raw_pkcs7.
d3bfe8412   David Howells   certs: Add a seco...
178
179
   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
   *					(void *)1UL for all trusted keys).
99db44350   David Howells   PKCS#7: Appropria...
180
   * @usage: The use to which the key is being put.
e68503bd6   David Howells   KEYS: Generalise ...
181
182
   * @view_content: Callback to gain access to content.
   * @ctx: Context for callback.
091f6e26e   David Howells   MODSIGN: Extract ...
183
   */
e68503bd6   David Howells   KEYS: Generalise ...
184
185
186
  int verify_pkcs7_signature(const void *data, size_t len,
  			   const void *raw_pkcs7, size_t pkcs7_len,
  			   struct key *trusted_keys,
e68503bd6   David Howells   KEYS: Generalise ...
187
188
189
190
191
  			   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 ...
192
193
  {
  	struct pkcs7_message *pkcs7;
091f6e26e   David Howells   MODSIGN: Extract ...
194
195
196
197
198
199
200
  	int ret;
  
  	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
  	if (IS_ERR(pkcs7))
  		return PTR_ERR(pkcs7);
  
  	/* The data should be detached - so we need to supply it. */
e68503bd6   David Howells   KEYS: Generalise ...
201
  	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
091f6e26e   David Howells   MODSIGN: Extract ...
202
203
204
205
206
  		pr_err("PKCS#7 signature with non-detached data
  ");
  		ret = -EBADMSG;
  		goto error;
  	}
99db44350   David Howells   PKCS#7: Appropria...
207
  	ret = pkcs7_verify(pkcs7, usage);
091f6e26e   David Howells   MODSIGN: Extract ...
208
209
  	if (ret < 0)
  		goto error;
d3bfe8412   David Howells   certs: Add a seco...
210
211
212
213
214
215
216
217
218
  	if (!trusted_keys) {
  		trusted_keys = builtin_trusted_keys;
  	} else if (trusted_keys == (void *)1UL) {
  #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
  		trusted_keys = secondary_trusted_keys;
  #else
  		trusted_keys = builtin_trusted_keys;
  #endif
  	}
bda850cd2   David Howells   PKCS#7: Make trus...
219
220
221
222
223
  	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
  	if (ret < 0) {
  		if (ret == -ENOKEY)
  			pr_err("PKCS#7 signature not signed with a trusted key
  ");
e68503bd6   David Howells   KEYS: Generalise ...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  		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 ...
239
240
241
242
243
244
245
246
  	}
  
  error:
  	pkcs7_free_message(pkcs7);
  	pr_devel("<==%s() = %d
  ", __func__, ret);
  	return ret;
  }
e68503bd6   David Howells   KEYS: Generalise ...
247
  EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
091f6e26e   David Howells   MODSIGN: Extract ...
248
249
  
  #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */