aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-07-22 16:54:43 -0400
committerDavid Howells <dhowells@redhat.com>2014-07-22 16:54:43 -0400
commit64724cfc6eea920dbaada14f0fb978b1dd31192d (patch)
treed2f491be07a05e2d96b5c8b8e5a0a878f285eb22 /crypto
parent6204e0025566ad3992ce649d4f44b7e8cdde2293 (diff)
parent7d2ce2320e8efdc4a6dcbae7b329ed3f0d1cd778 (diff)
Merge remote-tracking branch 'integrity/next-with-keys' into keys-next
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asymmetric_keys/asymmetric_keys.h2
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c51
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c109
3 files changed, 142 insertions, 20 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h
index 515b63430812..a63c551c6557 100644
--- a/crypto/asymmetric_keys/asymmetric_keys.h
+++ b/crypto/asymmetric_keys/asymmetric_keys.h
@@ -9,6 +9,8 @@
9 * 2 of the Licence, or (at your option) any later version. 9 * 2 of the Licence, or (at your option) any later version.
10 */ 10 */
11 11
12int asymmetric_keyid_match(const char *kid, const char *id);
13
12static inline const char *asymmetric_key_id(const struct key *key) 14static inline const char *asymmetric_key_id(const struct key *key)
13{ 15{
14 return key->type_data.p[1]; 16 return key->type_data.p[1];
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 21960a4e74e8..eb8cd46961a5 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -23,6 +23,35 @@ static LIST_HEAD(asymmetric_key_parsers);
23static DECLARE_RWSEM(asymmetric_key_parsers_sem); 23static DECLARE_RWSEM(asymmetric_key_parsers_sem);
24 24
25/* 25/*
26 * Match asymmetric key id with partial match
27 * @id: key id to match in a form "id:<id>"
28 */
29int asymmetric_keyid_match(const char *kid, const char *id)
30{
31 size_t idlen, kidlen;
32
33 if (!kid || !id)
34 return 0;
35
36 /* make it possible to use id as in the request: "id:<id>" */
37 if (strncmp(id, "id:", 3) == 0)
38 id += 3;
39
40 /* Anything after here requires a partial match on the ID string */
41 idlen = strlen(id);
42 kidlen = strlen(kid);
43 if (idlen > kidlen)
44 return 0;
45
46 kid += kidlen - idlen;
47 if (strcasecmp(id, kid) != 0)
48 return 0;
49
50 return 1;
51}
52EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
53
54/*
26 * Match asymmetric keys on (part of) their name 55 * Match asymmetric keys on (part of) their name
27 * We have some shorthand methods for matching keys. We allow: 56 * We have some shorthand methods for matching keys. We allow:
28 * 57 *
@@ -34,9 +63,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
34{ 63{
35 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); 64 const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
36 const char *spec = description; 65 const char *spec = description;
37 const char *id, *kid; 66 const char *id;
38 ptrdiff_t speclen; 67 ptrdiff_t speclen;
39 size_t idlen, kidlen;
40 68
41 if (!subtype || !spec || !*spec) 69 if (!subtype || !spec || !*spec)
42 return 0; 70 return 0;
@@ -55,23 +83,8 @@ static int asymmetric_key_match(const struct key *key, const void *description)
55 speclen = id - spec; 83 speclen = id - spec;
56 id++; 84 id++;
57 85
58 /* Anything after here requires a partial match on the ID string */ 86 if (speclen == 2 && memcmp(spec, "id", 2) == 0)
59 kid = asymmetric_key_id(key); 87 return asymmetric_keyid_match(asymmetric_key_id(key), id);
60 if (!kid)
61 return 0;
62
63 idlen = strlen(id);
64 kidlen = strlen(kid);
65 if (idlen > kidlen)
66 return 0;
67
68 kid += kidlen - idlen;
69 if (strcasecmp(id, kid) != 0)
70 return 0;
71
72 if (speclen == 2 &&
73 memcmp(spec, "id", 2) == 0)
74 return 1;
75 88
76 if (speclen == subtype->name_len && 89 if (speclen == subtype->name_len &&
77 memcmp(spec, subtype->name, speclen) == 0) 90 memcmp(spec, subtype->name, speclen) == 0)
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 3fc8a0634ed7..a0f7cd196c9b 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -18,11 +18,80 @@
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
27static bool use_builtin_keys;
28static char *ca_keyid;
29
30#ifndef MODULE
31static int __init ca_keys_setup(char *str)
32{
33 if (!str) /* default system keyring */
34 return 1;
35
36 if (strncmp(str, "id:", 3) == 0)
37 ca_keyid = str; /* owner key 'id:xxxxxx' */
38 else if (strcmp(str, "builtin") == 0)
39 use_builtin_keys = true;
40
41 return 1;
42}
43__setup("ca_keys=", ca_keys_setup);
44#endif
45
46/*
47 * Find a key in the given keyring by issuer and authority.
48 */
49static struct key *x509_request_asymmetric_key(struct key *keyring,
50 const char *signer,
51 size_t signer_len,
52 const char *authority,
53 size_t auth_len)
54{
55 key_ref_t key;
56 char *id;
57
58 /* Construct an identifier. */
59 id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
60 if (!id)
61 return ERR_PTR(-ENOMEM);
62
63 memcpy(id, signer, signer_len);
64 id[signer_len + 0] = ':';
65 id[signer_len + 1] = ' ';
66 memcpy(id + signer_len + 2, authority, auth_len);
67 id[signer_len + 2 + auth_len] = 0;
68
69 pr_debug("Look up: \"%s\"\n", id);
70
71 key = keyring_search(make_key_ref(keyring, 1),
72 &key_type_asymmetric, id);
73 if (IS_ERR(key))
74 pr_debug("Request for module key '%s' err %ld\n",
75 id, PTR_ERR(key));
76 kfree(id);
77
78 if (IS_ERR(key)) {
79 switch (PTR_ERR(key)) {
80 /* Hide some search errors */
81 case -EACCES:
82 case -ENOTDIR:
83 case -EAGAIN:
84 return ERR_PTR(-ENOKEY);
85 default:
86 return ERR_CAST(key);
87 }
88 }
89
90 pr_devel("<==%s() = 0 [%x]\n", __func__,
91 key_serial(key_ref_to_ptr(key)));
92 return key_ref_to_ptr(key);
93}
94
26/* 95/*
27 * Set up the signature parameters in an X.509 certificate. This involves 96 * Set up the signature parameters in an X.509 certificate. This involves
28 * digesting the signed data and extracting the signature. 97 * digesting the signed data and extracting the signature.
@@ -103,6 +172,40 @@ int x509_check_signature(const struct public_key *pub,
103EXPORT_SYMBOL_GPL(x509_check_signature); 172EXPORT_SYMBOL_GPL(x509_check_signature);
104 173
105/* 174/*
175 * Check the new certificate against the ones in the trust keyring. If one of
176 * those is the signing key and validates the new certificate, then mark the
177 * new certificate as being trusted.
178 *
179 * Return 0 if the new certificate was successfully validated, 1 if we couldn't
180 * find a matching parent certificate in the trusted list and an error if there
181 * is a matching certificate but the signature check fails.
182 */
183static int x509_validate_trust(struct x509_certificate *cert,
184 struct key *trust_keyring)
185{
186 struct key *key;
187 int ret = 1;
188
189 if (!trust_keyring)
190 return -EOPNOTSUPP;
191
192 if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid))
193 return -EPERM;
194
195 key = x509_request_asymmetric_key(trust_keyring,
196 cert->issuer, strlen(cert->issuer),
197 cert->authority,
198 strlen(cert->authority));
199 if (!IS_ERR(key)) {
200 if (!use_builtin_keys
201 || test_bit(KEY_FLAG_BUILTIN, &key->flags))
202 ret = x509_check_signature(key->payload.data, cert);
203 key_put(key);
204 }
205 return ret;
206}
207
208/*
106 * Attempt to parse a data blob for a key as an X509 certificate. 209 * Attempt to parse a data blob for a key as an X509 certificate.
107 */ 210 */
108static int x509_key_preparse(struct key_preparsed_payload *prep) 211static int x509_key_preparse(struct key_preparsed_payload *prep)
@@ -155,9 +258,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 */ 258 /* Check the signature on the key if it appears to be self-signed */
156 if (!cert->authority || 259 if (!cert->authority ||
157 strcmp(cert->fingerprint, cert->authority) == 0) { 260 strcmp(cert->fingerprint, cert->authority) == 0) {
158 ret = x509_check_signature(cert->pub, cert); 261 ret = x509_check_signature(cert->pub, cert); /* self-signed */
159 if (ret < 0) 262 if (ret < 0)
160 goto error_free_cert; 263 goto error_free_cert;
264 } else if (!prep->trusted) {
265 ret = x509_validate_trust(cert, get_system_trusted_keyring());
266 if (!ret)
267 prep->trusted = 1;
161 } 268 }
162 269
163 /* Propose a description */ 270 /* Propose a description */