#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/efi.h>
-#include <linux/verify_pefile.h>
-#include <keys/system_keyring.h>
+#include <linux/verification.h>
 
 #include <asm/bootparam.h>
 #include <asm/setup.h>
 #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
 static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
 {
-       bool trusted;
-       int ret;
-
-       ret = verify_pefile_signature(kernel, kernel_len,
-                                     system_trusted_keyring,
-                                     VERIFYING_KEXEC_PE_SIGNATURE,
-                                     &trusted);
-       if (ret < 0)
-               return ret;
-       if (!trusted)
-               return -EKEYREJECTED;
-       return 0;
+       return verify_pefile_signature(kernel, kernel_len,
+                                      NULL,
+                                      VERIFYING_KEXEC_PE_SIGNATURE);
 }
 #endif
 
 
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
 
 /**
- * Verify a PKCS#7-based signature on system data.
- * @data: The data to be verified.
+ * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
+ * @data: The data to be verified (NULL if expecting internal data).
  * @len: Size of @data.
  * @raw_pkcs7: The PKCS#7 message that is the signature.
  * @pkcs7_len: The size of @raw_pkcs7.
+ * @trusted_keys: Trusted keys to use (NULL for system_trusted_keyring).
  * @usage: The use to which the key is being put.
+ * @view_content: Callback to gain access to content.
+ * @ctx: Context for callback.
  */
-int system_verify_data(const void *data, unsigned long len,
-                      const void *raw_pkcs7, size_t pkcs7_len,
-                      enum key_being_used_for usage)
+int verify_pkcs7_signature(const void *data, size_t len,
+                          const void *raw_pkcs7, size_t pkcs7_len,
+                          struct key *trusted_keys,
+                          int untrusted_error,
+                          enum key_being_used_for usage,
+                          int (*view_content)(void *ctx,
+                                              const void *data, size_t len,
+                                              size_t asn1hdrlen),
+                          void *ctx)
 {
        struct pkcs7_message *pkcs7;
        bool trusted;
                return PTR_ERR(pkcs7);
 
        /* The data should be detached - so we need to supply it. */
-       if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
+       if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
                pr_err("PKCS#7 signature with non-detached data\n");
                ret = -EBADMSG;
                goto error;
        if (ret < 0)
                goto error;
 
-       ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
+       if (!trusted_keys)
+               trusted_keys = system_trusted_keyring;
+       ret = pkcs7_validate_trust(pkcs7, trusted_keys, &trusted);
        if (ret < 0)
                goto error;
 
-       if (!trusted) {
+       if (!trusted && untrusted_error) {
                pr_err("PKCS#7 signature not signed with a trusted key\n");
-               ret = -ENOKEY;
+               ret = untrusted_error;
+               goto error;
+       }
+
+       if (view_content) {
+               size_t asn1hdrlen;
+
+               ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
+               if (ret < 0) {
+                       if (ret == -ENODATA)
+                               pr_devel("PKCS#7 message does not contain data\n");
+                       goto error;
+               }
+
+               ret = view_content(ctx, data, len, asn1hdrlen);
        }
 
 error:
        pr_devel("<==%s() = %d\n", __func__, ret);
        return ret;
 }
-EXPORT_SYMBOL_GPL(system_verify_data);
+EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
 
 #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
 
 
 config PKCS7_TEST_KEY
        tristate "PKCS#7 testing key type"
-       depends on PKCS7_MESSAGE_PARSER
-       select SYSTEM_TRUSTED_KEYRING
+       depends on SYSTEM_DATA_VERIFICATION
        help
          This option provides a type of key that can be loaded up from a
          PKCS#7 message - provided the message is signed by a trusted key.  If
 config SIGNED_PE_FILE_VERIFICATION
        bool "Support for PE file signature verification"
        depends on PKCS7_MESSAGE_PARSER=y
+       depends on SYSTEM_DATA_VERIFICATION
        select ASN1
        select OID_REGISTRY
        help
 
 /*
  * Parse a Microsoft Individual Code Signing blob
  */
-int mscode_parse(struct pefile_context *ctx)
+int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
+                size_t asn1hdrlen)
 {
-       const void *content_data;
-       size_t data_len;
-       int ret;
-
-       ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
-
-       if (ret) {
-               pr_debug("PKCS#7 message does not contain data\n");
-               return ret;
-       }
+       struct pefile_context *ctx = _ctx;
 
+       content_data -= asn1hdrlen;
+       data_len += asn1hdrlen;
        pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
                 content_data);
 
 {
        struct pefile_context *ctx = context;
 
-       ctx->digest = value;
-       ctx->digest_len = vlen;
-       return 0;
+       ctx->digest = kmemdup(value, vlen, GFP_KERNEL);
+       return ctx->digest ? 0 : -ENOMEM;
 }
 
 #include <linux/key.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/verification.h>
 #include <linux/key-type.h>
-#include <keys/asymmetric-type.h>
-#include <crypto/pkcs7.h>
 #include <keys/user-type.h>
-#include <keys/system_keyring.h>
-#include "pkcs7_parser.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PKCS#7 testing key type");
                 "Usage to specify when verifying the PKCS#7 message");
 
 /*
- * Preparse a PKCS#7 wrapped and validated data blob.
+ * Retrieve the PKCS#7 message content.
  */
-static int pkcs7_preparse(struct key_preparsed_payload *prep)
+static int pkcs7_view_content(void *ctx, const void *data, size_t len,
+                             size_t asn1hdrlen)
 {
-       enum key_being_used_for usage = pkcs7_usage;
-       struct pkcs7_message *pkcs7;
-       const void *data, *saved_prep_data;
-       size_t datalen, saved_prep_datalen;
-       bool trusted;
+       struct key_preparsed_payload *prep = ctx;
+       const void *saved_prep_data;
+       size_t saved_prep_datalen;
        int ret;
 
-       kenter("");
-
-       if (usage >= NR__KEY_BEING_USED_FOR) {
-               pr_err("Invalid usage type %d\n", usage);
-               return -EINVAL;
-       }
-
        saved_prep_data = prep->data;
        saved_prep_datalen = prep->datalen;
-       pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
-       if (IS_ERR(pkcs7)) {
-               ret = PTR_ERR(pkcs7);
-               goto error;
-       }
-
-       ret = pkcs7_verify(pkcs7, usage);
-       if (ret < 0)
-               goto error_free;
-
-       ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
-       if (ret < 0)
-               goto error_free;
-       if (!trusted)
-               pr_warn("PKCS#7 message doesn't chain back to a trusted key\n");
-
-       ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false);
-       if (ret < 0)
-               goto error_free;
-
        prep->data = data;
-       prep->datalen = datalen;
+       prep->datalen = len;
+
        ret = user_preparse(prep);
+
        prep->data = saved_prep_data;
        prep->datalen = saved_prep_datalen;
-
-error_free:
-       pkcs7_free_message(pkcs7);
-error:
-       kleave(" = %d", ret);
        return ret;
 }
 
+/*
+ * Preparse a PKCS#7 wrapped and validated data blob.
+ */
+static int pkcs7_preparse(struct key_preparsed_payload *prep)
+{
+       enum key_being_used_for usage = pkcs7_usage;
+
+       if (usage >= NR__KEY_BEING_USED_FOR) {
+               pr_err("Invalid usage type %d\n", usage);
+               return -EINVAL;
+       }
+
+       return verify_pkcs7_signature(NULL, 0,
+                                     prep->data, prep->datalen,
+                                     NULL, -ENOKEY, usage,
+                                     pkcs7_view_content, prep);
+}
+
 /*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
 
  * @pkcs7: The preparsed PKCS#7 message to access
  * @_data: Place to return a pointer to the data
  * @_data_len: Place to return the data length
- * @want_wrapper: True if the ASN.1 object header should be included in the data
+ * @_headerlen: Size of ASN.1 header not included in _data
  *
- * Get access to the data content of the PKCS#7 message, including, optionally,
- * the header of the ASN.1 object that contains it.  Returns -ENODATA if the
- * data object was missing from the message.
+ * Get access to the data content of the PKCS#7 message.  The size of the
+ * header of the ASN.1 object that contains it is also provided and can be used
+ * to adjust *_data and *_data_len to get the entire object.
+ *
+ * Returns -ENODATA if the data object was missing from the message.
  */
 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
                           const void **_data, size_t *_data_len,
-                          bool want_wrapper)
+                          size_t *_headerlen)
 {
-       size_t wrapper;
-
        if (!pkcs7->data)
                return -ENODATA;
 
-       wrapper = want_wrapper ? pkcs7->data_hdrlen : 0;
-       *_data = pkcs7->data - wrapper;
-       *_data_len = pkcs7->data_len + wrapper;
+       *_data = pkcs7->data;
+       *_data_len = pkcs7->data_len;
+       if (_headerlen)
+               *_headerlen = pkcs7->data_hdrlen;
        return 0;
 }
 EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
 
 #include <linux/err.h>
 #include <linux/pe.h>
 #include <linux/asn1.h>
-#include <crypto/pkcs7.h>
+#include <linux/verification.h>
 #include <crypto/hash.h>
 #include "verify_pefile.h"
 
  * verify_pefile_signature - Verify the signature on a PE binary image
  * @pebuf: Buffer containing the PE binary image
  * @pelen: Length of the binary image
- * @trust_keyring: Signing certificates to use as starting points
+ * @trust_keys: Signing certificate(s) to use as starting points
  * @usage: The use to which the key is being put.
- * @_trusted: Set to true if trustworth, false otherwise
  *
  * Validate that the certificate chain inside the PKCS#7 message inside the PE
  * binary image intersects keys we already know and trust.
  * May also return -ENOMEM.
  */
 int verify_pefile_signature(const void *pebuf, unsigned pelen,
-                           struct key *trusted_keyring,
-                           enum key_being_used_for usage,
-                           bool *_trusted)
+                           struct key *trusted_keys,
+                           enum key_being_used_for usage)
 {
-       struct pkcs7_message *pkcs7;
        struct pefile_context ctx;
-       const void *data;
-       size_t datalen;
        int ret;
 
        kenter("");
        if (ret < 0)
                return ret;
 
-       pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len);
-       if (IS_ERR(pkcs7))
-               return PTR_ERR(pkcs7);
-       ctx.pkcs7 = pkcs7;
-
-       ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false);
-       if (ret < 0 || datalen == 0) {
-               pr_devel("PKCS#7 message does not contain data\n");
-               ret = -EBADMSG;
-               goto error;
-       }
-
-       ret = mscode_parse(&ctx);
+       ret = verify_pkcs7_signature(NULL, 0,
+                                    pebuf + ctx.sig_offset, ctx.sig_len,
+                                    trusted_keys, -EKEYREJECTED, usage,
+                                    mscode_parse, &ctx);
        if (ret < 0)
                goto error;
 
         * contents.
         */
        ret = pefile_digest_pe(pebuf, pelen, &ctx);
-       if (ret < 0)
-               goto error;
-
-       ret = pkcs7_verify(pkcs7, usage);
-       if (ret < 0)
-               goto error;
-
-       ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted);
 
 error:
-       pkcs7_free_message(ctx.pkcs7);
+       kfree(ctx.digest);
        return ret;
 }
 
  * 2 of the Licence, or (at your option) any later version.
  */
 
-#include <linux/verify_pefile.h>
 #include <crypto/pkcs7.h>
 #include <crypto/hash_info.h>
 
        unsigned        sig_offset;
        unsigned        sig_len;
        const struct section_header *secs;
-       struct pkcs7_message *pkcs7;
 
        /* PKCS#7 MS Individual Code Signing content */
        const void      *digest;                /* Digest */
 /*
  * mscode_parser.c
  */
-extern int mscode_parse(struct pefile_context *ctx);
+extern int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
+                       size_t asn1hdrlen);
 
 #ifndef _CRYPTO_PKCS7_H
 #define _CRYPTO_PKCS7_H
 
+#include <linux/verification.h>
 #include <crypto/public_key.h>
 
 struct key;
 
 extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
                                  const void **_data, size_t *_datalen,
-                                 bool want_wrapper);
+                                 size_t *_headerlen);
 
 /*
  * pkcs7_trust.c
 
 #ifndef _LINUX_PUBLIC_KEY_H
 #define _LINUX_PUBLIC_KEY_H
 
-/*
- * The use to which an asymmetric key is being put.
- */
-enum key_being_used_for {
-       VERIFYING_MODULE_SIGNATURE,
-       VERIFYING_FIRMWARE_SIGNATURE,
-       VERIFYING_KEXEC_PE_SIGNATURE,
-       VERIFYING_KEY_SIGNATURE,
-       VERIFYING_KEY_SELF_SIGNATURE,
-       VERIFYING_UNSPECIFIED_SIGNATURE,
-       NR__KEY_BEING_USED_FOR
-};
-extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
-
 /*
  * Cryptographic data for the public-key subtype of the asymmetric key type.
  *
 
 #define _KEYS_ASYMMETRIC_TYPE_H
 
 #include <linux/key-type.h>
+#include <linux/verification.h>
 
 extern struct key_type key_type_asymmetric;
 
 
 #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
 
 #include <linux/key.h>
+#include <linux/verification.h>
 #include <crypto/public_key.h>
 
 extern struct key *system_trusted_keyring;
 }
 #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,
-                             enum key_being_used_for usage);
-#endif
-
 #ifdef CONFIG_IMA_MOK_KEYRING
 extern struct key *ima_mok_keyring;
 extern struct key *ima_blacklist_keyring;
 
--- /dev/null
+/* Signature verification
+ *
+ * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_VERIFICATION_H
+#define _LINUX_VERIFICATION_H
+
+/*
+ * The use to which an asymmetric key is being put.
+ */
+enum key_being_used_for {
+       VERIFYING_MODULE_SIGNATURE,
+       VERIFYING_FIRMWARE_SIGNATURE,
+       VERIFYING_KEXEC_PE_SIGNATURE,
+       VERIFYING_KEY_SIGNATURE,
+       VERIFYING_KEY_SELF_SIGNATURE,
+       VERIFYING_UNSPECIFIED_SIGNATURE,
+       NR__KEY_BEING_USED_FOR
+};
+extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
+
+#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
+
+struct key;
+
+extern int verify_pkcs7_signature(const void *data, size_t len,
+                                 const void *raw_pkcs7, size_t pkcs7_len,
+                                 struct key *trusted_keys,
+                                 int untrusted_error,
+                                 enum key_being_used_for usage,
+                                 int (*view_content)(void *ctx,
+                                                     const void *data, size_t len,
+                                                     size_t asn1hdrlen),
+                                 void *ctx);
+
+#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION
+extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
+                                  struct key *trusted_keys,
+                                  enum key_being_used_for usage);
+#endif
+
+#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
+#endif /* _LINUX_VERIFY_PEFILE_H */
 
+++ /dev/null
-/* Signed PE file verification
- *
- * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#ifndef _LINUX_VERIFY_PEFILE_H
-#define _LINUX_VERIFY_PEFILE_H
-
-#include <crypto/public_key.h>
-
-extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
-                                  struct key *trusted_keyring,
-                                  enum key_being_used_for usage,
-                                  bool *_trusted);
-
-#endif /* _LINUX_VERIFY_PEFILE_H */
 
                return -EBADMSG;
        }
 
-       return system_verify_data(mod, modlen, mod + modlen, sig_len,
-                                 VERIFYING_MODULE_SIGNATURE);
+       return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+                                     NULL, -ENOKEY, VERIFYING_MODULE_SIGNATURE,
+                                     NULL, NULL);
 }