aboutsummaryrefslogtreecommitdiffstats
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
parent6204e0025566ad3992ce649d4f44b7e8cdde2293 (diff)
parent7d2ce2320e8efdc4a6dcbae7b329ed3f0d1cd778 (diff)
Merge remote-tracking branch 'integrity/next-with-keys' into keys-next
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--Documentation/kernel-parameters.txt5
-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
-rw-r--r--include/keys/system_keyring.h10
-rw-r--r--include/linux/key.h1
-rw-r--r--kernel/system_keyring.c1
-rw-r--r--security/integrity/digsig.c28
-rw-r--r--security/integrity/ima/Kconfig10
-rw-r--r--security/integrity/ima/ima.h12
-rw-r--r--security/integrity/ima/ima_main.c10
-rw-r--r--security/integrity/integrity.h5
-rw-r--r--security/keys/keyctl.c6
13 files changed, 225 insertions, 25 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8b2ab548b6e4..90c12c591168 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -566,6 +566,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
566 possible to determine what the correct size should be. 566 possible to determine what the correct size should be.
567 This option provides an override for these situations. 567 This option provides an override for these situations.
568 568
569 ca_keys= [KEYS] This parameter identifies a specific key(s) on
570 the system trusted keyring to be used for certificate
571 trust validation.
572 format: { id:<keyid> | builtin }
573
569 ccw_timeout_log [S390] 574 ccw_timeout_log [S390]
570 See Documentation/s390/CommonIO for details. 575 See Documentation/s390/CommonIO for details.
571 576
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 */
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 8dabc399bd1d..72665eb80692 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -17,7 +17,15 @@
17#include <linux/key.h> 17#include <linux/key.h>
18 18
19extern struct key *system_trusted_keyring; 19extern struct key *system_trusted_keyring;
20 20static inline struct key *get_system_trusted_keyring(void)
21{
22 return system_trusted_keyring;
23}
24#else
25static inline struct key *get_system_trusted_keyring(void)
26{
27 return NULL;
28}
21#endif 29#endif
22 30
23#endif /* _KEYS_SYSTEM_KEYRING_H */ 31#endif /* _KEYS_SYSTEM_KEYRING_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index 017b0826642f..65316f7ae794 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -170,6 +170,7 @@ struct key {
170#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ 170#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
171#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ 171#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */
172#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ 172#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */
173#define KEY_FLAG_BUILTIN 10 /* set if key is builtin */
173 174
174 /* the key type and key description string 175 /* the key type and key description string
175 * - the desc is used to match a key against search criteria 176 * - the desc is used to match a key against search criteria
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
index 52ebc70263f4..875f64e8935b 100644
--- a/kernel/system_keyring.c
+++ b/kernel/system_keyring.c
@@ -89,6 +89,7 @@ static __init int load_system_certificate_list(void)
89 pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", 89 pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
90 PTR_ERR(key)); 90 PTR_ERR(key));
91 } else { 91 } else {
92 set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
92 pr_notice("Loaded X.509 cert '%s'\n", 93 pr_notice("Loaded X.509 cert '%s'\n",
93 key_ref_to_ptr(key)->description); 94 key_ref_to_ptr(key)->description);
94 key_ref_put(key); 95 key_ref_put(key);
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index b4af4ebc5be2..8d4fbff8b87c 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -13,7 +13,9 @@
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 14
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/sched.h>
16#include <linux/rbtree.h> 17#include <linux/rbtree.h>
18#include <linux/cred.h>
17#include <linux/key-type.h> 19#include <linux/key-type.h>
18#include <linux/digsig.h> 20#include <linux/digsig.h>
19 21
@@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX];
24static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { 26static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
25 "_evm", 27 "_evm",
26 "_module", 28 "_module",
29#ifndef CONFIG_IMA_TRUSTED_KEYRING
27 "_ima", 30 "_ima",
31#else
32 ".ima",
33#endif
28}; 34};
29 35
30int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 36int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
@@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
56 62
57 return -EOPNOTSUPP; 63 return -EOPNOTSUPP;
58} 64}
65
66int integrity_init_keyring(const unsigned int id)
67{
68 const struct cred *cred = current_cred();
69 int err = 0;
70
71 keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
72 KGIDT_INIT(0), cred,
73 ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
74 KEY_USR_VIEW | KEY_USR_READ |
75 KEY_USR_WRITE | KEY_USR_SEARCH),
76 KEY_ALLOC_NOT_IN_QUOTA, NULL);
77 if (!IS_ERR(keyring[id]))
78 set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
79 else {
80 err = PTR_ERR(keyring[id]);
81 pr_info("Can't allocate %s keyring (%d)\n",
82 keyring_name[id], err);
83 keyring[id] = NULL;
84 }
85 return err;
86}
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 81a27971d884..08758fbd496f 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -123,3 +123,13 @@ config IMA_APPRAISE
123 For more information on integrity appraisal refer to: 123 For more information on integrity appraisal refer to:
124 <http://linux-ima.sourceforge.net> 124 <http://linux-ima.sourceforge.net>
125 If unsure, say N. 125 If unsure, say N.
126
127config IMA_TRUSTED_KEYRING
128 bool "Require all keys on the .ima keyring be signed"
129 depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
130 depends on INTEGRITY_ASYMMETRIC_KEYS
131 select KEYS_DEBUG_PROC_KEYS
132 default y
133 help
134 This option requires that all keys added to the .ima
135 keyring be signed by a key on the system trusted keyring.
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index f79fa8be203c..c42056edfc97 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -249,4 +249,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
249 return -EINVAL; 249 return -EINVAL;
250} 250}
251#endif /* CONFIG_IMA_LSM_RULES */ 251#endif /* CONFIG_IMA_LSM_RULES */
252
253#ifdef CONFIG_IMA_TRUSTED_KEYRING
254static inline int ima_init_keyring(const unsigned int id)
255{
256 return integrity_init_keyring(id);
257}
258#else
259static inline int ima_init_keyring(const unsigned int id)
260{
261 return 0;
262}
263#endif /* CONFIG_IMA_TRUSTED_KEYRING */
252#endif 264#endif
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f474c608fa11..0d696431209c 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -325,8 +325,14 @@ static int __init init_ima(void)
325 325
326 hash_setup(CONFIG_IMA_DEFAULT_HASH); 326 hash_setup(CONFIG_IMA_DEFAULT_HASH);
327 error = ima_init(); 327 error = ima_init();
328 if (!error) 328 if (error)
329 ima_initialized = 1; 329 goto out;
330
331 error = ima_init_keyring(INTEGRITY_KEYRING_IMA);
332 if (error)
333 goto out;
334 ima_initialized = 1;
335out:
330 return error; 336 return error;
331} 337}
332 338
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 33c0a70f6b15..09c440d9aaee 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -124,6 +124,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
124int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 124int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
125 const char *digest, int digestlen); 125 const char *digest, int digestlen);
126 126
127int integrity_init_keyring(const unsigned int id);
127#else 128#else
128 129
129static inline int integrity_digsig_verify(const unsigned int id, 130static inline int integrity_digsig_verify(const unsigned int id,
@@ -133,6 +134,10 @@ static inline int integrity_digsig_verify(const unsigned int id,
133 return -EOPNOTSUPP; 134 return -EOPNOTSUPP;
134} 135}
135 136
137static inline int integrity_init_keyring(const unsigned int id)
138{
139 return 0;
140}
136#endif /* CONFIG_INTEGRITY_SIGNATURE */ 141#endif /* CONFIG_INTEGRITY_SIGNATURE */
137 142
138#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS 143#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index cd5bd0cef25d..8a8c23357291 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -37,8 +37,6 @@ static int key_get_type_from_user(char *type,
37 return ret; 37 return ret;
38 if (ret == 0 || ret >= len) 38 if (ret == 0 || ret >= len)
39 return -EINVAL; 39 return -EINVAL;
40 if (type[0] == '.')
41 return -EPERM;
42 type[len - 1] = '\0'; 40 type[len - 1] = '\0';
43 return 0; 41 return 0;
44} 42}
@@ -86,6 +84,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
86 if (!*description) { 84 if (!*description) {
87 kfree(description); 85 kfree(description);
88 description = NULL; 86 description = NULL;
87 } else if ((description[0] == '.') &&
88 (strncmp(type, "keyring", 7) == 0)) {
89 ret = -EPERM;
90 goto error2;
89 } 91 }
90 } 92 }
91 93