[kernel] Update keys-x509-improv.patch to latest back from upstream git
Josh Boyer
jwboyer at fedoraproject.org
Sat Sep 14 14:45:40 UTC 2013
commit 675aa17081bae25384c433d8d7bc57cab5f02729
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date: Sat Sep 14 09:33:23 2013 -0400
Update keys-x509-improv.patch to latest back from upstream git
kernel.spec | 5 +-
keys-x509-improv.patch | 3046 ++++++++++++++++++++++++++----------------------
2 files changed, 1682 insertions(+), 1369 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index d439980..3f2d46e 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -62,7 +62,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
-%global baserelease 1
+%global baserelease 2
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@@ -2299,6 +2299,9 @@ fi
# ||----w |
# || ||
%changelog
+* Sat Sep 14 2013 Josh Boyer <jwboyer at fedoraproject.org>
+- Update keys-x509-improv.patch to latest back from upstream git
+
* Sat Sep 14 2013 Josh Boyer <jwboyer at fedoraproject.org> - 3.12.0-0.rc0.git25.1
- Linux v3.11-10050-g3711d86
diff --git a/keys-x509-improv.patch b/keys-x509-improv.patch
index e64a0dd..7176cc5 100644
--- a/keys-x509-improv.patch
+++ b/keys-x509-improv.patch
@@ -1,1579 +1,1889 @@
-From 7712dc43315febf4bce07a4c549787cf5c60a428 Mon Sep 17 00:00:00 2001
+From 775d395f8bd8ef08971c77f54c38ec7b9355ba4f Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:07:13 +0100
-Subject: [PATCH 01/13] 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.
+Date: Fri, 30 Aug 2013 16:15:10 +0100
+Subject: [PATCH 01/18] KEYS: Rename public key parameter name arrays
-The "extra_certificates" file is then redundant.
+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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at redhat.com>
---
- kernel/Makefile | 35 +++++++++++++++++++++++++++++------
- kernel/modsign_certificate.S | 3 +--
- 2 files changed, 30 insertions(+), 8 deletions(-)
+ 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/kernel/Makefile b/kernel/Makefile
-index 35ef118..ab231ac 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -142,17 +142,40 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
- $(call if_changed,bc)
+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 @@
- 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
+ MODULE_LICENSE("GPL");
--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)
+-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);
--extra_certificates:
-- $(call cmd,touch)
-+targets += $(obj)/.x509.list
-+$(obj)/.x509.list:
-+ @echo $(X509_CERTIFICATES) >$@
+-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);
--kernel/modsign_certificate.o: signing_key.x509 extra_certificates
-+clean-files := x509_certificate_list .x509.list
+-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);
- ###############################################################################
- #
-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"
+ /*
+ * 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,
- GLOBAL(modsign_certificate_list)
-- .incbin "signing_key.x509"
-- .incbin "extra_certificates"
-+ .incbin "kernel/x509_certificate_list"
- GLOBAL(modsign_certificate_list_end)
+ 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 d1bf7ed78a52477636cdcb5a1bff5b19352472f5 Mon Sep 17 00:00:00 2001
+From d12f06db05dacb455714f00f070cce844fb3e44c Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:07:30 +0100
-Subject: [PATCH 02/13] KEYS: Separate the kernel signature checking keyring
- from module signing
+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
-Separate the kernel signature checking keyring from module signing so that it
-can be used by code other than the module-signing code.
+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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at redhat.com>
---
- include/keys/system_keyring.h | 23 ++++++++++
- init/Kconfig | 13 ++++++
- kernel/Makefile | 17 ++++---
- 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, 163 insertions(+), 124 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
+ 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/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 at 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.
-+ */
+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);
+
-+#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
+ 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 8d2905bce58b356e9b5313a4aaebb5085bb4c151 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at 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;
+
-+#endif /* _KEYS_SYSTEM_KEYRING_H */
-diff --git a/init/Kconfig b/init/Kconfig
-index 18bd9e3..cf14d07 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1668,6 +1668,18 @@ config BASE_SMALL
- default 0 if BASE_FULL
- default 1 if !BASE_FULL
++ /* 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)
-+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.
+ 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 df1662a5b9f37a88c1e112d4052eca79efc8e6fc Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at 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;
+
-+ Keys in this keyring are used by module signature checking.
++ 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]);
+
- menuconfig MODULES
- bool "Enable loadable module support"
- option modules
-@@ -1741,6 +1753,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 ab231ac..1262c6d 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -53,8 +53,9 @@ obj-$(CONFIG_SMP) += spinlock.o
- obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
- obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
- 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
-@@ -141,13 +142,14 @@ targets += timeconst.h
- $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
- $(call if_changed,bc)
++ algo = pk->algo;
++ if (!algo) {
++ if (pk->pkey_algo >= PKEY_ALGO__LAST)
++ return -ENOPKG;
++ algo = pkey_algo[pk->pkey_algo];
++ if (!algo)
++ return -ENOPKG;
++ }
--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 so that they get loaded into the system trusted keyring during
-+# boot.
- #
- ###############################################################################
-+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 $(X509_CERTIFICATES-y))
-@@ -163,10 +165,11 @@ $(shell rm $(obj)/.x509.list)
- endif
- endif
+- if (!pk->algo->verify_signature)
++ if (!algo->verify_signature)
+ return -ENOTSUPP;
--kernel/modsign_certificate.o: $(obj)/x509_certificate_list
-+kernel/system_certificates.o: $(obj)/x509_certificate_list
+- 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;
+ }
- 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)")
+- return pk->algo->verify_signature(pk, sig);
++ return algo->verify_signature(pk, sig);
++}
++EXPORT_SYMBOL_GPL(public_key_verify_signature);
+
- targets += $(obj)/x509_certificate_list
- $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
- $(call if_changed,x509certs)
-@@ -176,7 +179,9 @@ $(obj)/.x509.list:
- @echo $(X509_CERTIFICATES) >$@
++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);
+ }
- clean-files := x509_certificate_list .x509.list
-+endif
+ /*
+@@ -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 {
+ };
-+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 at 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 @@
+ 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 322d3b7e2debb3c7983dce2b80a5aefa4e7b1bda Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at 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 743143dd12661df376dcfc916b626b01d8ec84a4 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at 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.
*/
--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 f2970bd..0034e36 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -14,6 +14,7 @@
++#include <linux/time.h>
#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,
+ struct x509_certificate {
+--
+1.8.3.1
+
+
+From a326ca89468c73dacb00fa247e92873d09e1387b Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at chromium.org>
+Reviewed-by: Josh Boyer <jwboyer at 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 */
- pr_debug("Look up: \"%s\"\n", id);
+ 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;
-- 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 at 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);
+ 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);
+
+/*
-+ * Load the compiled-in list of X.509 certificates.
++ * x509_public_key.c
+ */
-+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;
++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__);
+-
+
-+ 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;
-+ }
++ if (cert->sig.rsa.s)
++ return 0;
+
-+ 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;
+
-+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 209cfd7eda86173415d394a9ff868345197d7b3d Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:07:37 +0100
-Subject: [PATCH 03/13] 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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at 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 */
- };
+ /* 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);
- 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 */
+ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+ digest_size = crypto_shash_digestsize(tfm);
- /* 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 */
+- /* 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;
- 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");
+- 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;
-+ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
- return 0;
- }
+- 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;
-@@ -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,
+ 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);
- 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;
+- 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;
- memset(&key->type_data, 0, sizeof(key->type_data));
+- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
+- if (ret < 0)
+- goto error_mpi;
++ pr_devel("==>%s()\n", __func__);
-@@ -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);
+- ret = public_key_verify_signature(pub, sig);
++ ret = x509_get_sig_params(cert);
++ if (ret < 0)
++ return ret;
-+ 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);
++ 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);
-+ 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));
+ /*
+ * 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 6549cbca91abf561df8f501c763a8e7822936294 Mon Sep 17 00:00:00 2001
+From 2857db9154b0fcfb8ba490c12f98cd47cc3f46fc Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:15:10 +0100
-Subject: [PATCH 04/13] KEYS: Rename public key parameter name arrays
+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
-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".
+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 at chromium.org>
Signed-off-by: David Howells <dhowells at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at 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(-)
+ crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
-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
+index b7c81d8..eb368d4 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)
+@@ -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);
-- 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]);
++
++ 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,
- 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 0034e36..0b6b870 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -55,7 +55,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);
-
-@@ -218,7 +218,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 b2c8f8924f17c25209d8fe55f74b9d5830ad191c Mon Sep 17 00:00:00 2001
+From f78f0e8694517a3b1e5393d6ea0d46084bdc816a Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:15:18 +0100
-Subject: [PATCH 05/13] KEYS: Move the algorithm pointer array from x509 to
- public_key.c
+Date: Fri, 30 Aug 2013 16:18:31 +0100
+Subject: [PATCH 09/18] X.509: Handle certificates that lack an
+ authorityKeyIdentifier field
-Move the public-key algorithm pointer array from x509_public_key.c to
-public_key.c as it isn't X.509 specific.
+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 at redhat.com>
Reviewed-by: Kees Cook <keescook at chromium.org>
Reviewed-by: Josh Boyer <jwboyer at 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(-)
+ crypto/asymmetric_keys/x509_public_key.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 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
+index eb368d4..0f55e3b 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"
+@@ -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]);
--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)
+- 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;
- }
-
-- cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
-+ cert->pub->algo = pkey_algo[cert->pkey_algo];
+@@ -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 */
-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,
+- /* 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 760486c4376aab8cd8ce9c7d2ad67a19d713b119 Mon Sep 17 00:00:00 2001
+From 4d729ace6be1c3b2b5d9b0d0301a4ffd342ec74a Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:15:24 +0100
-Subject: [PATCH 06/13] KEYS: Store public key algo ID in public_key struct
+Date: Tue, 18 Jun 2013 17:40:44 +0100
+Subject: [PATCH 10/18] X.509: Remove certificate date checks
-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().
+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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at redhat.com>
+cc: David Woodhouse <dwmw2 at infradead.org>
+cc: Rusty Russell <rusty at rustcorp.com.au>
+cc: Josh Boyer <jwboyer at redhat.com>
+cc: Alexander Holler <holler at ahsoftware.de>
+cc: stable at vger.kernel.org
---
- 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(-)
+ crypto/asymmetric_keys/x509_public_key.c | 38 --------------------------------
+ 1 file changed, 38 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
+index 0f55e3b..c1540e8 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)
+@@ -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;
}
-- cert->pub->algo = pkey_algo[cert->pkey_algo];
-+ cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
+- 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;
- /* 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 37688af0338d8c521ffefce187b03a5fbaefa423 Mon Sep 17 00:00:00 2001
+From 33f859fea67ab5307da4049e947fbc23cdd13a27 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:15:30 +0100
-Subject: [PATCH 07/13] KEYS: Split public_key_verify_signature() and make
- available
+Date: Fri, 30 Aug 2013 16:07:13 +0100
+Subject: [PATCH 11/18] KEYS: Load *.x509 files into kernel keyring
-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.
+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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at 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(-)
+ kernel/Makefile | 35 +++++++++++++++++++++++++++++------
+ kernel/modsign_certificate.S | 3 +--
+ 2 files changed, 30 insertions(+), 8 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;
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 1ce4755..c34e5f9 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -142,17 +142,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))
+
-+ 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]);
++ifeq ($(X509_CERTIFICATES),)
++$(warning *** No X.509 certificates found ***)
++endif
+
-+ 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);
++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
+
-+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);
- }
++kernel/modsign_certificate.o: $(obj)/x509_certificate_list
- /*
-@@ -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 {
- };
+-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)
- 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;
+-extra_certificates:
+- $(call cmd,touch)
++targets += $(obj)/.x509.list
++$(obj)/.x509.list:
++ @echo $(X509_CERTIFICATES) >$@
-- ret = pub->algo->verify_signature(pub, sig);
-+ ret = public_key_verify_signature(pub, sig);
+-kernel/modsign_certificate.o: signing_key.x509 extra_certificates
++clean-files := x509_certificate_list .x509.list
- pr_debug("Cert Verification: %d\n", ret);
+ ###############################################################################
+ #
+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 49763042e968f7342711ecf28e9465f6d77c0ddd Mon Sep 17 00:00:00 2001
+From 068606ba7df3206e5a09b544b4b89ed09cd30f44 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:15:37 +0100
-Subject: [PATCH 08/13] KEYS: Store public key algo ID in public_key_signature
- struct
+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
-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.
+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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at redhat.com>
---
- include/crypto/public_key.h | 1 +
- 1 file changed, 1 insertion(+)
+ kernel/Makefile | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
-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];
+diff --git a/kernel/Makefile b/kernel/Makefile
+index c34e5f9..2c24195 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -144,13 +144,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 d759ad5c13364bc7dcd6dd66d1a63f29f3432f72 Mon Sep 17 00:00:00 2001
+From 9006cfbd669e9ba52d1a91db2ffd9482ad8a6090 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:16:34 +0100
-Subject: [PATCH 09/13] X.509: struct x509_certificate needs struct tm
- declaring
+Date: Fri, 30 Aug 2013 16:07:30 +0100
+Subject: [PATCH 13/18] KEYS: Separate the kernel signature checking keyring
+ from module signing
-struct x509_certificate needs struct tm declaring by #inclusion of linux/time.h
-prior to its definition.
+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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at redhat.com>
---
- crypto/asymmetric_keys/x509_parser.h | 1 +
- 1 file changed, 1 insertion(+)
+ 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/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 @@
+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 at 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 18bd9e3..cf14d07 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1668,6 +1668,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
+@@ -1741,6 +1753,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 2c24195..6313698 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -54,8 +54,9 @@ obj-$(CONFIG_SMP) += spinlock.o
+ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
+ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
+ 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
+@@ -141,11 +142,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
+@@ -153,6 +154,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), \
+@@ -169,10 +171,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)
+@@ -182,7 +185,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 at 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.
*/
-+#include <linux/time.h>
+-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"
- struct x509_certificate {
---
-1.8.3.1
-
-
-From 779ecd05627f895cfd6970dcfbd3ed35092f7510 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:18:02 +0100
-Subject: [PATCH 10/13] 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 at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at 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;
- }
+ /*
+@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
-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 */
- };
+ pr_debug("Look up: \"%s\"\n", id);
- /*
-@@ -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);
+- 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 at 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[];
+
+/*
-+ * x509_public_key.c
++ * Load the compiled-in keys
+ */
-+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__);
--
++static __init int system_trusted_keyring_init(void)
++{
++ pr_notice("Initialise system trusted keyring\n");
+
-+ if (cert->sig.rsa.s)
-+ return 0;
++ 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");
+
-+ 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;
++ return 0;
++}
+
- /* 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;
++/*
++ * 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 c0522b3236c27359bd61fee0f0b74be9f8e2ad60 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at 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 at redhat.com>
+Reviewed-by: Kees Cook <keescook at 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 */
+ };
-- 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;
+ 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 */
-- 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;
+ /* 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 */
- 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);
+ 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");
-- 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;
++ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
+ return 0;
+ }
-- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
-- if (ret < 0)
-- goto error_mpi;
-+ pr_devel("==>%s()\n", __func__);
+@@ -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,
-- ret = public_key_verify_signature(pub, sig);
-+ ret = x509_get_sig_params(cert);
-+ if (ret < 0)
-+ return ret;
+ 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;
-+ 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);
+ memset(&key->type_data, 0, sizeof(key->type_data));
- /*
- * 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]);
+@@ -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);
- if (!cert->fingerprint || !cert->authority) {
- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
++ 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 81dc804bab8ac3703f237e74464054fae71c429e Mon Sep 17 00:00:00 2001
+From e8e9a6af1d2de6aca01751ccaf0475ed46f9bdb2 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:18:15 +0100
-Subject: [PATCH 11/13] X.509: Check the algorithm IDs obtained from parsing an
- X.509 certificate
+Date: Wed, 4 Sep 2013 19:28:03 +0100
+Subject: [PATCH 15/18] KEYS: Set the asymmetric-key type default search method
-Check that the algorithm IDs obtained from the ASN.1 parse by OID lookup
-corresponds to algorithms that are available to us.
+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.
-Reported-by: Kees Cook <keescook at chromium.org>
Signed-off-by: David Howells <dhowells at redhat.com>
---
- crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
+ crypto/asymmetric_keys/asymmetric_type.c | 1 +
+ 1 file changed, 1 insertion(+)
-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)
+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);
- 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 9d3c831f1409174fcda6a21ede05f3a3155b1671 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 30 Aug 2013 16:18:31 +0100
-Subject: [PATCH 12/13] X.509: Handle certificates that lack an
- authorityKeyIdentifier field
+From dfb7781ebba28004f95f7af4e039d8b44697c87c Mon Sep 17 00:00:00 2001
+From: Mimi Zohar <zohar at 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
-Handle certificates that lack an authorityKeyIdentifier field by assuming
-they're self-signed and checking their signatures against themselves.
+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 at us.ibm.com>
Signed-off-by: David Howells <dhowells at redhat.com>
-Reviewed-by: Kees Cook <keescook at chromium.org>
-Reviewed-by: Josh Boyer <jwboyer at redhat.com>
---
- crypto/asymmetric_keys/x509_public_key.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
+ 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 052744b12209e66ede2a04ec31b9bb7ff40bbc9a Mon Sep 17 00:00:00 2001
+From: Mimi Zohar <zohar at 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 at linux.vnet.ibm.com>
+Signed-off-by: David Howells <dhowells at 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 eb368d4..0f55e3b 100644
+index c1540e8..8761264 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]);
+@@ -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"
-- 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;
+ /*
++ * 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 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);
+ /*
++ * 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 1a62a422d6b6e084ba88062d1d1f33e6a92dc35c Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Tue, 18 Jun 2013 17:40:44 +0100
-Subject: [PATCH 13/13] X.509: Remove certificate date checks
+From 8b39d9a6d9f805f6a2e837bf8b9595f701ea4a1c Mon Sep 17 00:00:00 2001
+From: Mimi Zohar <zohar at 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
-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?
+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 at us.ibm.com>
Signed-off-by: David Howells <dhowells at redhat.com>
-cc: David Woodhouse <dwmw2 at infradead.org>
-cc: Rusty Russell <rusty at rustcorp.com.au>
-cc: Josh Boyer <jwboyer at redhat.com>
-cc: Alexander Holler <holler at ahsoftware.de>
-cc: stable at vger.kernel.org
---
- crypto/asymmetric_keys/x509_public_key.c | 38 --------------------------------
- 1 file changed, 38 deletions(-)
+ security/keys/process_keys.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
-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;
+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
More information about the scm-commits
mailing list