MODSIGN: Extract the blob PKCS#7 signature verifier from module signing
authorDavid Howells <dhowells@redhat.com>
Mon, 20 Jul 2015 20:16:28 +0000 (21:16 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 7 Aug 2015 15:26:13 +0000 (16:26 +0100)
Extract the function that drives the PKCS#7 signature verification given a
data blob and a PKCS#7 blob out from the module signing code and lump it with
the system keyring code as it's generic.  This makes it independent of module
config options and opens it to use by the firmware loader.

Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Ming Lei <ming.lei@canonical.com>
Cc: Seth Forshee <seth.forshee@canonical.com>
Cc: Kyle McMartin <kyle@kernel.org>
include/keys/system_keyring.h
init/Kconfig
kernel/module_signing.c
kernel/system_keyring.c

index 72665eb8069269f4e1b6726c8cd2d04374405ab8..9791c907cdb70c502e570f26eb20060f5763d71d 100644 (file)
@@ -28,4 +28,9 @@ static inline struct key *get_system_trusted_keyring(void)
 }
 #endif
 
+#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
+extern int system_verify_data(const void *data, unsigned long len,
+                             const void *raw_pkcs7, size_t pkcs7_len);
+#endif
+
 #endif /* _KEYS_SYSTEM_KEYRING_H */
index e16d9e587cee88d884b63b67faf318dbc57de744..14b3d8422502c49f580941c22a037815b785b500 100644 (file)
@@ -1752,6 +1752,24 @@ config SYSTEM_TRUSTED_KEYRING
 
          Keys in this keyring are used by module signature checking.
 
+config SYSTEM_DATA_VERIFICATION
+       def_bool n
+       select SYSTEM_TRUSTED_KEYRING
+       select KEYS
+       select CRYPTO
+       select ASYMMETRIC_KEY_TYPE
+       select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+       select PUBLIC_KEY_ALGO_RSA
+       select ASN1
+       select OID_REGISTRY
+       select X509_CERTIFICATE_PARSER
+       select PKCS7_MESSAGE_PARSER
+       help
+         Provide PKCS#7 message verification using the contents of the system
+         trusted keyring to provide public keys.  This then can be used for
+         module verification, kexec image verification and firmware blob
+         verification.
+
 config PROFILING
        bool "Profiling support"
        help
@@ -1860,16 +1878,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
-       select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-       select PUBLIC_KEY_ALGO_RSA
-       select ASN1
-       select OID_REGISTRY
-       select X509_CERTIFICATE_PARSER
-       select PKCS7_MESSAGE_PARSER
+       select SYSTEM_DATA_VERIFICATION
        help
          Check modules for valid signatures upon load: the signature
          is simply appended to the module. For more information see
index 8eb20cc66b396193b27ba3d4defcb7010ec7946b..70ad463f6df059c43267490da7fcfa0744cec6d4 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/err.h>
 #include <keys/system_keyring.h>
 #include <crypto/public_key.h>
-#include <crypto/pkcs7.h>
 #include "module-internal.h"
 
 /*
@@ -36,46 +34,6 @@ struct module_signature {
        __be32  sig_len;        /* Length of signature data */
 };
 
-/*
- * Verify a PKCS#7-based signature on a module.
- */
-static int mod_verify_pkcs7(const void *mod, unsigned long modlen,
-                           const void *raw_pkcs7, size_t pkcs7_len)
-{
-       struct pkcs7_message *pkcs7;
-       bool trusted;
-       int ret;
-
-       pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
-       if (IS_ERR(pkcs7))
-               return PTR_ERR(pkcs7);
-
-       /* The data should be detached - so we need to supply it. */
-       if (pkcs7_supply_detached_data(pkcs7, mod, modlen) < 0) {
-               pr_err("PKCS#7 signature with non-detached data\n");
-               ret = -EBADMSG;
-               goto error;
-       }
-
-       ret = pkcs7_verify(pkcs7);
-       if (ret < 0)
-               goto error;
-
-       ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
-       if (ret < 0)
-               goto error;
-
-       if (!trusted) {
-               pr_err("PKCS#7 signature not signed with a trusted key\n");
-               ret = -ENOKEY;
-       }
-
-error:
-       pkcs7_free_message(pkcs7);
-       pr_devel("<==%s() = %d\n", __func__, ret);
-       return ret;
-}
-
 /*
  * Verify the signature on a module.
  */
@@ -114,5 +72,5 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
                return -EBADMSG;
        }
 
-       return mod_verify_pkcs7(mod, modlen, mod + modlen, sig_len);
+       return system_verify_data(mod, modlen, mod + modlen, sig_len);
 }
index 4cda71ee51c7a1171c8ebccf1a791164173b077f..95f2dcbc761626dfad3f61d48ce6073396576a21 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
+#include <crypto/pkcs7.h>
 
 struct key *system_trusted_keyring;
 EXPORT_SYMBOL_GPL(system_trusted_keyring);
@@ -103,3 +104,52 @@ dodgy_cert:
        return 0;
 }
 late_initcall(load_system_certificate_list);
+
+#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
+
+/**
+ * Verify a PKCS#7-based signature on system data.
+ * @data: The data to be verified.
+ * @len: Size of @data.
+ * @raw_pkcs7: The PKCS#7 message that is the signature.
+ * @pkcs7_len: The size of @raw_pkcs7.
+ */
+int system_verify_data(const void *data, unsigned long len,
+                      const void *raw_pkcs7, size_t pkcs7_len)
+{
+       struct pkcs7_message *pkcs7;
+       bool trusted;
+       int ret;
+
+       pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
+       if (IS_ERR(pkcs7))
+               return PTR_ERR(pkcs7);
+
+       /* The data should be detached - so we need to supply it. */
+       if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
+               pr_err("PKCS#7 signature with non-detached data\n");
+               ret = -EBADMSG;
+               goto error;
+       }
+
+       ret = pkcs7_verify(pkcs7);
+       if (ret < 0)
+               goto error;
+
+       ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
+       if (ret < 0)
+               goto error;
+
+       if (!trusted) {
+               pr_err("PKCS#7 signature not signed with a trusted key\n");
+               ret = -ENOKEY;
+       }
+
+error:
+       pkcs7_free_message(pkcs7);
+       pr_devel("<==%s() = %d\n", __func__, ret);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(system_verify_data);
+
+#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */