diff options
-rw-r--r-- | certs/system_keyring.c | 20 | ||||
-rw-r--r-- | crypto/asymmetric_keys/restrict.c | 62 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 21 | ||||
-rw-r--r-- | include/crypto/public_key.h | 7 | ||||
-rw-r--r-- | include/keys/system_keyring.h | 19 | ||||
-rw-r--r-- | kernel/module_signing.c | 2 | ||||
-rw-r--r-- | security/integrity/digsig.c | 33 | ||||
-rw-r--r-- | security/integrity/ima/ima_mok.c | 6 |
9 files changed, 100 insertions, 76 deletions
diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 417d65882870..4e2fa8ab01d6 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c | |||
@@ -18,12 +18,26 @@ | |||
18 | #include <keys/system_keyring.h> | 18 | #include <keys/system_keyring.h> |
19 | #include <crypto/pkcs7.h> | 19 | #include <crypto/pkcs7.h> |
20 | 20 | ||
21 | struct key *system_trusted_keyring; | 21 | static struct key *system_trusted_keyring; |
22 | EXPORT_SYMBOL_GPL(system_trusted_keyring); | ||
23 | 22 | ||
24 | extern __initconst const u8 system_certificate_list[]; | 23 | extern __initconst const u8 system_certificate_list[]; |
25 | extern __initconst const unsigned long system_certificate_list_size; | 24 | extern __initconst const unsigned long system_certificate_list_size; |
26 | 25 | ||
26 | /** | ||
27 | * restrict_link_by_builtin_trusted - Restrict keyring addition by system CA | ||
28 | * | ||
29 | * Restrict the addition of keys into a keyring based on the key-to-be-added | ||
30 | * being vouched for by a key in the system keyring. | ||
31 | */ | ||
32 | int restrict_link_by_builtin_trusted(struct key *keyring, | ||
33 | const struct key_type *type, | ||
34 | unsigned long flags, | ||
35 | const union key_payload *payload) | ||
36 | { | ||
37 | return restrict_link_by_signature(system_trusted_keyring, | ||
38 | type, payload); | ||
39 | } | ||
40 | |||
27 | /* | 41 | /* |
28 | * Load the compiled-in keys | 42 | * Load the compiled-in keys |
29 | */ | 43 | */ |
@@ -37,7 +51,7 @@ static __init int system_trusted_keyring_init(void) | |||
37 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | 51 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | |
38 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), | 52 | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), |
39 | KEY_ALLOC_NOT_IN_QUOTA, | 53 | KEY_ALLOC_NOT_IN_QUOTA, |
40 | keyring_restrict_trusted_only, NULL); | 54 | restrict_link_by_builtin_trusted, NULL); |
41 | if (IS_ERR(system_trusted_keyring)) | 55 | if (IS_ERR(system_trusted_keyring)) |
42 | panic("Can't allocate system trusted keyring\n"); | 56 | panic("Can't allocate system trusted keyring\n"); |
43 | return 0; | 57 | return 0; |
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c index b4c10f2f5034..ac4bddf669de 100644 --- a/crypto/asymmetric_keys/restrict.c +++ b/crypto/asymmetric_keys/restrict.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Instantiate a public key crypto key from an X.509 Certificate | 1 | /* Instantiate a public key crypto key from an X.509 Certificate |
2 | * | 2 | * |
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -9,20 +9,12 @@ | |||
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 | ||
12 | #define pr_fmt(fmt) "X.509: "fmt | 12 | #define pr_fmt(fmt) "ASYM: "fmt |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/err.h> | 15 | #include <linux/err.h> |
17 | #include <linux/mpi.h> | ||
18 | #include <linux/asn1_decoder.h> | ||
19 | #include <keys/asymmetric-subtype.h> | ||
20 | #include <keys/asymmetric-parser.h> | ||
21 | #include <keys/system_keyring.h> | ||
22 | #include <crypto/hash.h> | ||
23 | #include <crypto/public_key.h> | 16 | #include <crypto/public_key.h> |
24 | #include "asymmetric_keys.h" | 17 | #include "asymmetric_keys.h" |
25 | #include "x509_parser.h" | ||
26 | 18 | ||
27 | static bool use_builtin_keys; | 19 | static bool use_builtin_keys; |
28 | static struct asymmetric_key_id *ca_keyid; | 20 | static struct asymmetric_key_id *ca_keyid; |
@@ -62,45 +54,55 @@ static int __init ca_keys_setup(char *str) | |||
62 | __setup("ca_keys=", ca_keys_setup); | 54 | __setup("ca_keys=", ca_keys_setup); |
63 | #endif | 55 | #endif |
64 | 56 | ||
65 | /* | 57 | /** |
58 | * restrict_link_by_signature - Restrict additions to a ring of public keys | ||
59 | * @trust_keyring: A ring of keys that can be used to vouch for the new cert. | ||
60 | * @type: The type of key being added. | ||
61 | * @payload: The payload of the new key. | ||
62 | * | ||
66 | * Check the new certificate against the ones in the trust keyring. If one of | 63 | * Check the new certificate against the ones in the trust keyring. If one of |
67 | * those is the signing key and validates the new certificate, then mark the | 64 | * those is the signing key and validates the new certificate, then mark the |
68 | * new certificate as being trusted. | 65 | * new certificate as being trusted. |
69 | * | 66 | * |
70 | * Return 0 if the new certificate was successfully validated, 1 if we couldn't | 67 | * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a |
71 | * find a matching parent certificate in the trusted list and an error if there | 68 | * matching parent certificate in the trusted list, -EKEYREJECTED if the |
72 | * is a matching certificate but the signature check fails. | 69 | * signature check fails or the key is blacklisted and some other error if |
70 | * there is a matching certificate but the signature check cannot be performed. | ||
73 | */ | 71 | */ |
74 | int x509_validate_trust(struct x509_certificate *cert, | 72 | int restrict_link_by_signature(struct key *trust_keyring, |
75 | struct key *trust_keyring) | 73 | const struct key_type *type, |
74 | const union key_payload *payload) | ||
76 | { | 75 | { |
77 | struct public_key_signature *sig = cert->sig; | 76 | const struct public_key_signature *sig; |
78 | struct key *key; | 77 | struct key *key; |
79 | int ret = 1; | 78 | int ret; |
80 | 79 | ||
81 | if (!sig->auth_ids[0] && !sig->auth_ids[1]) | 80 | pr_devel("==>%s()\n", __func__); |
82 | return 1; | ||
83 | 81 | ||
84 | if (!trust_keyring) | 82 | if (!trust_keyring) |
83 | return -ENOKEY; | ||
84 | |||
85 | if (type != &key_type_asymmetric) | ||
85 | return -EOPNOTSUPP; | 86 | return -EOPNOTSUPP; |
87 | |||
88 | sig = payload->data[asym_auth]; | ||
89 | if (!sig->auth_ids[0] && !sig->auth_ids[1]) | ||
90 | return 0; | ||
91 | |||
86 | if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) | 92 | if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) |
87 | return -EPERM; | 93 | return -EPERM; |
88 | if (cert->unsupported_sig) | ||
89 | return -ENOPKG; | ||
90 | 94 | ||
95 | /* See if we have a key that signed this one. */ | ||
91 | key = find_asymmetric_key(trust_keyring, | 96 | key = find_asymmetric_key(trust_keyring, |
92 | sig->auth_ids[0], sig->auth_ids[1], | 97 | sig->auth_ids[0], sig->auth_ids[1], |
93 | false); | 98 | false); |
94 | if (IS_ERR(key)) | 99 | if (IS_ERR(key)) |
95 | return PTR_ERR(key); | 100 | return -ENOKEY; |
96 | 101 | ||
97 | if (!use_builtin_keys || | 102 | if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) |
98 | test_bit(KEY_FLAG_BUILTIN, &key->flags)) { | 103 | ret = -ENOKEY; |
99 | ret = verify_signature(key, cert->sig); | 104 | else |
100 | if (ret == -ENOPKG) | 105 | ret = verify_signature(key, sig); |
101 | cert->unsupported_sig = true; | ||
102 | } | ||
103 | key_put(key); | 106 | key_put(key); |
104 | return ret; | 107 | return ret; |
105 | } | 108 | } |
106 | EXPORT_SYMBOL_GPL(x509_validate_trust); | ||
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 7a802b09a509..05eef1c68881 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h | |||
@@ -58,9 +58,3 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen, | |||
58 | */ | 58 | */ |
59 | extern int x509_get_sig_params(struct x509_certificate *cert); | 59 | extern int x509_get_sig_params(struct x509_certificate *cert); |
60 | extern int x509_check_for_self_signed(struct x509_certificate *cert); | 60 | extern int x509_check_for_self_signed(struct x509_certificate *cert); |
61 | |||
62 | /* | ||
63 | * public_key_trust.c | ||
64 | */ | ||
65 | extern int x509_validate_trust(struct x509_certificate *cert, | ||
66 | struct key *trust_keyring); | ||
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 6d7f42f0de9a..fb732296cd36 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
@@ -178,31 +178,12 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
178 | 178 | ||
179 | cert->pub->id_type = "X509"; | 179 | cert->pub->id_type = "X509"; |
180 | 180 | ||
181 | /* See if we can derive the trustability of this certificate. | 181 | if (cert->unsupported_sig) { |
182 | * | ||
183 | * When it comes to self-signed certificates, we cannot evaluate | ||
184 | * trustedness except by the fact that we obtained it from a trusted | ||
185 | * location. So we just rely on x509_validate_trust() failing in this | ||
186 | * case. | ||
187 | * | ||
188 | * Note that there's a possibility of a self-signed cert matching a | ||
189 | * cert that we have (most likely a duplicate that we already trust) - | ||
190 | * in which case it will be marked trusted. | ||
191 | */ | ||
192 | if (cert->unsupported_sig || cert->self_signed) { | ||
193 | public_key_signature_free(cert->sig); | 182 | public_key_signature_free(cert->sig); |
194 | cert->sig = NULL; | 183 | cert->sig = NULL; |
195 | } else { | 184 | } else { |
196 | pr_devel("Cert Signature: %s + %s\n", | 185 | pr_devel("Cert Signature: %s + %s\n", |
197 | cert->sig->pkey_algo, cert->sig->hash_algo); | 186 | cert->sig->pkey_algo, cert->sig->hash_algo); |
198 | |||
199 | ret = x509_validate_trust(cert, get_system_trusted_keyring()); | ||
200 | if (ret) | ||
201 | ret = x509_validate_trust(cert, get_ima_mok_keyring()); | ||
202 | if (ret == -EKEYREJECTED) | ||
203 | goto error_free_cert; | ||
204 | if (!ret) | ||
205 | prep->trusted = true; | ||
206 | } | 187 | } |
207 | 188 | ||
208 | /* Propose a description */ | 189 | /* Propose a description */ |
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 96ef27b8dd41..882ca0e1e7a5 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h | |||
@@ -47,6 +47,13 @@ extern void public_key_signature_free(struct public_key_signature *sig); | |||
47 | extern struct asymmetric_key_subtype public_key_subtype; | 47 | extern struct asymmetric_key_subtype public_key_subtype; |
48 | 48 | ||
49 | struct key; | 49 | struct key; |
50 | struct key_type; | ||
51 | union key_payload; | ||
52 | |||
53 | extern int restrict_link_by_signature(struct key *trust_keyring, | ||
54 | const struct key_type *type, | ||
55 | const union key_payload *payload); | ||
56 | |||
50 | extern int verify_signature(const struct key *key, | 57 | extern int verify_signature(const struct key *key, |
51 | const struct public_key_signature *sig); | 58 | const struct public_key_signature *sig); |
52 | 59 | ||
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index b2d645ac35a0..93715913a0b1 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h | |||
@@ -12,22 +12,17 @@ | |||
12 | #ifndef _KEYS_SYSTEM_KEYRING_H | 12 | #ifndef _KEYS_SYSTEM_KEYRING_H |
13 | #define _KEYS_SYSTEM_KEYRING_H | 13 | #define _KEYS_SYSTEM_KEYRING_H |
14 | 14 | ||
15 | #include <linux/key.h> | ||
16 | |||
15 | #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING | 17 | #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING |
16 | 18 | ||
17 | #include <linux/key.h> | 19 | extern int restrict_link_by_builtin_trusted(struct key *keyring, |
18 | #include <linux/verification.h> | 20 | const struct key_type *type, |
19 | #include <crypto/public_key.h> | 21 | unsigned long flags, |
22 | const union key_payload *payload); | ||
20 | 23 | ||
21 | extern struct key *system_trusted_keyring; | ||
22 | static inline struct key *get_system_trusted_keyring(void) | ||
23 | { | ||
24 | return system_trusted_keyring; | ||
25 | } | ||
26 | #else | 24 | #else |
27 | static inline struct key *get_system_trusted_keyring(void) | 25 | #define restrict_link_by_builtin_trusted restrict_link_reject |
28 | { | ||
29 | return NULL; | ||
30 | } | ||
31 | #endif | 26 | #endif |
32 | 27 | ||
33 | #ifdef CONFIG_IMA_MOK_KEYRING | 28 | #ifdef CONFIG_IMA_MOK_KEYRING |
diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 6a64e03b9f44..937c844bee4a 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
15 | #include <keys/system_keyring.h> | 15 | #include <linux/verification.h> |
16 | #include <crypto/public_key.h> | 16 | #include <crypto/public_key.h> |
17 | #include "module-internal.h" | 17 | #include "module-internal.h" |
18 | 18 | ||
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 659566c2200b..d647178c6bbd 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/cred.h> | 18 | #include <linux/cred.h> |
19 | #include <linux/key-type.h> | 19 | #include <linux/key-type.h> |
20 | #include <linux/digsig.h> | 20 | #include <linux/digsig.h> |
21 | #include <crypto/public_key.h> | ||
22 | #include <keys/system_keyring.h> | ||
21 | 23 | ||
22 | #include "integrity.h" | 24 | #include "integrity.h" |
23 | 25 | ||
@@ -40,6 +42,35 @@ static bool init_keyring __initdata = true; | |||
40 | static bool init_keyring __initdata; | 42 | static bool init_keyring __initdata; |
41 | #endif | 43 | #endif |
42 | 44 | ||
45 | #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING | ||
46 | /* | ||
47 | * Restrict the addition of keys into the IMA keyring. | ||
48 | * | ||
49 | * Any key that needs to go in .ima keyring must be signed by CA in | ||
50 | * either .system or .ima_mok keyrings. | ||
51 | */ | ||
52 | static int restrict_link_by_ima_mok(struct key *keyring, | ||
53 | const struct key_type *type, | ||
54 | unsigned long flags, | ||
55 | const union key_payload *payload) | ||
56 | { | ||
57 | int ret; | ||
58 | |||
59 | ret = restrict_link_by_builtin_trusted(keyring, type, flags, payload); | ||
60 | if (ret != -ENOKEY) | ||
61 | return ret; | ||
62 | |||
63 | return restrict_link_by_signature(get_ima_mok_keyring(), | ||
64 | type, payload); | ||
65 | } | ||
66 | #else | ||
67 | /* | ||
68 | * If there's no system trusted keyring, then keys cannot be loaded into | ||
69 | * .ima_mok and added keys cannot be marked trusted. | ||
70 | */ | ||
71 | #define restrict_link_by_ima_mok restrict_link_reject | ||
72 | #endif | ||
73 | |||
43 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 74 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
44 | const char *digest, int digestlen) | 75 | const char *digest, int digestlen) |
45 | { | 76 | { |
@@ -84,7 +115,7 @@ int __init integrity_init_keyring(const unsigned int id) | |||
84 | KEY_USR_VIEW | KEY_USR_READ | | 115 | KEY_USR_VIEW | KEY_USR_READ | |
85 | KEY_USR_WRITE | KEY_USR_SEARCH), | 116 | KEY_USR_WRITE | KEY_USR_SEARCH), |
86 | KEY_ALLOC_NOT_IN_QUOTA, | 117 | KEY_ALLOC_NOT_IN_QUOTA, |
87 | NULL, NULL); | 118 | restrict_link_by_ima_mok, NULL); |
88 | if (IS_ERR(keyring[id])) { | 119 | if (IS_ERR(keyring[id])) { |
89 | err = PTR_ERR(keyring[id]); | 120 | err = PTR_ERR(keyring[id]); |
90 | pr_info("Can't allocate %s keyring (%d)\n", | 121 | pr_info("Can't allocate %s keyring (%d)\n", |
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index ef91248cb934..2988726d30d6 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/cred.h> | 17 | #include <linux/cred.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <keys/asymmetric-type.h> | 20 | #include <keys/system_keyring.h> |
21 | 21 | ||
22 | 22 | ||
23 | struct key *ima_mok_keyring; | 23 | struct key *ima_mok_keyring; |
@@ -36,7 +36,7 @@ __init int ima_mok_init(void) | |||
36 | KEY_USR_VIEW | KEY_USR_READ | | 36 | KEY_USR_VIEW | KEY_USR_READ | |
37 | KEY_USR_WRITE | KEY_USR_SEARCH, | 37 | KEY_USR_WRITE | KEY_USR_SEARCH, |
38 | KEY_ALLOC_NOT_IN_QUOTA, | 38 | KEY_ALLOC_NOT_IN_QUOTA, |
39 | keyring_restrict_trusted_only, NULL); | 39 | restrict_link_by_builtin_trusted, NULL); |
40 | 40 | ||
41 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", | 41 | ima_blacklist_keyring = keyring_alloc(".ima_blacklist", |
42 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), | 42 | KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), |
@@ -44,7 +44,7 @@ __init int ima_mok_init(void) | |||
44 | KEY_USR_VIEW | KEY_USR_READ | | 44 | KEY_USR_VIEW | KEY_USR_READ | |
45 | KEY_USR_WRITE | KEY_USR_SEARCH, | 45 | KEY_USR_WRITE | KEY_USR_SEARCH, |
46 | KEY_ALLOC_NOT_IN_QUOTA, | 46 | KEY_ALLOC_NOT_IN_QUOTA, |
47 | keyring_restrict_trusted_only, NULL); | 47 | restrict_link_by_builtin_trusted, NULL); |
48 | 48 | ||
49 | if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) | 49 | if (IS_ERR(ima_mok_keyring) || IS_ERR(ima_blacklist_keyring)) |
50 | panic("Can't allocate IMA MOK or blacklist keyrings."); | 50 | panic("Can't allocate IMA MOK or blacklist keyrings."); |