aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2013-08-20 14:36:27 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2014-07-17 09:35:15 -0400
commit3be4beaf7c91ec9c6fefa5f11173af37113d10ae (patch)
treec4007c5fc0ddd6bccb279fbae8a5ee52f7af01de /crypto/asymmetric_keys
parenta4e3b8d79a5c6d40f4a9703abf7fe3abcc6c3b8d (diff)
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. Changelog v6: - on error free key - Dmitry - validate trust only for not already trusted keys - Dmitry - formatting cleanup Changelog: - define get_system_trusted_keyring() to fix kbuild issues Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 382ef0d2ff2e..436fbd8552fc 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,12 +18,62 @@
18#include <linux/asn1_decoder.h> 18#include <linux/asn1_decoder.h>
19#include <keys/asymmetric-subtype.h> 19#include <keys/asymmetric-subtype.h>
20#include <keys/asymmetric-parser.h> 20#include <keys/asymmetric-parser.h>
21#include <keys/system_keyring.h>
21#include <crypto/hash.h> 22#include <crypto/hash.h>
22#include "asymmetric_keys.h" 23#include "asymmetric_keys.h"
23#include "public_key.h" 24#include "public_key.h"
24#include "x509_parser.h" 25#include "x509_parser.h"
25 26
26/* 27/*
28 * Find a key in the given keyring by issuer and authority.
29 */
30static struct key *x509_request_asymmetric_key(struct key *keyring,
31 const char *signer,
32 size_t signer_len,
33 const char *authority,
34 size_t auth_len)
35{
36 key_ref_t key;
37 char *id;
38
39 /* Construct an identifier. */
40 id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
41 if (!id)
42 return ERR_PTR(-ENOMEM);
43
44 memcpy(id, signer, signer_len);
45 id[signer_len + 0] = ':';
46 id[signer_len + 1] = ' ';
47 memcpy(id + signer_len + 2, authority, auth_len);
48 id[signer_len + 2 + auth_len] = 0;
49
50 pr_debug("Look up: \"%s\"\n", id);
51
52 key = keyring_search(make_key_ref(keyring, 1),
53 &key_type_asymmetric, id);
54 if (IS_ERR(key))
55 pr_debug("Request for module key '%s' err %ld\n",
56 id, PTR_ERR(key));
57 kfree(id);
58
59 if (IS_ERR(key)) {
60 switch (PTR_ERR(key)) {
61 /* Hide some search errors */
62 case -EACCES:
63 case -ENOTDIR:
64 case -EAGAIN:
65 return ERR_PTR(-ENOKEY);
66 default:
67 return ERR_CAST(key);
68 }
69 }
70
71 pr_devel("<==%s() = 0 [%x]\n", __func__,
72 key_serial(key_ref_to_ptr(key)));
73 return key_ref_to_ptr(key);
74}
75
76/*
27 * Set up the signature parameters in an X.509 certificate. This involves 77 * Set up the signature parameters in an X.509 certificate. This involves
28 * digesting the signed data and extracting the signature. 78 * digesting the signed data and extracting the signature.
29 */ 79 */
@@ -103,6 +153,37 @@ int x509_check_signature(const struct public_key *pub,
103EXPORT_SYMBOL_GPL(x509_check_signature); 153EXPORT_SYMBOL_GPL(x509_check_signature);
104 154
105/* 155/*
156 * Check the new certificate against the ones in the trust keyring. If one of
157 * those is the signing key and validates the new certificate, then mark the
158 * new certificate as being trusted.
159 *
160 * Return 0 if the new certificate was successfully validated, 1 if we couldn't
161 * find a matching parent certificate in the trusted list and an error if there
162 * is a matching certificate but the signature check fails.
163 */
164static int x509_validate_trust(struct x509_certificate *cert,
165 struct key *trust_keyring)
166{
167 const struct public_key *pk;
168 struct key *key;
169 int ret = 1;
170
171 if (!trust_keyring)
172 return -EOPNOTSUPP;
173
174 key = x509_request_asymmetric_key(trust_keyring,
175 cert->issuer, strlen(cert->issuer),
176 cert->authority,
177 strlen(cert->authority));
178 if (!IS_ERR(key)) {
179 pk = key->payload.data;
180 ret = x509_check_signature(pk, cert);
181 key_put(key);
182 }
183 return ret;
184}
185
186/*
106 * Attempt to parse a data blob for a key as an X509 certificate. 187 * Attempt to parse a data blob for a key as an X509 certificate.
107 */ 188 */
108static int x509_key_preparse(struct key_preparsed_payload *prep) 189static int x509_key_preparse(struct key_preparsed_payload *prep)
@@ -155,9 +236,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
155 /* Check the signature on the key if it appears to be self-signed */ 236 /* Check the signature on the key if it appears to be self-signed */
156 if (!cert->authority || 237 if (!cert->authority ||
157 strcmp(cert->fingerprint, cert->authority) == 0) { 238 strcmp(cert->fingerprint, cert->authority) == 0) {
158 ret = x509_check_signature(cert->pub, cert); 239 ret = x509_check_signature(cert->pub, cert); /* self-signed */
159 if (ret < 0) 240 if (ret < 0)
160 goto error_free_cert; 241 goto error_free_cert;
242 } else if (!prep->trusted) {
243 ret = x509_validate_trust(cert, get_system_trusted_keyring());
244 if (!ret)
245 prep->trusted = 1;
161 } 246 }
162 247
163 /* Propose a description */ 248 /* Propose a description */