Commit 09fbc47373826d67531380662b516de2da120545
Committed by
David Howells
1 parent
af34cb0c3d
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
KEYS: verify a certificate is signed by a 'trusted' key
Only public keys, with certificates signed by an existing 'trusted' key on the system trusted keyring, should be added to a trusted keyring. This patch adds support for verifying a certificate's signature. This is derived from David Howells pkcs7_request_asymmetric_key() patch. Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: David Howells <dhowells@redhat.com>
Showing 1 changed file with 80 additions and 1 deletions Side-by-side Diff
crypto/asymmetric_keys/x509_public_key.c
... | ... | @@ -18,12 +18,60 @@ |
18 | 18 | #include <linux/asn1_decoder.h> |
19 | 19 | #include <keys/asymmetric-subtype.h> |
20 | 20 | #include <keys/asymmetric-parser.h> |
21 | +#include <keys/system_keyring.h> | |
21 | 22 | #include <crypto/hash.h> |
22 | 23 | #include "asymmetric_keys.h" |
23 | 24 | #include "public_key.h" |
24 | 25 | #include "x509_parser.h" |
25 | 26 | |
26 | 27 | /* |
28 | + * Find a key in the given keyring by issuer and authority. | |
29 | + */ | |
30 | +static struct key *x509_request_asymmetric_key( | |
31 | + struct key *keyring, | |
32 | + const char *signer, size_t signer_len, | |
33 | + const char *authority, size_t auth_len) | |
34 | +{ | |
35 | + key_ref_t key; | |
36 | + char *id; | |
37 | + | |
38 | + /* Construct an identifier. */ | |
39 | + id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); | |
40 | + if (!id) | |
41 | + return ERR_PTR(-ENOMEM); | |
42 | + | |
43 | + memcpy(id, signer, signer_len); | |
44 | + id[signer_len + 0] = ':'; | |
45 | + id[signer_len + 1] = ' '; | |
46 | + memcpy(id + signer_len + 2, authority, auth_len); | |
47 | + id[signer_len + 2 + auth_len] = 0; | |
48 | + | |
49 | + pr_debug("Look up: \"%s\"\n", id); | |
50 | + | |
51 | + key = keyring_search(make_key_ref(keyring, 1), | |
52 | + &key_type_asymmetric, id); | |
53 | + if (IS_ERR(key)) | |
54 | + pr_debug("Request for module key '%s' err %ld\n", | |
55 | + id, PTR_ERR(key)); | |
56 | + kfree(id); | |
57 | + | |
58 | + if (IS_ERR(key)) { | |
59 | + switch (PTR_ERR(key)) { | |
60 | + /* Hide some search errors */ | |
61 | + case -EACCES: | |
62 | + case -ENOTDIR: | |
63 | + case -EAGAIN: | |
64 | + return ERR_PTR(-ENOKEY); | |
65 | + default: | |
66 | + return ERR_CAST(key); | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); | |
71 | + return key_ref_to_ptr(key); | |
72 | +} | |
73 | + | |
74 | +/* | |
27 | 75 | * Set up the signature parameters in an X.509 certificate. This involves |
28 | 76 | * digesting the signed data and extracting the signature. |
29 | 77 | */ |
... | ... | @@ -103,6 +151,33 @@ |
103 | 151 | EXPORT_SYMBOL_GPL(x509_check_signature); |
104 | 152 | |
105 | 153 | /* |
154 | + * Check the new certificate against the ones in the trust keyring. If one of | |
155 | + * those is the signing key and validates the new certificate, then mark the | |
156 | + * new certificate as being trusted. | |
157 | + * | |
158 | + * Return 0 if the new certificate was successfully validated, 1 if we couldn't | |
159 | + * find a matching parent certificate in the trusted list and an error if there | |
160 | + * is a matching certificate but the signature check fails. | |
161 | + */ | |
162 | +static int x509_validate_trust(struct x509_certificate *cert, | |
163 | + struct key *trust_keyring) | |
164 | +{ | |
165 | + const struct public_key *pk; | |
166 | + struct key *key; | |
167 | + int ret = 1; | |
168 | + | |
169 | + key = x509_request_asymmetric_key(trust_keyring, | |
170 | + cert->issuer, strlen(cert->issuer), | |
171 | + cert->authority, | |
172 | + strlen(cert->authority)); | |
173 | + if (!IS_ERR(key)) { | |
174 | + pk = key->payload.data; | |
175 | + ret = x509_check_signature(pk, cert); | |
176 | + } | |
177 | + return ret; | |
178 | +} | |
179 | + | |
180 | +/* | |
106 | 181 | * Attempt to parse a data blob for a key as an X509 certificate. |
107 | 182 | */ |
108 | 183 | static int x509_key_preparse(struct key_preparsed_payload *prep) |
109 | 184 | |
... | ... | @@ -155,9 +230,13 @@ |
155 | 230 | /* Check the signature on the key if it appears to be self-signed */ |
156 | 231 | if (!cert->authority || |
157 | 232 | strcmp(cert->fingerprint, cert->authority) == 0) { |
158 | - ret = x509_check_signature(cert->pub, cert); | |
233 | + ret = x509_check_signature(cert->pub, cert); /* self-signed */ | |
159 | 234 | if (ret < 0) |
160 | 235 | goto error_free_cert; |
236 | + } else { | |
237 | + ret = x509_validate_trust(cert, system_trusted_keyring); | |
238 | + if (!ret) | |
239 | + prep->trusted = 1; | |
161 | 240 | } |
162 | 241 | |
163 | 242 | /* Propose a description */ |