diff options
Diffstat (limited to 'keys-x509-improv.patch')
-rw-r--r-- | keys-x509-improv.patch | 1889 |
1 files changed, 0 insertions, 1889 deletions
diff --git a/keys-x509-improv.patch b/keys-x509-improv.patch deleted file mode 100644 index 161675819..000000000 --- a/keys-x509-improv.patch +++ /dev/null @@ -1,1889 +0,0 @@ -From db25f1d9f45079db5860c0fd1938032248ad2f06 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:15:10 +0100 -Subject: [PATCH 01/18] KEYS: Rename public key parameter name arrays - -Rename the arrays of public key parameters (public key algorithm names, hash -algorithm names and ID type names) so that the array name ends in "_name". - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/public_key.c | 14 +++++++------- - crypto/asymmetric_keys/x509_public_key.c | 8 ++++---- - include/crypto/public_key.h | 6 +++--- - kernel/module_signing.c | 4 ++-- - 4 files changed, 16 insertions(+), 16 deletions(-) - -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -index cb2e291..b313df1 100644 ---- a/crypto/asymmetric_keys/public_key.c -+++ b/crypto/asymmetric_keys/public_key.c -@@ -22,13 +22,13 @@ - - MODULE_LICENSE("GPL"); - --const char *const pkey_algo[PKEY_ALGO__LAST] = { -+const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = "DSA", - [PKEY_ALGO_RSA] = "RSA", - }; --EXPORT_SYMBOL_GPL(pkey_algo); -+EXPORT_SYMBOL_GPL(pkey_algo_name); - --const char *const pkey_hash_algo[PKEY_HASH__LAST] = { -+const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { - [PKEY_HASH_MD4] = "md4", - [PKEY_HASH_MD5] = "md5", - [PKEY_HASH_SHA1] = "sha1", -@@ -38,13 +38,13 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = { - [PKEY_HASH_SHA512] = "sha512", - [PKEY_HASH_SHA224] = "sha224", - }; --EXPORT_SYMBOL_GPL(pkey_hash_algo); -+EXPORT_SYMBOL_GPL(pkey_hash_algo_name); - --const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { -+const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { - [PKEY_ID_PGP] = "PGP", - [PKEY_ID_X509] = "X509", - }; --EXPORT_SYMBOL_GPL(pkey_id_type); -+EXPORT_SYMBOL_GPL(pkey_id_type_name); - - /* - * Provide a part of a description of the key for /proc/keys. -@@ -56,7 +56,7 @@ static void public_key_describe(const struct key *asymmetric_key, - - if (key) - seq_printf(m, "%s.%s", -- pkey_id_type[key->id_type], key->algo->name); -+ pkey_id_type_name[key->id_type], key->algo->name); - } - - /* -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 06007f0..afbbc36 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -49,7 +49,7 @@ static int x509_check_signature(const struct public_key *pub, - /* Allocate the hashing algorithm we're going to need and find out how - * big the hash operational data will be. - */ -- tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); -+ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); - if (IS_ERR(tfm)) - return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); - -@@ -117,7 +117,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); -- pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); -+ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); - pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, - cert->valid_from.tm_mday, cert->valid_from.tm_hour, -@@ -127,8 +127,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - cert->valid_to.tm_mday, cert->valid_to.tm_hour, - cert->valid_to.tm_min, cert->valid_to.tm_sec); - pr_devel("Cert Signature: %s + %s\n", -- pkey_algo[cert->sig_pkey_algo], -- pkey_hash_algo[cert->sig_hash_algo]); -+ pkey_algo_name[cert->sig_pkey_algo], -+ pkey_hash_algo_name[cert->sig_hash_algo]); - - if (!cert->fingerprint || !cert->authority) { - pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index f5b0224..619d570 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -22,7 +22,7 @@ enum pkey_algo { - PKEY_ALGO__LAST - }; - --extern const char *const pkey_algo[PKEY_ALGO__LAST]; -+extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; - - enum pkey_hash_algo { - PKEY_HASH_MD4, -@@ -36,7 +36,7 @@ enum pkey_hash_algo { - PKEY_HASH__LAST - }; - --extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; -+extern const char *const pkey_hash_algo_name[PKEY_HASH__LAST]; - - enum pkey_id_type { - PKEY_ID_PGP, /* OpenPGP generated key ID */ -@@ -44,7 +44,7 @@ enum pkey_id_type { - PKEY_ID_TYPE__LAST - }; - --extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; -+extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; - - /* - * Cryptographic data for the public-key subtype of the asymmetric key type. -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index f2970bd..ee47640 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -54,7 +54,7 @@ static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, - /* Allocate the hashing algorithm we're going to need and find out how - * big the hash operational data will be. - */ -- tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); -+ tfm = crypto_alloc_shash(pkey_hash_algo_name[hash], 0, 0); - if (IS_ERR(tfm)) - return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); - -@@ -217,7 +217,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) - return -ENOPKG; - - if (ms.hash >= PKEY_HASH__LAST || -- !pkey_hash_algo[ms.hash]) -+ !pkey_hash_algo_name[ms.hash]) - return -ENOPKG; - - key = request_asymmetric_key(sig, ms.signer_len, --- -1.8.3.1 - - -From 1881703e6a0943f5d45278d19ffc5268495f57a8 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:15:18 +0100 -Subject: [PATCH 02/18] KEYS: Move the algorithm pointer array from x509 to - public_key.c - -Move the public-key algorithm pointer array from x509_public_key.c to -public_key.c as it isn't X.509 specific. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/public_key.c | 8 ++++++++ - crypto/asymmetric_keys/x509_public_key.c | 11 +---------- - include/crypto/public_key.h | 1 + - 3 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -index b313df1..796ce08 100644 ---- a/crypto/asymmetric_keys/public_key.c -+++ b/crypto/asymmetric_keys/public_key.c -@@ -28,6 +28,14 @@ const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - }; - EXPORT_SYMBOL_GPL(pkey_algo_name); - -+const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { -+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ -+ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) -+ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -+#endif -+}; -+EXPORT_SYMBOL_GPL(pkey_algo); -+ - const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { - [PKEY_HASH_MD4] = "md4", - [PKEY_HASH_MD5] = "md5", -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index afbbc36..fe38628 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -23,15 +23,6 @@ - #include "public_key.h" - #include "x509_parser.h" - --static const --struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { -- [PKEY_ALGO_DSA] = NULL, --#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ -- defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) -- [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, --#endif --}; -- - /* - * Check the signature on a certificate using the provided public key - */ -@@ -174,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; -+ cert->pub->algo = pkey_algo[cert->pkey_algo]; - cert->pub->id_type = PKEY_ID_X509; - - /* Check the signature on the key */ -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 619d570..46bde25 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -23,6 +23,7 @@ enum pkey_algo { - }; - - extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; -+extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST]; - - enum pkey_hash_algo { - PKEY_HASH_MD4, --- -1.8.3.1 - - -From 564f7dc3b31d53d195d046e6a717e9a2277296bd Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:15:24 +0100 -Subject: [PATCH 03/18] KEYS: Store public key algo ID in public_key struct - -Store public key algo ID in public_key struct for reference purposes. This -allows it to be removed from the x509_certificate struct and used to find a -default in public_key_verify_signature(). - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/x509_cert_parser.c | 5 +++-- - crypto/asymmetric_keys/x509_parser.h | 1 - - crypto/asymmetric_keys/x509_public_key.c | 4 ++-- - include/crypto/public_key.h | 1 + - 4 files changed, 6 insertions(+), 5 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index facbf26..8cc253d 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -343,8 +343,9 @@ int x509_extract_key_data(void *context, size_t hdrlen, - if (ctx->last_oid != OID_rsaEncryption) - return -ENOPKG; - -- /* There seems to be an extraneous 0 byte on the front of the data */ -- ctx->cert->pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; -+ -+ /* Discard the BIT STRING metadata */ - ctx->key = value + 1; - ctx->key_size = vlen - 1; - return 0; -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index f86dc5f..e583ad0 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -20,7 +20,6 @@ struct x509_certificate { - char *authority; /* Authority key fingerprint as hex */ - struct tm valid_from; - struct tm valid_to; -- enum pkey_algo pkey_algo : 8; /* Public key algorithm */ - enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ - enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ - const void *tbs; /* Signed data */ -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index fe38628..fac574c 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -108,7 +108,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); -- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); -+ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); - pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, - cert->valid_from.tm_mday, cert->valid_from.tm_hour, -@@ -165,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- cert->pub->algo = pkey_algo[cert->pkey_algo]; -+ cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; - cert->pub->id_type = PKEY_ID_X509; - - /* Check the signature on the key */ -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 46bde25..05778df 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -60,6 +60,7 @@ struct public_key { - #define PKEY_CAN_DECRYPT 0x02 - #define PKEY_CAN_SIGN 0x04 - #define PKEY_CAN_VERIFY 0x08 -+ enum pkey_algo pkey_algo : 8; - enum pkey_id_type id_type : 8; - union { - MPI mpi[5]; --- -1.8.3.1 - - -From 2666dd8e330d6792cc32e8739e89f9ad0acd04c6 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:15:30 +0100 -Subject: [PATCH 04/18] KEYS: Split public_key_verify_signature() and make - available - -Modify public_key_verify_signature() so that it now takes a public_key struct -rather than a key struct and supply a wrapper that takes a key struct. The -wrapper is then used by the asymmetric key subtype and the modified function is -used by X.509 self-signature checking and can be used by other things also. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/public_key.c | 40 +++++++++++++++++++++++++------- - crypto/asymmetric_keys/public_key.h | 6 +++++ - crypto/asymmetric_keys/x509_public_key.c | 2 +- - 3 files changed, 39 insertions(+), 9 deletions(-) - -diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c -index 796ce08..49ac8d8 100644 ---- a/crypto/asymmetric_keys/public_key.c -+++ b/crypto/asymmetric_keys/public_key.c -@@ -86,21 +86,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy); - /* - * Verify a signature using a public key. - */ --static int public_key_verify_signature(const struct key *key, -- const struct public_key_signature *sig) -+int public_key_verify_signature(const struct public_key *pk, -+ const struct public_key_signature *sig) - { -- const struct public_key *pk = key->payload.data; -+ const struct public_key_algorithm *algo; -+ -+ BUG_ON(!pk); -+ BUG_ON(!pk->mpi[0]); -+ BUG_ON(!pk->mpi[1]); -+ BUG_ON(!sig); -+ BUG_ON(!sig->digest); -+ BUG_ON(!sig->mpi[0]); -+ -+ algo = pk->algo; -+ if (!algo) { -+ if (pk->pkey_algo >= PKEY_ALGO__LAST) -+ return -ENOPKG; -+ algo = pkey_algo[pk->pkey_algo]; -+ if (!algo) -+ return -ENOPKG; -+ } - -- if (!pk->algo->verify_signature) -+ if (!algo->verify_signature) - return -ENOTSUPP; - -- if (sig->nr_mpi != pk->algo->n_sig_mpi) { -+ if (sig->nr_mpi != algo->n_sig_mpi) { - pr_debug("Signature has %u MPI not %u\n", -- sig->nr_mpi, pk->algo->n_sig_mpi); -+ sig->nr_mpi, algo->n_sig_mpi); - return -EINVAL; - } - -- return pk->algo->verify_signature(pk, sig); -+ return algo->verify_signature(pk, sig); -+} -+EXPORT_SYMBOL_GPL(public_key_verify_signature); -+ -+static int public_key_verify_signature_2(const struct key *key, -+ const struct public_key_signature *sig) -+{ -+ const struct public_key *pk = key->payload.data; -+ return public_key_verify_signature(pk, sig); - } - - /* -@@ -111,6 +135,6 @@ struct asymmetric_key_subtype public_key_subtype = { - .name = "public_key", - .describe = public_key_describe, - .destroy = public_key_destroy, -- .verify_signature = public_key_verify_signature, -+ .verify_signature = public_key_verify_signature_2, - }; - EXPORT_SYMBOL_GPL(public_key_subtype); -diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h -index 5e5e356..5c37a22 100644 ---- a/crypto/asymmetric_keys/public_key.h -+++ b/crypto/asymmetric_keys/public_key.h -@@ -28,3 +28,9 @@ struct public_key_algorithm { - }; - - extern const struct public_key_algorithm RSA_public_key_algorithm; -+ -+/* -+ * public_key.c -+ */ -+extern int public_key_verify_signature(const struct public_key *pk, -+ const struct public_key_signature *sig); -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index fac574c..8cb2f70 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -76,7 +76,7 @@ static int x509_check_signature(const struct public_key *pub, - if (ret < 0) - goto error_mpi; - -- ret = pub->algo->verify_signature(pub, sig); -+ ret = public_key_verify_signature(pub, sig); - - pr_debug("Cert Verification: %d\n", ret); - --- -1.8.3.1 - - -From 9c814dcdc6d5836d82dc194f8f11ca9769251439 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:15:37 +0100 -Subject: [PATCH 05/18] KEYS: Store public key algo ID in public_key_signature - struct - -Store public key algorithm ID in public_key_signature struct for reference -purposes. This allows a public_key_signature struct to be embedded in -struct x509_certificate and other places more easily. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - include/crypto/public_key.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h -index 05778df..b34fda4 100644 ---- a/include/crypto/public_key.h -+++ b/include/crypto/public_key.h -@@ -90,6 +90,7 @@ struct public_key_signature { - u8 *digest; - u8 digest_size; /* Number of bytes in digest */ - u8 nr_mpi; /* Occupancy of mpi[] */ -+ enum pkey_algo pkey_algo : 8; - enum pkey_hash_algo pkey_hash_algo : 8; - union { - MPI mpi[2]; --- -1.8.3.1 - - -From b467a1c6be1c64c6abf4efd357a348f39c4b7daa Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:16:34 +0100 -Subject: [PATCH 06/18] X.509: struct x509_certificate needs struct tm - declaring - -struct x509_certificate needs struct tm declaring by #inclusion of linux/time.h -prior to its definition. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/x509_parser.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index e583ad0..2d01182 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -9,6 +9,7 @@ - * 2 of the Licence, or (at your option) any later version. - */ - -+#include <linux/time.h> - #include <crypto/public_key.h> - - struct x509_certificate { --- -1.8.3.1 - - -From 37137e9377322a4fe92f679d78f8181feefe4d21 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:18:02 +0100 -Subject: [PATCH 07/18] X.509: Embed public_key_signature struct and create - filler function - -Embed a public_key_signature struct in struct x509_certificate, eliminating -now unnecessary fields, and split x509_check_signature() to create a filler -function for it that attaches a digest of the signed data and an MPI that -represents the signature data. x509_free_certificate() is then modified to -deal with these. - -Whilst we're at it, export both x509_check_signature() and the new -x509_get_sig_params(). - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/x509_cert_parser.c | 30 +++++------ - crypto/asymmetric_keys/x509_parser.h | 16 ++++-- - crypto/asymmetric_keys/x509_public_key.c | 83 +++++++++++++++++-------------- - 3 files changed, 74 insertions(+), 55 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c -index 8cc253d..144201c 100644 ---- a/crypto/asymmetric_keys/x509_cert_parser.c -+++ b/crypto/asymmetric_keys/x509_cert_parser.c -@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert) - kfree(cert->subject); - kfree(cert->fingerprint); - kfree(cert->authority); -+ kfree(cert->sig.digest); -+ mpi_free(cert->sig.rsa.s); - kfree(cert); - } - } -@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, - return -ENOPKG; /* Unsupported combination */ - - case OID_md4WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_MD5; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_MD5; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - - case OID_sha1WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA1; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - - case OID_sha256WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA256; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - - case OID_sha384WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA384; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - - case OID_sha512WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA512; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - - case OID_sha224WithRSAEncryption: -- ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; -- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; -+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA224; -+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; - break; - } - -@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen, - return -EINVAL; - } - -- ctx->cert->sig = value; -- ctx->cert->sig_size = vlen; -+ ctx->cert->raw_sig = value; -+ ctx->cert->raw_sig_size = vlen; - return 0; - } - -diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h -index 2d01182..87d9cc2 100644 ---- a/crypto/asymmetric_keys/x509_parser.h -+++ b/crypto/asymmetric_keys/x509_parser.h -@@ -21,12 +21,11 @@ struct x509_certificate { - char *authority; /* Authority key fingerprint as hex */ - struct tm valid_from; - struct tm valid_to; -- enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ -- enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ - const void *tbs; /* Signed data */ -- size_t tbs_size; /* Size of signed data */ -- const void *sig; /* Signature data */ -- size_t sig_size; /* Size of sigature */ -+ unsigned tbs_size; /* Size of signed data */ -+ unsigned raw_sig_size; /* Size of sigature */ -+ const void *raw_sig; /* Signature data */ -+ struct public_key_signature sig; /* Signature parameters */ - }; - - /* -@@ -34,3 +33,10 @@ struct x509_certificate { - */ - extern void x509_free_certificate(struct x509_certificate *cert); - extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); -+ -+/* -+ * x509_public_key.c -+ */ -+extern int x509_get_sig_params(struct x509_certificate *cert); -+extern int x509_check_signature(const struct public_key *pub, -+ struct x509_certificate *cert); -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 8cb2f70..b7c81d8 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -24,72 +24,83 @@ - #include "x509_parser.h" - - /* -- * Check the signature on a certificate using the provided public key -+ * Set up the signature parameters in an X.509 certificate. This involves -+ * digesting the signed data and extracting the signature. - */ --static int x509_check_signature(const struct public_key *pub, -- const struct x509_certificate *cert) -+int x509_get_sig_params(struct x509_certificate *cert) - { -- struct public_key_signature *sig; - struct crypto_shash *tfm; - struct shash_desc *desc; - size_t digest_size, desc_size; -+ void *digest; - int ret; - - pr_devel("==>%s()\n", __func__); -- -+ -+ if (cert->sig.rsa.s) -+ return 0; -+ -+ cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); -+ if (!cert->sig.rsa.s) -+ return -ENOMEM; -+ cert->sig.nr_mpi = 1; -+ - /* Allocate the hashing algorithm we're going to need and find out how - * big the hash operational data will be. - */ -- tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); -+ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); - if (IS_ERR(tfm)) - return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); - - desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - digest_size = crypto_shash_digestsize(tfm); - -- /* We allocate the hash operational data storage on the end of our -- * context data. -+ /* We allocate the hash operational data storage on the end of the -+ * digest storage space. - */ - ret = -ENOMEM; -- sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); -- if (!sig) -- goto error_no_sig; -+ digest = kzalloc(digest_size + desc_size, GFP_KERNEL); -+ if (!digest) -+ goto error; - -- sig->pkey_hash_algo = cert->sig_hash_algo; -- sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; -- sig->digest_size = digest_size; -+ cert->sig.digest = digest; -+ cert->sig.digest_size = digest_size; - -- desc = (void *)sig + sizeof(*sig); -- desc->tfm = tfm; -- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ desc = digest + digest_size; -+ desc->tfm = tfm; -+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - - ret = crypto_shash_init(desc); - if (ret < 0) - goto error; -+ might_sleep(); -+ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); -+error: -+ crypto_free_shash(tfm); -+ pr_devel("<==%s() = %d\n", __func__, ret); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(x509_get_sig_params); - -- ret = -ENOMEM; -- sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); -- if (!sig->rsa.s) -- goto error; -+/* -+ * Check the signature on a certificate using the provided public key -+ */ -+int x509_check_signature(const struct public_key *pub, -+ struct x509_certificate *cert) -+{ -+ int ret; - -- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); -- if (ret < 0) -- goto error_mpi; -+ pr_devel("==>%s()\n", __func__); - -- ret = public_key_verify_signature(pub, sig); -+ ret = x509_get_sig_params(cert); -+ if (ret < 0) -+ return ret; - -+ ret = public_key_verify_signature(pub, &cert->sig); - pr_debug("Cert Verification: %d\n", ret); -- --error_mpi: -- mpi_free(sig->rsa.s); --error: -- kfree(sig); --error_no_sig: -- crypto_free_shash(tfm); -- -- pr_devel("<==%s() = %d\n", __func__, ret); - return ret; - } -+EXPORT_SYMBOL_GPL(x509_check_signature); - - /* - * Attempt to parse a data blob for a key as an X509 certificate. -@@ -118,8 +129,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - cert->valid_to.tm_mday, cert->valid_to.tm_hour, - cert->valid_to.tm_min, cert->valid_to.tm_sec); - pr_devel("Cert Signature: %s + %s\n", -- pkey_algo_name[cert->sig_pkey_algo], -- pkey_hash_algo_name[cert->sig_hash_algo]); -+ pkey_algo_name[cert->sig.pkey_algo], -+ pkey_hash_algo_name[cert->sig.pkey_hash_algo]); - - if (!cert->fingerprint || !cert->authority) { - pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", --- -1.8.3.1 - - -From 51432bf93bf4ff11cccf91c5ca22e9e92c05f4b4 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:18:15 +0100 -Subject: [PATCH 08/18] X.509: Check the algorithm IDs obtained from parsing an - X.509 certificate - -Check that the algorithm IDs obtained from the ASN.1 parse by OID lookup -corresponds to algorithms that are available to us. - -Reported-by: Kees Cook <keescook@chromium.org> -Signed-off-by: David Howells <dhowells@redhat.com> ---- - crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index b7c81d8..eb368d4 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -119,6 +119,17 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - - pr_devel("Cert Issuer: %s\n", cert->issuer); - pr_devel("Cert Subject: %s\n", cert->subject); -+ -+ if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || -+ cert->sig.pkey_algo >= PKEY_ALGO__LAST || -+ cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || -+ !pkey_algo[cert->pub->pkey_algo] || -+ !pkey_algo[cert->sig.pkey_algo] || -+ !pkey_hash_algo_name[cert->sig.pkey_hash_algo]) { -+ ret = -ENOPKG; -+ goto error_free_cert; -+ } -+ - pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); - pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", - cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, --- -1.8.3.1 - - -From 8f943dd14f8a4d8aa2126f8544e140d019ceb36d Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:18:31 +0100 -Subject: [PATCH 09/18] X.509: Handle certificates that lack an - authorityKeyIdentifier field - -Handle certificates that lack an authorityKeyIdentifier field by assuming -they're self-signed and checking their signatures against themselves. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> -Reviewed-by: Josh Boyer <jwboyer@redhat.com> ---- - crypto/asymmetric_keys/x509_public_key.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index eb368d4..0f55e3b 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -143,8 +143,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - pkey_algo_name[cert->sig.pkey_algo], - pkey_hash_algo_name[cert->sig.pkey_hash_algo]); - -- if (!cert->fingerprint || !cert->authority) { -- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", -+ if (!cert->fingerprint) { -+ pr_warn("Cert for '%s' must have a SubjKeyId extension\n", - cert->subject); - ret = -EKEYREJECTED; - goto error_free_cert; -@@ -190,8 +190,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; - cert->pub->id_type = PKEY_ID_X509; - -- /* Check the signature on the key */ -- if (strcmp(cert->fingerprint, cert->authority) == 0) { -+ /* Check the signature on the key if it appears to be self-signed */ -+ if (!cert->authority || -+ strcmp(cert->fingerprint, cert->authority) == 0) { - ret = x509_check_signature(cert->pub, cert); - if (ret < 0) - goto error_free_cert; --- -1.8.3.1 - - -From 89c63be02d8eea6403d6b7d7a045e8f115787a81 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Tue, 18 Jun 2013 17:40:44 +0100 -Subject: [PATCH 10/18] X.509: Remove certificate date checks - -Remove the certificate date checks that are performed when a certificate is -parsed. There are two checks: a valid from and a valid to. The first check is -causing a lot of problems with system clocks that don't keep good time and the -second places an implicit expiry date upon the kernel when used for module -signing, so do we really need them? - -Signed-off-by: David Howells <dhowells@redhat.com> -cc: David Woodhouse <dwmw2@infradead.org> -cc: Rusty Russell <rusty@rustcorp.com.au> -cc: Josh Boyer <jwboyer@redhat.com> -cc: Alexander Holler <holler@ahsoftware.de> -cc: stable@vger.kernel.org ---- - crypto/asymmetric_keys/x509_public_key.c | 38 -------------------------------- - 1 file changed, 38 deletions(-) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index 0f55e3b..c1540e8 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -108,7 +108,6 @@ EXPORT_SYMBOL_GPL(x509_check_signature); - static int x509_key_preparse(struct key_preparsed_payload *prep) - { - struct x509_certificate *cert; -- struct tm now; - size_t srlen, sulen; - char *desc = NULL; - int ret; -@@ -150,43 +149,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - goto error_free_cert; - } - -- time_to_tm(CURRENT_TIME.tv_sec, 0, &now); -- pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", -- now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, -- now.tm_hour, now.tm_min, now.tm_sec); -- if (now.tm_year < cert->valid_from.tm_year || -- (now.tm_year == cert->valid_from.tm_year && -- (now.tm_mon < cert->valid_from.tm_mon || -- (now.tm_mon == cert->valid_from.tm_mon && -- (now.tm_mday < cert->valid_from.tm_mday || -- (now.tm_mday == cert->valid_from.tm_mday && -- (now.tm_hour < cert->valid_from.tm_hour || -- (now.tm_hour == cert->valid_from.tm_hour && -- (now.tm_min < cert->valid_from.tm_min || -- (now.tm_min == cert->valid_from.tm_min && -- (now.tm_sec < cert->valid_from.tm_sec -- ))))))))))) { -- pr_warn("Cert %s is not yet valid\n", cert->fingerprint); -- ret = -EKEYREJECTED; -- goto error_free_cert; -- } -- if (now.tm_year > cert->valid_to.tm_year || -- (now.tm_year == cert->valid_to.tm_year && -- (now.tm_mon > cert->valid_to.tm_mon || -- (now.tm_mon == cert->valid_to.tm_mon && -- (now.tm_mday > cert->valid_to.tm_mday || -- (now.tm_mday == cert->valid_to.tm_mday && -- (now.tm_hour > cert->valid_to.tm_hour || -- (now.tm_hour == cert->valid_to.tm_hour && -- (now.tm_min > cert->valid_to.tm_min || -- (now.tm_min == cert->valid_to.tm_min && -- (now.tm_sec > cert->valid_to.tm_sec -- ))))))))))) { -- pr_warn("Cert %s has expired\n", cert->fingerprint); -- ret = -EKEYEXPIRED; -- goto error_free_cert; -- } -- - cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; - cert->pub->id_type = PKEY_ID_X509; - --- -1.8.3.1 - - -From cdbd1f60c92814fa44ca968dd3fdc78c8b65400c Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:07:13 +0100 -Subject: [PATCH 11/18] KEYS: Load *.x509 files into kernel keyring - -Load all the files matching the pattern "*.x509" that are to be found in kernel -base source dir and base build dir into the module signing keyring. - -The "extra_certificates" file is then redundant. - -Signed-off-by: David Howells <dhowells@redhat.com> ---- - kernel/Makefile | 35 +++++++++++++++++++++++++++++------ - kernel/modsign_certificate.S | 3 +-- - 2 files changed, 30 insertions(+), 8 deletions(-) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 09a9c94..0246125 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -123,17 +123,40 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE - $(call if_changed,bc) - - ifeq ($(CONFIG_MODULE_SIG),y) -+############################################################################### - # --# Pull the signing certificate and any extra certificates into the kernel -+# Roll all the X.509 certificates that we can find together and pull -+# them into the kernel. - # -+############################################################################### -+X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) -+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 -+X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) -+ -+ifeq ($(X509_CERTIFICATES),) -+$(warning *** No X.509 certificates found ***) -+endif -+ -+ifneq ($(wildcard $(obj)/.x509.list),) -+ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES)) -+$(info X.509 certificate list changed) -+$(shell rm $(obj)/.x509.list) -+endif -+endif -+ -+kernel/modsign_certificate.o: $(obj)/x509_certificate_list - --quiet_cmd_touch = TOUCH $@ -- cmd_touch = touch $@ -+quiet_cmd_x509certs = CERTS $@ -+ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ -+targets += $(obj)/x509_certificate_list -+$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list -+ $(call if_changed,x509certs) - --extra_certificates: -- $(call cmd,touch) -+targets += $(obj)/.x509.list -+$(obj)/.x509.list: -+ @echo $(X509_CERTIFICATES) >$@ - --kernel/modsign_certificate.o: signing_key.x509 extra_certificates -+clean-files := x509_certificate_list .x509.list - - ############################################################################### - # -diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S -index 4a9a86d..6fe03c7 100644 ---- a/kernel/modsign_certificate.S -+++ b/kernel/modsign_certificate.S -@@ -7,6 +7,5 @@ - .section ".init.data","aw" - - GLOBAL(modsign_certificate_list) -- .incbin "signing_key.x509" -- .incbin "extra_certificates" -+ .incbin "kernel/x509_certificate_list" - GLOBAL(modsign_certificate_list_end) --- -1.8.3.1 - - -From d38add998f9fb35e901e022c14b0f771823b35e2 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 17:13:15 +0100 -Subject: [PATCH 12/18] KEYS: Have make canonicalise the paths of the X.509 - certs better to deduplicate - -Have make canonicalise the paths of the X.509 certificates before we sort them -as this allows $(sort) to better remove duplicates. - -Signed-off-by: David Howells <dhowells@redhat.com> ---- - kernel/Makefile | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/kernel/Makefile b/kernel/Makefile -index 0246125..c71d596 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -125,13 +125,19 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE - ifeq ($(CONFIG_MODULE_SIG),y) - ############################################################################### - # --# Roll all the X.509 certificates that we can find together and pull --# them into the kernel. -+# Roll all the X.509 certificates that we can find together and pull them into -+# the kernel. -+# -+# We look in the source root and the build root for all files whose name ends -+# in ".x509". Unfortunately, this will generate duplicate filenames, so we -+# have make canonicalise the pathnames and then sort them to discard the -+# duplicates. - # - ############################################################################### - X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) - X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 --X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) -+X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ -+ $(or $(realpath $(CERT)),$(CERT)))) - - ifeq ($(X509_CERTIFICATES),) - $(warning *** No X.509 certificates found ***) --- -1.8.3.1 - - -From 1e326161658f6c4bd5dba53bc2076d915400124a Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:07:30 +0100 -Subject: [PATCH 13/18] KEYS: Separate the kernel signature checking keyring - from module signing - -Separate the kernel signature checking keyring from module signing so that it -can be used by code other than the module-signing code. - -Signed-off-by: David Howells <dhowells@redhat.com> ---- - include/keys/system_keyring.h | 23 ++++++++++ - init/Kconfig | 13 ++++++ - kernel/Makefile | 15 ++++-- - kernel/modsign_certificate.S | 11 ----- - kernel/modsign_pubkey.c | 104 ------------------------------------------ - kernel/module-internal.h | 2 - - kernel/module_signing.c | 3 +- - kernel/system_certificates.S | 11 +++++ - kernel/system_keyring.c | 103 +++++++++++++++++++++++++++++++++++++++++ - 9 files changed, 162 insertions(+), 123 deletions(-) - create mode 100644 include/keys/system_keyring.h - delete mode 100644 kernel/modsign_certificate.S - delete mode 100644 kernel/modsign_pubkey.c - create mode 100644 kernel/system_certificates.S - create mode 100644 kernel/system_keyring.c - -diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h -new file mode 100644 -index 0000000..8dabc39 ---- /dev/null -+++ b/include/keys/system_keyring.h -@@ -0,0 +1,23 @@ -+/* System keyring containing trusted public keys. -+ * -+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#ifndef _KEYS_SYSTEM_KEYRING_H -+#define _KEYS_SYSTEM_KEYRING_H -+ -+#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING -+ -+#include <linux/key.h> -+ -+extern struct key *system_trusted_keyring; -+ -+#endif -+ -+#endif /* _KEYS_SYSTEM_KEYRING_H */ -diff --git a/init/Kconfig b/init/Kconfig -index 5496f30..b5c524c 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1675,6 +1675,18 @@ config BASE_SMALL - default 0 if BASE_FULL - default 1 if !BASE_FULL - -+config SYSTEM_TRUSTED_KEYRING -+ bool "Provide system-wide ring of trusted keys" -+ depends on KEYS -+ help -+ Provide a system keyring to which trusted keys can be added. Keys in -+ the keyring are considered to be trusted. Keys may be added at will -+ by the kernel from compiled-in data and from hardware key stores, but -+ userspace may only add extra keys if those keys can be verified by -+ keys already in the keyring. -+ -+ Keys in this keyring are used by module signature checking. -+ - menuconfig MODULES - bool "Enable loadable module support" - option modules -@@ -1748,6 +1760,7 @@ config MODULE_SRCVERSION_ALL - config MODULE_SIG - bool "Module signature verification" - depends on MODULES -+ select SYSTEM_TRUSTED_KEYRING - select KEYS - select CRYPTO - select ASYMMETRIC_KEY_TYPE -diff --git a/kernel/Makefile b/kernel/Makefile -index c71d596..bbaf7d5 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -41,8 +41,9 @@ ifneq ($(CONFIG_SMP),y) - obj-y += up.o - endif - obj-$(CONFIG_UID16) += uid16.o -+obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o - obj-$(CONFIG_MODULES) += module.o --obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o -+obj-$(CONFIG_MODULE_SIG) += module_signing.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -@@ -122,11 +123,11 @@ targets += timeconst.h - $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE - $(call if_changed,bc) - --ifeq ($(CONFIG_MODULE_SIG),y) - ############################################################################### - # - # Roll all the X.509 certificates that we can find together and pull them into --# the kernel. -+# the kernel so that they get loaded into the system trusted keyring during -+# boot. - # - # We look in the source root and the build root for all files whose name ends - # in ".x509". Unfortunately, this will generate duplicate filenames, so we -@@ -134,6 +135,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) - # duplicates. - # - ############################################################################### -+ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) - X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) - X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 - X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \ -@@ -150,10 +152,11 @@ $(shell rm $(obj)/.x509.list) - endif - endif - --kernel/modsign_certificate.o: $(obj)/x509_certificate_list -+kernel/system_certificates.o: $(obj)/x509_certificate_list - - quiet_cmd_x509certs = CERTS $@ -- cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ -+ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") -+ - targets += $(obj)/x509_certificate_list - $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list - $(call if_changed,x509certs) -@@ -163,7 +166,9 @@ $(obj)/.x509.list: - @echo $(X509_CERTIFICATES) >$@ - - clean-files := x509_certificate_list .x509.list -+endif - -+ifeq ($(CONFIG_MODULE_SIG),y) - ############################################################################### - # - # If module signing is requested, say by allyesconfig, but a key has not been -diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S -deleted file mode 100644 -index 6fe03c7..0000000 ---- a/kernel/modsign_certificate.S -+++ /dev/null -@@ -1,11 +0,0 @@ --#include <linux/export.h> -- --#define GLOBAL(name) \ -- .globl VMLINUX_SYMBOL(name); \ -- VMLINUX_SYMBOL(name): -- -- .section ".init.data","aw" -- --GLOBAL(modsign_certificate_list) -- .incbin "kernel/x509_certificate_list" --GLOBAL(modsign_certificate_list_end) -diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c -deleted file mode 100644 -index 7cbd450..0000000 ---- a/kernel/modsign_pubkey.c -+++ /dev/null -@@ -1,104 +0,0 @@ --/* Public keys for module signature verification -- * -- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -- * Written by David Howells (dhowells@redhat.com) -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public Licence -- * as published by the Free Software Foundation; either version -- * 2 of the Licence, or (at your option) any later version. -- */ -- --#include <linux/kernel.h> --#include <linux/sched.h> --#include <linux/cred.h> --#include <linux/err.h> --#include <keys/asymmetric-type.h> --#include "module-internal.h" -- --struct key *modsign_keyring; -- --extern __initconst const u8 modsign_certificate_list[]; --extern __initconst const u8 modsign_certificate_list_end[]; -- --/* -- * We need to make sure ccache doesn't cache the .o file as it doesn't notice -- * if modsign.pub changes. -- */ --static __initconst const char annoy_ccache[] = __TIME__ "foo"; -- --/* -- * Load the compiled-in keys -- */ --static __init int module_verify_init(void) --{ -- pr_notice("Initialise module verification\n"); -- -- modsign_keyring = keyring_alloc(".module_sign", -- KUIDT_INIT(0), KGIDT_INIT(0), -- current_cred(), -- ((KEY_POS_ALL & ~KEY_POS_SETATTR) | -- KEY_USR_VIEW | KEY_USR_READ), -- KEY_ALLOC_NOT_IN_QUOTA, NULL); -- if (IS_ERR(modsign_keyring)) -- panic("Can't allocate module signing keyring\n"); -- -- return 0; --} -- --/* -- * Must be initialised before we try and load the keys into the keyring. -- */ --device_initcall(module_verify_init); -- --/* -- * Load the compiled-in keys -- */ --static __init int load_module_signing_keys(void) --{ -- key_ref_t key; -- const u8 *p, *end; -- size_t plen; -- -- pr_notice("Loading module verification certificates\n"); -- -- end = modsign_certificate_list_end; -- p = modsign_certificate_list; -- while (p < end) { -- /* Each cert begins with an ASN.1 SEQUENCE tag and must be more -- * than 256 bytes in size. -- */ -- if (end - p < 4) -- goto dodgy_cert; -- if (p[0] != 0x30 && -- p[1] != 0x82) -- goto dodgy_cert; -- plen = (p[2] << 8) | p[3]; -- plen += 4; -- if (plen > end - p) -- goto dodgy_cert; -- -- key = key_create_or_update(make_key_ref(modsign_keyring, 1), -- "asymmetric", -- NULL, -- p, -- plen, -- (KEY_POS_ALL & ~KEY_POS_SETATTR) | -- KEY_USR_VIEW, -- KEY_ALLOC_NOT_IN_QUOTA); -- if (IS_ERR(key)) -- pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", -- PTR_ERR(key)); -- else -- pr_notice("MODSIGN: Loaded cert '%s'\n", -- key_ref_to_ptr(key)->description); -- p += plen; -- } -- -- return 0; -- --dodgy_cert: -- pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); -- return 0; --} --late_initcall(load_module_signing_keys); -diff --git a/kernel/module-internal.h b/kernel/module-internal.h -index 24f9247..915e123 100644 ---- a/kernel/module-internal.h -+++ b/kernel/module-internal.h -@@ -9,6 +9,4 @@ - * 2 of the Licence, or (at your option) any later version. - */ - --extern struct key *modsign_keyring; -- - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); -diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index ee47640..0b6b870 100644 ---- a/kernel/module_signing.c -+++ b/kernel/module_signing.c -@@ -14,6 +14,7 @@ - #include <crypto/public_key.h> - #include <crypto/hash.h> - #include <keys/asymmetric-type.h> -+#include <keys/system_keyring.h> - #include "module-internal.h" - - /* -@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, - - pr_debug("Look up: \"%s\"\n", id); - -- key = keyring_search(make_key_ref(modsign_keyring, 1), -+ key = keyring_search(make_key_ref(system_trusted_keyring, 1), - &key_type_asymmetric, id); - if (IS_ERR(key)) - pr_warn("Request for unknown module key '%s' err %ld\n", -diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S -new file mode 100644 -index 0000000..5cffe86 ---- /dev/null -+++ b/kernel/system_certificates.S -@@ -0,0 +1,11 @@ -+#include <linux/export.h> -+ -+#define GLOBAL(name) \ -+ .globl VMLINUX_SYMBOL(name); \ -+ VMLINUX_SYMBOL(name): -+ -+ .section ".init.data","aw" -+ -+GLOBAL(system_certificate_list) -+ .incbin "kernel/x509_certificate_list" -+GLOBAL(system_certificate_list_end) -diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c -new file mode 100644 -index 0000000..51c3514 ---- /dev/null -+++ b/kernel/system_keyring.c -@@ -0,0 +1,103 @@ -+/* System trusted keyring for trusted public keys -+ * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include <linux/export.h> -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/cred.h> -+#include <linux/err.h> -+#include <keys/asymmetric-type.h> -+#include <keys/system_keyring.h> -+#include "module-internal.h" -+ -+struct key *system_trusted_keyring; -+EXPORT_SYMBOL_GPL(system_trusted_keyring); -+ -+extern __initconst const u8 system_certificate_list[]; -+extern __initconst const u8 system_certificate_list_end[]; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int system_trusted_keyring_init(void) -+{ -+ pr_notice("Initialise system trusted keyring\n"); -+ -+ system_trusted_keyring = -+ keyring_alloc(".system_keyring", -+ KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), -+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ), -+ KEY_ALLOC_NOT_IN_QUOTA, NULL); -+ if (IS_ERR(system_trusted_keyring)) -+ panic("Can't allocate system trusted keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(system_trusted_keyring_init); -+ -+/* -+ * Load the compiled-in list of X.509 certificates. -+ */ -+static __init int load_system_certificate_list(void) -+{ -+ key_ref_t key; -+ const u8 *p, *end; -+ size_t plen; -+ -+ pr_notice("Loading compiled-in X.509 certificates\n"); -+ -+ end = system_certificate_list_end; -+ p = system_certificate_list; -+ while (p < end) { -+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more -+ * than 256 bytes in size. -+ */ -+ if (end - p < 4) -+ goto dodgy_cert; -+ if (p[0] != 0x30 && -+ p[1] != 0x82) -+ goto dodgy_cert; -+ plen = (p[2] << 8) | p[3]; -+ plen += 4; -+ if (plen > end - p) -+ goto dodgy_cert; -+ -+ key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), -+ "asymmetric", -+ NULL, -+ p, -+ plen, -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(key)) { -+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ } else { -+ pr_notice("Loaded X.509 cert '%s'\n", -+ key_ref_to_ptr(key)->description); -+ key_ref_put(key); -+ } -+ p += plen; -+ } -+ -+ return 0; -+ -+dodgy_cert: -+ pr_err("Problem parsing in-kernel X.509 certificate list\n"); -+ return 0; -+} -+late_initcall(load_system_certificate_list); --- -1.8.3.1 - - -From 5d862c1ec2e5e033527a5e6ac17042d8d7408f7b Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Fri, 30 Aug 2013 16:07:37 +0100 -Subject: [PATCH 14/18] KEYS: Add a 'trusted' flag and a 'trusted only' flag - -Add KEY_FLAG_TRUSTED to indicate that a key either comes from a trusted source -or had a cryptographic signature chain that led back to a trusted key the -kernel already possessed. - -Add KEY_FLAGS_TRUSTED_ONLY to indicate that a keyring will only accept links to -keys marked with KEY_FLAGS_TRUSTED. - -Signed-off-by: David Howells <dhowells@redhat.com> -Reviewed-by: Kees Cook <keescook@chromium.org> ---- - include/linux/key-type.h | 1 + - include/linux/key.h | 3 +++ - kernel/system_keyring.c | 4 +++- - security/keys/key.c | 8 ++++++++ - security/keys/keyring.c | 4 ++++ - 5 files changed, 19 insertions(+), 1 deletion(-) - -diff --git a/include/linux/key-type.h b/include/linux/key-type.h -index f58737b..a74c3a8 100644 ---- a/include/linux/key-type.h -+++ b/include/linux/key-type.h -@@ -45,6 +45,7 @@ struct key_preparsed_payload { - const void *data; /* Raw data */ - size_t datalen; /* Raw datalen */ - size_t quotalen; /* Quota length for proposed payload */ -+ bool trusted; /* True if key is trusted */ - }; - - typedef int (*request_key_actor_t)(struct key_construction *key, -diff --git a/include/linux/key.h b/include/linux/key.h -index 010dbb6..80d6774 100644 ---- a/include/linux/key.h -+++ b/include/linux/key.h -@@ -168,6 +168,8 @@ struct key { - #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ - #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ - #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ -+#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ -+#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ - - /* the key type and key description string - * - the desc is used to match a key against search criteria -@@ -218,6 +220,7 @@ extern struct key *key_alloc(struct key_type *type, - #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ - #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ - #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ -+#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ - - extern void key_revoke(struct key *key); - extern void key_invalidate(struct key *key); -diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c -index 51c3514..5296721 100644 ---- a/kernel/system_keyring.c -+++ b/kernel/system_keyring.c -@@ -40,6 +40,7 @@ static __init int system_trusted_keyring_init(void) - if (IS_ERR(system_trusted_keyring)) - panic("Can't allocate system trusted keyring\n"); - -+ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); - return 0; - } - -@@ -82,7 +83,8 @@ static __init int load_system_certificate_list(void) - plen, - (KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW, -- KEY_ALLOC_NOT_IN_QUOTA); -+ KEY_ALLOC_NOT_IN_QUOTA | -+ KEY_ALLOC_TRUSTED); - if (IS_ERR(key)) { - pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", - PTR_ERR(key)); -diff --git a/security/keys/key.c b/security/keys/key.c -index a819b5c..d331ea9 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -300,6 +300,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, - - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) - key->flags |= 1 << KEY_FLAG_IN_QUOTA; -+ if (flags & KEY_ALLOC_TRUSTED) -+ key->flags |= 1 << KEY_FLAG_TRUSTED; - - memset(&key->type_data, 0, sizeof(key->type_data)); - -@@ -813,6 +815,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - prep.data = payload; - prep.datalen = plen; - prep.quotalen = index_key.type->def_datalen; -+ prep.trusted = flags & KEY_ALLOC_TRUSTED; - if (index_key.type->preparse) { - ret = index_key.type->preparse(&prep); - if (ret < 0) { -@@ -827,6 +830,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, - } - index_key.desc_len = strlen(index_key.description); - -+ key_ref = ERR_PTR(-EPERM); -+ if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) -+ goto error_free_prep; -+ flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; -+ - ret = __key_link_begin(keyring, &index_key, &edit); - if (ret < 0) { - key_ref = ERR_PTR(ret); -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index f7cdea2..9b6f6e0 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -1183,6 +1183,10 @@ int key_link(struct key *keyring, struct key *key) - key_check(keyring); - key_check(key); - -+ if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && -+ !test_bit(KEY_FLAG_TRUSTED, &key->flags)) -+ return -EPERM; -+ - ret = __key_link_begin(keyring, &key->index_key, &edit); - if (ret == 0) { - kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); --- -1.8.3.1 - - -From 6270395cb613c47a5ca459649c4d4ba6eeea2ce4 Mon Sep 17 00:00:00 2001 -From: David Howells <dhowells@redhat.com> -Date: Wed, 4 Sep 2013 19:28:03 +0100 -Subject: [PATCH 15/18] KEYS: Set the asymmetric-key type default search method - -The keyring expansion patches introduces a new search method by which -key_search() attempts to walk directly to the key that has exactly the same -description as the requested one. - -However, this causes inexact matching of asymmetric keys to fail. The -solution to this is to select iterative rather than direct search as the -default search type for asymmetric keys. - -As an example, the kernel might have a key like this: - - Magrathea: Glacier signing key: 6a2a0f82bad7e396665f465e4e3e1f9bd24b1226 - -and: - - keyctl search <keyring-ID> asymmetric id:d24b1226 - -should find the key, despite that not being its exact description. - -Signed-off-by: David Howells <dhowells@redhat.com> ---- - crypto/asymmetric_keys/asymmetric_type.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c -index cf80765..b77eb53 100644 ---- a/crypto/asymmetric_keys/asymmetric_type.c -+++ b/crypto/asymmetric_keys/asymmetric_type.c -@@ -209,6 +209,7 @@ struct key_type key_type_asymmetric = { - .match = asymmetric_key_match, - .destroy = asymmetric_key_destroy, - .describe = asymmetric_key_describe, -+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE, - }; - EXPORT_SYMBOL_GPL(key_type_asymmetric); - --- -1.8.3.1 - - -From cf64858d1b141c9c7d3477f686a923eb8908b438 Mon Sep 17 00:00:00 2001 -From: Mimi Zohar <zohar@linux.vnet.ibm.com> -Date: Tue, 20 Aug 2013 14:36:26 -0400 -Subject: [PATCH 16/18] KEYS: Make the system 'trusted' keyring viewable by - userspace - -Give the root user the ability to read the system keyring and put read -permission on the trusted keys added during boot. The latter is actually more -theoretical than real for the moment as asymmetric keys do not currently -provide a read operation. - -Signed-off-by: Mimi Zohar <zohar@us.ibm.com> -Signed-off-by: David Howells <dhowells@redhat.com> ---- - kernel/system_keyring.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c -index 5296721..564dd93 100644 ---- a/kernel/system_keyring.c -+++ b/kernel/system_keyring.c -@@ -35,7 +35,7 @@ static __init int system_trusted_keyring_init(void) - keyring_alloc(".system_keyring", - KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | -- KEY_USR_VIEW | KEY_USR_READ), -+ KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), - KEY_ALLOC_NOT_IN_QUOTA, NULL); - if (IS_ERR(system_trusted_keyring)) - panic("Can't allocate system trusted keyring\n"); -@@ -81,8 +81,8 @@ static __init int load_system_certificate_list(void) - NULL, - p, - plen, -- (KEY_POS_ALL & ~KEY_POS_SETATTR) | -- KEY_USR_VIEW, -+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA | - KEY_ALLOC_TRUSTED); - if (IS_ERR(key)) { --- -1.8.3.1 - - -From c8bbb1491c7be6193f502e4d1326f2bd23263616 Mon Sep 17 00:00:00 2001 -From: Mimi Zohar <zohar@linux.vnet.ibm.com> -Date: Tue, 20 Aug 2013 14:36:27 -0400 -Subject: [PATCH 17/18] 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> ---- - crypto/asymmetric_keys/x509_public_key.c | 81 +++++++++++++++++++++++++++++++- - 1 file changed, 80 insertions(+), 1 deletion(-) - -diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c -index c1540e8..8761264 100644 ---- a/crypto/asymmetric_keys/x509_public_key.c -+++ b/crypto/asymmetric_keys/x509_public_key.c -@@ -18,12 +18,60 @@ - #include <linux/asn1_decoder.h> - #include <keys/asymmetric-subtype.h> - #include <keys/asymmetric-parser.h> -+#include <keys/system_keyring.h> - #include <crypto/hash.h> - #include "asymmetric_keys.h" - #include "public_key.h" - #include "x509_parser.h" - - /* -+ * Find a key in the given keyring by issuer and authority. -+ */ -+static struct key *x509_request_asymmetric_key( -+ struct key *keyring, -+ const char *signer, size_t signer_len, -+ const char *authority, size_t auth_len) -+{ -+ key_ref_t key; -+ char *id; -+ -+ /* Construct an identifier. */ -+ id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); -+ if (!id) -+ return ERR_PTR(-ENOMEM); -+ -+ memcpy(id, signer, signer_len); -+ id[signer_len + 0] = ':'; -+ id[signer_len + 1] = ' '; -+ memcpy(id + signer_len + 2, authority, auth_len); -+ id[signer_len + 2 + auth_len] = 0; -+ -+ pr_debug("Look up: \"%s\"\n", id); -+ -+ key = keyring_search(make_key_ref(keyring, 1), -+ &key_type_asymmetric, id); -+ if (IS_ERR(key)) -+ pr_debug("Request for module key '%s' err %ld\n", -+ id, PTR_ERR(key)); -+ kfree(id); -+ -+ if (IS_ERR(key)) { -+ switch (PTR_ERR(key)) { -+ /* Hide some search errors */ -+ case -EACCES: -+ case -ENOTDIR: -+ case -EAGAIN: -+ return ERR_PTR(-ENOKEY); -+ default: -+ return ERR_CAST(key); -+ } -+ } -+ -+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); -+ return key_ref_to_ptr(key); -+} -+ -+/* - * Set up the signature parameters in an X.509 certificate. This involves - * digesting the signed data and extracting the signature. - */ -@@ -103,6 +151,33 @@ int x509_check_signature(const struct public_key *pub, - EXPORT_SYMBOL_GPL(x509_check_signature); - - /* -+ * Check the new certificate against the ones in the trust keyring. If one of -+ * those is the signing key and validates the new certificate, then mark the -+ * new certificate as being trusted. -+ * -+ * Return 0 if the new certificate was successfully validated, 1 if we couldn't -+ * find a matching parent certificate in the trusted list and an error if there -+ * is a matching certificate but the signature check fails. -+ */ -+static int x509_validate_trust(struct x509_certificate *cert, -+ struct key *trust_keyring) -+{ -+ const struct public_key *pk; -+ struct key *key; -+ int ret = 1; -+ -+ key = x509_request_asymmetric_key(trust_keyring, -+ cert->issuer, strlen(cert->issuer), -+ cert->authority, -+ strlen(cert->authority)); -+ if (!IS_ERR(key)) { -+ pk = key->payload.data; -+ ret = x509_check_signature(pk, cert); -+ } -+ return ret; -+} -+ -+/* - * Attempt to parse a data blob for a key as an X509 certificate. - */ - static int x509_key_preparse(struct key_preparsed_payload *prep) -@@ -155,9 +230,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) - /* Check the signature on the key if it appears to be self-signed */ - if (!cert->authority || - strcmp(cert->fingerprint, cert->authority) == 0) { -- ret = x509_check_signature(cert->pub, cert); -+ ret = x509_check_signature(cert->pub, cert); /* self-signed */ - if (ret < 0) - goto error_free_cert; -+ } else { -+ ret = x509_validate_trust(cert, system_trusted_keyring); -+ if (!ret) -+ prep->trusted = 1; - } - - /* Propose a description */ --- -1.8.3.1 - - -From 40faeaee1ca7822dc39d24db4b04e4d6c2feba4d Mon Sep 17 00:00:00 2001 -From: Mimi Zohar <zohar@linux.vnet.ibm.com> -Date: Wed, 4 Sep 2013 13:26:22 +0100 -Subject: [PATCH 18/18] KEYS: initialize root uid and session keyrings early - -In order to create the integrity keyrings (eg. _evm, _ima), root's -uid and session keyrings need to be initialized early. - -Signed-off-by: Mimi Zohar <zohar@us.ibm.com> -Signed-off-by: David Howells <dhowells@redhat.com> ---- - security/keys/process_keys.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index 68548ea..0cf8a13 100644 ---- a/security/keys/process_keys.c -+++ b/security/keys/process_keys.c -@@ -857,3 +857,13 @@ void key_change_session_keyring(struct callback_head *twork) - - commit_creds(new); - } -+ -+/* -+ * Make sure that root's user and user-session keyrings exist. -+ */ -+static int __init init_root_keyring(void) -+{ -+ return install_user_keyrings(); -+} -+ -+late_initcall(init_root_keyring); --- -1.8.3.1 - |