aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2013-08-20 14:36:27 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-25 12:17:01 -0400
commit09fbc47373826d67531380662b516de2da120545 (patch)
tree4f2828a7114313c70eec4cef99f893dbe67c762b /crypto
parentaf34cb0c3d16b46d88b661692b885d1d998a8ecb (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. Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index c1540e8f454a..87612642f1b1 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,12 +18,60 @@
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(
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 * Set up the signature parameters in an X.509 certificate. This involves 75 * Set up the signature parameters in an X.509 certificate. This involves
28 * digesting the signed data and extracting the signature. 76 * digesting the signed data and extracting the signature.
29 */ 77 */
@@ -103,6 +151,33 @@ int x509_check_signature(const struct public_key *pub,
103EXPORT_SYMBOL_GPL(x509_check_signature); 151EXPORT_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 */
162static 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 * Attempt to parse a data blob for a key as an X509 certificate. 181 * Attempt to parse a data blob for a key as an X509 certificate.
107 */ 182 */
108static int x509_key_preparse(struct key_preparsed_payload *prep) 183static int x509_key_preparse(struct key_preparsed_payload *prep)
@@ -155,9 +230,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 */ 230 /* Check the signature on the key if it appears to be self-signed */
156 if (!cert->authority || 231 if (!cert->authority ||
157 strcmp(cert->fingerprint, cert->authority) == 0) { 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 if (ret < 0) 234 if (ret < 0)
160 goto error_free_cert; 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 /* Propose a description */ 242 /* Propose a description */