[kernel] Add kernel module signing on x86

Josh Boyer jwboyer at fedoraproject.org
Wed Mar 7 20:07:36 UTC 2012


commit c2a12cd16fff536ed98eb457a85b3a0842b4f825
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Tue Mar 6 16:09:57 2012 -0500

    Add kernel module signing on x86
    
    Leave enforcing disabled for now, so unsigned modules can still load.  This
    can be switched by adding "enforcemodulesig=1" to the kernel command line.

 config-generic         |    7 +-
 config-x86-generic     |    5 +
 genkey                 |    8 +
 kernel.spec            |   56 +-
 modsign-20111207.patch | 7361 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 7435 insertions(+), 2 deletions(-)
---
diff --git a/config-generic b/config-generic
index a68f37f..d63c834 100644
--- a/config-generic
+++ b/config-generic
@@ -3842,7 +3842,7 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SEQIV=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TGR192=m
@@ -4392,3 +4392,8 @@ CONFIG_INTEL_MID_PTI=m
 CONFIG_IOMMU_SUPPORT=y
 
 # CONFIG_PM_DEVFREQ is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_VERIFY_ELF is not set
+# CONFIG_CRYPTO_KEY_TYPE is not set
+# CONFIG_PGP_LIBRARY is not set
+# CONFIG_PGP_PRELOAD is not set
diff --git a/config-x86-generic b/config-x86-generic
index 02e1fe7..d8f4d03 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -403,3 +403,8 @@ CONFIG_DRM_GMA500=m
 # Maybe enable in debug kernels?
 # CONFIG_DEBUG_NMI_SELFTEST is not set
 
+CONFIG_MPILIB=y
+CONFIG_MODULE_SIG=y
+# CONFIG_MODULE_SIG_SHA1 is not set
+CONFIG_MODULE_SIG_SHA256=y
+# CONFIG_MODULE_SIG_FORCE is not set
diff --git a/genkey b/genkey
new file mode 100644
index 0000000..4868504
--- /dev/null
+++ b/genkey
@@ -0,0 +1,8 @@
+%pubring kernel.pub
+%secring kernel.sec
+Key-Type: RSA
+Key-Length: 2048
+Name-Real: Fedora Project
+Name-Comment: Kernel Module GPG key
+%commit
+
diff --git a/kernel.spec b/kernel.spec
index e4ee511..e3ec5d0 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -8,6 +8,14 @@ Summary: The Linux kernel
 # be 0.
 %global released_kernel 0
 
+# Sign modules on x86.  Make sure the config files match this setting if more
+# architectures are added.
+%ifarch %{ix86} x86_64
+%global signmodules 1
+%else
+%global signmodules 0
+%endif
+
 # Save original buildid for later if it's defined
 %if 0%{?buildid:1}
 %global orig_buildid %{buildid}
@@ -54,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 2
+%global baserelease 3
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -573,9 +581,17 @@ BuildRequires: rpm-build >= 4.9.0-1, elfutils >= elfutils-0.153-1
 %define debuginfo_args --strict-build-id -r
 %endif
 
+%if %{signmodules}
+BuildRequires: gnupg
+%endif
+
 Source0: ftp://ftp.kernel.org/pub/linux/kernel/v3.0/linux-%{kversion}.tar.xz
 Source1: compat-wireless-%{cwversion}.tar.bz2
 
+%if %{signmodules}
+Source11: genkey
+%endif
+
 Source15: merge.pl
 Source16: mod-extra.list
 
@@ -696,6 +712,7 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch
 Patch800: linux-2.6-crash-driver.patch
 
 # crypto/
+Patch900: modsign-20111207.patch
 
 # virt + ksm patches
 Patch1555: fix_xen_guest_on_old_EC2.patch
@@ -1430,6 +1447,7 @@ ApplyPatch linux-2.6-crash-driver.patch
 ApplyPatch linux-2.6-e1000-ich9-montevina.patch
 
 # crypto/
+ApplyPatch modsign-20111207.patch
 
 # Assorted Virt Fixes
 ApplyPatch fix_xen_guest_on_old_EC2.patch
@@ -1556,6 +1574,30 @@ done
 # remove unnecessary SCM files
 find . -name .gitignore -exec rm -f {} \; >/dev/null
 
+%if %{signmodules}
+cat <<EOF
+###
+### Now generating a PGP key pair to be used for signing modules.
+###
+### If this takes a long time, you might wish to run rngd in the background to
+### keep the supply of entropy topped up.  It needs to be run as root, and
+### should use a hardware random number generator if one is available, eg:
+###
+###     rngd -r /dev/hwrandom
+###
+### If one isn't available, the pseudo-random number generator can be used:
+###
+###     rngd -r /dev/urandom
+###
+EOF
+gpg --homedir . --batch --gen-key %{SOURCE11}
+cat <<EOF
+###
+### Key pair generated.
+###
+EOF
+%endif
+
 cd ..
 
 %if %{with_backports}
@@ -1581,6 +1623,7 @@ cd ..
 # get rid of unwanted files resulting from patch fuzz
 find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null
 
+
 ###
 ### build
 ###
@@ -1679,6 +1722,14 @@ BuildKernel() {
     # Override $(mod-fw) because we don't want it to install any firmware
     # we'll get it from the linux-firmware package and we don't want conflicts
     make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw=
+
+%if %{signmodules}
+        if [ -z "$(readelf -n $(find fs/ -name \*.ko | head -n 1) | grep module.sig)" ]; then
+            echo "ERROR: modules are NOT signed" >&2;
+            exit 1;
+        fi
+%endif
+
 %ifarch %{vdso_arches}
     make -s ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT vdso_install KERNELRELEASE=$KernelVer
     if [ ! -s ldconfig-kernel.conf ]; then
@@ -2377,6 +2428,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Wed Mar 07 2012 Josh Boyer <jwboyer at redhat.com>
+- Add modsign for x86 builds
+
 * Wed Mar 07 2012 Dave Jones <davej at redhat.com> - 3.3.0-0.rc6.git2.2
 - Disable debugging options.
 
diff --git a/modsign-20111207.patch b/modsign-20111207.patch
new file mode 100644
index 0000000..8e43422
--- /dev/null
+++ b/modsign-20111207.patch
@@ -0,0 +1,7361 @@
+From 5ba13e189c831b8ad2bfb14f4599b9b9d00cc5ae Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:04 +0000
+Subject: MPILIB: Export some more symbols
+
+Export some more symbols for use by the DSA key subtype.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ lib/mpi/mpi-cmp.c  |    2 ++
+ lib/mpi/mpi-div.c  |    1 +
+ lib/mpi/mpi-inv.c  |    1 +
+ lib/mpi/mpi-mpow.c |    1 +
+ lib/mpi/mpi-mul.c  |    1 +
+ 5 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
+index 914bc42..1871e7b 100644
+--- a/lib/mpi/mpi-cmp.c
++++ b/lib/mpi/mpi-cmp.c
+@@ -39,6 +39,7 @@ int mpi_cmp_ui(MPI u, unsigned long v)
+ 	else
+ 		return -1;
+ }
++EXPORT_SYMBOL_GPL(mpi_cmp_ui);
+ 
+ int mpi_cmp(MPI u, MPI v)
+ {
+@@ -66,3 +67,4 @@ int mpi_cmp(MPI u, MPI v)
+ 		return 1;
+ 	return -1;
+ }
++EXPORT_SYMBOL_GPL(mpi_cmp);
+diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c
+index c3087d1..3da9402 100644
+--- a/lib/mpi/mpi-div.c
++++ b/lib/mpi/mpi-div.c
+@@ -59,6 +59,7 @@ nomem:
+ 		mpi_free(temp_divisor);
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(mpi_fdiv_r);
+ 
+ /****************
+  * Division rounding the quotient towards -infinity.
+diff --git a/lib/mpi/mpi-inv.c b/lib/mpi/mpi-inv.c
+index 0951f98..bfc5ca1 100644
+--- a/lib/mpi/mpi-inv.c
++++ b/lib/mpi/mpi-inv.c
+@@ -185,3 +185,4 @@ cleanup:
+ 	mpi_free(v);
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(mpi_invm);
+diff --git a/lib/mpi/mpi-mpow.c b/lib/mpi/mpi-mpow.c
+index 4cc7593..5752194 100644
+--- a/lib/mpi/mpi-mpow.c
++++ b/lib/mpi/mpi-mpow.c
+@@ -131,3 +131,4 @@ nomem:
+ 	kfree(G);
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(mpi_mulpowm);
+diff --git a/lib/mpi/mpi-mul.c b/lib/mpi/mpi-mul.c
+index 1f3219e..3d514b9 100644
+--- a/lib/mpi/mpi-mul.c
++++ b/lib/mpi/mpi-mul.c
+@@ -192,3 +192,4 @@ int mpi_mulm(MPI w, MPI u, MPI v, MPI m)
+ 		return -ENOMEM;
+ 	return mpi_fdiv_r(w, w, m);
+ }
++EXPORT_SYMBOL_GPL(mpi_mulm);
+-- 
+1.7.9.1
+
+
+From 7a5782bc39eba97f3499e3d2686fe48d26f261b0 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:06 +0000
+Subject: KEYS: Move the key config into security/keys/Kconfig
+
+Move the key config into security/keys/Kconfig as there are going to be a lot
+of key-related options.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/Kconfig      |   68 +----------------------------------------------
+ security/keys/Kconfig |   71 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 72 insertions(+), 67 deletions(-)
+ create mode 100644 security/keys/Kconfig
+
+diff --git a/security/Kconfig b/security/Kconfig
+index 51bd5a0..1c5a7a4 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -4,73 +4,7 @@
+ 
+ menu "Security options"
+ 
+-config KEYS
+-	bool "Enable access key retention support"
+-	help
+-	  This option provides support for retaining authentication tokens and
+-	  access keys in the kernel.
+-
+-	  It also includes provision of methods by which such keys might be
+-	  associated with a process so that network filesystems, encryption
+-	  support and the like can find them.
+-
+-	  Furthermore, a special type of key is available that acts as keyring:
+-	  a searchable sequence of keys. Each process is equipped with access
+-	  to five standard keyrings: UID-specific, GID-specific, session,
+-	  process and thread.
+-
+-	  If you are unsure as to whether this is required, answer N.
+-
+-config TRUSTED_KEYS
+-	tristate "TRUSTED KEYS"
+-	depends on KEYS && TCG_TPM
+-	select CRYPTO
+-	select CRYPTO_HMAC
+-	select CRYPTO_SHA1
+-	help
+-	  This option provides support for creating, sealing, and unsealing
+-	  keys in the kernel. Trusted keys are random number symmetric keys,
+-	  generated and RSA-sealed by the TPM. The TPM only unseals the keys,
+-	  if the boot PCRs and other criteria match.  Userspace will only ever
+-	  see encrypted blobs.
+-
+-	  If you are unsure as to whether this is required, answer N.
+-
+-config ENCRYPTED_KEYS
+-	tristate "ENCRYPTED KEYS"
+-	depends on KEYS
+-	select CRYPTO
+-	select CRYPTO_HMAC
+-	select CRYPTO_AES
+-	select CRYPTO_CBC
+-	select CRYPTO_SHA256
+-	select CRYPTO_RNG
+-	help
+-	  This option provides support for create/encrypting/decrypting keys
+-	  in the kernel.  Encrypted keys are kernel generated random numbers,
+-	  which are encrypted/decrypted with a 'master' symmetric key. The
+-	  'master' key can be either a trusted-key or user-key type.
+-	  Userspace only ever sees/stores encrypted blobs.
+-
+-	  If you are unsure as to whether this is required, answer N.
+-
+-config KEYS_DEBUG_PROC_KEYS
+-	bool "Enable the /proc/keys file by which keys may be viewed"
+-	depends on KEYS
+-	help
+-	  This option turns on support for the /proc/keys file - through which
+-	  can be listed all the keys on the system that are viewable by the
+-	  reading process.
+-
+-	  The only keys included in the list are those that grant View
+-	  permission to the reading process whether or not it possesses them.
+-	  Note that LSM security checks are still performed, and may further
+-	  filter out keys that the current process is not authorised to view.
+-
+-	  Only key attributes are listed here; key payloads are not included in
+-	  the resulting table.
+-
+-	  If you are unsure as to whether this is required, answer N.
++source security/keys/Kconfig
+ 
+ config SECURITY_DMESG_RESTRICT
+ 	bool "Restrict unprivileged access to the kernel syslog"
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+new file mode 100644
+index 0000000..a90d6d3
+--- /dev/null
++++ b/security/keys/Kconfig
+@@ -0,0 +1,71 @@
++#
++# Key management configuration
++#
++
++config KEYS
++	bool "Enable access key retention support"
++	help
++	  This option provides support for retaining authentication tokens and
++	  access keys in the kernel.
++
++	  It also includes provision of methods by which such keys might be
++	  associated with a process so that network filesystems, encryption
++	  support and the like can find them.
++
++	  Furthermore, a special type of key is available that acts as keyring:
++	  a searchable sequence of keys. Each process is equipped with access
++	  to five standard keyrings: UID-specific, GID-specific, session,
++	  process and thread.
++
++	  If you are unsure as to whether this is required, answer N.
++
++config TRUSTED_KEYS
++	tristate "TRUSTED KEYS"
++	depends on KEYS && TCG_TPM
++	select CRYPTO
++	select CRYPTO_HMAC
++	select CRYPTO_SHA1
++	help
++	  This option provides support for creating, sealing, and unsealing
++	  keys in the kernel. Trusted keys are random number symmetric keys,
++	  generated and RSA-sealed by the TPM. The TPM only unseals the keys,
++	  if the boot PCRs and other criteria match.  Userspace will only ever
++	  see encrypted blobs.
++
++	  If you are unsure as to whether this is required, answer N.
++
++config ENCRYPTED_KEYS
++	tristate "ENCRYPTED KEYS"
++	depends on KEYS
++	select CRYPTO
++	select CRYPTO_HMAC
++	select CRYPTO_AES
++	select CRYPTO_CBC
++	select CRYPTO_SHA256
++	select CRYPTO_RNG
++	help
++	  This option provides support for create/encrypting/decrypting keys
++	  in the kernel.  Encrypted keys are kernel generated random numbers,
++	  which are encrypted/decrypted with a 'master' symmetric key. The
++	  'master' key can be either a trusted-key or user-key type.
++	  Userspace only ever sees/stores encrypted blobs.
++
++	  If you are unsure as to whether this is required, answer N.
++
++config KEYS_DEBUG_PROC_KEYS
++	bool "Enable the /proc/keys file by which keys may be viewed"
++	depends on KEYS
++	help
++	  This option turns on support for the /proc/keys file - through which
++	  can be listed all the keys on the system that are viewable by the
++	  reading process.
++
++	  The only keys included in the list are those that grant View
++	  permission to the reading process whether or not it possesses them.
++	  Note that LSM security checks are still performed, and may further
++	  filter out keys that the current process is not authorised to view.
++
++	  Only key attributes are listed here; key payloads are not included in
++	  the resulting table.
++
++	  If you are unsure as to whether this is required, answer N.
+-- 
+1.7.9.1
+
+
+From f8b45d1f0f1bdd4c29733f462f6f43518ea625d3 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:07 +0000
+Subject: KEYS: Announce key type (un)registration
+
+Announce the (un)registration of a key type in the core key code rather than
+in the callers.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ net/dns_resolver/dns_key.c |    5 -----
+ security/keys/key.c        |    3 +++
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
+index fa000d2..689d7c8 100644
+--- a/net/dns_resolver/dns_key.c
++++ b/net/dns_resolver/dns_key.c
+@@ -249,9 +249,6 @@ static int __init init_dns_resolver(void)
+ 	struct key *keyring;
+ 	int ret;
+ 
+-	printk(KERN_NOTICE "Registering the %s key type\n",
+-	       key_type_dns_resolver.name);
+-
+ 	/* create an override credential set with a special thread keyring in
+ 	 * which DNS requests are cached
+ 	 *
+@@ -300,8 +297,6 @@ static void __exit exit_dns_resolver(void)
+ 	key_revoke(dns_resolver_cache->thread_keyring);
+ 	unregister_key_type(&key_type_dns_resolver);
+ 	put_cred(dns_resolver_cache);
+-	printk(KERN_NOTICE "Unregistered %s key type\n",
+-	       key_type_dns_resolver.name);
+ }
+ 
+ module_init(init_dns_resolver)
+diff --git a/security/keys/key.c b/security/keys/key.c
+index 4414abd..a8086a1 100644
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -957,6 +957,8 @@ int register_key_type(struct key_type *ktype)
+ 
+ 	/* store the type */
+ 	list_add(&ktype->link, &key_types_list);
++
++	pr_notice("Key type %s registered\n", ktype->name);
+ 	ret = 0;
+ 
+ out:
+@@ -979,6 +981,7 @@ void unregister_key_type(struct key_type *ktype)
+ 	list_del_init(&ktype->link);
+ 	downgrade_write(&key_types_sem);
+ 	key_gc_keytype(ktype);
++	pr_notice("Key type %s unregistered\n", ktype->name);
+ 	up_read(&key_types_sem);
+ }
+ EXPORT_SYMBOL(unregister_key_type);
+-- 
+1.7.9.1
+
+
+From bc9e72fd7ba0f06b89c2887a2e2eefef0441d92d Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:08 +0000
+Subject: KEYS: Reorganise keys Makefile
+
+Reorganise the keys directory Makefile to put all the core bits together and
+the type-specific bits after.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Makefile |   12 +++++++++---
+ 1 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index a56f1ff..504aaa0 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -2,6 +2,9 @@
+ # Makefile for key management
+ #
+ 
++#
++# Core
++#
+ obj-y := \
+ 	gc.o \
+ 	key.o \
+@@ -12,9 +15,12 @@ obj-y := \
+ 	request_key.o \
+ 	request_key_auth.o \
+ 	user_defined.o
+-
+-obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+-obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+ obj-$(CONFIG_KEYS_COMPAT) += compat.o
+ obj-$(CONFIG_PROC_FS) += proc.o
+ obj-$(CONFIG_SYSCTL) += sysctl.o
++
++#
++# Key types
++#
++obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
++obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+-- 
+1.7.9.1
+
+
+From b78b34f3950b08d1def84449e10e4560d7cee280 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:08 +0000
+Subject: KEYS: Create a key type that can be used for general cryptographic
+ operations
+
+Create a key type that can be used for general cryptographic operations, such
+as encryption, decryption, signature generation and signature verification.
+
+The key type is "crypto" and can provide access to a variety of cryptographic
+algorithms.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ Documentation/security/keys-crypto.txt |  181 +++++++++++++++++++++++++
+ include/keys/crypto-subtype.h          |   56 ++++++++
+ include/keys/crypto-type.h             |   25 ++++
+ security/keys/Kconfig                  |    8 +
+ security/keys/Makefile                 |    3 +
+ security/keys/crypto_keys.h            |   28 ++++
+ security/keys/crypto_type.c            |  228 ++++++++++++++++++++++++++++++++
+ 7 files changed, 529 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/security/keys-crypto.txt
+ create mode 100644 include/keys/crypto-subtype.h
+ create mode 100644 include/keys/crypto-type.h
+ create mode 100644 security/keys/crypto_keys.h
+ create mode 100644 security/keys/crypto_type.c
+
+diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
+new file mode 100644
+index 0000000..97dee80
+--- /dev/null
++++ b/Documentation/security/keys-crypto.txt
+@@ -0,0 +1,181 @@
++			    ======================
++			    CRYPTOGRAPHIC KEY TYPE
++			    ======================
++
++Contents:
++
++  - Overview.
++  - Key identification.
++  - Accessing crypto keys.
++  - Implementing crypto parsers.
++  - Implementing crypto subtypes.
++
++
++========
++OVERVIEW
++========
++
++The "crypto" key type is designed to be a container for cryptographic keys,
++without imposing any particular restrictions on the form of the cryptography or
++the key.
++
++The crypto key is given a subtype that defines what sort of data is associated
++with the key and provides operations to describe and destroy it.  However, no
++requirement is made that the key data actually be loaded into the key.
++
++The crypto key also has a number of data parsers registered with it.  The data
++parsers are responsible for extracing information the blobs of data passed to
++the instantiator function.  The first data parser that recognises the blob gets
++to set the subtype of the key and define the operations that can be done on
++that key.
++
++Completely in-kernel key retention and operation subtypes and parsers can be
++defined, but it would also be possible to provide access to cryptographic
++hardware (such as a TPM) that might be used to both retain the relevant key and
++perform operations using that key.  In such a case, the crypto key would then
++merely be an interface to the TPM driver.
++
++
++==================
++KEY IDENTIFICATION
++==================
++
++Because the identity of a key is not necessarily known and may not be easily
++calculated when a crypto key is allocated, it may not be a simple matter to set
++a key description to something that's useful for determining whether this is
++the key you're looking for.  Furthermore, it may be necessary to perform a
++partial match upon the key identity.
++
++To help with this, when a key is loaded, the parser calculates the key
++fingerprint and stores a copy in the key structure.
++
++The crypto key type's key matching function then performs more checks than just
++the straightforward comparison of the description with the criterion string:
++
++ (1) If the criterion string is of the form "id:<hexdigits>" then the match
++     function will examine a key's fingerprint to see if the hex digits given
++     after the "id:" match the tail.  For instance:
++
++	keyctl search @s crypto id:5acc2142
++
++     will match a key with fingerprint:
++
++	1A00 2040 7601 7889 DE11  882C 3823 04AD 5ACC 2142
++
++ (2) If the criterion string is of the form "<subtype>:<hexdigits>" then the
++     match will match the ID as in (1), but with the added restriction that
++     only keys of the specified subtype (e.g. dsa or rsa) will be matched.  For
++     instance:
++
++	keyctl search @s crypto dsa:5acc2142
++
++Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
++displayed, along with the subtype:
++
++	1a39e171 I-----     1 perm 3f010000     0     0 crypto    modsign.0: DSA 5acc2142 []
++
++
++=====================
++ACCESSING CRYPTO KEYS
++=====================
++
++To access crypto keys from within the kernel, the following inclusion is
++required:
++
++	#include <keys/crypto-type.h>
++
++This gives access to the key type:
++
++	struct key_type key_type_crypto;
++
++
++===========================
++IMPLEMENTING CRYPTO PARSERS
++===========================
++
++The crypto key type keeps a list of registered data parsers.  An example of
++such a parser is one that parses OpenPGP packet formatted data [RFC 4880].
++
++During key instantiation each parser in the list is tried until one doesn't
++return -EBADMSG.
++
++The parser definition structure looks like the following:
++
++	struct crypto_key_parser {
++		struct module		*owner;
++		const char		*name;
++
++		int (*instantiate)(struct key *key,
++				   const void *data, size_t datalen);
++	};
++
++The owner and name fields should be set to the owning module and the name of
++the parser.
++
++There are a number of operations defined by the parser.  They are all optional,
++but it is expected that at least one will be defined.
++
++ (1) instantiate().
++
++     The arguments are the same as for the instantiate function in the key
++     type.  'key' is the crypto key being instantiated; data and datalen are
++     the instantiation data, presumably containing cryptographic key data, and
++     the length of that data.
++
++     If the data format is not recognised, -EBADMSG should be returned.  If it
++     is recognised, but the key cannot for some reason be set up, some other
++     negative error code should be returned.
++
++     If the key can be successfully set up, then key->payload should be set to
++     point to the retained data, key->type_data.p[0] should be set to point to
++     the subtype chosen and key->type_data.p[1] should be set to point to a
++     copy of the key's identity string and 0 should be returned.
++
++     The key's identity string may be partially matched upon.  For a public-key
++     algorithm such as RSA and DSA this will likely be a printable hex version
++     of the key's fingerprint.
++
++Functions are provided to register and unregister parsers:
++
++	int register_crypto_key_parser(struct crypto_key_parser *parser);
++	void unregister_crypto_key_parser(struct crypto_key_parser *subtype);
++
++Parsers may not have the same name.  The names are only used for displaying in
++debugging messages.
++
++
++============================
++IMPLEMENTING CRYPTO SUBTYPES
++============================
++
++The parser selects the appropriate subtype directly and sets it on the key; the
++crypto key then retains a reference on the subtype module (which means the
++parser can be removed thereafter).
++
++The subtype definition structure looks like the following:
++
++	struct crypto_key_subtype {
++		struct module		*owner;
++		const char		*name;
++
++		void (*describe)(const struct key *key, struct seq_file *m);
++		void (*destroy)(void *payload);
++	};
++
++The owner and name fields should be set to the owning module and the name of
++the subtype.
++
++There are a number of operations defined by the subtype:
++
++ (1) describe().
++
++     Mandatory.  This allows the subtype to display something in /proc/keys
++     against the key.  For instance the name of the public key algorithm type
++     could be displayed.  The key type will display the tail of the key
++     identity string after this.
++
++ (2) destroy().
++
++     Mandatory.  This should free the memory associated with the key.  The
++     crypto key will look after freeing the fingerprint and releasing the
++     reference on the subtype module.
+diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
+new file mode 100644
+index 0000000..fa87555
+--- /dev/null
++++ b/include/keys/crypto-subtype.h
+@@ -0,0 +1,56 @@
++/* Cryptographic key subtype
++ *
++ * Copyright (C) 2011 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.
++ *
++ * See Documentation/security/keys-crypto.txt
++ */
++
++#ifndef _KEYS_CRYPTO_SUBTYPE_H
++#define _KEYS_CRYPTO_SUBTYPE_H
++
++#include <linux/seq_file.h>
++#include <keys/crypto-type.h>
++
++extern struct key_type key_type_crypto;
++
++/*
++ * Keys of this type declare a subtype that indicates the handlers and
++ * capabilities.
++ */
++struct crypto_key_subtype {
++	struct module		*owner;
++	const char		*name;
++	unsigned short		name_len;	/* length of name */
++
++	void (*describe)(const struct key *key, struct seq_file *m);
++
++	void (*destroy)(void *payload);
++};
++
++/*
++ * Data parser.  Called during instantiation and signature verification
++ * initiation.
++ */
++struct crypto_key_parser {
++	struct list_head	link;
++	struct module		*owner;
++	const char		*name;
++
++	/* Attempt to instantiate a key from the data blob passed to add_key()
++	 * or keyctl_instantiate().
++	 *
++	 * Return EBADMSG if not recognised.
++	 */
++	int (*instantiate)(struct key *key, const void *data, size_t datalen);
++};
++
++extern int register_crypto_key_parser(struct crypto_key_parser *);
++extern void unregister_crypto_key_parser(struct crypto_key_parser *);
++
++#endif /* _KEYS_CRYPTO_SUBTYPE_H */
+diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
+new file mode 100644
+index 0000000..47c00c7
+--- /dev/null
++++ b/include/keys/crypto-type.h
+@@ -0,0 +1,25 @@
++/* Cryptographic key type interface
++ *
++ * Copyright (C) 2011 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.
++ *
++ * See Documentation/security/keys-crypto.txt
++ */
++
++#ifndef _KEYS_CRYPTO_TYPE_H
++#define _KEYS_CRYPTO_TYPE_H
++
++#include <linux/key-type.h>
++
++extern struct key_type key_type_crypto;
++
++/*
++ * The payload is at the discretion of the subtype.
++ */
++
++#endif /* _KEYS_CRYPTO_TYPE_H */
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index a90d6d3..290c9d3 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -69,3 +69,11 @@ config KEYS_DEBUG_PROC_KEYS
+ 	  the resulting table.
+ 
+ 	  If you are unsure as to whether this is required, answer N.
++
++config CRYPTO_KEY_TYPE
++	tristate "Cryptographic key type"
++	depends on KEYS
++	help
++	  This option provides support for a type of key that holds the keys
++	  required for cryptographic operations such as encryption, decryption,
++	  signature generation and signature verification.
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 504aaa0..67fceaa 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -24,3 +24,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
+ #
+ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
++obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
++
++crypto_keys-y := crypto_type.o
+diff --git a/security/keys/crypto_keys.h b/security/keys/crypto_keys.h
+new file mode 100644
+index 0000000..a339ce0
+--- /dev/null
++++ b/security/keys/crypto_keys.h
+@@ -0,0 +1,28 @@
++/* Internal crypto type stuff
++ *
++ * Copyright (C) 2011 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.
++ */
++
++static inline
++struct crypto_key_subtype *crypto_key_subtype(const struct key *key)
++{
++	return key->type_data.p[0];
++}
++
++static inline char *crypto_key_id(const struct key *key)
++{
++	return key->type_data.p[1];
++}
++
++
++/*
++ * crypto_type.c
++ */
++extern struct list_head crypto_key_parsers;
++extern struct rw_semaphore crypto_key_parsers_sem;
+diff --git a/security/keys/crypto_type.c b/security/keys/crypto_type.c
+new file mode 100644
+index 0000000..33d279b
+--- /dev/null
++++ b/security/keys/crypto_type.c
+@@ -0,0 +1,228 @@
++/* Cryptographic key type
++ *
++ * Copyright (C) 2011 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.
++ *
++ * See Documentation/security/keys-crypto.txt
++ */
++#include <keys/crypto-subtype.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include "crypto_keys.h"
++
++MODULE_LICENSE("GPL");
++
++LIST_HEAD(crypto_key_parsers);
++DECLARE_RWSEM(crypto_key_parsers_sem);
++
++/*
++ * Match crypto_keys on (part of) their name
++ * We have some shorthand methods for matching keys.  We allow:
++ *
++ *	"<desc>"	- request a key by description
++ *	"id:<id>"	- request a key matching the ID
++ *	"<subtype>:<id>" - request a key of a subtype
++ */
++static int crypto_key_match(const struct key *key, const void *description)
++{
++	const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
++	const char *spec = description;
++	const char *id, *kid;
++	ptrdiff_t speclen;
++	size_t idlen, kidlen;
++
++	if (!subtype || !spec || !*spec)
++		return 0;
++
++	/* See if the full key description matches as is */
++	if (key->description && strcmp(key->description, description) == 0)
++		return 1;
++
++	/* All tests from here on break the criterion description into a
++	 * specifier, a colon and then an identifier.
++	 */
++	id = strchr(spec, ':');
++	if (!id)
++		return 0;
++
++	speclen = id - spec;
++	id++;
++
++	/* Anything after here requires a partial match on the ID string */
++	kid = crypto_key_id(key);
++	if (!kid)
++		return 0;
++
++	idlen = strlen(id);
++	kidlen = strlen(kid);
++	if (idlen > kidlen)
++		return 0;
++
++	kid += kidlen - idlen;
++	if (strcasecmp(id, kid) != 0)
++		return 0;
++
++	if (speclen == 2 &&
++	    memcmp(spec, "id", 2) == 0)
++		return 1;
++
++	if (speclen == subtype->name_len &&
++	    memcmp(spec, subtype->name, speclen) == 0)
++		return 1;
++
++	return 0;
++}
++
++/*
++ * Describe the crypto key
++ */
++static void crypto_key_describe(const struct key *key, struct seq_file *m)
++{
++	const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
++	const char *kid = crypto_key_id(key);
++	size_t n;
++
++	seq_puts(m, key->description);
++
++	if (subtype) {
++		seq_puts(m, ": ");
++		subtype->describe(key, m);
++
++		if (kid) {
++			seq_putc(m, ' ');
++			n = strlen(kid);
++			if (n <= 8)
++				seq_puts(m, kid);
++			else
++				seq_puts(m, kid + n - 8);
++		}
++
++		seq_puts(m, " [");
++		/* put something here to indicate the key's capabilities */
++		seq_putc(m, ']');
++	}
++}
++
++/*
++ * Instantiate a crypto_key defined key
++ */
++static int crypto_key_instantiate(struct key *key,
++				  const void *data, size_t datalen)
++{
++	struct crypto_key_parser *parser;
++	int ret;
++
++	pr_devel("==>%s()\n", __func__);
++
++	if (datalen == 0)
++		return -EINVAL;
++
++	down_read(&crypto_key_parsers_sem);
++
++	ret = -EBADMSG;
++	list_for_each_entry(parser, &crypto_key_parsers, link) {
++		pr_debug("Trying parser '%s'\n", parser->name);
++
++		ret = parser->instantiate(key, data, datalen);
++		if (ret != -EBADMSG) {
++			pr_debug("Parser recognised the format (ret %d)\n",
++				 ret);
++			break;
++		}
++	}
++
++	up_read(&crypto_key_parsers_sem);
++	pr_devel("<==%s() = %d\n", __func__, ret);
++	return ret;
++}
++
++/*
++ * dispose of the data dangling from the corpse of a crypto key
++ */
++static void crypto_key_destroy(struct key *key)
++{
++	struct crypto_key_subtype *subtype = crypto_key_subtype(key);
++	if (subtype) {
++		subtype->destroy(key->payload.data);
++		module_put(subtype->owner);
++		key->type_data.p[0] = NULL;
++	}
++	kfree(key->type_data.p[1]);
++	key->type_data.p[1] = NULL;
++}
++
++struct key_type key_type_crypto = {
++	.name		= "crypto",
++	.instantiate	= crypto_key_instantiate,
++	.match		= crypto_key_match,
++	.destroy	= crypto_key_destroy,
++	.describe	= crypto_key_describe,
++};
++EXPORT_SYMBOL_GPL(key_type_crypto);
++
++/**
++ * register_crypto_key_parser - Register a crypto key blob parser
++ * @parser: The parser to register
++ */
++int register_crypto_key_parser(struct crypto_key_parser *parser)
++{
++	struct crypto_key_parser *cursor;
++	int ret;
++
++	down_write(&crypto_key_parsers_sem);
++
++	list_for_each_entry(cursor, &crypto_key_parsers, link) {
++		if (strcmp(cursor->name, parser->name) == 0) {
++			pr_err("Crypto key parser '%s' already registered\n",
++			       parser->name);
++			ret = -EEXIST;
++			goto out;
++		}
++	}
++
++	list_add_tail(&parser->link, &crypto_key_parsers);
++
++	pr_notice("Crypto key parser '%s' registered\n", parser->name);
++	ret = 0;
++
++out:
++	up_write(&crypto_key_parsers_sem);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(register_crypto_key_parser);
++
++/**
++ * unregister_crypto_key_parser - Unregister a crypto key blob parser
++ * @parser: The parser to unregister
++ */
++void unregister_crypto_key_parser(struct crypto_key_parser *parser)
++{
++	down_write(&crypto_key_parsers_sem);
++	list_del(&parser->link);
++	up_write(&crypto_key_parsers_sem);
++
++	pr_notice("Crypto key parser '%s' unregistered\n", parser->name);
++}
++EXPORT_SYMBOL_GPL(unregister_crypto_key_parser);
++
++/*
++ * Module stuff
++ */
++static int __init crypto_key_init(void)
++{
++	return register_key_type(&key_type_crypto);
++}
++
++static void __exit crypto_key_cleanup(void)
++{
++	unregister_key_type(&key_type_crypto);
++}
++
++module_init(crypto_key_init);
++module_exit(crypto_key_cleanup);
+-- 
+1.7.9.1
+
+
+From 9d66ee5300d0d1391367dd002eba6663aaf33760 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:09 +0000
+Subject: KEYS: Add signature verification facility
+
+Add a facility whereby a key subtype may be asked to verify a signature against
+the data it is purported to have signed.
+
+This adds four routines:
+
+ (1) struct crypto_key_verify_context *
+     verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
+
+     This sets up a verification context for the given signature using
+     information in that signature to select a key from the specified keyring
+     and to request a hash algorithm from the crypto layer.
+
+ (2) int verify_sig_add_data(struct crypto_key_verify_context *ctx,
+			     const void *data, size_t datalen);
+
+     Incrementally supply data to be signed.  May be called multiple times.
+
+ (3) int verify_sig_end(struct crypto_key_verify_context *ctx,
+			const void *sig, size_t siglen);
+
+     Complete the verification process and return the result.  -EKEYREJECTED
+     will indicate that the verification failed and 0 will indicate success.
+     Other errors are also possible.
+
+ (4) void verify_sig_cancel(struct crypto_key_verify_context *ctx);
+
+     Cancel the verification process.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ Documentation/security/keys-crypto.txt |  101 +++++++++++++++++++++++++++++
+ include/keys/crypto-subtype.h          |   21 ++++++
+ include/keys/crypto-type.h             |    9 +++
+ security/keys/Makefile                 |    2 +-
+ security/keys/crypto_verify.c          |  111 ++++++++++++++++++++++++++++++++
+ 5 files changed, 243 insertions(+), 1 deletions(-)
+ create mode 100644 security/keys/crypto_verify.c
+
+diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
+index 97dee80..a964717 100644
+--- a/Documentation/security/keys-crypto.txt
++++ b/Documentation/security/keys-crypto.txt
+@@ -7,6 +7,7 @@ Contents:
+   - Overview.
+   - Key identification.
+   - Accessing crypto keys.
++    - Signature verification.
+   - Implementing crypto parsers.
+   - Implementing crypto subtypes.
+ 
+@@ -89,6 +90,65 @@ This gives access to the key type:
+ 	struct key_type key_type_crypto;
+ 
+ 
++SIGNATURE VERIFICATION
++----------------------
++
++The four operations that can perform cryptographic signature verification,
++using one of a set of keys to provide the public key:
++
++ (1) Begin verification procedure.
++
++	struct crypto_key_verify_context *
++	verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
++
++     This function sets up a verification context from the information in the
++     signature and looks for a suitable key in the keyring.  The signature blob
++     must be presented again at the end of the procedure.  The keys will be
++     checked against parameters in the signature, and if the matching one is
++     not found then -ENOKEY will be returned.
++
++     The hashing algorithm, if such a thing applies, will be determined from
++     information in the signature and the appropriate crypto module will be
++     used.  -ENOPKG will be returned if the hash algorithm is unavailable.
++
++     The return value is an opaque pointer to be passed to the other functions,
++     or a negative error code.
++
++ (2) Indicate data to be verified.
++
++	int verify_sig_add_data(struct crypto_key_verify_context *ctx,
++				const void *data, size_t datalen);
++
++     This function is used to shovel data to the verification procedure so that
++     it can load it into the hash, pass it to hardware or whatever is
++     appropriate for the algorithm being employed.
++
++     The data is not canonicalised for the document type specified in the
++     signature.  The caller must do that.
++
++     It will return 0 if successful and a negative error code if not.
++
++ (3) Complete the verification process.
++
++	int verify_sig_end(struct crypto_key_verify_context *ctx,
++			   const void *sig, size_t siglen);
++
++     This function performs the actual signature verification step and cleans
++     up the resources allocated at the beginning.  The signature must be
++     presented again as some of the data therein may need to be added to the
++     internal hash.
++
++     It will return -EKEYREJECTED if the signature didn't match, 0 if
++     successful and may return other errors as appropriate.
++
++ (4) Cancel the verification process.
++
++	void verify_sig_cancel(struct crypto_key_verify_context *ctx);
++
++     This function cleans up the resources allocated at the beginning.  This is
++     not necessary if verify_sig_end() was called.
++
++
+ ===========================
+ IMPLEMENTING CRYPTO PARSERS
+ ===========================
+@@ -96,6 +156,7 @@ IMPLEMENTING CRYPTO PARSERS
+ The crypto key type keeps a list of registered data parsers.  An example of
+ such a parser is one that parses OpenPGP packet formatted data [RFC 4880].
+ 
++
+ During key instantiation each parser in the list is tried until one doesn't
+ return -EBADMSG.
+ 
+@@ -107,6 +168,8 @@ The parser definition structure looks like the following:
+ 
+ 		int (*instantiate)(struct key *key,
+ 				   const void *data, size_t datalen);
++		struct crypto_key_verify_context *(*verify_sig_begin)(
++			struct key *keyring, const u8 *sig, size_t siglen);
+ 	};
+ 
+ The owner and name fields should be set to the owning module and the name of
+@@ -135,6 +198,44 @@ but it is expected that at least one will be defined.
+      algorithm such as RSA and DSA this will likely be a printable hex version
+      of the key's fingerprint.
+ 
++ (2) verify_sig_begin().
++
++     This is similar in concept to the instantiate() function, except that it
++     is given a signature blob to parse rather than a key data blob.
++
++     If the data format is not recognised, -EBADMSG should be returned.  If it
++     is recognised, but the signature verification process cannot for some
++     reason be set up, some other negative error code should be returned.
++     -ENOKEY should be used to indicate that no matching key is available and
++     -ENOPKG should be returned if the hash algorithm or the verification
++     algorithm are unavailable.
++
++     If successful, the parser should allocate a verification context and embed
++     the following struct in it:
++
++	struct crypto_key_verify_context {
++		struct key *key;
++		int (*add_data)(struct crypto_key_verify_context *ctx,
++				const void *data, size_t datalen);
++		int (*end)(struct crypto_key_verify_context *ctx,
++			   const u8 *sig, size_t siglen);
++		void (*cancel)(struct crypto_key_verify_context *ctx);
++	};
++
++     and return a pointer to this to the caller, who will then pass it to the
++     verification operation wrappers described in the "Signature Verification"
++     section.  The three operation pointers here correspond exactly to those
++     wrappers and are all mandatory.  container_of() should be used to retrieve
++     the actual context.
++
++     Note that the crypto key type retains a reference on the parser module for
++     the lifetime of this context, though the operation pointers need not point
++     into this module.
++
++     The parser should also record a pointer to the key selected and take a
++     reference on that key with key_get().
++
++
+ Functions are provided to register and unregister parsers:
+ 
+ 	int register_crypto_key_parser(struct crypto_key_parser *parser);
+diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
+index fa87555..f2b927a 100644
+--- a/include/keys/crypto-subtype.h
++++ b/include/keys/crypto-subtype.h
+@@ -20,6 +20,20 @@
+ extern struct key_type key_type_crypto;
+ 
+ /*
++ * Context base for signature verification methods.  Allocated by the subtype
++ * and presumably embedded in something appropriate.
++ */
++struct crypto_key_verify_context {
++	struct key *key;
++	struct crypto_key_parser *parser;
++	int (*add_data)(struct crypto_key_verify_context *ctx,
++			const void *data, size_t datalen);
++	int (*end)(struct crypto_key_verify_context *ctx,
++		   const u8 *sig, size_t siglen);
++	void (*cancel)(struct crypto_key_verify_context *ctx);
++};
++
++/*
+  * Keys of this type declare a subtype that indicates the handlers and
+  * capabilities.
+  */
+@@ -48,6 +62,13 @@ struct crypto_key_parser {
+ 	 * Return EBADMSG if not recognised.
+ 	 */
+ 	int (*instantiate)(struct key *key, const void *data, size_t datalen);
++
++	/* Attempt to recognise a signature blob and find a matching key.
++	 *
++	 * Return EBADMSG if not recognised.
++	 */
++	struct crypto_key_verify_context *(*verify_sig_begin)(
++		struct key *keyring, const u8 *sig, size_t siglen);
+ };
+ 
+ extern int register_crypto_key_parser(struct crypto_key_parser *);
+diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
+index 47c00c7..6b93366 100644
+--- a/include/keys/crypto-type.h
++++ b/include/keys/crypto-type.h
+@@ -18,6 +18,15 @@
+ 
+ extern struct key_type key_type_crypto;
+ 
++struct crypto_key_verify_context;
++extern struct crypto_key_verify_context *verify_sig_begin(
++	struct key *key, const void *sig, size_t siglen);
++extern int verify_sig_add_data(struct crypto_key_verify_context *ctx,
++			       const void *data, size_t datalen);
++extern int verify_sig_end(struct crypto_key_verify_context *ctx,
++			  const void *sig, size_t siglen);
++extern void verify_sig_cancel(struct crypto_key_verify_context *ctx);
++
+ /*
+  * The payload is at the discretion of the subtype.
+  */
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 67fceaa..8462904 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -26,4 +26,4 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ 
+-crypto_keys-y := crypto_type.o
++crypto_keys-y := crypto_type.o crypto_verify.o
+diff --git a/security/keys/crypto_verify.c b/security/keys/crypto_verify.c
+new file mode 100644
+index 0000000..65f734c
+--- /dev/null
++++ b/security/keys/crypto_verify.c
+@@ -0,0 +1,111 @@
++/* Signature verification with a crypto key
++ *
++ * Copyright (C) 2011 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.
++ *
++ * See Documentation/security/keys-crypto.txt
++ */
++
++#include <keys/crypto-subtype.h>
++#include <linux/module.h>
++#include "crypto_keys.h"
++
++/**
++ * verify_sig_begin - Initiate the use of a crypto key to verify a signature
++ * @keyring: The public keys to verify against
++ * @sig: The signature data
++ * @siglen: The signature length
++ *
++ * Returns a context or an error.
++ */
++struct crypto_key_verify_context *verify_sig_begin(
++	struct key *keyring, const void *sig, size_t siglen)
++{
++	struct crypto_key_verify_context *ret;
++	struct crypto_key_parser *parser;
++
++	pr_devel("==>%s()\n", __func__);
++
++	if (siglen == 0 || !sig)
++		return ERR_PTR(-EINVAL);
++
++	down_read(&crypto_key_parsers_sem);
++
++	ret = ERR_PTR(-EBADMSG);
++	list_for_each_entry(parser, &crypto_key_parsers, link) {
++		if (parser->verify_sig_begin) {
++			if (!try_module_get(parser->owner))
++				continue;
++
++			pr_debug("Trying parser '%s'\n", parser->name);
++
++			ret = parser->verify_sig_begin(keyring, sig, siglen);
++			if (IS_ERR(ret))
++				module_put(parser->owner);
++			else
++				ret->parser = parser;
++			if (ret != ERR_PTR(-EBADMSG)) {
++				pr_debug("Parser recognised the format"
++					 " (ret %ld)\n",
++					 PTR_ERR(ret));
++				break;
++			}
++		}
++	}
++
++	up_read(&crypto_key_parsers_sem);
++	pr_devel("<==%s() = %p\n", __func__, ret);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(verify_sig_begin);
++
++/**
++ * verify_sig_add_data - Incrementally provide data to be verified
++ * @ctx: The context from verify_sig_begin()
++ * @data: Data
++ * @datalen: The amount of @data
++ *
++ * This may be called multiple times.
++ */
++int verify_sig_add_data(struct crypto_key_verify_context *ctx,
++			const void *data, size_t datalen)
++{
++	return ctx->add_data(ctx, data, datalen);
++}
++EXPORT_SYMBOL_GPL(verify_sig_add_data);
++
++/**
++ * verify_sig_end - Finalise signature verification and return result
++ * @ctx: The context from verify_sig_begin()
++ * @sig: The signature data
++ * @siglen: The signature length
++ */
++int verify_sig_end(struct crypto_key_verify_context *ctx,
++		   const void *sig, size_t siglen)
++{
++	struct crypto_key_parser *parser = ctx->parser;
++	int ret;
++
++	ret = ctx->end(ctx, sig, siglen);
++	module_put(parser->owner);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(verify_sig_end);
++
++/**
++ * verify_sig_end - Cancel signature verification
++ * @ctx: The context from verify_sig_begin()
++ */
++void verify_sig_cancel(struct crypto_key_verify_context *ctx)
++{
++	struct crypto_key_parser *parser = ctx->parser;
++
++	ctx->cancel(ctx);
++	module_put(parser->owner);
++}
++EXPORT_SYMBOL_GPL(verify_sig_cancel);
+-- 
+1.7.9.1
+
+
+From 8842a89fac8ac5a9691fb8ff381cdf98e23e8029 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:10 +0000
+Subject: KEYS: Asymmetric public-key algorithm crypto key subtype
+
+Add a subtype for supporting asymmetric public-key encryption algorithms such
+as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337).
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Kconfig      |    9 ++++
+ security/keys/Makefile     |    1 +
+ security/keys/public_key.c |   55 +++++++++++++++++++++++
+ security/keys/public_key.h |  106 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 171 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/public_key.c
+ create mode 100644 security/keys/public_key.h
+
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index 290c9d3..07c7f3b 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -77,3 +77,12 @@ config CRYPTO_KEY_TYPE
+ 	  This option provides support for a type of key that holds the keys
+ 	  required for cryptographic operations such as encryption, decryption,
+ 	  signature generation and signature verification.
++
++config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
++	tristate "Asymmetric public-key crypto algorithm subtype"
++	depends on CRYPTO_KEY_TYPE
++	help
++	  This option provides support for asymmetric public key type handling.
++	  If signature generation and/or verification are to be used,
++	  appropriate hash algorithms (such as SHA-1) must be available.
++	  ENOPKG will be reported if the requisite algorithm is unavailable.
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 8462904..dc3281f 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -25,5 +25,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
+ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
++obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+ 
+ crypto_keys-y := crypto_type.o crypto_verify.o
+diff --git a/security/keys/public_key.c b/security/keys/public_key.c
+new file mode 100644
+index 0000000..c00ddac
+--- /dev/null
++++ b/security/keys/public_key.c
+@@ -0,0 +1,55 @@
++/* Asymmetric public key crypto subtype
++ *
++ * Copyright (C) 2011 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.
++ */
++
++#define pr_fmt(fmt) "PKEY: "fmt
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include "public_key.h"
++
++MODULE_LICENSE("GPL");
++
++/*
++ * Provide a part of a description of the key for /proc/keys.
++ */
++static void public_key_describe(const struct key *crypto_key,
++				struct seq_file *m)
++{
++	struct public_key *key = crypto_key->payload.data;
++
++	if (key)
++		seq_puts(m, key->algo->name);
++}
++
++/*
++ * Destroy a public key algorithm key
++ */
++static void public_key_destroy(void *payload)
++{
++	struct public_key *key = payload;
++	int i;
++
++	if (key) {
++		for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
++			mpi_free(key->mpi[i]);
++		kfree(key);
++	}
++}
++
++/*
++ * Public key algorithm crypto key subtype
++ */
++struct crypto_key_subtype public_key_crypto_key_subtype = {
++	.owner		= THIS_MODULE,
++	.name		= "public_key",
++	.describe	= public_key_describe,
++	.destroy	= public_key_destroy,
++};
++EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype);
+diff --git a/security/keys/public_key.h b/security/keys/public_key.h
+new file mode 100644
+index 0000000..81ed603
+--- /dev/null
++++ b/security/keys/public_key.h
+@@ -0,0 +1,106 @@
++/* Asymmetric public-key algorithm definitions
++ *
++ * Copyright (C) 2011 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 _LINUX_PUBLIC_KEY_H
++#define _LINUX_PUBLIC_KEY_H
++
++#include <linux/mpi.h>
++#include <crypto/hash.h>
++#include <keys/crypto-subtype.h>
++
++struct public_key;
++struct public_key_signature;
++
++enum pkey_hash_algo {
++	PKEY_HASH_MD5,
++	PKEY_HASH_SHA1,
++	PKEY_HASH_RIPE_MD_160,
++	PKEY_HASH_SHA256,
++	PKEY_HASH_SHA384,
++	PKEY_HASH_SHA512,
++	PKEY_HASH_SHA224,
++	PKEY_HASH__LAST
++};
++
++/*
++ * Public key type definition
++ */
++struct public_key_algorithm {
++	const char	*name;
++	u8		n_pub_mpi;	/* Number of MPIs in public key */
++	u8		n_sec_mpi;	/* Number of MPIs in secret key */
++	u8		n_sig_mpi;	/* Number of MPIs in a signature */
++	int (*verify)(const struct public_key *key,
++		      const struct public_key_signature *sig);
++};
++
++/*
++ * Asymmetric public key data
++ */
++struct public_key {
++	const struct public_key_algorithm *algo;
++	u8	capabilities;
++#define PKEY_CAN_ENCRYPT	0x01
++#define PKEY_CAN_DECRYPT	0x02
++#define PKEY_CAN_ENCDEC		(PKEY_CAN_ENCRYPT | PKEY_CAN_DECRYPT)
++#define PKEY_CAN_SIGN		0x04
++#define PKEY_CAN_VERIFY		0x08
++#define PKEY_CAN_SIGVER		(PKEY_CAN_SIGN | PKEY_CAN_VERIFY)
++	union {
++		MPI	mpi[5];
++		struct {
++			MPI	p;	/* DSA prime */
++			MPI	q;	/* DSA group order */
++			MPI	g;	/* DSA group generator */
++			MPI	y;	/* DSA public-key value = g^x mod p */
++			MPI	x;	/* DSA secret exponent (if present) */
++		} dsa;
++		struct {
++			MPI	n;	/* RSA public modulus */
++			MPI	e;	/* RSA public encryption exponent */
++			MPI	d;	/* RSA secret encryption exponent (if present) */
++			MPI	p;	/* RSA secret prime (if present) */
++			MPI	q;	/* RSA secret prime (if present) */
++		} rsa;
++	};
++
++	u8	key_id[8];	/* ID of this key pair */
++	u8	key_id_size;	/* Number of bytes in key_id */
++};
++
++/*
++ * Asymmetric public key algorithm signature data
++ */
++struct public_key_signature {
++	struct crypto_key_verify_context base;
++	u8 *digest;
++	enum pkey_hash_algo pkey_hash_algo : 8;
++	u8 signed_hash_msw[2];
++	u8 digest_size;	/* Number of bytes in digest */
++	union {
++		MPI mpi[2];
++		struct {
++			MPI s;			/* m^d mod n */
++		} rsa;
++		struct {
++			MPI r;
++			MPI s;
++		} dsa;
++	};
++	struct shash_desc hash;			/* This must go last! */
++};
++
++extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
++	struct key *crypto_key, const u8 *sigdata, size_t siglen);
++
++extern struct crypto_key_subtype public_key_crypto_key_subtype;
++
++#endif /* _LINUX_PUBLIC_KEY_H */
+-- 
+1.7.9.1
+
+
+From 6fc88dcf4610907920e8ec8fc9d11610a23b12ae Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:11 +0000
+Subject: KEYS: RSA signature verification algorithm
+
+Implement the RSA algorithm (PKCS#1 / RFC3447).  At this time, only signature
+verification is supported.  This uses the asymmetric public key subtype to hold
+its key data.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Kconfig      |    6 +
+ security/keys/Makefile     |    1 +
+ security/keys/crypto_rsa.c |  282 ++++++++++++++++++++++++++++++++++++++++++++
+ security/keys/public_key.h |    2 +
+ 4 files changed, 291 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/crypto_rsa.c
+
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index 07c7f3b..65d640b 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -86,3 +86,9 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+ 	  If signature generation and/or verification are to be used,
+ 	  appropriate hash algorithms (such as SHA-1) must be available.
+ 	  ENOPKG will be reported if the requisite algorithm is unavailable.
++
++config CRYPTO_KEY_PKEY_ALGO_RSA
++	tristate "RSA public-key algorithm"
++	depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
++	help
++	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index dc3281f..59e7180 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -26,5 +26,6 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
++obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
+ 
+ crypto_keys-y := crypto_type.o crypto_verify.o
+diff --git a/security/keys/crypto_rsa.c b/security/keys/crypto_rsa.c
+new file mode 100644
+index 0000000..beb5181
+--- /dev/null
++++ b/security/keys/crypto_rsa.c
+@@ -0,0 +1,282 @@
++/* RSA asymmetric public-key algorithm [RFC3447]
++ *
++ * Copyright (C) 2011 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.
++ */
++
++#define pr_fmt(fmt) "RSA: "fmt
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include "public_key.h"
++
++MODULE_LICENSE("GPL");
++
++#define kenter(FMT, ...) \
++	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
++#define kleave(FMT, ...) \
++	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
++
++/*
++ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
++ */
++static const u8 RSA_digest_info_MD5[] = {
++	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
++	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
++	0x05, 0x00, 0x04, 0x10
++};
++
++static const u8 RSA_digest_info_SHA1[] = {
++	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
++	0x2B, 0x0E, 0x03, 0x02, 0x1A,
++	0x05, 0x00, 0x04, 0x14
++};
++
++static const u8 RSA_digest_info_RIPE_MD_160[] = {
++	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
++	0x2B, 0x24, 0x03, 0x02, 0x01,
++	0x05, 0x00, 0x04, 0x14
++};
++
++static const u8 RSA_digest_info_SHA224[] = {
++	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
++	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
++	0x05, 0x00, 0x04, 0x1C
++};
++
++static const u8 RSA_digest_info_SHA256[] = {
++	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
++	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
++	0x05, 0x00, 0x04, 0x20
++};
++
++static const u8 RSA_digest_info_SHA384[] = {
++	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
++	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
++	0x05, 0x00, 0x04, 0x30
++};
++
++static const u8 RSA_digest_info_SHA512[] = {
++	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
++	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
++	0x05, 0x00, 0x04, 0x40
++};
++
++static const struct {
++	const u8 const *data;
++	size_t size;
++} RSA_ASN1_templates[PKEY_HASH__LAST] = {
++#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
++	[PKEY_HASH_MD5]		= _(MD5),
++	[PKEY_HASH_SHA1]	= _(SHA1),
++	[PKEY_HASH_RIPE_MD_160]	= _(RIPE_MD_160),
++	[PKEY_HASH_SHA256]	= _(SHA256),
++	[PKEY_HASH_SHA384]	= _(SHA384),
++	[PKEY_HASH_SHA512]	= _(SHA512),
++	[PKEY_HASH_SHA224]	= _(SHA224),
++#undef _
++};
++
++/*
++ * RSAVP1() function [RFC3447 sec 5.2.2]
++ */
++static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
++{
++	MPI m;
++	int ret;
++
++	/* (1) Validate 0 <= s < n */
++	if (mpi_cmp_ui(s, 0) < 0) {
++		kleave(" = -EBADMSG [s < 0]");
++		return -EBADMSG;
++	}
++	if (mpi_cmp(s, key->rsa.n) >= 0) {
++		kleave(" = -EBADMSG [s >= n]");
++		return -EBADMSG;
++	}
++
++	m = mpi_alloc(0);
++	if (!m)
++		return -ENOMEM;
++
++	/* (2) m = s^e mod n */
++	ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
++	if (ret < 0) {
++		mpi_free(m);
++		return ret;
++	}
++
++	*_m = m;
++	return 0;
++}
++
++/*
++ * Integer to Octet String conversion [RFC3447 sec 4.1]
++ */
++static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X)
++{
++	unsigned X_size, x_size;
++	int X_sign;
++	u8 *X;
++
++	/* Make sure the string is the right length.  The number should begin
++	 * with { 0x00, 0x01, ... } so we have to account for 15 leading zero
++	 * bits not being reported by MPI.
++	 */
++	x_size = mpi_get_nbits(x);
++	pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
++	if (x_size != xLen * 8 - 15)
++		return -ERANGE;
++
++	X = mpi_get_buffer(x, &X_size, &X_sign);
++	if (!X)
++		return -ENOMEM;
++	if (X_sign < 0) {
++		kfree(X);
++		return -EBADMSG;
++	}
++	if (X_size != xLen - 1) {
++		kfree(X);
++		return -EBADMSG;
++	}
++
++	*_X = X;
++	return 0;
++}
++
++/*
++ * Perform the RSA signature verification.
++ * @H: Value of hash of data and metadata
++ * @EM: The computed signature value
++ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
++ * @hash_size: The size of H
++ * @asn1_template: The DigestInfo ASN.1 template
++ * @asn1_size: Size of asm1_template[]
++ */
++static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
++		      const u8 *asn1_template, size_t asn1_size)
++{
++	unsigned PS_end, T_offset, i;
++
++	kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
++
++	if (k < 2 + 1 + asn1_size + hash_size)
++		return -EBADMSG;
++
++	/* Decode the EMSA-PKCS1-v1_5 */
++	if (EM[1] != 0x01) {
++		kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
++		return -EBADMSG;
++	}
++
++	T_offset = k - (asn1_size + hash_size);
++	PS_end = T_offset - 1;
++	if (EM[PS_end] != 0x00) {
++		kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
++		return -EBADMSG;
++	}
++
++	for (i = 2; i < PS_end; i++) {
++		if (EM[i] != 0xff) {
++			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
++			return -EBADMSG;
++		}
++	}
++
++	if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) {
++		kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
++		return -EBADMSG;
++	}
++
++	if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) {
++		kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
++		return -EKEYREJECTED;
++	}
++
++	kleave(" = 0");
++	return 0;
++}
++
++/*
++ * Perform the verification step [RFC3447 sec 8.2.2].
++ */
++static int RSA_verify_signature(const struct public_key *key,
++				const struct public_key_signature *sig)
++{
++	size_t tsize;
++	int ret;
++
++	/* Variables as per RFC3447 sec 8.2.2 */
++	const u8 *H = sig->digest;
++	u8 *EM = NULL;
++	MPI m = NULL;
++	size_t k;
++
++	kenter("");
++
++	/* (1) Check the signature size against the public key modulus size */
++	k = (mpi_get_nbits(key->rsa.n) + 7) / 8;
++
++	tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8;
++	pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
++	if (tsize != k) {
++		ret = -EBADMSG;
++		goto error;
++	}
++
++	/* (2b) Apply the RSAVP1 verification primitive to the public key */
++	ret = RSAVP1(key, sig->rsa.s, &m);
++	if (ret < 0)
++		goto error;
++
++	/* (2c) Convert the message representative (m) to an encoded message
++	 *      (EM) of length k octets.
++	 *
++	 *      NOTE!  The leading zero byte is suppressed by MPI, so we pass a
++	 *      pointer to the _preceding_ byte to RSA_verify()!
++	 */
++	ret = RSA_I2OSP(m, k, &EM);
++	if (ret < 0)
++		goto error;
++
++#if 0
++	{
++		int i;
++		printk("H:  ");
++		for (i = 0; i < sig->digest_size; i++)
++			printk("%02x", H[i]);
++		printk("\n");
++	}
++
++	{
++		int i;
++		printk("EM: 00");
++		for (i = 0; i < k - 1; i++)
++			printk("%02x", EM[i]);
++		printk("\n");
++	}
++#endif
++
++	ret = RSA_verify(H, EM - 1, k, sig->digest_size,
++			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
++			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
++
++error:
++	kfree(EM);
++	mpi_free(m);
++	kleave(" = %d", ret);
++	return ret;
++}
++
++const struct public_key_algorithm RSA_public_key_algorithm = {
++	.name		= "RSA",
++	.n_pub_mpi	= 2,
++	.n_sec_mpi	= 3,
++	.n_sig_mpi	= 1,
++	.verify		= RSA_verify_signature,
++};
++EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
+diff --git a/security/keys/public_key.h b/security/keys/public_key.h
+index 81ed603..7913615 100644
+--- a/security/keys/public_key.h
++++ b/security/keys/public_key.h
+@@ -42,6 +42,8 @@ struct public_key_algorithm {
+ 		      const struct public_key_signature *sig);
+ };
+ 
++extern const struct public_key_algorithm RSA_public_key_algorithm;
++
+ /*
+  * Asymmetric public key data
+  */
+-- 
+1.7.9.1
+
+
+From 82b8d487e66a5218ca9f91ca406db97b2113da60 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:11 +0000
+Subject: PGPLIB: PGP definitions (RFC 4880)
+
+Provide some useful PGP definitions from RFC 4880.  These describe details of
+public key crypto as used by crypto keys for things like signature
+verification.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ include/linux/pgp.h |  206 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 206 insertions(+), 0 deletions(-)
+ create mode 100644 include/linux/pgp.h
+
+diff --git a/include/linux/pgp.h b/include/linux/pgp.h
+new file mode 100644
+index 0000000..1359f64
+--- /dev/null
++++ b/include/linux/pgp.h
+@@ -0,0 +1,206 @@
++/* PGP definitions (RFC 4880)
++ *
++ * Copyright (C) 2011 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 _LINUX_PGP_H
++#define _LINUX_PGP_H
++
++#include <linux/types.h>
++
++struct pgp_key_ID {
++	u8 id[8];
++};
++
++struct pgp_time {
++	u8 time[4];
++};
++
++/*
++ * PGP public-key algorithm identifiers [RFC4880: 9.1]
++ */
++enum pgp_pubkey_algo {
++	PGP_PUBKEY_RSA_ENC_OR_SIG	= 1,
++	PGP_PUBKEY_RSA_ENC_ONLY		= 2,
++	PGP_PUBKEY_RSA_SIG_ONLY		= 3,
++	PGP_PUBKEY_ELGAMAL		= 16,
++	PGP_PUBKEY_DSA			= 17,
++	PGP_PUBKEY__LAST
++};
++
++/*
++ * PGP symmetric-key algorithm identifiers [RFC4880: 9.2]
++ */
++enum pgp_symkey_algo {
++	PGP_SYMKEY_PLAINTEXT		= 0,
++	PGP_SYMKEY_IDEA			= 1,
++	PGP_SYMKEY_3DES			= 2,
++	PGP_SYMKEY_CAST5		= 3,
++	PGP_SYMKEY_BLOWFISH		= 4,
++	PGP_SYMKEY_AES_128KEY		= 7,
++	PGP_SYMKEY_AES_192KEY		= 8,
++	PGP_SYMKEY_AES_256KEY		= 9,
++	PGP_SYMKEY_TWOFISH_256KEY	= 10,
++};
++
++/*
++ * PGP compression algorithm identifiers [RFC4880: 9.3]
++ */
++enum pgp_compr_algo {
++	PGP_COMPR_UNCOMPRESSED		= 0,
++	PGP_COMPR_ZIP			= 1,
++	PGP_COMPR_ZLIB			= 2,
++	PGP_COMPR_BZIP2			= 3,
++};
++
++/*
++ * PGP hash algorithm identifiers [RFC4880: 9.4]
++ */
++enum pgp_hash_algo {
++	PGP_HASH_MD5			= 1,
++	PGP_HASH_SHA1			= 2,
++	PGP_HASH_RIPE_MD_160		= 3,
++	PGP_HASH_SHA256			= 8,
++	PGP_HASH_SHA384			= 9,
++	PGP_HASH_SHA512			= 10,
++	PGP_HASH_SHA224			= 11,
++	PGP_HASH__LAST
++};
++
++extern const char *const pgp_hash_algorithms[PGP_HASH__LAST];
++
++/*
++ * PGP packet type tags [RFC4880: 4.3].
++ */
++enum pgp_packet_tag {
++	PGP_PKT_RESERVED		= 0,
++	PGP_PKT_PUBKEY_ENC_SESSION_KEY	= 1,
++	PGP_PKT_SIGNATURE		= 2,
++	PGP_PKT_SYMKEY_ENC_SESSION_KEY	= 3,
++	PGP_PKT_ONEPASS_SIGNATURE	= 4,
++	PGP_PKT_SECRET_KEY		= 5,
++	PGP_PKT_PUBLIC_KEY		= 6,
++	PGP_PKT_SECRET_SUBKEY		= 7,
++	PGP_PKT_COMPRESSED_DATA		= 8,
++	PGP_PKT_SYM_ENC_DATA		= 9,
++	PGP_PKT_MARKER			= 10,
++	PGP_PKT_LITERAL_DATA		= 11,
++	PGP_PKT_TRUST			= 12,
++	PGP_PKT_USER_ID			= 13,
++	PGP_PKT_PUBLIC_SUBKEY		= 14,
++	PGP_PKT_USER_ATTRIBUTE		= 17,
++	PGP_PKT_SYM_ENC_AND_INTEG_DATA	= 18,
++	PGP_PKT_MODIFY_DETECT_CODE	= 19,
++	PGP_PKT_PRIVATE_0		= 60,
++	PGP_PKT_PRIVATE_3		= 63,
++	PGP_PKT__HIGHEST		= 63
++};
++
++/*
++ * Signature (tag 2) packet [RFC4880: 5.2].
++ */
++enum pgp_signature_version {
++	PGP_SIG_VERSION_3			= 3,
++	PGP_SIG_VERSION_4			= 4,
++};
++
++enum pgp_signature_type {
++	PGP_SIG_BINARY_DOCUMENT_SIG		= 0x00,
++	PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG	= 0x01,
++	PGP_SIG_STANDALONE_SIG			= 0x02,
++	PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY	= 0x10,
++	PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY	= 0x11,
++	PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY	= 0x12,
++	PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY	= 0x13,
++	PGP_SIG_SUBKEY_BINDING_SIG		= 0x18,
++	PGP_SIG_PRIMARY_KEY_BINDING_SIG		= 0x19,
++	PGP_SIG_DIRECTLY_ON_KEY			= 0x1F,
++	PGP_SIG_KEY_REVOCATION_SIG		= 0x20,
++	PGP_SIG_SUBKEY_REVOCATION_SIG		= 0x28,
++	PGP_SIG_CERT_REVOCATION_SIG		= 0x30,
++	PGP_SIG_TIMESTAMP_SIG			= 0x40,
++	PGP_SIG_THIRD_PARTY_CONFIRM_SIG		= 0x50,
++};
++
++struct pgp_signature_v3_packet {
++	enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_3 */
++	u8	length_of_hashed;	/* == 5 */
++	struct {
++		enum pgp_signature_type signature_type : 8;
++		struct pgp_time	creation_time;
++	} hashed;
++	struct pgp_key_ID issuer;
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	enum pgp_hash_algo hash_algo : 8;
++} __packed;
++
++struct pgp_signature_v4_packet {
++	enum pgp_signature_version version : 8;	/* == PGP_SIG_VERSION_4 */
++	enum pgp_signature_type signature_type : 8;
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	enum pgp_hash_algo hash_algo : 8;
++} __packed;
++
++/*
++ * V4 signature subpacket types [RFC4880: 5.2.3.1].
++ */
++enum pgp_sig_subpkt_type {
++	PGP_SIG_CREATION_TIME			= 2,
++	PGP_SIG_EXPIRATION_TIME			= 3,
++	PGP_SIG_EXPORTABLE_CERT			= 4,
++	PGP_SIG_TRUST_SIG			= 5,
++	PGP_SIG_REGEXP				= 6,
++	PGP_SIG_REVOCABLE			= 7,
++	PGP_SIG_KEY_EXPIRATION_TIME		= 9,
++	PGP_SIG_PREF_SYM_ALGO			= 11,
++	PGP_SIG_REVOCATION_KEY			= 12,
++	PGP_SIG_ISSUER				= 16,
++	PGP_SIG_NOTATION_DATA			= 20,
++	PGP_SIG_PREF_HASH_ALGO			= 21,
++	PGP_SIG_PREF_COMPR_ALGO			= 22,
++	PGP_SIG_KEY_SERVER_PREFS		= 23,
++	PGP_SIG_PREF_KEY_SERVER			= 24,
++	PGP_SIG_PRIMARY_USER_ID			= 25,
++	PGP_SIG_POLICY_URI			= 26,
++	PGP_SIG_KEY_FLAGS			= 27,
++	PGP_SIG_SIGNERS_USER_ID			= 28,
++	PGP_SIG_REASON_FOR_REVOCATION		= 29,
++	PGP_SIG_FEATURES			= 30,
++	PGP_SIG_TARGET				= 31,
++	PGP_SIG_EMBEDDED_SIG			= 32,
++	PGP_SIG__LAST
++};
++
++#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK	0x80
++
++/*
++ * Key (tag 5, 6, 7 and 14) packet
++ */
++enum pgp_key_version {
++	PGP_KEY_VERSION_2			= 2,
++	PGP_KEY_VERSION_3			= 3,
++	PGP_KEY_VERSION_4			= 4,
++};
++
++struct pgp_key_v3_packet {
++	enum pgp_key_version version : 8;
++	struct pgp_time	creation_time;
++	u8 expiry[2];				/* 0 or time in days till expiry */
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	u8 key_material[0];
++} __packed;
++
++struct pgp_key_v4_packet {
++	enum pgp_key_version version : 8;
++	struct pgp_time	creation_time;
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	u8 key_material[0];
++} __packed;
++
++#endif /* _LINUX_PGP_H */
+-- 
+1.7.9.1
+
+
+From 570b106e22577e362c2772bdbfa1049c894b5cfb Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:12 +0000
+Subject: PGPLIB: Basic packet parser
+
+Provide a simple parser that extracts the packets from a PGP packet blob and
+passes the desirous ones to the given processor function:
+
+	struct pgp_parse_context {
+		u64 types_of_interest;
+		int (*process_packet)(struct pgp_parse_context *context,
+				      enum pgp_packet_tag type,
+				      u8 headerlen,
+				      const u8 *data,
+				      size_t datalen);
+	};
+
+	int pgp_parse_packets(const u8 *data, size_t datalen,
+			      struct pgp_parse_context *ctx);
+
+This is configured on with CONFIG_PGP_LIBRARY.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ include/linux/pgp.h         |   25 ++++
+ security/keys/Kconfig       |    6 +
+ security/keys/Makefile      |    1 +
+ security/keys/pgp_library.c |  254 +++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 286 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/pgp_library.c
+
+diff --git a/include/linux/pgp.h b/include/linux/pgp.h
+index 1359f64..235270a 100644
+--- a/include/linux/pgp.h
++++ b/include/linux/pgp.h
+@@ -203,4 +203,29 @@ struct pgp_key_v4_packet {
+ 	u8 key_material[0];
+ } __packed;
+ 
++/*
++ * PGP library packet parser
++ */
++struct pgp_parse_context {
++	u64 types_of_interest;
++	int (*process_packet)(struct pgp_parse_context *context,
++			      enum pgp_packet_tag type,
++			      u8 headerlen,
++			      const u8 *data,
++			      size_t datalen);
++};
++
++extern int pgp_parse_packets(const u8 *data, size_t datalen,
++			     struct pgp_parse_context *ctx);
++
++struct pgp_parse_pubkey {
++	enum pgp_key_version version : 8;
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	time_t		creation_time;
++	time_t		expires_at;
++};
++
++extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
++				struct pgp_parse_pubkey *pk);
++
+ #endif /* _LINUX_PGP_H */
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index 65d640b..aa3954c 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -92,3 +92,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA
+ 	depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+ 	help
+ 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
++
++config PGP_LIBRARY
++	tristate "PGP parsing library"
++	help
++	  This option enables a library that provides a number of simple
++	  utility functions for parsing PGP (RFC 4880) packet-based messages.
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 59e7180..2dbbe6c 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -27,5 +27,6 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
+ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+ obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
++obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
+ 
+ crypto_keys-y := crypto_type.o crypto_verify.o
+diff --git a/security/keys/pgp_library.c b/security/keys/pgp_library.c
+new file mode 100644
+index 0000000..685660f
+--- /dev/null
++++ b/security/keys/pgp_library.c
+@@ -0,0 +1,254 @@
++/* PGP packet parser (RFC 4880)
++ *
++ * Copyright (C) 2011 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.
++ */
++#define pr_fmt(fmt) "PGP: "fmt
++#include <linux/pgp.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++MODULE_LICENSE("GPL");
++
++const char *const pgp_hash_algorithms[PGP_HASH__LAST] = {
++	[PGP_HASH_MD5]			= "md5",
++	[PGP_HASH_SHA1]			= "sha1",
++	[PGP_HASH_RIPE_MD_160]		= "rmd160",
++	[PGP_HASH_SHA256]		= "sha256",
++	[PGP_HASH_SHA384]		= "sha384",
++	[PGP_HASH_SHA512]		= "sha512",
++	[PGP_HASH_SHA224]		= "sha224",
++};
++EXPORT_SYMBOL_GPL(pgp_hash_algorithms);
++
++/**
++ * pgp_parse_packet_header - Parse a PGP packet header
++ * @_data: Start of the PGP packet (updated to PGP packet data)
++ * @_datalen: Amount of data remaining in buffer (decreased)
++ * @_type: Where the packet type will be returned
++ * @_headerlen: Where the header length will be returned
++ *
++ * Parse a set of PGP packet header [RFC 4880: 4.2].
++ *
++ * Returns packet data size on success; non-zero on error.  If successful,
++ * *_data and *_datalen will have been updated and *_headerlen will be set to
++ * hold the length of the packet header.
++ */
++ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
++				enum pgp_packet_tag *_type,
++				u8 *_headerlen)
++{
++	enum pgp_packet_tag type;
++	const u8 *data = *_data;
++	size_t size, datalen = *_datalen;
++
++	pr_devel("-->pgp_parse_packet_header(,%zu,,)", datalen);
++
++	if (datalen < 2)
++		goto short_packet;
++
++	pr_devel("pkthdr %02x, %02x\n", data[0], data[1]);
++
++	type = *data++;
++	datalen--;
++	if (!(type & 0x80)) {
++		pr_debug("Packet type does not have MSB set\n");
++		return -EBADMSG;
++	}
++	type &= ~0x80;
++
++	if (type & 0x40) {
++		/* New packet length format */
++		type &= ~0x40;
++		pr_devel("new format: t=%u\n", type);
++		switch (data[0]) {
++		case 0x00 ... 0xbf:
++			/* One-byte length */
++			size = data[0];
++			data++;
++			datalen--;
++			*_headerlen = 2;
++			break;
++		case 0xc0 ... 0xdf:
++			/* Two-byte length */
++			if (datalen < 2)
++				goto short_packet;
++			size = (data[0] - 192) * 256;
++			size += data[1] + 192;
++			data += 2;
++			datalen -= 2;
++			*_headerlen = 3;
++			break;
++		case 0xff:
++			pr_debug("Five-byte packet length not supported\n");
++			return -EBADMSG;
++		default:
++			pr_debug("Error parsing packet length\n");
++			return -EBADMSG;
++		}
++	} else {
++		/* Old packet length format */
++		u8 length_type = type & 0x03;
++		type >>= 2;
++		pr_devel("old format: t=%u lt=%u\n", type, length_type);
++
++		switch (length_type) {
++		case 0:
++			/* One-byte length */
++			size = data[0];
++			data++;
++			datalen--;
++			*_headerlen = 2;
++			break;
++		case 1:
++			/* Two-byte length */
++			if (datalen < 2)
++				goto short_packet;
++			size  = data[0] << 8;
++			size |= data[1];
++			data += 2;
++			datalen -= 2;
++			*_headerlen = 3;
++			break;
++		case 2:
++			/* Four-byte length */
++			if (datalen < 4)
++				goto short_packet;
++			size  = data[0] << 24;
++			size |= data[1] << 16;
++			size |= data[2] << 8;
++			size |= data[3];
++			data += 4;
++			datalen -= 4;
++			*_headerlen = 5;
++			break;
++		default:
++			pr_debug("Indefinite length packet not supported\n");
++			return -EBADMSG;
++		}
++	}
++
++	pr_devel("datalen=%zu size=%zu", datalen, size);
++	if (datalen < size)
++		goto short_packet;
++
++	*_data = data;
++	*_datalen = datalen;
++	*_type = type;
++	pr_devel("Found packet type=%u size=%zd\n", type, size);
++	return size;
++
++short_packet:
++	pr_debug("Attempt to parse short packet\n");
++	return -EBADMSG;
++}
++
++/**
++ * pgp_parse_packets - Parse a set of PGP packets
++ * @_data: Data to be parsed (updated)
++ * @_datalen: Amount of data (updated)
++ * @ctx: Parsing context
++ *
++ * Parse a set of PGP packets [RFC 4880: 4].
++ */
++int pgp_parse_packets(const u8 *data, size_t datalen,
++		      struct pgp_parse_context *ctx)
++{
++	enum pgp_packet_tag type;
++	ssize_t pktlen;
++	u8 headerlen;
++	int ret;
++
++	while (datalen > 2) {
++		pktlen = pgp_parse_packet_header(&data, &datalen, &type,
++						 &headerlen);
++		if (pktlen < 0)
++			return pktlen;
++
++		if ((ctx->types_of_interest >> type) & 1) {
++			ret = ctx->process_packet(ctx, type, headerlen,
++						  data, pktlen);
++			if (ret < 0)
++				return ret;
++		}
++		data += pktlen;
++		datalen -= pktlen;
++	}
++
++	if (datalen != 0) {
++		pr_debug("Excess octets in packet stream\n");
++		return -EBADMSG;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(pgp_parse_packets);
++
++/**
++ * pgp_parse_public_key - Parse the common part of a PGP pubkey packet
++ * @_data: Content of packet (updated)
++ * @_datalen: Length of packet remaining (updated)
++ * @pk: Public key data
++ *
++ * Parse the common data struct for a PGP pubkey packet [RFC 4880: 5.5.2].
++ */
++int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
++			 struct pgp_parse_pubkey *pk)
++{
++	const u8 *data = *_data;
++	size_t datalen = *_datalen;
++	__be32 tmp;
++
++	if (datalen < 12) {
++		pr_debug("Public key packet too short\n");
++		return -EBADMSG;
++	}
++
++	pk->version = *data++;
++	switch (pk->version) {
++	case PGP_KEY_VERSION_2:
++	case PGP_KEY_VERSION_3:
++	case PGP_KEY_VERSION_4:
++		break;
++	default:
++		pr_debug("Public key packet with unhandled version %d\n",
++			   pk->version);
++		return -EBADMSG;
++	}
++
++	tmp  = *data++ << 24;
++	tmp |= *data++ << 16;
++	tmp |= *data++ << 8;
++	tmp |= *data++;
++	pk->creation_time = tmp;
++	if (pk->version == PGP_KEY_VERSION_4) {
++		pk->expires_at = 0; /* Have to get it from the selfsignature */
++	} else {
++		unsigned short ndays;
++		ndays  = *data++ << 8;
++		ndays |= *data++;
++		if (ndays)
++			pk->expires_at = pk->creation_time + ndays * 86400UL;
++		else
++			pk->expires_at = 0;
++		datalen -= 2;
++	}
++
++	pk->pubkey_algo = *data++;
++	datalen -= 6;
++
++	pr_devel("%x,%x,%lx,%lx",
++		 pk->version, pk->pubkey_algo, pk->creation_time,
++		 pk->expires_at);
++
++	*_data = data;
++	*_datalen = datalen;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(pgp_parse_public_key);
+-- 
+1.7.9.1
+
+
+From 194b547524cc4abf00e357948d949871d42bed84 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:13 +0000
+Subject: PGPLIB: Signature parser
+
+Provide some PGP signature parsing helpers:
+
+ (1) A function to parse V4 signature subpackets and pass the desired ones to
+     a processor function:
+
+	int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
+				  struct pgp_parse_sig_context *ctx);
+
+ (2) A function to parse out basic signature parameters from any PGP signature
+     such that the algorithms and public key can be selected:
+
+	int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
+				 struct pgp_sig_parameters *p);
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ include/linux/pgp.h         |   24 ++++
+ security/keys/pgp_library.c |  277 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 301 insertions(+), 0 deletions(-)
+
+diff --git a/include/linux/pgp.h b/include/linux/pgp.h
+index 235270a..ab1a8fa 100644
+--- a/include/linux/pgp.h
++++ b/include/linux/pgp.h
+@@ -228,4 +228,28 @@ struct pgp_parse_pubkey {
+ extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
+ 				struct pgp_parse_pubkey *pk);
+ 
++struct pgp_parse_sig_context {
++	unsigned long types_of_interest[128 / BITS_PER_LONG];
++	int (*process_packet)(struct pgp_parse_sig_context *context,
++			      enum pgp_sig_subpkt_type type,
++			      const u8 *data,
++			      size_t datalen);
++};
++
++extern int pgp_parse_sig_packets(const u8 *data, size_t datalen,
++				 struct pgp_parse_sig_context *ctx);
++
++struct pgp_sig_parameters {
++	enum pgp_signature_type signature_type : 8;
++	union {
++		struct pgp_key_ID issuer;
++		__be32 issuer32[2];
++	};
++	enum pgp_pubkey_algo pubkey_algo : 8;
++	enum pgp_hash_algo hash_algo : 8;
++};
++
++extern int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
++				struct pgp_sig_parameters *p);
++
+ #endif /* _LINUX_PGP_H */
+diff --git a/security/keys/pgp_library.c b/security/keys/pgp_library.c
+index 685660f..f6b831f 100644
+--- a/security/keys/pgp_library.c
++++ b/security/keys/pgp_library.c
+@@ -252,3 +252,280 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(pgp_parse_public_key);
++
++/**
++ * pgp_parse_sig_subpkt_header - Parse a PGP V4 signature subpacket header
++ * @_data: Start of the subpacket (updated to subpacket data)
++ * @_datalen: Amount of data remaining in buffer (decreased)
++ * @_type: Where the subpacket type will be returned
++ *
++ * Parse a PGP V4 signature subpacket header [RFC 4880: 5.2.3.1].
++ *
++ * Returns packet data size on success; non-zero on error.  If successful,
++ * *_data and *_datalen will have been updated and *_headerlen will be set to
++ * hold the length of the packet header.
++ */
++ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
++				    enum pgp_sig_subpkt_type *_type)
++{
++	enum pgp_sig_subpkt_type type;
++	const u8 *data = *_data;
++	size_t size, datalen = *_datalen;
++
++	pr_devel("-->pgp_parse_sig_subpkt_header(,%zu,,)", datalen);
++
++	if (datalen < 2)
++		goto short_subpacket;
++
++	pr_devel("subpkt hdr %02x, %02x\n", data[0], data[1]);
++
++	switch (data[0]) {
++	case 0x00 ... 0xbf:
++		/* One-byte length */
++		size = data[0];
++		data++;
++		datalen--;
++		break;
++	case 0xc0 ... 0xfe:
++		/* Two-byte length */
++		if (datalen < 3)
++			goto short_subpacket;
++		size = (data[0] - 192) * 256;
++		size += data[1] + 192;
++		data += 2;
++		datalen -= 2;
++		break;
++	case 0xff:
++		if (datalen < 6)
++			goto short_subpacket;
++		size  = data[1] << 24;
++		size |= data[2] << 16;
++		size |= data[3] << 8;
++		size |= data[4];
++		data += 5;
++		datalen -= 5;
++		break;
++	}
++
++	/* The type octet is included in the size */
++	if (size == 0) {
++		pr_debug("Signature subpacket size can't be zero\n");
++		return -EBADMSG;
++	}
++
++	type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK;
++	datalen--;
++	size--;
++
++	pr_devel("datalen=%zu size=%zu", datalen, size);
++	if (datalen < size)
++		goto short_subpacket;
++
++	*_data = data;
++	*_datalen = datalen;
++	*_type = type;
++	pr_devel("Found subpkt type=%u size=%zd\n", type, size);
++	return size;
++
++short_subpacket:
++	pr_debug("Attempt to parse short signature subpacket\n");
++	return -EBADMSG;
++}
++
++/**
++ * pgp_parse_sig_subpkts - Parse a set of PGP V4 signatute subpackets
++ * @_data: Data to be parsed (updated)
++ * @_datalen: Amount of data (updated)
++ * @ctx: Parsing context
++ *
++ * Parse a set of PGP signature subpackets [RFC 4880: 5.2.3].
++ */
++int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
++			  struct pgp_parse_sig_context *ctx)
++{
++	enum pgp_sig_subpkt_type type;
++	ssize_t pktlen;
++	int ret;
++
++	pr_devel("-->pgp_parse_sig_subpkts(,%zu,,)", datalen);
++
++	while (datalen > 2) {
++		pktlen = pgp_parse_sig_subpkt_header(&data, &datalen, &type);
++		if (pktlen < 0)
++			return pktlen;
++		if (test_bit(type, ctx->types_of_interest)) {
++			ret = ctx->process_packet(ctx, type, data, pktlen);
++			if (ret < 0)
++				return ret;
++		}
++		data += pktlen;
++		datalen -= pktlen;
++	}
++
++	if (datalen != 0) {
++		pr_debug("Excess octets in signature subpacket stream\n");
++		return -EBADMSG;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(pgp_parse_sig_subpkts);
++
++struct pgp_parse_sig_params_ctx {
++	struct pgp_parse_sig_context base;
++	struct pgp_sig_parameters *params;
++	bool got_the_issuer;
++};
++
++/*
++ * Process a V4 signature subpacket.
++ */
++static int pgp_process_sig_params_subpkt(struct pgp_parse_sig_context *context,
++					 enum pgp_sig_subpkt_type type,
++					 const u8 *data,
++					 size_t datalen)
++{
++	struct pgp_parse_sig_params_ctx *ctx =
++		container_of(context, struct pgp_parse_sig_params_ctx, base);
++
++	if (ctx->got_the_issuer) {
++		pr_debug("V4 signature packet has multiple issuers\n");
++		return -EBADMSG;
++	}
++
++	if (datalen != 8) {
++		pr_debug("V4 signature issuer subpkt not 8 long (%zu)\n",
++			   datalen);
++		return -EBADMSG;
++	}
++
++	memcpy(&ctx->params->issuer, data, 8);
++	ctx->got_the_issuer = true;
++	return 0;
++}
++
++/**
++ * pgp_parse_sig_params - Parse basic parameters from a PGP signature packet
++ * @_data: Content of packet (updated)
++ * @_datalen: Length of packet remaining (updated)
++ * @p: The basic parameters
++ *
++ * Parse the basic parameters from a PGP signature packet [RFC 4880: 5.2] that
++ * are needed to start off a signature verification operation.  The only ones
++ * actually necessary are the signature type (which affects how the data is
++ * transformed) and the has algorithm.
++ *
++ * We also extract the public key algorithm and the issuer's key ID as we'll
++ * need those to determine if we actually have the public key available.  If
++ * not, then we can't verify the signature anyway.
++ *
++ * Returns 0 if successful or a negative error code.  *_data and *_datalen are
++ * updated to point to the 16-bit subset of the hash value and the set of MPIs.
++ */
++int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
++			 struct pgp_sig_parameters *p)
++{
++	enum pgp_signature_version version;
++	const u8 *data = *_data;
++	size_t datalen = *_datalen;
++	int ret;
++
++	pr_devel("-->pgp_parse_sig_params(,%zu,,)", datalen);
++
++	if (datalen < 1)
++		return -EBADMSG;
++	version = *data;
++
++	if (version == PGP_SIG_VERSION_3) {
++		const struct pgp_signature_v3_packet *v3 = (const void *)data;
++
++		if (datalen < sizeof(*v3)) {
++			pr_debug("Short V3 signature packet\n");
++			return -EBADMSG;
++		}
++		datalen -= sizeof(*v3);
++		data += sizeof(*v3);
++
++		/* V3 has everything we need in the header */
++		p->signature_type = v3->hashed.signature_type;
++		p->issuer = v3->issuer;
++		p->pubkey_algo = v3->pubkey_algo;
++		p->hash_algo = v3->hash_algo;
++
++	} else if (version == PGP_SIG_VERSION_4) {
++		const struct pgp_signature_v4_packet *v4 = (const void *)data;
++		struct pgp_parse_sig_params_ctx ctx = {
++			.base.process_packet = pgp_process_sig_params_subpkt,
++			.params = p,
++			.got_the_issuer = false,
++		};
++		size_t subdatalen;
++
++		if (datalen < sizeof(*v4) + 2 + 2 + 2) {
++			pr_debug("Short V4 signature packet\n");
++			return -EBADMSG;
++		}
++		datalen -= sizeof(*v4);
++		data += sizeof(*v4);
++
++		/* V4 has most things in the header... */
++		p->signature_type = v4->signature_type;
++		p->pubkey_algo = v4->pubkey_algo;
++		p->hash_algo = v4->hash_algo;
++
++		/* ... but we have to get the key ID from the subpackets, of
++		 * which there are two sets. */
++		__set_bit(PGP_SIG_ISSUER, ctx.base.types_of_interest);
++
++		subdatalen  = *data++ << 8;
++		subdatalen |= *data++;
++		datalen -= 2;
++		if (subdatalen) {
++			/* Hashed subpackets */
++			pr_devel("hashed data: %zu (after %zu)\n",
++				 subdatalen, sizeof(*v4));
++			if (subdatalen > datalen + 2 + 2) {
++				pr_debug("Short V4 signature packet [hdata]\n");
++				return -EBADMSG;
++			}
++			ret = pgp_parse_sig_subpkts(data, subdatalen,
++						    &ctx.base);
++			if (ret < 0)
++				return ret;
++			data += subdatalen;
++			datalen += subdatalen;
++		}
++
++		subdatalen  = *data++ << 8;
++		subdatalen |= *data++;
++		datalen -= 2;
++		if (subdatalen) {
++			/* Unhashed subpackets */
++			pr_devel("unhashed data: %zu\n", subdatalen);
++			if (subdatalen > datalen + 2) {
++				pr_debug("Short V4 signature packet [udata]\n");
++				return -EBADMSG;
++			}
++			ret = pgp_parse_sig_subpkts(data, subdatalen,
++						    &ctx.base);
++			if (ret < 0)
++				return ret;
++			data += subdatalen;
++			datalen += subdatalen;
++		}
++
++		if (!ctx.got_the_issuer) {
++			pr_debug("V4 signature packet lacks issuer\n");
++			return -EBADMSG;
++		}
++	} else {
++		pr_debug("Signature packet with unhandled version %d\n",
++			 version);
++		return -EBADMSG;
++	}
++
++	*_data = data;
++	*_datalen = datalen;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(pgp_parse_sig_params);
+-- 
+1.7.9.1
+
+
+From ee32f2d2d24a635e7bb46cbd37a0622850f4c66e Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:13 +0000
+Subject: KEYS: PGP data parser
+
+Implement a PGP data parser for the crypto key type to use when instantiating a
+key.
+
+This parser attempts to parse the instantiation data as a PGP packet sequence
+(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm
+key or subkey from it.
+
+If it finds such a key, it will set up a public_key subtype payload with
+appropriate handler routines (DSA or RSA) and attach it to the key.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Kconfig          |   12 ++
+ security/keys/Makefile         |    4 +
+ security/keys/pgp_key_parser.c |  343 ++++++++++++++++++++++++++++++++++++++++
+ security/keys/pgp_parser.h     |   23 +++
+ 4 files changed, 382 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/pgp_key_parser.c
+ create mode 100644 security/keys/pgp_parser.h
+
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index aa3954c..fd53028 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -98,3 +98,15 @@ config PGP_LIBRARY
+ 	help
+ 	  This option enables a library that provides a number of simple
+ 	  utility functions for parsing PGP (RFC 4880) packet-based messages.
++
++config CRYPTO_KEY_PGP_PARSER
++	tristate "PGP key blob parser"
++	depends on CRYPTO_KEY_TYPE
++	select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
++	select PGP_LIBRARY
++	select MD5 # V3 fingerprint generation
++	select SHA1 # V4 fingerprint generation
++	help
++	  This option provides support for parsing PGP (RFC 4880) format blobs
++	  for key data and provides the ability to instantiate a crypto key
++	  from a public key packet found inside the blob.
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 2dbbe6c..416670c 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -28,5 +28,9 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+ obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
+ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
++obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o
+ 
+ crypto_keys-y := crypto_type.o crypto_verify.o
++
++pgp_parser-y := \
++	pgp_key_parser.o
+diff --git a/security/keys/pgp_key_parser.c b/security/keys/pgp_key_parser.c
+new file mode 100644
+index 0000000..4efc4de
+--- /dev/null
++++ b/security/keys/pgp_key_parser.c
+@@ -0,0 +1,343 @@
++/* Parser for PGP format key data [RFC 4880]
++ *
++ * Copyright (C) 2011 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.
++ */
++
++#define pr_fmt(fmt) "PGP: "fmt
++#include <keys/crypto-subtype.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/mpi.h>
++#include <linux/pgp.h>
++#include <crypto/hash.h>
++#include "public_key.h"
++#include "pgp_parser.h"
++
++MODULE_LICENSE("GPL");
++
++const
++struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = {
++#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \
++	defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE)
++	[PGP_PUBKEY_RSA_ENC_OR_SIG]	= &RSA_public_key_algorithm,
++	[PGP_PUBKEY_RSA_ENC_ONLY]	= &RSA_public_key_algorithm,
++	[PGP_PUBKEY_RSA_SIG_ONLY]	= &RSA_public_key_algorithm,
++#endif
++	[PGP_PUBKEY_ELGAMAL]		= NULL,
++	[PGP_PUBKEY_DSA]		= NULL,
++};
++
++static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = {
++	[PGP_PUBKEY_RSA_ENC_OR_SIG]	= PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER,
++	[PGP_PUBKEY_RSA_ENC_ONLY]	= PKEY_CAN_ENCDEC,
++	[PGP_PUBKEY_RSA_SIG_ONLY]	= PKEY_CAN_SIGVER,
++	[PGP_PUBKEY_ELGAMAL]		= 0,
++	[PGP_PUBKEY_DSA]		= 0,
++};
++
++static inline void digest_putc(struct shash_desc *digest, uint8_t ch)
++{
++	crypto_shash_update(digest, &ch, 1);
++}
++
++struct pgp_key_data_parse_context {
++	struct pgp_parse_context pgp;
++	struct crypto_key_subtype *subtype;
++	char *fingerprint;
++	void *payload;
++};
++
++/*
++ * Calculate the public key ID (RFC4880 12.2)
++ */
++static int pgp_calc_pkey_keyid(struct shash_desc *digest,
++			       struct pgp_parse_pubkey *pgp,
++			       struct public_key *key)
++{
++	unsigned nb[ARRAY_SIZE(key->mpi)];
++	unsigned nn[ARRAY_SIZE(key->mpi)];
++	unsigned n;
++	u8 *pp[ARRAY_SIZE(key->mpi)];
++	u32 a32;
++	int npkey = key->algo->n_pub_mpi;
++	int i, ret = -ENOMEM;
++
++	kenter("");
++
++	n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6;
++	for (i = 0; i < npkey; i++) {
++		nb[i] = mpi_get_nbits(key->mpi[i]);
++		pp[i] = mpi_get_buffer(key->mpi[i], nn + i, NULL);
++		if (!pp[i])
++			goto error;
++		n += 2 + nn[i];
++	}
++
++	digest_putc(digest, 0x99);     /* ctb */
++	digest_putc(digest, n >> 8);   /* 16-bit header length */
++	digest_putc(digest, n);
++	digest_putc(digest, pgp->version);
++
++	a32 = pgp->creation_time;
++	digest_putc(digest, a32 >> 24);
++	digest_putc(digest, a32 >> 16);
++	digest_putc(digest, a32 >>  8);
++	digest_putc(digest, a32 >>  0);
++
++	if (pgp->version < PGP_KEY_VERSION_4) {
++		u16 a16;
++
++		if( pgp->expires_at)
++			a16 = (pgp->expires_at - pgp->creation_time) / 86400UL;
++		else
++			a16 = 0;
++		digest_putc(digest, a16 >> 8);
++		digest_putc(digest, a16 >> 0);
++	}
++
++	digest_putc(digest, pgp->pubkey_algo);
++
++	for (i = 0; i < npkey; i++) {
++		digest_putc(digest, nb[i] >> 8);
++		digest_putc(digest, nb[i]);
++		crypto_shash_update(digest, pp[i], nn[i]);
++	}
++	ret = 0;
++
++error:
++	for (i = 0; i < npkey; i++)
++		kfree(pp[i]);
++	kleave(" = %d", ret);
++	return ret;
++}
++
++/*
++ * Calculate the public key ID fingerprint
++ */
++static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx,
++				    struct pgp_parse_pubkey *pgp,
++				    struct public_key *key)
++{
++	struct crypto_shash *tfm;
++	struct shash_desc *digest;
++	char *fingerprint;
++	u8 *raw_fingerprint;
++	int digest_size, offset;
++	int ret, i;
++
++	ret = -ENOMEM;
++	tfm = crypto_alloc_shash(pgp->version < PGP_KEY_VERSION_4 ?
++				 "md5" : "sha1", 0, 0);
++	if (!tfm)
++		goto cleanup;
++
++	digest = kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm),
++			 GFP_KERNEL);
++	if (!digest)
++		goto cleanup_tfm;
++
++	digest->tfm = tfm;
++	digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
++	ret = crypto_shash_init(digest);
++	if (ret < 0)
++		goto cleanup_hash;
++
++	ret = pgp_calc_pkey_keyid(digest, pgp, key);
++	if (ret < 0)
++		goto cleanup_hash;
++
++	digest_size = crypto_shash_digestsize(tfm);
++
++	raw_fingerprint = kmalloc(digest_size, GFP_KERNEL);
++	if (!raw_fingerprint)
++		goto cleanup_hash;
++
++	ret = crypto_shash_final(digest, raw_fingerprint);
++	if (ret < 0)
++		goto cleanup_raw_fingerprint;
++
++	fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL);
++	if (!fingerprint)
++		goto cleanup_raw_fingerprint;
++
++	offset = digest_size - 8;
++	pr_debug("offset %u/%u\n", offset, digest_size);
++
++	for (i = 0; i < digest_size; i++)
++		sprintf(fingerprint + i * 2, "%02x", raw_fingerprint[i]);
++	pr_debug("fingerprint %s\n", fingerprint);
++
++	memcpy(&key->key_id, raw_fingerprint + offset, 8);
++	key->key_id_size = 8;
++
++	ctx->fingerprint = fingerprint;
++	ret = 0;
++cleanup_raw_fingerprint:
++	kfree(raw_fingerprint);
++cleanup_hash:
++	kfree(digest);
++cleanup_tfm:
++	crypto_free_shash(tfm);
++cleanup:
++	kleave(" = %d", ret);
++	return ret;
++}
++
++/*
++ * Extract a public key or public subkey from the PGP stream.
++ */
++static int pgp_process_public_key(struct pgp_parse_context *context,
++				  enum pgp_packet_tag type,
++				  u8 headerlen,
++				  const u8 *data,
++				  size_t datalen)
++{
++	const struct public_key_algorithm *algo;
++	struct pgp_key_data_parse_context *ctx =
++		container_of(context, struct pgp_key_data_parse_context, pgp);
++	struct pgp_parse_pubkey pgp;
++	struct public_key *key;
++	int i, ret;
++
++	kenter(",%u,%u,,%zu", type, headerlen, datalen);
++
++	if (ctx->subtype) {
++		kleave(" = -ENOKEY [already]");
++		return -EBADMSG;
++	}
++
++	key = kzalloc(sizeof(struct public_key), GFP_KERNEL);
++	if (!key)
++		return -ENOMEM;
++
++	ret = pgp_parse_public_key(&data, &datalen, &pgp);
++	if (ret < 0)
++		goto cleanup;
++
++	if (pgp.pubkey_algo >= PGP_PUBKEY__LAST ||
++	    !pgp_public_key_algorithms[pgp.pubkey_algo]) {
++		pr_debug("Unsupported public key algorithm %u\n",
++			 pgp.pubkey_algo);
++		ret = -ENOPKG;
++		goto cleanup;
++	}
++
++	algo = key->algo = pgp_public_key_algorithms[pgp.pubkey_algo];
++
++	/* It's a public key, so that only gives us encrypt and verify
++	 * capabilities.
++	 */
++	key->capabilities = pgp_public_key_capabilities[pgp.pubkey_algo] &
++		(PKEY_CAN_ENCRYPT | PKEY_CAN_VERIFY);
++
++	ret = -ENOMEM;
++	for (i = 0; i < algo->n_pub_mpi; i++) {
++		unsigned int remaining = datalen;
++		ret = -EBADMSG;
++		if (remaining == 0) {
++			pr_debug("short %zu mpi %d\n", datalen, i);
++			goto cleanup;
++		}
++		key->mpi[i] = mpi_read_from_buffer(data, &remaining);
++		if (!key->mpi[i])
++			goto cleanup;
++		data += remaining;
++		datalen -= remaining;
++	}
++
++	ret = -EBADMSG;
++	if (datalen != 0) {
++		pr_debug("excess %zu\n", datalen);
++		goto cleanup;
++	}
++
++	ret = pgp_generate_fingerprint(ctx, &pgp, key);
++	if (ret < 0)
++		goto cleanup;
++
++	/* We're pinning the module by being linked against it */
++	__module_get(public_key_crypto_key_subtype.owner);
++	ctx->subtype = &public_key_crypto_key_subtype;
++	ctx->payload = key;
++	kleave(" = 0 [use]");
++	return 0;
++
++cleanup:
++	pr_devel("cleanup");
++	if (key) {
++		for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
++			mpi_free(key->mpi[i]);
++		kfree(key);
++	}
++	kleave(" = %d", ret);
++	return ret;
++}
++
++/*
++ * Attempt to parse the instantiation data blob for a key as a PGP packet
++ * message holding a key.
++ */
++static int pgp_key_instantiate(struct key *key,
++			       const void *data, size_t datalen)
++{
++	struct pgp_key_data_parse_context ctx;
++	int ret;
++
++	kenter("");
++
++	ret = key_payload_reserve(key, datalen);
++	if (ret < 0)
++		return ret;
++
++	ctx.pgp.types_of_interest =
++		(1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
++	ctx.pgp.process_packet = pgp_process_public_key;
++	ctx.subtype = NULL;
++	ctx.fingerprint = NULL;
++	ctx.payload = NULL;
++
++	ret = pgp_parse_packets(data, datalen, &ctx.pgp);
++	if (ret < 0) {
++		if (ctx.payload)
++			ctx.subtype->destroy(ctx.payload);
++		if (ctx.subtype)
++			module_put(ctx.subtype->owner);
++		kfree(ctx.fingerprint);
++		key_payload_reserve(key, 0);
++		return ret;
++	}
++
++	key->type_data.p[0] = ctx.subtype;
++	key->type_data.p[1] = ctx.fingerprint;
++	key->payload.data = ctx.payload;
++	return 0;
++}
++
++static struct crypto_key_parser pgp_key_parser = {
++	.owner		= THIS_MODULE,
++	.name		= "pgp",
++	.instantiate	= pgp_key_instantiate,
++};
++
++/*
++ * Module stuff
++ */
++static int __init pgp_key_init(void)
++{
++	return register_crypto_key_parser(&pgp_key_parser);
++}
++
++static void __exit pgp_key_exit(void)
++{
++	unregister_crypto_key_parser(&pgp_key_parser);
++}
++
++module_init(pgp_key_init);
++module_exit(pgp_key_exit);
+diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h
+new file mode 100644
+index 0000000..1cda231
+--- /dev/null
++++ b/security/keys/pgp_parser.h
+@@ -0,0 +1,23 @@
++/* PGP crypto data parser internal definitions
++ *
++ * Copyright (C) 2011 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/pgp.h>
++
++#define kenter(FMT, ...) \
++	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
++#define kleave(FMT, ...) \
++	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
++
++/*
++ * pgp_key_parser.c
++ */
++extern const
++struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
+-- 
+1.7.9.1
+
+
+From 0e862034535288f2ee5653563178f6a6b99f8c47 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:14 +0000
+Subject: KEYS: PGP-based public key signature verification
+
+Provide handlers for PGP-based public-key algorithm signature verification.
+This does most of the work involved in signature verification as most of it is
+public-key algorithm agnostic.  The public-key verification algorithm itself
+is just the last little bit and is supplied the complete hash data to process.
+
+This requires glue logic putting on top to make use of it - something the next
+patch provides.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Makefile         |    3 +-
+ security/keys/pgp_parser.h     |    6 +
+ security/keys/pgp_pubkey_sig.c |  323 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 331 insertions(+), 1 deletions(-)
+ create mode 100644 security/keys/pgp_pubkey_sig.c
+
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 416670c..24e83a2 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -33,4 +33,5 @@ obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o
+ crypto_keys-y := crypto_type.o crypto_verify.o
+ 
+ pgp_parser-y := \
+-	pgp_key_parser.o
++	pgp_key_parser.o \
++	pgp_pubkey_sig.o
+diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h
+index 1cda231..a6192ce 100644
+--- a/security/keys/pgp_parser.h
++++ b/security/keys/pgp_parser.h
+@@ -21,3 +21,9 @@
+  */
+ extern const
+ struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
++
++/*
++ * pgp_pubkey_sig.c
++ */
++extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
++	struct key *crypto_key, const u8 *sigdata, size_t siglen);
+diff --git a/security/keys/pgp_pubkey_sig.c b/security/keys/pgp_pubkey_sig.c
+new file mode 100644
+index 0000000..b4b7cb0
+--- /dev/null
++++ b/security/keys/pgp_pubkey_sig.c
+@@ -0,0 +1,323 @@
++/* Handling for PGP public key signature data [RFC 4880]
++ *
++ * Copyright (C) 2011 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.
++ */
++
++#define pr_fmt(fmt) "PGPSIG: "fmt
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/pgp.h>
++#include "public_key.h"
++#include "pgp_parser.h"
++
++const struct {
++	enum pkey_hash_algo algo : 8;
++} pgp_pubkey_hash[PGP_HASH__LAST] = {
++	[PGP_HASH_MD5].algo		= PKEY_HASH_MD5,
++	[PGP_HASH_SHA1].algo		= PKEY_HASH_SHA1,
++	[PGP_HASH_RIPE_MD_160].algo	= PKEY_HASH_RIPE_MD_160,
++	[PGP_HASH_SHA256].algo		= PKEY_HASH_SHA256,
++	[PGP_HASH_SHA384].algo		= PKEY_HASH_SHA384,
++	[PGP_HASH_SHA512].algo		= PKEY_HASH_SHA512,
++	[PGP_HASH_SHA224].algo		= PKEY_HASH_SHA224,
++};
++
++static int pgp_pkey_verify_sig_add_data(struct crypto_key_verify_context *ctx,
++					const void *data, size_t datalen);
++static int pgp_pkey_verify_sig_end(struct crypto_key_verify_context *ctx,
++				   const u8 *sig, size_t siglen);
++static void pgp_pkey_verify_sig_cancel(struct crypto_key_verify_context *ctx);
++
++struct pgp_pkey_sig_parse_context {
++	struct pgp_parse_context pgp;
++	struct pgp_sig_parameters params;
++};
++
++static int pgp_pkey_parse_signature(struct pgp_parse_context *context,
++				    enum pgp_packet_tag type,
++				    u8 headerlen,
++				    const u8 *data,
++				    size_t datalen)
++{
++	struct pgp_pkey_sig_parse_context *ctx =
++		container_of(context, struct pgp_pkey_sig_parse_context, pgp);
++
++	return pgp_parse_sig_params(&data, &datalen, &ctx->params);
++}
++
++/*
++ * Begin the process of verifying a DSA signature.
++ *
++ * This involves allocating the hash into which first the data and then the
++ * metadata will be put, and parsing the signature to check that it matches the
++ * key.
++ */
++struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
++	struct key *crypto_key, const u8 *sigdata, size_t siglen)
++{
++	struct pgp_pkey_sig_parse_context p;
++	struct public_key_signature *sig;
++	struct crypto_shash *tfm;
++	const struct public_key *key = crypto_key->payload.data;
++	size_t digest_size, desc_size;
++	int ret;
++
++	kenter("{%d},,%zu", key_serial(crypto_key), siglen);
++
++	if (!key) {
++		kleave(" = -ENOKEY [no public key]");
++		return ERR_PTR(-ENOKEY);
++	}
++
++	p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
++	p.pgp.process_packet = pgp_pkey_parse_signature;
++	ret = pgp_parse_packets(sigdata, siglen, &p.pgp);
++	if (ret < 0)
++		return ERR_PTR(ret);
++
++	if (p.params.pubkey_algo >= PGP_PUBKEY__LAST ||
++	    !pgp_public_key_algorithms[p.params.pubkey_algo]) {
++		pr_debug("Unsupported public key algorithm %u\n",
++			 p.params.pubkey_algo);
++		return ERR_PTR(-ENOKEY);
++	}
++
++	if (pgp_public_key_algorithms[p.params.pubkey_algo] != key->algo) {
++		kleave(" = -ENOKEY [wrong pk algo]");
++		return ERR_PTR(-ENOKEY);
++	}
++
++	if (!(key->capabilities & PKEY_CAN_VERIFY)) {
++		kleave(" = -EKEYREJECTED [key can't verify]");
++		return ERR_PTR(-EKEYREJECTED);
++	}
++
++	if (p.params.hash_algo >= PGP_HASH__LAST ||
++	    !pgp_hash_algorithms[p.params.hash_algo]) {
++		kleave(" = -ENOPKG [hash]");
++		return ERR_PTR(-ENOPKG);
++	}
++
++	pr_debug("Signature generated with %s hash\n",
++		 pgp_hash_algorithms[p.params.hash_algo]);
++
++	if (memcmp(&p.params.issuer, key->key_id, 8) != 0) {
++		kleave(" = -ENOKEY [wrong key ID]");
++		return ERR_PTR(-ENOKEY);
++	}
++
++	if (p.params.signature_type != PGP_SIG_BINARY_DOCUMENT_SIG &&
++	    p.params.signature_type != PGP_SIG_STANDALONE_SIG) {
++		/* We don't want to canonicalise */
++		kleave(" = -EOPNOTSUPP [canon]");
++		return ERR_PTR(-EOPNOTSUPP);
++	}
++
++	/* Allocate the hashing algorithm we're going to need and find out how
++	 * big the hash operational data will be.
++	 */
++	tfm = crypto_alloc_shash(pgp_hash_algorithms[p.params.hash_algo], 0, 0);
++	if (IS_ERR(tfm))
++		return PTR_ERR(tfm) == -ENOENT ?
++			ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
++
++	desc_size = crypto_shash_descsize(tfm);
++	digest_size = crypto_shash_digestsize(tfm);
++
++	/* We allocate the hash operational data storage on the end of our
++	 * context data.
++	 */
++	sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL);
++	if (!sig) {
++		crypto_free_shash(tfm);
++		return ERR_PTR(-ENOMEM);
++	}
++
++	sig->base.key		= crypto_key;
++	sig->base.add_data	= pgp_pkey_verify_sig_add_data;
++	sig->base.end		= pgp_pkey_verify_sig_end;
++	sig->base.cancel	= pgp_pkey_verify_sig_cancel;
++	sig->pkey_hash_algo	= pgp_pubkey_hash[p.params.hash_algo].algo;
++	sig->digest		= (u8 *)sig + sizeof(*sig) + desc_size;
++	sig->digest_size	= digest_size;
++	sig->hash.tfm		= tfm;
++	sig->hash.flags		= CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	ret = crypto_shash_init(&sig->hash);
++	if (ret < 0) {
++		crypto_free_shash(sig->hash.tfm);
++		kfree(sig);
++		return ERR_PTR(ret);
++	}
++
++	key_get(sig->base.key);
++	kleave(" = %p", sig);
++	return &sig->base;
++}
++
++/*
++ * Load data into the hash
++ */
++static int pgp_pkey_verify_sig_add_data(struct crypto_key_verify_context *ctx,
++					const void *data, size_t datalen)
++{
++	struct public_key_signature *sig =
++		container_of(ctx, struct public_key_signature, base);
++
++	return crypto_shash_update(&sig->hash, data, datalen);
++}
++
++struct pgp_pkey_sig_digest_context {
++	struct pgp_parse_context pgp;
++	const struct public_key *key;
++	struct public_key_signature *sig;
++};
++
++/*
++ * Extract required metadata from the signature packet and add what we need to
++ * to the hash.
++ */
++static int pgp_pkey_digest_signature(struct pgp_parse_context *context,
++				     enum pgp_packet_tag type,
++				     u8 headerlen,
++				     const u8 *data,
++				     size_t datalen)
++{
++	struct pgp_pkey_sig_digest_context *ctx =
++		container_of(context, struct pgp_pkey_sig_digest_context, pgp);
++	enum pgp_signature_version version;
++	int i;
++
++	kenter(",%u,%u,,%zu", type, headerlen, datalen);
++
++	version = *data;
++	if (version == PGP_SIG_VERSION_3) {
++		/* We just include an excerpt of the metadata from a V3
++		 * signature.
++		 */
++		crypto_shash_update(&ctx->sig->hash, data + 1, 5);
++		data += sizeof(struct pgp_signature_v3_packet);
++		datalen -= sizeof(struct pgp_signature_v3_packet);
++	} else if (version == PGP_SIG_VERSION_4) {
++		/* We add the whole metadata header and some of the hashed data
++		 * for a V4 signature, plus a trailer.
++		 */
++		size_t hashedsz, unhashedsz;
++		u8 trailer[6];
++
++		hashedsz = 4 + 2 + (data[4] << 8) + data[5];
++		crypto_shash_update(&ctx->sig->hash, data, hashedsz);
++
++		trailer[0] = version;
++		trailer[1] = 0xffU;
++		trailer[2] = hashedsz >> 24;
++		trailer[3] = hashedsz >> 16;
++		trailer[4] = hashedsz >> 8;
++		trailer[5] = hashedsz;
++
++		crypto_shash_update(&ctx->sig->hash, trailer, 6);
++		data += hashedsz;
++		datalen -= hashedsz;
++
++		unhashedsz = 2 + (data[0] << 8) + data[1];
++		data += unhashedsz;
++		datalen -= unhashedsz;
++	}
++
++	if (datalen <= 2) {
++		kleave(" = -EBADMSG");
++		return -EBADMSG;
++	}
++
++	/* There's a quick check on the hash available. */
++	ctx->sig->signed_hash_msw[0] = *data++;
++	ctx->sig->signed_hash_msw[1] = *data++;
++	datalen -= 2;
++
++	/* And then the cryptographic data, which we'll need for the
++	 * algorithm.
++	 */
++	for (i = 0; i < ctx->key->algo->n_sig_mpi; i++) {
++		unsigned int remaining = datalen;
++		if (remaining == 0) {
++			pr_debug("short %zu mpi %d\n", datalen, i);
++			return -EBADMSG;
++		}
++		ctx->sig->mpi[i] = mpi_read_from_buffer(data, &remaining);
++		if (!ctx->sig->mpi[i])
++			return -ENOMEM;
++		data += remaining;
++		datalen -= remaining;
++	}
++
++	if (datalen != 0) {
++		kleave(" = -EBADMSG [trailer %zu]", datalen);
++		return -EBADMSG;
++	}
++
++	kleave(" = 0");
++	return 0;
++}
++
++/*
++ * The data is now all loaded into the hash; load the metadata, finalise the
++ * hash and perform the verification step.
++ */
++static int pgp_pkey_verify_sig_end(struct crypto_key_verify_context *ctx,
++				   const u8 *sigdata, size_t siglen)
++{
++	struct public_key_signature *sig =
++		container_of(ctx, struct public_key_signature, base);
++	const struct public_key *key = sig->base.key->payload.data;
++	struct pgp_pkey_sig_digest_context p;
++	int ret;
++
++	kenter("");
++
++	/* Firstly we add metadata, starting with some of the data from the
++	 * signature packet */
++	p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
++	p.pgp.process_packet = pgp_pkey_digest_signature;
++	p.key = key;
++	p.sig = sig;
++	ret = pgp_parse_packets(sigdata, siglen, &p.pgp);
++	if (ret < 0)
++		goto error_free_ctx;
++
++	crypto_shash_final(&sig->hash, sig->digest);
++
++	ret = key->algo->verify(key, sig);
++
++error_free_ctx:
++	pgp_pkey_verify_sig_cancel(ctx);
++	kleave(" = %d", ret);
++	return ret;
++}
++
++/*
++ * Cancel an in-progress data loading
++ */
++static void pgp_pkey_verify_sig_cancel(struct crypto_key_verify_context *ctx)
++{
++	struct public_key_signature *sig =
++		container_of(ctx, struct public_key_signature, base);
++	int i;
++
++	kenter("");
++
++	/* !!! Do we need to tell the crypto layer to cancel too? */
++	crypto_free_shash(sig->hash.tfm);
++	key_put(sig->base.key);
++	for (i = 0; i < ARRAY_SIZE(sig->mpi); i++)
++		mpi_free(sig->mpi[i]);
++	kfree(sig);
++
++	kleave("");
++}
+-- 
+1.7.9.1
+
+
+From b8d572f41734596c3abbd15b1d2e30f5fa603c01 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:15 +0000
+Subject: KEYS: PGP format signature parser
+
+Implement a signature parser that will attempt to parse a signature blob as a
+PGP packet format message.  If it can, it will find an appropriate crypto key
+and set the public-key algorithm according to the data in the signature.
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ security/keys/Makefile         |    1 +
+ security/keys/pgp_key_parser.c |    1 +
+ security/keys/pgp_parser.h     |    6 ++
+ security/keys/pgp_sig_parser.c |  104 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 112 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/pgp_sig_parser.c
+
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 24e83a2..9aa48fe 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -34,4 +34,5 @@ crypto_keys-y := crypto_type.o crypto_verify.o
+ 
+ pgp_parser-y := \
+ 	pgp_key_parser.o \
++	pgp_sig_parser.o \
+ 	pgp_pubkey_sig.o
+diff --git a/security/keys/pgp_key_parser.c b/security/keys/pgp_key_parser.c
+index 4efc4de..1407e2e 100644
+--- a/security/keys/pgp_key_parser.c
++++ b/security/keys/pgp_key_parser.c
+@@ -324,6 +324,7 @@ static struct crypto_key_parser pgp_key_parser = {
+ 	.owner		= THIS_MODULE,
+ 	.name		= "pgp",
+ 	.instantiate	= pgp_key_instantiate,
++	.verify_sig_begin = pgp_verify_sig_begin,
+ };
+ 
+ /*
+diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h
+index a6192ce..73c900e 100644
+--- a/security/keys/pgp_parser.h
++++ b/security/keys/pgp_parser.h
+@@ -23,6 +23,12 @@ extern const
+ struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
+ 
+ /*
++ * pgp_sig_parser.c
++ */
++extern struct crypto_key_verify_context *pgp_verify_sig_begin(
++	struct key *keyring, const u8 *sig, size_t siglen);
++
++/*
+  * pgp_pubkey_sig.c
+  */
+ extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
+diff --git a/security/keys/pgp_sig_parser.c b/security/keys/pgp_sig_parser.c
+new file mode 100644
+index 0000000..b72c505
+--- /dev/null
++++ b/security/keys/pgp_sig_parser.c
+@@ -0,0 +1,104 @@
++/* Handling for PGP public key signature data [RFC 4880]
++ *
++ * Copyright (C) 2011 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.
++ */
++
++#define pr_fmt(fmt) "PGPSIG: "fmt
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/pgp.h>
++#include "public_key.h"
++#include "pgp_parser.h"
++
++struct PGP_sig_parse_context {
++	struct pgp_parse_context pgp;
++	struct pgp_sig_parameters params;
++	bool found_sig;
++};
++
++/*
++ * Look inside signature sections for a key ID
++ */
++static int pgp_process_signature(struct pgp_parse_context *context,
++				 enum pgp_packet_tag type,
++				 u8 headerlen,
++				 const u8 *data,
++				 size_t datalen)
++{
++	struct PGP_sig_parse_context *ctx =
++		container_of(context, struct PGP_sig_parse_context, pgp);
++
++	ctx->found_sig = true;
++	return pgp_parse_sig_params(&data, &datalen, &ctx->params);
++}
++
++/*
++ * Attempt to find a key to use for PGP signature verification, starting off by
++ * looking in the supplied keyring.
++ *
++ * The function may also look for other key sources such as a TPM.  If an
++ * alternative key is found it can be added to the keyring for future
++ * reference.
++ */
++static struct key *find_key_for_pgp_sig(struct key *keyring,
++					const u8 *sig, size_t siglen)
++{
++	struct PGP_sig_parse_context p;
++	key_ref_t key;
++	char criterion[3 + 8 * 2 + 1];
++	int ret;
++
++	if (!keyring)
++		return ERR_PTR(-ENOKEY);
++
++	/* Need to find the key ID */
++	p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
++	p.pgp.process_packet = pgp_process_signature;
++	p.found_sig = false;
++	ret = pgp_parse_packets(sig, siglen, &p.pgp);
++	if (ret < 0)
++		return ERR_PTR(ret);
++
++	if (!p.found_sig)
++		return ERR_PTR(-EINVAL);
++
++	sprintf(criterion, "id:%08x%08x",
++		be32_to_cpu(p.params.issuer32[0]),
++		be32_to_cpu(p.params.issuer32[1]));
++
++	pr_debug("Look up: %s\n", criterion);
++
++	key = keyring_search(make_key_ref(keyring, 1),
++			     &key_type_crypto, criterion);
++	if (IS_ERR(key))
++		return ERR_CAST(key);
++
++	pr_debug("Found key %x\n", key_serial(key_ref_to_ptr(key)));
++	return key_ref_to_ptr(key);
++}
++
++/*
++ * Attempt to parse a signature as a PGP packet format blob and find a
++ * matching key.
++ */
++struct crypto_key_verify_context *pgp_verify_sig_begin(
++	struct key *keyring, const u8 *sig, size_t siglen)
++{
++	struct crypto_key_verify_context *ctx;
++	struct key *key;
++
++	key = find_key_for_pgp_sig(keyring, sig, siglen);
++	if (IS_ERR(key))
++		return ERR_CAST(key);
++
++	/* We only handle in-kernel public key signatures for the moment */
++	ctx = pgp_pkey_verify_sig_begin(key, sig, siglen);
++	key_put(key);
++	return ctx;
++}
+-- 
+1.7.9.1
+
+
+From e25da6c545204746a8011dc27ce179816f715449 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:16 +0000
+Subject: KEYS: Provide a function to load keys from a PGP keyring blob
+
+Provide a function to load keys from a PGP keyring blob for use in initialising
+the module signing key keyring:
+
+	int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen,
+			  struct key *keyring, const char *descprefix);
+
+The keys are labelled with descprefix plus a number to uniquify them.  The keys
+will actually be identified by the ID calculated from the PGP data rather than
+by the description, so this shouldn't be a problem.
+
+The keys are attached to the keyring supplied.
+
+Looking as root in /proc/keys after the module signing keyring has been loaded:
+
+24460d1c I-----     1 perm 3f010000     0     0 crypto    modsign.0: dsa 5acc2142 []
+3ca85723 I-----     1 perm 1f010000     0     0 keyring   .module_sign: 1/4
+
+Signed-off-by: David Howells <dhowells at redhat.com>
+---
+ Documentation/security/keys-crypto.txt |   20 +++++++
+ include/keys/crypto-type.h             |    3 +
+ security/keys/Kconfig                  |    9 +++
+ security/keys/Makefile                 |    1 +
+ security/keys/pgp_preload.c            |   90 ++++++++++++++++++++++++++++++++
+ 5 files changed, 123 insertions(+), 0 deletions(-)
+ create mode 100644 security/keys/pgp_preload.c
+
+diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
+index a964717..ba2ab55 100644
+--- a/Documentation/security/keys-crypto.txt
++++ b/Documentation/security/keys-crypto.txt
+@@ -10,6 +10,7 @@ Contents:
+     - Signature verification.
+   - Implementing crypto parsers.
+   - Implementing crypto subtypes.
++  - Initial PGP key preloading.
+ 
+ 
+ ========
+@@ -280,3 +281,22 @@ There are a number of operations defined by the subtype:
+      Mandatory.  This should free the memory associated with the key.  The
+      crypto key will look after freeing the fingerprint and releasing the
+      reference on the subtype module.
++
++
++=======================
++INITIAL PGP KEY LOADING
++=======================
++
++A function is provided to perform an initial load of a set of public keys bound
++into a PGP packet format blob:
++
++	int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
++			     struct key *keyring, const char *descprefix);
++
++This takes the blob of data defined by pgpdata and pgpdatalen, extracts keys
++from them and adds them to the specified keyring.  The keys are labelled with
++descprefix plus a simple uniquifier - it is not expected that the description
++will be used to identify the key.  The description is required to prevent all
++but the last key being discarded when the keys are linked into the keyring.
++
++This function is only available during initial kernel set up.
+diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
+index 6b93366..710e77f 100644
+--- a/include/keys/crypto-type.h
++++ b/include/keys/crypto-type.h
+@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_key_verify_context *ctx);
+  * The payload is at the discretion of the subtype.
+  */
+ 
++extern __init int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
++				   struct key *keyring, const char *descprefix);
++
+ #endif /* _KEYS_CRYPTO_TYPE_H */
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index fd53028..5e77c2a 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -110,3 +110,12 @@ config CRYPTO_KEY_PGP_PARSER
+ 	  This option provides support for parsing PGP (RFC 4880) format blobs
+ 	  for key data and provides the ability to instantiate a crypto key
+ 	  from a public key packet found inside the blob.
++
++config PGP_PRELOAD
++	bool "PGP public key preloading facility"
++	select PGP_LIBRARY
++	select CRYPTO_KEY_PGP_PARSER
++	help
++	  This option provides a facility for the kernel to preload PGP-wrapped
++	  bundles of keys during boot.  It is used by module signing to load
++	  the module signing keys for example.
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 9aa48fe..5a43bdb 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -28,6 +28,7 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+ obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
+ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
++obj-$(CONFIG_PGP_PRELOAD) += pgp_preload.o
+ obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o
+ 
+ crypto_keys-y := crypto_type.o crypto_verify.o
+diff --git a/security/keys/pgp_preload.c b/security/keys/pgp_preload.c
+new file mode 100644
+index 0000000..25154e3
+--- /dev/null
++++ b/security/keys/pgp_preload.c
+@@ -0,0 +1,90 @@
++/* Cryptographic key request handling
++ *
++ * Copyright (C) 2011 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.
++ *
++ * See Documentation/security/keys-crypto.txt
++ */
++
++#include <linux/module.h>
++#include <linux/key.h>
++#include <linux/pgp.h>
++#include "crypto_keys.h"
++
++struct preload_pgp_keys_context {
++	struct pgp_parse_context pgp;
++	key_ref_t keyring;
++	char descbuf[20];
++	u8 key_n;
++	u8 dsize;
++};
++
++/*
++ * Extract a public key or subkey from the PGP stream.
++ */
++static int __init found_pgp_key(struct pgp_parse_context *context,
++				enum pgp_packet_tag type, u8 headerlen,
++				const u8 *data, size_t datalen)
++{
++	struct preload_pgp_keys_context *ctx =
++		container_of(context, struct preload_pgp_keys_context, pgp);
++	key_ref_t key;
++
++	sprintf(ctx->descbuf + ctx->dsize, "%d", ctx->key_n++);
++
++	key = key_create_or_update(ctx->keyring, "crypto", ctx->descbuf,
++				   data - headerlen, datalen + headerlen,
++				   KEY_POS_ALL | KEY_USR_VIEW,
++				   KEY_ALLOC_NOT_IN_QUOTA);
++
++	if (IS_ERR(key))
++		return PTR_ERR(key);
++
++	pr_notice("Loaded %s key: %s\n",
++		  key_ref_to_ptr(key)->description,
++		  crypto_key_id(key_ref_to_ptr(key)));
++
++	key_ref_put(key);
++	return 0;
++}
++
++/**
++ * preload_pgp_keys - Load keys from a PGP keyring blob
++ * @pgpdata: The PGP keyring blob containing the keys.
++ * @pgpdatalen: The size of the @pgpdata blob.
++ * @keyring: The keyring to add the new keys to.
++ * @descprefix: The key description prefix.
++ *
++ * Preload a pack of keys from a PGP keyring blob.
++ *
++ * The keys are given description of @descprefix + the number of the key in the
++ * list.  Since keys can be matched on their key IDs independently of the key
++ * description, the description is mostly irrelevant apart from the fact that
++ * keys of the same description displace one another from a keyring.
++ *
++ * The caller should override the current creds if they want the keys to be
++ * owned by someone other than the current process's owner.  Keys will not be
++ * accounted towards the owner's quota.
++ *
++ * This function may only be called whilst the kernel is booting.
++ */
++int __init preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
++			    struct key *keyring, const char *descprefix)
++{
++	struct preload_pgp_keys_context ctx;
++
++	ctx.pgp.types_of_interest =
++		(1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
++	ctx.pgp.process_packet = found_pgp_key;
++	ctx.keyring = make_key_ref(keyring, 1);
++	ctx.key_n = 0;
++	ctx.dsize = strlen(descprefix);
++	strcpy(ctx.descbuf, descprefix);
++
++	return pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp);
++}
+-- 
+1.7.9.1
+
+
+From dad531381fad892fda776ddb354e1eb936b46b62 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:16 +0000
+Subject: MODSIGN: Add indications of module ELF types
+
+Add per-arch indications of module ELF types and relocation table entry types.
+
+Signed-Off-By: David Howells <dhowells at redhat.com>
+---
+ arch/alpha/include/asm/module.h   |    3 +++
+ arch/arm/include/asm/module.h     |    5 +++++
+ arch/cris/include/asm/module.h    |    5 +++++
+ arch/h8300/include/asm/module.h   |    5 +++++
+ arch/ia64/include/asm/module.h    |    5 +++++
+ arch/m32r/include/asm/module.h    |    5 +++++
+ arch/m68k/include/asm/module.h    |    5 +++++
+ arch/mips/include/asm/module.h    |   12 ++++++++++--
+ arch/parisc/include/asm/module.h  |    8 ++++++++
+ arch/powerpc/include/asm/module.h |   10 ++++++++++
+ arch/s390/include/asm/module.h    |    3 +++
+ include/asm-generic/module.h      |   10 ++++++++++
+ 12 files changed, 74 insertions(+), 2 deletions(-)
+
+diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h
+index 7b63743..3d5a3ea 100644
+--- a/arch/alpha/include/asm/module.h
++++ b/arch/alpha/include/asm/module.h
+@@ -6,6 +6,7 @@ struct mod_arch_specific
+ 	unsigned int gotsecindex;
+ };
+ 
++#define MODULES_ARE_ELF64
+ #define Elf_Sym Elf64_Sym
+ #define Elf_Shdr Elf64_Shdr
+ #define Elf_Ehdr Elf64_Ehdr
+@@ -13,6 +14,8 @@ struct mod_arch_specific
+ #define Elf_Dyn Elf64_Dyn
+ #define Elf_Rel Elf64_Rel
+ #define Elf_Rela Elf64_Rela
++#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ 
+ #define ARCH_SHF_SMALL SHF_ALPHA_GPREL
+ 
+diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
+index 6c6809f..f47d9cd 100644
+--- a/arch/arm/include/asm/module.h
++++ b/arch/arm/include/asm/module.h
+@@ -1,9 +1,14 @@
+ #ifndef _ASM_ARM_MODULE_H
+ #define _ASM_ARM_MODULE_H
+ 
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr	Elf32_Shdr
+ #define Elf_Sym		Elf32_Sym
+ #define Elf_Ehdr	Elf32_Ehdr
++#define Elf_Rel		Elf32_Rel
++#define Elf_Rela	Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ 
+ struct unwind_table;
+ 
+diff --git a/arch/cris/include/asm/module.h b/arch/cris/include/asm/module.h
+index 7ee7231..03f7b2e 100644
+--- a/arch/cris/include/asm/module.h
++++ b/arch/cris/include/asm/module.h
+@@ -3,7 +3,12 @@
+ /* cris is simple */
+ struct mod_arch_specific { };
+ 
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++#define Elf_Rel Elf32_Rel
++#define Elf_Rela Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ #endif /* _ASM_CRIS_MODULE_H */
+diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h
+index 8e46724..5140128 100644
+--- a/arch/h8300/include/asm/module.h
++++ b/arch/h8300/include/asm/module.h
+@@ -4,8 +4,13 @@
+  * This file contains the H8/300 architecture specific module code.
+  */
+ struct mod_arch_specific { };
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++#define Elf_Rel Elf32_Rel
++#define Elf_Rela Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ 
+ #endif /* _ASM_H8/300_MODULE_H */
+diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h
+index 908eaef..3c4cd94 100644
+--- a/arch/ia64/include/asm/module.h
++++ b/arch/ia64/include/asm/module.h
+@@ -29,9 +29,14 @@ struct mod_arch_specific {
+ 	unsigned int next_got_entry;	/* index of next available got entry */
+ };
+ 
++#define MODULES_ARE_ELF64
+ #define Elf_Shdr	Elf64_Shdr
+ #define Elf_Sym		Elf64_Sym
+ #define Elf_Ehdr	Elf64_Ehdr
++#define Elf_Rel		Elf64_Rel
++#define Elf_Rela	Elf64_Rela
++#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ 
+ #define MODULE_PROC_FAMILY	"ia64"
+ #define MODULE_ARCH_VERMAGIC	MODULE_PROC_FAMILY \
+diff --git a/arch/m32r/include/asm/module.h b/arch/m32r/include/asm/module.h
+index eb73ee0..7146455 100644
+--- a/arch/m32r/include/asm/module.h
++++ b/arch/m32r/include/asm/module.h
+@@ -3,8 +3,13 @@
+ 
+ struct mod_arch_specific { };
+ 
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr	Elf32_Shdr
+ #define Elf_Sym		Elf32_Sym
+ #define Elf_Ehdr	Elf32_Ehdr
++#define Elf_Rel		Elf32_Rel
++#define Elf_Rela	Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ 
+ #endif /* _ASM_M32R_MODULE_H */
+diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
+index edffe66..9e2cd74 100644
+--- a/arch/m68k/include/asm/module.h
++++ b/arch/m68k/include/asm/module.h
+@@ -36,8 +36,13 @@ struct module;
+ extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+ 			 struct m68k_fixup_info *end);
+ 
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++#define Elf_Rel		Elf32_Rel
++#define Elf_Rela	Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ 
+ #endif /* _ASM_M68K_MODULE_H */
+diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
+index bc01a02..73c71a2 100644
+--- a/arch/mips/include/asm/module.h
++++ b/arch/mips/include/asm/module.h
+@@ -33,11 +33,15 @@ typedef struct {
+ } Elf64_Mips_Rela;
+ 
+ #ifdef CONFIG_32BIT
+-
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr	Elf32_Shdr
+ #define Elf_Sym		Elf32_Sym
+ #define Elf_Ehdr	Elf32_Ehdr
+ #define Elf_Addr	Elf32_Addr
++#define Elf_Rel		Elf32_Rel
++#define Elf_Rela	Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ 
+ #define Elf_Mips_Rel	Elf32_Rel
+ #define Elf_Mips_Rela	Elf32_Rela
+@@ -48,11 +52,15 @@ typedef struct {
+ #endif
+ 
+ #ifdef CONFIG_64BIT
+-
++#define MODULES_ARE_ELF64
+ #define Elf_Shdr	Elf64_Shdr
+ #define Elf_Sym		Elf64_Sym
+ #define Elf_Ehdr	Elf64_Ehdr
+ #define Elf_Addr	Elf64_Addr
++#define Elf_Rel		Elf64_Rel
++#define Elf_Rela	Elf64_Rela
++#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ 
+ #define Elf_Mips_Rel	Elf64_Mips_Rel
+ #define Elf_Mips_Rela	Elf64_Mips_Rela
+diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h
+index 1f41234..3e13f69 100644
+--- a/arch/parisc/include/asm/module.h
++++ b/arch/parisc/include/asm/module.h
+@@ -4,17 +4,25 @@
+  * This file contains the parisc architecture specific module code.
+  */
+ #ifdef CONFIG_64BIT
++#define MODULES_ARE_ELF64
+ #define Elf_Shdr Elf64_Shdr
+ #define Elf_Sym Elf64_Sym
+ #define Elf_Ehdr Elf64_Ehdr
+ #define Elf_Addr Elf64_Addr
++#define Elf_Rel	 Elf64_Rel
+ #define Elf_Rela Elf64_Rela
++#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ #else
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
+ #define Elf_Addr Elf32_Addr
++#define Elf_Rel  Elf32_Rel
+ #define Elf_Rela Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ #endif
+ 
+ struct unwind_table;
+diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
+index 0192a4e..e949704 100644
+--- a/arch/powerpc/include/asm/module.h
++++ b/arch/powerpc/include/asm/module.h
+@@ -60,16 +60,26 @@ struct mod_arch_specific {
+  */
+ 
+ #ifdef __powerpc64__
++#    define MODULES_ARE_ELF64
+ #    define Elf_Shdr	Elf64_Shdr
+ #    define Elf_Sym	Elf64_Sym
+ #    define Elf_Ehdr	Elf64_Ehdr
++#    define Elf_Rel Elf64_Rel
++#    define Elf_Rela Elf64_Rela
++#    define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#    define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ #    ifdef MODULE
+ 	asm(".section .stubs,\"ax\", at nobits; .align 3; .previous");
+ #    endif
+ #else
++#    define MODULES_ARE_ELF32
+ #    define Elf_Shdr	Elf32_Shdr
+ #    define Elf_Sym	Elf32_Sym
+ #    define Elf_Ehdr	Elf32_Ehdr
++#    define Elf_Rel Elf32_Rel
++#    define Elf_Rela Elf32_Rela
++#    define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#    define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ #    ifdef MODULE
+ 	asm(".section .plt,\"ax\", at nobits; .align 3; .previous");
+ 	asm(".section .init.plt,\"ax\", at nobits; .align 3; .previous");
+diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h
+index 1cc1c5a..b64dab0 100644
+--- a/arch/s390/include/asm/module.h
++++ b/arch/s390/include/asm/module.h
+@@ -29,14 +29,17 @@ struct mod_arch_specific
+ };
+ 
+ #ifdef __s390x__
++#define MODULES_ARE_ELF64
+ #define ElfW(x) Elf64_ ## x
+ #define ELFW(x) ELF64_ ## x
+ #else
++#define MODULES_ARE_ELF32
+ #define ElfW(x) Elf32_ ## x
+ #define ELFW(x) ELF32_ ## x
+ #endif
+ 
+ #define Elf_Addr ElfW(Addr)
++#define Elf_Rel ElfW(Rel)
+ #define Elf_Rela ElfW(Rela)
+ #define Elf_Shdr ElfW(Shdr)
+ #define Elf_Sym ElfW(Sym)
+diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h
+index ed5b44d..e053617b 100644
+--- a/include/asm-generic/module.h
++++ b/include/asm-generic/module.h
+@@ -10,13 +10,23 @@ struct mod_arch_specific
+ };
+ 
+ #ifdef CONFIG_64BIT
++#define MODULES_ARE_ELF64
+ #define Elf_Shdr Elf64_Shdr
+ #define Elf_Sym Elf64_Sym
+ #define Elf_Ehdr Elf64_Ehdr
++#define Elf_Rel		Elf64_Rel
++#define Elf_Rela	Elf64_Rela
++#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF64_R_SYM(X)
+ #else
++#define MODULES_ARE_ELF32
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++#define Elf_Rel		Elf32_Rel
++#define Elf_Rela	Elf32_Rela
++#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
++#define ELF_R_SYM(X)	ELF32_R_SYM(X)
+ #endif
+ 
+ #endif /* __ASM_GENERIC_MODULE_H */
+-- 
+1.7.9.1
+
+
+
+From a66294fc859a6a9374a6d873d8a6ca3ec683538f Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:17 +0000
+Subject: MODSIGN: Module ELF verifier
+
+Do preliminary verification of the ELF structure of a module.  This is used to
+make sure that the ELF structure can then be used to check the module signature
+and access the module data without breaking the module loader.
+
+If the module's ELF metadata is determined to be bad, then ELIBBAD will be
+returned and a message will be logged to the kernel log.
+
+Signed-Off-By: David Howells <dhowells at redhat.com>
+
+Rebased-to-3.3-rc6: Josh Boyer <jwboyer at redhat.com>
+---
+ init/Kconfig               |   11 ++
+ kernel/Makefile            |    2 +
+ kernel/module-verify-elf.c |  344 ++++++++++++++++++++++++++++++++++++++++++++
+ kernel/module-verify.c     |   41 ++++++
+ kernel/module-verify.h     |   53 +++++++
+ kernel/module.c            |    6 +
+ 6 files changed, 457 insertions(+), 0 deletions(-)
+ create mode 100644 kernel/module-verify-elf.c
+ create mode 100644 kernel/module-verify.c
+ create mode 100644 kernel/module-verify.h
+
+diff --git a/init/Kconfig b/init/Kconfig
+index 3f42cd6..61b5f03 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1418,6 +1418,17 @@ config MODULE_SRCVERSION_ALL
+ 	  the version).  With this option, such a "srcversion" field
+ 	  will be created for all modules.  If unsure, say N.
+ 
++config MODULE_VERIFY_ELF
++	bool "Module ELF structure verification"
++	depends on MODULES
++	help
++	  Check ELF structure of modules upon load
++
++config MODULE_VERIFY
++	bool
++	depends on MODULES
++	default y if MODULE_VERIFY_ELF
++
+ endif # MODULES
+ 
+ config INIT_ALL_POSSIBLE
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 2d9de86..77b7a39 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -52,6 +52,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
+ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
+ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += module.o
++obj-$(CONFIG_MODULE_VERIFY) += module-verify.o
++obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+ obj-$(CONFIG_KEXEC) += kexec.o
+diff --git a/kernel/module-verify-elf.c b/kernel/module-verify-elf.c
+new file mode 100644
+index 0000000..4dea8d0
+--- /dev/null
++++ b/kernel/module-verify-elf.c
+@@ -0,0 +1,344 @@
++/* module-verify-elf.c: module ELF verifier
++ *
++ * 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 License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/elf.h>
++#include <linux/ctype.h>
++#include "module-verify.h"
++
++#if 0
++#define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
++#else
++#define _debug(FMT, ...) do {} while (0)
++#endif
++
++/*
++ * verify the ELF structure of a module
++ */
++int module_verify_elf(struct module_verify_data *mvdata)
++{
++	const struct elf_note *note;
++	const Elf_Ehdr *hdr = mvdata->hdr;
++	const Elf_Shdr *section, *section2, *secstop;
++	const Elf_Rela *relas, *rela, *relastop;
++	const Elf_Rel *rels, *rel, *relstop;
++	const Elf_Sym *symbol, *symstop;
++	const void *start, *p, *stop;
++	const char *q, *qs;
++	size_t size, sssize, *secsize, tmp, tmp2;
++	long last;
++	int line;
++
++	size = mvdata->size;
++	mvdata->nsects = hdr->e_shnum;
++
++#define elfcheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0)
++
++#define seccheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0)
++
++#define symcheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0)
++
++#define relcheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto relcheck_error; } } while(0)
++
++#define relacheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto relacheck_error; } } while(0)
++
++#define notecheck(X)							\
++do { if (unlikely(!(X))) { line = __LINE__; goto notecheck_error; } } while(0)
++
++	/* validate the ELF header */
++	elfcheck(hdr->e_ehsize < size);
++	/*elfcheck(hdr->e_entry == 0);*/
++	elfcheck(hdr->e_phoff == 0);
++	elfcheck(hdr->e_phnum == 0);
++
++	elfcheck(hdr->e_shnum < SHN_LORESERVE);
++	elfcheck(hdr->e_shoff < size);
++	elfcheck(hdr->e_shoff >= hdr->e_ehsize);
++	elfcheck((hdr->e_shoff & (sizeof(long) - 1)) == 0);
++	elfcheck(hdr->e_shstrndx > 0);
++	elfcheck(hdr->e_shstrndx < hdr->e_shnum);
++	elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
++
++	tmp = (size_t) hdr->e_shentsize * (size_t) hdr->e_shnum;
++	elfcheck(tmp <= size - hdr->e_shoff);
++
++	/* allocate a table to hold in-file section sizes */
++	mvdata->secsizes = kcalloc(hdr->e_shnum, sizeof(size_t), GFP_KERNEL);
++	if (!mvdata->secsizes)
++		return -ENOMEM;
++
++	/* validate the ELF section headers */
++	mvdata->sections = mvdata->buffer + hdr->e_shoff;
++	secstop = mvdata->sections + mvdata->nsects;
++
++	sssize = mvdata->sections[hdr->e_shstrndx].sh_size;
++	elfcheck(sssize > 0);
++
++	section = mvdata->sections;
++	seccheck(section->sh_type == SHT_NULL);
++	seccheck(section->sh_size == 0);
++	seccheck(section->sh_offset == 0);
++
++	secsize = mvdata->secsizes + 1;
++	for (section++; section < secstop; secsize++, section++) {
++		seccheck(section->sh_name < sssize);
++		seccheck(section->sh_link < hdr->e_shnum);
++
++		if (section->sh_entsize > 0)
++			seccheck(section->sh_size % section->sh_entsize == 0);
++
++		seccheck(section->sh_offset >= hdr->e_ehsize);
++		seccheck(section->sh_offset < size);
++
++		/* determine the section's in-file size */
++		tmp = size - section->sh_offset;
++		if (section->sh_offset < hdr->e_shoff)
++			tmp = hdr->e_shoff - section->sh_offset;
++
++		for (section2 = mvdata->sections + 1;
++		     section2 < secstop;
++		     section2++) {
++			if (section->sh_offset < section2->sh_offset) {
++				tmp2 = section2->sh_offset -
++					section->sh_offset;
++				if (tmp2 < tmp)
++					tmp = tmp2;
++			}
++		}
++		*secsize = tmp;
++
++		_debug("Section %ld: %zx bytes at %lx\n",
++		       section - mvdata->sections,
++		       *secsize,
++		       (unsigned long) section->sh_offset);
++
++		/* perform section type specific checks */
++		switch (section->sh_type) {
++		case SHT_NOBITS:
++			break;
++
++		case SHT_REL:
++			seccheck(section->sh_entsize == sizeof(Elf_Rel));
++			goto more_rel_checks;
++
++		case SHT_RELA:
++			seccheck(section->sh_entsize == sizeof(Elf_Rela));
++		more_rel_checks:
++			seccheck(section->sh_info > 0);
++			seccheck(section->sh_info < hdr->e_shnum);
++			goto more_sec_checks;
++
++		case SHT_SYMTAB:
++			seccheck(section->sh_entsize == sizeof(Elf_Sym));
++			goto more_sec_checks;
++
++		default:
++		more_sec_checks:
++			/* most types of section must be contained entirely
++			 * within the file */
++			seccheck(section->sh_size <= *secsize);
++			break;
++		}
++	}
++
++	/* validate the ELF section names */
++	section = &mvdata->sections[hdr->e_shstrndx];
++
++	seccheck(section->sh_offset != hdr->e_shoff);
++
++	mvdata->secstrings = mvdata->buffer + section->sh_offset;
++
++	last = -1;
++	for (section = mvdata->sections + 1; section < secstop; section++) {
++		const char *secname;
++		tmp = sssize - section->sh_name;
++		secname = mvdata->secstrings + section->sh_name;
++		seccheck(secname[0] != 0);
++		if (section->sh_name > last)
++			last = section->sh_name;
++	}
++
++	if (last > -1) {
++		tmp = sssize - last;
++		elfcheck(memchr(mvdata->secstrings + last, 0, tmp) != NULL);
++	}
++
++	/* look for various sections in the module */
++	for (section = mvdata->sections + 1; section < secstop; section++) {
++		switch (section->sh_type) {
++		case SHT_SYMTAB:
++			if (strcmp(mvdata->secstrings + section->sh_name,
++				   ".symtab") == 0
++			    ) {
++				seccheck(mvdata->symbols == NULL);
++				mvdata->symbols =
++					mvdata->buffer + section->sh_offset;
++				mvdata->nsyms =
++					section->sh_size / sizeof(Elf_Sym);
++				seccheck(section->sh_size > 0);
++			}
++			break;
++
++		case SHT_STRTAB:
++			if (strcmp(mvdata->secstrings + section->sh_name,
++				   ".strtab") == 0
++			    ) {
++				seccheck(mvdata->strings == NULL);
++				mvdata->strings =
++					mvdata->buffer + section->sh_offset;
++				sssize = mvdata->nstrings = section->sh_size;
++				seccheck(section->sh_size > 0);
++			}
++			break;
++		}
++	}
++
++	if (!mvdata->symbols) {
++		printk("Couldn't locate module symbol table\n");
++		goto format_error;
++	}
++
++	if (!mvdata->strings) {
++		printk("Couldn't locate module strings table\n");
++		goto format_error;
++	}
++
++	/* validate the symbol table */
++	symstop = mvdata->symbols + mvdata->nsyms;
++
++	symbol = mvdata->symbols;
++	symcheck(ELF_ST_TYPE(symbol[0].st_info) == STT_NOTYPE);
++	symcheck(symbol[0].st_shndx == SHN_UNDEF);
++	symcheck(symbol[0].st_value == 0);
++	symcheck(symbol[0].st_size == 0);
++
++	last = -1;
++	for (symbol++; symbol < symstop; symbol++) {
++		symcheck(symbol->st_name < sssize);
++		if (symbol->st_name > last)
++			last = symbol->st_name;
++		symcheck(symbol->st_shndx < mvdata->nsects ||
++			 symbol->st_shndx >= SHN_LORESERVE);
++	}
++
++	if (last > -1) {
++		tmp = sssize - last;
++		elfcheck(memchr(mvdata->strings + last, 0, tmp) != NULL);
++	}
++
++	/* validate each relocation table and note list as best we can */
++	for (section = mvdata->sections + 1; section < secstop; section++) {
++		section2 = mvdata->sections + section->sh_info;
++		start = mvdata->buffer + section->sh_offset;
++		stop = start + section->sh_size;
++
++		switch (section->sh_type) {
++		case SHT_REL:
++			rels = start;
++			relstop = stop;
++
++			for (rel = rels; rel < relstop; rel++) {
++				relcheck(rel->r_offset < section2->sh_size);
++				relcheck(ELF_R_SYM(rel->r_info) <
++					 mvdata->nsyms);
++			}
++
++			break;
++
++		case SHT_RELA:
++			relas = start;
++			relastop = stop;
++
++			for (rela = relas; rela < relastop; rela++) {
++				relacheck(rela->r_offset < section2->sh_size);
++				relacheck(ELF_R_SYM(rela->r_info) <
++					  mvdata->nsyms);
++			}
++
++			break;
++
++		case SHT_NOTE:
++			p = start;
++			while (p < stop) {
++				note = p;
++				notecheck(stop - p >= sizeof(*note));
++				p += sizeof(*note);
++				tmp = note->n_namesz;
++				if (tmp > 0) {
++					notecheck(stop - p >= tmp);
++					qs = p + tmp - 1;
++					notecheck(*qs == '\0');
++					for (q = p; q < qs; q++)
++						notecheck(*q != '\0');
++					tmp = roundup(tmp, 4);
++					notecheck(stop - p >= tmp);
++					p += tmp;
++				}
++				tmp = note->n_descsz;
++				if (tmp > 0) {
++					notecheck(stop - p >= tmp);
++					tmp = roundup(tmp, 4);
++					notecheck(stop - p >= tmp);
++					p += tmp;
++				}
++			}
++			seccheck(p == stop);
++			break;
++
++		default:
++			break;
++		}
++	}
++
++	_debug("ELF okay\n");
++	return 0;
++
++elfcheck_error:
++	printk("Verify ELF error (assertion %d)\n", line);
++	goto format_error;
++
++seccheck_error:
++	printk("Verify ELF error [sec %ld] (assertion %d)\n",
++	       (long)(section - mvdata->sections), line);
++	goto format_error;
++
++symcheck_error:
++	printk("Verify ELF error [sym %ld] (assertion %d)\n",
++	       (long)(symbol - mvdata->symbols), line);
++	goto format_error;
++
++relcheck_error:
++	printk("Verify ELF error [sec %ld rel %ld] (assertion %d)\n",
++	       (long)(section - mvdata->sections),
++	       (long)(rel - rels), line);
++	goto format_error;
++
++relacheck_error:
++	printk("Verify ELF error [sec %ld rela %ld] (assertion %d)\n",
++	       (long)(section - mvdata->sections),
++	       (long)(rela - relas), line);
++	goto format_error;
++
++notecheck_error:
++	printk("Verify ELF error [sec %ld note %ld] (assertion %d)\n",
++	       (long)(section - mvdata->sections),
++	       (long)(p - start), line);
++	goto format_error;
++
++format_error:
++	return -ELIBBAD;
++}
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+new file mode 100644
+index 0000000..875279f
+--- /dev/null
++++ b/kernel/module-verify.c
+@@ -0,0 +1,41 @@
++/* module-verify.c: module verifier
++ *
++ * 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 License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include "module-verify.h"
++
++/*
++ * verify a module's integrity
++ * - check the ELF is viable
++ */
++int module_verify(const Elf_Ehdr *hdr, size_t size)
++{
++	struct module_verify_data mvdata;
++	int ret;
++
++	memset(&mvdata, 0, sizeof(mvdata));
++	mvdata.buffer	= hdr;
++	mvdata.hdr	= hdr;
++	mvdata.size	= size;
++
++	ret = module_verify_elf(&mvdata);
++	if (ret < 0) {
++		if (ret == -ELIBBAD)
++			printk("Module failed ELF checks\n");
++		goto error;
++	}
++
++error:
++	kfree(mvdata.secsizes);
++	kfree(mvdata.canonlist);
++	return ret;
++}
+diff --git a/kernel/module-verify.h b/kernel/module-verify.h
+new file mode 100644
+index 0000000..20884fc
+--- /dev/null
++++ b/kernel/module-verify.h
+@@ -0,0 +1,53 @@
++/* module-verify.h: module verification definitions
++ *
++ * Copyright (C) 2004 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 License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/types.h>
++#include <asm/module.h>
++
++#ifdef CONFIG_MODULE_VERIFY
++struct module_verify_data {
++	const void		*buffer;	/* module buffer */
++	const Elf_Ehdr		*hdr;		/* ELF header */
++	const Elf_Shdr		*sections;	/* ELF section table */
++	const Elf_Sym		*symbols;	/* ELF symbol table */
++	const char		*secstrings;	/* ELF section string table */
++	const char		*strings;	/* ELF string table */
++	size_t			*secsizes;	/* section size list */
++	size_t			size;		/* module object size */
++	size_t			nsects;		/* number of sections */
++	size_t			nsyms;		/* number of symbols */
++	size_t			nstrings;	/* size of strings section */
++	size_t			signed_size;	/* count of bytes contributed to digest */
++	int			*canonlist;	/* list of canonicalised sections */
++	int			*canonmap;	/* section canonicalisation map */
++	int			ncanon;		/* number of canonicalised sections */
++	int			sig_index;	/* module signature section index */
++	uint8_t			xcsum;		/* checksum of bytes contributed to digest */
++	uint8_t			csum;		/* checksum of bytes representing a section */
++};
++
++/*
++ * module-verify.c
++ */
++extern int module_verify(const Elf_Ehdr *hdr, size_t size);
++
++/*
++ * module-verify-elf.c
++ */
++#ifdef CONFIG_MODULE_VERIFY_ELF
++extern int module_verify_elf(struct module_verify_data *mvdata);
++#else
++#define module_verify_elf(m) (0)
++#endif
++
++#else
++#define module_verify(h, s) (0)
++#endif
+diff --git a/kernel/module.c b/kernel/module.c
+index 2c93276..54d6910 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -58,6 +58,7 @@
+ #include <linux/jump_label.h>
+ #include <linux/pfn.h>
+ #include <linux/bsearch.h>
++#include "module-verify.h"
+ 
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/module.h>
+@@ -2404,6 +2405,11 @@ static int copy_and_check(struct load_info *info,
+ 		goto free_hdr;
+ 	}
+ 
++	/* Verify the module's contents */
++	err = module_verify(hdr, len);
++	if (err < 0)
++		goto free_hdr;
++
+ 	info->hdr = hdr;
+ 	info->len = len;
+ 	return 0;
+-- 
+1.7.9.1
+
+
+From 1ecd333ad910d539e75f8f85d1fb1e3d87547c4e Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells at redhat.com>
+Date: Wed, 7 Dec 2011 14:07:18 +0000
+Subject: MODSIGN: Apply signature checking to modules on module load
+
+Apply signature checking to modules on module load, checking the signature
+against the ring of public keys compiled into the kernel (if enabled by
+CONFIG_MODULE_SIG).  Turning on signature checking will also force the module's
+ELF metadata to be verified first.
+
+These patches have been in use by RHEL and Fedora kernels for years, and so
+have been thoroughly tested.  The signed modules survive both the debuginfo
+separation performed by rpmbuild and the strip performed when modules are being
+reduced as much as possible before being included in an initial ramdisk
+composition.  Signed modules have been tested to work with LE and BE, 32- and
+64-bit arch kernels, including i386, x86_64, ppc64, ia64, s390 and s390x.
+
+There are several reasons why these patches are useful, amongst which are:
+
+ (1) to protect against accidentally-corrupted modules causing damage;
+
+ (2) to protect against maliciously modified modules causing damage;
+
+ (3) to allow a sysadmin (or more likely an IT department) to enforce a policy
+     that only known and approved modules shall be loaded onto machines which
+     they're expected to support;
+
+ (4) to allow other support providers to do likewise, or at least to _detect_
+     the fact that unsupported modules are loaded;
+
+ (5) to allow the detection of modules replaced by a second-order distro or a
+     preloaded Linux purveyor.
+
+These patches have two main appeals: (a) preventing malicious modules from
+being loaded, and (b) reducing support workload by pointing out modules on a
+crashing box that aren't what they're expected to be.
+
+Now, this is not a complete solution by any means: the core kernel is not
+protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least
+controls) one relatively simple attack vector.
+
+This facility is optional: the builder of a kernel is by no means under any
+requirement to actually enable it, let alone force the set of loadable modules
+to be restricted to just those that the builder provides (there are degrees of
+restriction available).
+
+Use of the module signing facility is documentated in:
+
+	Documentation/module-signing.txt
+
+which I've included here for reference:
+
+			==============================
+			KERNEL MODULE SIGNING FACILITY
+			==============================
+
+The module signing facilitiy applies cryptographic signature checking to
+modules on module load, checking the signature against a ring of public keys
+compiled into the kernel.  GPG is used to do the cryptographic work and
+determines the format of the signature and key data.  The facility uses GPG's
+MPI library to handle the huge numbers involved.
+
+This facility is enabled through CONFIG_MODULE_SIG.  Turning on signature
+checking will also force the module's ELF metadata to be verified before the
+signature is checked.
+
+=====================
+SUPPLYING PUBLIC KEYS
+=====================
+
+A set of public keys must be supplied at main kernel compile time.  This is
+done by taking a GPG public key file, running it through the kernel's bin2c
+program and writing the result over crypto/signature/key.h.  To automate this
+process, something like this could be done:
+
+	cat >genkey <<EOF
+	%pubring kernel.pub
+	%secring kernel.sec
+	Key-Type: DSA
+	Key-Length: 512
+	Name-Real: A. N. Other
+	Name-Comment: Kernel Module GPG key
+	%commit
+	EOF
+	make scripts/bin2c
+	gpg --homedir . --batch --gen-key genkey
+
+The above generates fresh keys using /dev/random.  If there's insufficient data
+in /dev/random, more can be provided more by running:
+
+	rngd -r /dev/urandom
+
+in the background.
+
+Note:
+
+ (1) That "keyname" is the name of the key in the keyring.  This differentiates
+     it from any other keys that may be added to the keyring.
+
+ (2) That no GPG password is used in the above scriptlet.
+
+ (3) It may be desirable to shred and delete the private key file after signing
+     the modules.
+
+==============
+MODULE SIGNING
+==============
+
+Modules will then be signed automatically.  The kernel make command line can
+include the following options:
+
+ (*) MODSECKEY=<secret-key-ring-path>
+
+     This indicates the whereabouts of the GPG keyring that is the source of
+     the secret key to be used.  The default is "./kernel.sec".
+
+ (*) MODPUBKEY=<public-key-ring-path>
+
+     This indicates the whereabouts of the GPG keyring that is the source of
+     the public key to be used.  The default is "./kernel.pub".
+
+ (*) MODKEYNAME=<key-name>
+
+     The name of the key pair to be used from the aforementioned keyrings.
+     This defaults to being unset, thus leaving the choice of default key to
+     gpg.
+
+ (*) KEYFLAGS="gpg-options"
+
+     Override the complete gpg command line, including the preceding three
+     options.  The default options supplied to gpg are:
+
+	--no-default-keyring
+	--secret-keyring $(MODSECKEY)
+	--keyring $(MODPUBKEY)
+	--no-default-keyring
+	--homedir .
+	--no-options
+	--no-auto-check-trustdb
+	--no-permission-warning
+
+      with:
+
+	--default-key $(MODKEYNAME)
+
+      being added if requested.
+
+The resulting module.ko file will be the signed module.
+
+========================
+STRIPPING SIGNED MODULES
+========================
+
+Signed modules may be safely stripped as the signature only covers those parts
+of the module the kernel actually uses and any ELF metadata required to deal
+with them.  Any necessary ELF metadata that is affected by stripping is
+canonicalised by the sig generator and the sig checker to hide strip effects.
+
+This permits the debuginfo to be detached from the module and placed in another
+spot so that gdb can find it when referring to that module without the need for
+multiple signed versions of the module.  Such is done by rpmbuild when
+producing RPMs.
+
+It also permits the module to be stripped as far as possible for when modules
+are being reduced prior to being included in an initial ramdisk composition.
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, exactly as for unsigned modules.  The signature
+is inserted into the module object file as an ELF section called ".module_sig".
+The signature checker will spot it and apply signature checking.
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on
+the kernel command line, the kernel will _only_ load validly signed modules
+for which it has a public key.  Otherwise, it will also load modules that are
+unsigned.  Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load (returning EKEYREJECTED).
+
+This table indicates the behaviours of the various situations:
+
+	MODULE STATE			PERMISSIVE MODE	ENFORCING MODE
+	===============================	===============	===============
+	Unsigned			Ok		EKEYREJECTED
+	Signed, no public key		ENOKEY		ENOKEY
+	Validly signed, public key	Ok		Ok
+	Invalidly signed, public key	EKEYREJECTED	EKEYREJECTED
+	Validly signed, expired key	EKEYEXPIRED	EKEYEXPIRED
+	Corrupt signature		ELIBBAD		ELIBBAD
+	Corrupt ELF			ELIBBAD		ELIBBAD
+
+Signed-Off-By: David Howells <dhowells at redhat.com>
+
+Rebased-to-3.3-rc6-by: Josh Boyer <jwboyer at redhat.com>
+---
+ .gitignore                       |   15 +
+ Documentation/module-signing.txt |  186 ++++++++
+ Makefile                         |    1 +
+ include/linux/elfnote.h          |    4 +
+ include/linux/modsign.h          |   27 ++
+ include/linux/module.h           |    3 +
+ init/Kconfig                     |   56 +++-
+ kernel/Makefile                  |    2 +
+ kernel/modsign-pubkey.c          |   44 ++
+ kernel/module-verify-sig.c       |  526 ++++++++++++++++++++++
+ kernel/module-verify.c           |    5 +-
+ kernel/module-verify.h           |   19 +-
+ kernel/module.c                  |   21 +-
+ scripts/Makefile.modpost         |   85 ++++-
+ scripts/mod/.gitignore           |    1 +
+ scripts/mod/Makefile             |    2 +-
+ scripts/mod/mod-extract.c        |  913 ++++++++++++++++++++++++++++++++++++++
+ scripts/mod/modsign-note.sh      |   16 +
+ 18 files changed, 1914 insertions(+), 12 deletions(-)
+ create mode 100644 Documentation/module-signing.txt
+ create mode 100644 include/linux/modsign.h
+ create mode 100644 kernel/modsign-pubkey.c
+ create mode 100644 kernel/module-verify-sig.c
+ create mode 100644 scripts/mod/mod-extract.c
+ create mode 100644 scripts/mod/modsign-note.sh
+
+diff --git a/.gitignore b/.gitignore
+index 57af07c..841a17ee 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -14,6 +14,9 @@
+ *.o.*
+ *.a
+ *.s
++*.ko.unsigned
++*.ko.digest
++*.ko.digest.sig
+ *.ko
+ *.so
+ *.so.dbg
+@@ -84,3 +87,15 @@ GTAGS
+ *.orig
+ *~
+ \#*#
++
++#
++# GPG leavings from module signing
++#
++trustdb.gpg
++random_seed
++kernel.pub
++kernel.sec
++extract.pub
++secring.gpg
++pubring.gpg
++crypto/signature/key.h
+diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
+new file mode 100644
+index 0000000..300b91a
+--- /dev/null
++++ b/Documentation/module-signing.txt
+@@ -0,0 +1,186 @@
++			==============================
++			KERNEL MODULE SIGNING FACILITY
++			==============================
++
++The module signing facility applies cryptographic signature checking to modules
++on module load, checking the signature against a ring of public keys compiled
++into the kernel.  GPG is used to do the cryptographic work and determines the
++format of the signature and key data.  The facility uses GPG's MPI library to
++handle the huge numbers involved.
++
++This facility is enabled through CONFIG_MODULE_SIG.  Turning on signature
++checking will also force the module's ELF metadata to be verified before the
++signature is checked.
++
++The signature checker in the kernel is capable of handling multiple keys of
++either DSA or RSA type, and can support any of MD5, RIPE-MD-160, SHA-1,
++SHA-224, SHA-256, SHA-384 and SHA-512 hashes - PROVIDED(!) the requisite
++algorithms are compiled into the kernel.
++
++(!) NOTE: Modules may only be verified initially with algorithms compiled into
++the kernel.  Further algorithm modules may be loaded and used - but these must
++first pass a verification step using already loaded/compiled-in algorithms.
++
++
++=====================
++SUPPLYING PUBLIC KEYS
++=====================
++
++A set of public keys must be supplied at kernel image build time.  This is done
++by taking a GPG public key file and placing it in the base of the kernel
++directory in a file called kernel.pub.
++
++For example, a throwaway key could be generated automatically by something like
++the following:
++
++	cat >genkey <<EOF
++	%pubring kernel.pub
++	%secring kernel.sec
++	Key-Type: DSA
++	Key-Length: 512
++	Name-Real: A. N. Other
++	Name-Comment: Kernel Module GPG key
++	%commit
++	EOF
++	gpg --homedir . --batch --gen-key genkey
++
++The above generates fresh keys using /dev/random.  If there's insufficient data
++in /dev/random, more can be provided more by running:
++
++	rngd -r /dev/urandom
++
++in the background.
++
++Note that no GPG password is used in the above scriptlet.
++
++The kernel.pub file is compiled into the kernel directly by the assembler by
++means of an ".incbin" directive in kernel/modsign-pubkey.c.
++
++Once the kernel is running, the keys are visible to root as kernel crypto keys
++in /proc/keys in a keyring called .module_sign:
++
++335ab517 I-----     1 perm 1f030000     0     0 keyring   .module_sign: 2/4
++38d7d169 I-----     1 perm 3f010000     0     0 crypto    modsign.0: rsa 57532ca5 []
++195fa736 I-----     1 perm 3f010000     0     0 crypto    modsign.1: dsa 5acc2142 []
++
++This keyring can be listed with the keyctl program.  See:
++
++	Documentation/security/keys-crypto.txt
++
++for more information of crypto keys.
++
++
++============================
++SELECTING THE HASH ALGORITHM
++============================
++
++The hash algorithm to be used is selected by a multiple choice configuration
++item that enables one of the following variables:
++
++	CONFIG_SIG_SHA1
++	CONFIG_SIG_SHA224
++	CONFIG_SIG_SHA256
++	CONFIG_SIG_SHA384
++	CONFIG_SIG_SHA512
++
++These cause an appropriate "--digest-algo=" parameter to be passed to gpg when
++signing a module and force the appropriate hash algorithm to be compiled
++directly into the kernel rather than being built as a module.
++
++
++==============
++MODULE SIGNING
++==============
++
++Modules will then be signed automatically.  The kernel make command line can
++include the following options:
++
++ (*) MODSECKEY=<secret-key-ring-path>
++
++     This indicates the whereabouts of the GPG keyring that is the source of
++     the secret key to be used.  The default is "./kernel.sec".
++
++ (*) MODPUBKEY=<public-key-ring-path>
++
++     This indicates the whereabouts of the GPG keyring that is the source of
++     the public key to be used.  The default is "./kernel.pub".
++
++ (*) MODKEYNAME=<key-name>
++
++     The name of the key pair to be used from the aforementioned keyrings.
++     This defaults to being unset, thus leaving the choice of default key to
++     gpg.
++
++ (*) KEYFLAGS="gpg-options"
++
++     Override the complete gpg command line, including the preceding three
++     options.  The default options supplied to gpg are:
++
++	--no-default-keyring
++	--secret-keyring $(MODSECKEY)
++	--keyring $(MODPUBKEY)
++	--no-default-keyring
++	--homedir .
++	--no-options
++	--no-auto-check-trustdb
++	--no-permission-warning
++	--digest-algo=<hash-algorithm>
++
++      with:
++
++	--default-key $(MODKEYNAME)
++
++      being added if requested.
++
++The resulting module.ko file will be the signed module.
++
++
++========================
++STRIPPING SIGNED MODULES
++========================
++
++Signed modules may be safely stripped as the signature only covers those parts
++of the module the kernel actually uses and any ELF metadata required to deal
++with them.  Any necessary ELF metadata that is affected by stripping is
++canonicalised by the sig generator and the sig checker to hide strip effects.
++
++This permits the debuginfo to be detached from the module and placed in another
++spot so that gdb can find it when referring to that module without the need for
++multiple signed versions of the module.  Such is done by rpmbuild when
++producing RPMs.
++
++It also permits the module to be stripped as far as possible for when modules
++are being reduced prior to being included in an initial ramdisk composition.
++
++
++======================
++LOADING SIGNED MODULES
++======================
++
++Modules are loaded with insmod, exactly as for unsigned modules.  The signature
++is inserted into the module object file as an ELF section called ".module_sig".
++The signature checker will detect it and apply signature checking.
++
++
++=========================================
++NON-VALID SIGNATURES AND UNSIGNED MODULES
++=========================================
++
++If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on
++the kernel command line, the kernel will _only_ load validly signed modules
++for which it has a public key.  Otherwise, it will also load modules that are
++unsigned.  Any module for which the kernel has a key, but which proves to have
++a signature mismatch will not be permitted to load (returning EKEYREJECTED).
++
++This table indicates the behaviours of the various situations:
++
++	MODULE STATE				PERMISSIVE MODE	ENFORCING MODE
++	=======================================	===============	===============
++	Unsigned				Ok		EKEYREJECTED
++	Signed, no public key			ENOKEY		ENOKEY
++	Validly signed, public key		Ok		Ok
++	Invalidly signed, public key		EKEYREJECTED	EKEYREJECTED
++	Validly signed, expired key		EKEYEXPIRED	EKEYEXPIRED
++	Signed, hash algorithm unavailable	ENOPKG		ENOPKG
++	Corrupt signature			EBADMSG		EBADMSG
++	Corrupt ELF				ELIBBAD		ELIBBAD
+diff --git a/Makefile b/Makefile
+index 66d13c9..8ba824f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1407,6 +1407,7 @@ clean: $(clean-dirs)
+ 	$(call cmd,rmfiles)
+ 	@find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ 		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
++		-o -name '*.ko.*' \
+ 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+ 		-o -name '*.symtypes' -o -name 'modules.order' \
+ 		-o -name modules.builtin -o -name '.tmp_*.o.*' \
+diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h
+index 278e3ef..949d494 100644
+--- a/include/linux/elfnote.h
++++ b/include/linux/elfnote.h
+@@ -58,6 +58,7 @@
+ 	ELFNOTE_END
+ 
+ #else	/* !__ASSEMBLER__ */
++#include <linux/stringify.h>
+ #include <linux/elf.h>
+ /*
+  * Use an anonymous structure which matches the shape of
+@@ -93,6 +94,9 @@
+ 
+ #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
+ #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
++
++#define ELFNOTE_NAME(name)	__stringify(name)
++#define ELFNOTE_SECTION(name)	".note."ELFNOTE_NAME(name)
+ #endif	/* __ASSEMBLER__ */
+ 
+ #endif /* _LINUX_ELFNOTE_H */
+diff --git a/include/linux/modsign.h b/include/linux/modsign.h
+new file mode 100644
+index 0000000..c5ac87a
+--- /dev/null
++++ b/include/linux/modsign.h
+@@ -0,0 +1,27 @@
++/* Module signing definitions
++ *
++ * Copyright (C) 2009 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 _LINUX_MODSIGN_H
++#define _LINUX_MODSIGN_H
++
++#ifdef CONFIG_MODULE_SIG
++
++#include <linux/elfnote.h>
++
++/*
++ * The parameters of the ELF note used to carry the signature
++ */
++#define MODSIGN_NOTE_NAME	module.sig
++#define MODSIGN_NOTE_TYPE	100
++
++#endif
++
++#endif /* _LINUX_MODSIGN_H */
+diff --git a/include/linux/module.h b/include/linux/module.h
+index 4598bf0..2bd03f1 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -294,6 +294,9 @@ struct module
+ 
+ 	unsigned int taints;	/* same bits as kernel:tainted */
+ 
++	/* Is this module GPG signed */
++	int gpgsig_ok;
++
+ #ifdef CONFIG_GENERIC_BUG
+ 	/* Support for BUG */
+ 	unsigned num_bugs;
+diff --git a/init/Kconfig b/init/Kconfig
+index 61b5f03..b21dcae 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1424,10 +1424,64 @@ config MODULE_VERIFY_ELF
+ 	help
+ 	  Check ELF structure of modules upon load
+ 
++config MODULE_SIG
++	bool "Module signature verification (EXPERIMENTAL)"
++	depends on MODULES && EXPERIMENTAL
++	select CRYPTO_KEY_TYPE
++	select CRYPTO_KEY_PKEY_ALGO_DSA
++	select CRYPTO_KEY_PKEY_ALGO_RSA
++	select PGP_PARSER
++	select PGP_PRELOAD
++	select MODULE_VERIFY_ELF
++	help
++	  Check modules for valid signatures upon load.  For more information
++	  see:
++
++	  Documentation/module-signing.txt
++
++choice
++	prompt "Which hash algorithm should modules be signed with?"
++	depends on MODULE_SIG
++	help
++	  This determines which sort of hashing algorithm will be used during
++	  signature generation.  This algorithm _must_ be built into the kernel
++	  directly so that signature verification can take place.  It is not
++	  possible to load a signed module containing the algorithm to check
++	  the signature on that module.
++
++config MODULE_SIG_SHA1
++	bool "Sign modules with SHA-1"
++	select CRYPTO_SHA1
++
++config MODULE_SIG_SHA224
++	bool "Sign modules with SHA-224"
++	select CRYPTO_SHA224
++
++config MODULE_SIG_SHA256
++	bool "Sign modules with SHA-256"
++	select CRYPTO_SHA256
++
++config MODULE_SIG_SHA384
++	bool "Sign modules with SHA-384"
++	select CRYPTO_SHA384
++
++config MODULE_SIG_SHA512
++	bool "Sign modules with SHA-512"
++	select CRYPTO_SHA512
++
++endchoice
++
++config MODULE_SIG_FORCE
++	bool "Required modules to be validly signed (EXPERIMENTAL)"
++	depends on MODULE_SIG
++	help
++	  Reject unsigned modules or signed modules for which we don't have a
++	  key.
++
+ config MODULE_VERIFY
+ 	bool
+ 	depends on MODULES
+-	default y if MODULE_VERIFY_ELF
++	default y if MODULE_VERIFY_ELF || MODULE_SIG
+ 
+ endif # MODULES
+ 
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 77b7a39..9732e11 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -54,6 +54,8 @@ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_MODULE_VERIFY) += module-verify.o
+ obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o
++obj-$(CONFIG_MODULE_SIG) += module-verify-sig.o modsign-pubkey.o
++kernel/modsign-pubkey.o: kernel.pub
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+ obj-$(CONFIG_KEXEC) += kexec.o
+diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c
+new file mode 100644
+index 0000000..df55565
+--- /dev/null
++++ b/kernel/modsign-pubkey.c
+@@ -0,0 +1,44 @@
++/* Public keys for module signature verification
++ *
++ * Copyright (C) 2011 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 <keys/crypto-type.h>
++#include "module-verify.h"
++
++extern __initdata const u8 modsign_public_keys[];
++extern __initdata const u8 modsign_public_keys_end[];
++asm(".section .init.data,\"aw\"\n"
++    "modsign_public_keys:\n"
++    ".incbin \"kernel.pub\"\n"
++    "modsign_public_keys_end:"
++    );
++
++/*
++ * We need to make sure ccache doesn't cache the .o file as it doesn't notice
++ * if kernel.pub changes.
++ */
++static __initdata const char annoy_ccache[] = __TIME__ "foo";
++
++/*
++ * Load the compiled-in keys
++ */
++static __init int modsign_pubkey_init(void)
++{
++	pr_notice("Load module verification keys\n");
++
++	if (preload_pgp_keys(modsign_public_keys,
++			     modsign_public_keys_end - modsign_public_keys,
++			     modsign_keyring, "modsign.") < 0)
++		panic("Can't load module signing keys\n");
++
++	return 0;
++}
++late_initcall(modsign_pubkey_init);
+diff --git a/kernel/module-verify-sig.c b/kernel/module-verify-sig.c
+new file mode 100644
+index 0000000..ced5681
+--- /dev/null
++++ b/kernel/module-verify-sig.c
+@@ -0,0 +1,526 @@
++/* Module signature checker
++ *
++ * Copyright (C) 2004,2011 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells at redhat.com)
++ * - Derived from GregKH's RSA module signer
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/elf.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <linux/modsign.h>
++#include <keys/keyring-type.h>
++#include "module-verify.h"
++
++#undef MODSIGN_DEBUG
++
++struct key *modsign_keyring;
++
++int modsign_debug;
++core_param(modsign_debug, modsign_debug, bool, 0644);
++
++#define _debug(FMT, ...)			      \
++	do {					      \
++		if (unlikely(modsign_debug))	      \
++			pr_debug(FMT, ##__VA_ARGS__); \
++	} while(0)
++
++#ifdef MODSIGN_DEBUG
++#define count_and_csum(C, __p, __n)			\
++do {							\
++	int __loop;					\
++	for (__loop = 0; __loop < __n; __loop++) {	\
++		(C)->csum += __p[__loop];		\
++		(C)->xcsum += __p[__loop];		\
++	}						\
++	(C)->signed_size += __n;			\
++} while (0)
++#else
++#define count_and_csum(C, __p, __n)		\
++do {						\
++	(C)->signed_size += __n;		\
++} while (0)
++#endif
++
++#define crypto_digest_update_data(C, PTR, N)			\
++do {								\
++	uint8_t *__p = (uint8_t *)(PTR);			\
++	size_t __n = (N);					\
++	count_and_csum((C), __p, __n);				\
++	verify_sig_add_data((C)->mod_sig, __p, __n);		\
++} while (0)
++
++#define crypto_digest_update_val(C, VAL)			\
++do {								\
++	uint8_t *__p = (uint8_t *)&(VAL);			\
++	size_t __n = sizeof(VAL);				\
++	count_and_csum((C), __p, __n);				\
++	verify_sig_add_data((C)->mod_sig, __p, __n);		\
++} while (0)
++
++static int module_verify_canonicalise(struct module_verify_data *mvdata);
++
++static int extract_elf_rela(struct module_verify_data *mvdata,
++			    int secix,
++			    const Elf_Rela *relatab, size_t nrels,
++			    const char *sh_name);
++
++static int extract_elf_rel(struct module_verify_data *mvdata,
++			   int secix,
++			   const Elf_Rel *reltab, size_t nrels,
++			   const char *sh_name);
++
++#ifdef CONFIG_MODULE_SIG_FORCE
++static int signedonly = 1;
++#else
++static int signedonly;
++#endif
++
++static int __init sign_setup(char *str)
++{
++	signedonly = 1;
++	return 0;
++}
++__setup("enforcemodulesig", sign_setup);
++
++static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
++static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
++
++/*
++ * verify a module's signature
++ */
++int module_verify_signature(struct module_verify_data *mvdata,
++			    int *_gpgsig_ok)
++{
++	struct crypto_key_verify_context *mod_sig;
++	const struct elf_note *note;
++	const Elf_Shdr *sechdrs = mvdata->sections;
++	const char *secstrings = mvdata->secstrings;
++	const char *sig;
++	unsigned note_size, sig_size, note_namesz;
++	int loop, ret;
++
++	_debug("looking for sig section '%s'\n", modsign_note_section);
++
++	for (loop = 1; loop < mvdata->nsects; loop++) {
++		switch (sechdrs[loop].sh_type) {
++		case SHT_NOTE:
++			if (strcmp(mvdata->secstrings + sechdrs[loop].sh_name,
++				   modsign_note_section) == 0)
++				mvdata->sig_index = loop;
++			break;
++		}
++	}
++
++	if (mvdata->sig_index <= 0)
++		goto no_signature;
++
++	note = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset;
++	note_size = sechdrs[mvdata->sig_index].sh_size;
++
++	/* there should be one note of the appropriate type */
++	if (note_size < sizeof(*note) + 2 * 4)
++		goto format_error_no_free;
++	note_namesz = note->n_namesz;
++	sig_size = note->n_descsz;
++	if (note_namesz != sizeof(modsign_note_name))
++		goto format_error_no_free;
++	if (note->n_type != MODSIGN_NOTE_TYPE)
++		goto format_error_no_free;
++	if (memcmp(note + 1, modsign_note_name, note_namesz) != 0)
++		goto format_error_no_free;
++	sig = (void *)(note + 1) + roundup(note_namesz, 4);
++
++	_debug("sig in section %d (size %d)\n",
++	       mvdata->sig_index, sig_size);
++	_debug("%02x%02x%02x%02x%02x%02x%02x%02x\n",
++	       sig[0], sig[1], sig[2], sig[3],
++	       sig[4], sig[5], sig[6], sig[7]);
++
++	/* produce a canonicalisation map for the sections */
++	ret = module_verify_canonicalise(mvdata);
++	if (ret < 0)
++		return ret;
++
++	/* Find the crypto key for the module signature
++	 * - !!! if this tries to load the required hash algorithm module,
++	 *       we will deadlock!!!
++	 */
++	mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size);
++	if (IS_ERR(mod_sig)) {
++		pr_err("Couldn't initiate module signature verification: %ld\n",
++		       PTR_ERR(mod_sig));
++		return PTR_ERR(mod_sig);
++	}
++
++	mvdata->mod_sig = mod_sig;
++
++#ifdef MODSIGN_DEBUG
++	mvdata->xcsum = 0;
++#endif
++
++	/* load data from each relevant section into the digest */
++	for (loop = 0; loop < mvdata->ncanon; loop++) {
++		int sect = mvdata->canonlist[loop];
++		unsigned long sh_type = sechdrs[sect].sh_type;
++		unsigned long sh_info = sechdrs[sect].sh_info;
++		unsigned long sh_size = sechdrs[sect].sh_size;
++		unsigned long sh_flags = sechdrs[sect].sh_flags;
++		const char *sh_name = secstrings + sechdrs[sect].sh_name;
++		const void *data = mvdata->buffer + sechdrs[sect].sh_offset;
++
++#ifdef MODSIGN_DEBUG
++		mvdata->csum = 0;
++#endif
++
++		/* it would be nice to include relocation sections, but the act
++		 * of adding a signature to the module seems changes their
++		 * contents, because the symtab gets changed when sections are
++		 * added or removed */
++		if (sh_type == SHT_REL || sh_type == SHT_RELA) {
++			uint32_t xsh_info = mvdata->canonmap[sh_info];
++
++			crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_type);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_size);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign);
++			crypto_digest_update_val(mvdata, xsh_info);
++
++			if (sh_type == SHT_RELA)
++				ret = extract_elf_rela(
++					mvdata, sect,
++					data,
++					sh_size / sizeof(Elf_Rela),
++					sh_name);
++			else
++				ret = extract_elf_rel(
++					mvdata, sect,
++					data,
++					sh_size / sizeof(Elf_Rel),
++					sh_name);
++
++			if (ret < 0)
++				goto format_error;
++			continue;
++		}
++
++		/* include the headers of BSS sections */
++		if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
++			crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_type);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_size);
++			crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign);
++			goto digested;
++		}
++
++		/* include allocatable loadable sections */
++		if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
++			goto include_section;
++
++		continue;
++
++	include_section:
++		crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
++		crypto_digest_update_val(mvdata, sechdrs[sect].sh_type);
++		crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags);
++		crypto_digest_update_val(mvdata, sechdrs[sect].sh_size);
++		crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign);
++
++		crypto_digest_update_data(mvdata, data, sh_size);
++
++	digested:
++		_debug("%08zx %02x digested the %s section, size %ld\n",
++		       mvdata->signed_size, mvdata->csum, sh_name, sh_size);
++	}
++
++	_debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
++	       mvdata->signed_size, mvdata->xcsum);
++
++	/* do the actual signature verification */
++	ret = verify_sig_end(mvdata->mod_sig, sig, sig_size);
++	mvdata->mod_sig = NULL;
++
++	_debug("verify-sig : %d\n", ret);
++
++	switch (ret) {
++	case 0:			/* good signature */
++		*_gpgsig_ok = 1;
++		break;
++	case -EKEYREJECTED:	/* signature mismatch or number format error */
++		pr_err("Module signature verification failed\n");
++		break;
++	case -ENOKEY:		/* signed, but we don't have the public key */
++		pr_err("Module signed with unknown public key\n");
++		break;
++	default:		/* other error (probably ENOMEM) */
++		break;
++	}
++
++	return ret;
++
++format_error:
++	verify_sig_cancel(mvdata->mod_sig);
++	mvdata->mod_sig = NULL;
++format_error_no_free:
++	pr_err("Module format error encountered\n");
++	return -ELIBBAD;
++
++	/* deal with the case of an unsigned module */
++no_signature:
++	_debug("no signature found\n");
++	if (!signedonly)
++		return 0;
++	pr_err("An attempt to load unsigned module was rejected\n");
++	return -EKEYREJECTED;
++}
++
++/*
++ * canonicalise the section table index numbers
++ */
++static int module_verify_canonicalise(struct module_verify_data *mvdata)
++{
++	int canon, loop, changed, tmp;
++
++	/* produce a list of index numbers of sections that contribute
++	 * to the kernel's module image
++	 */
++	mvdata->canonlist =
++		kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
++	if (!mvdata->canonlist)
++		return -ENOMEM;
++
++	mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
++	canon = 0;
++
++	for (loop = 1; loop < mvdata->nsects; loop++) {
++		const Elf_Shdr *section = mvdata->sections + loop;
++
++		if (loop == mvdata->sig_index)
++			continue;
++
++		/* we only need to canonicalise allocatable sections */
++		if (section->sh_flags & SHF_ALLOC)
++			mvdata->canonlist[canon++] = loop;
++		else if ((section->sh_type == SHT_REL ||
++			  section->sh_type == SHT_RELA) &&
++			 mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC)
++			mvdata->canonlist[canon++] = loop;
++	}
++
++	/* canonicalise the index numbers of the contributing section */
++	do {
++		changed = 0;
++
++		for (loop = 0; loop < canon - 1; loop++) {
++			const char *x, *y;
++
++			x = mvdata->secstrings +
++				mvdata->sections[mvdata->canonlist[loop + 0]].sh_name;
++			y = mvdata->secstrings +
++				mvdata->sections[mvdata->canonlist[loop + 1]].sh_name;
++
++			if (strcmp(x, y) > 0) {
++				tmp = mvdata->canonlist[loop + 0];
++				mvdata->canonlist[loop + 0] =
++					mvdata->canonlist[loop + 1];
++				mvdata->canonlist[loop + 1] = tmp;
++				changed = 1;
++			}
++		}
++
++	} while (changed);
++
++	for (loop = 0; loop < canon; loop++)
++		mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
++	mvdata->ncanon = canon;
++	return 0;
++}
++
++/*
++ * extract an ELF RELA table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static int extract_elf_rela(struct module_verify_data *mvdata,
++			    int secix,
++			    const Elf_Rela *relatab, size_t nrels,
++			    const char *sh_name)
++{
++	struct {
++#if defined(MODULES_ARE_ELF32)
++		uint32_t	r_offset;
++		uint32_t	r_addend;
++		uint32_t	st_value;
++		uint32_t	st_size;
++		uint16_t	st_shndx;
++		uint8_t		r_type;
++		uint8_t		st_info;
++		uint8_t		st_other;
++#elif defined(MODULES_ARE_ELF64)
++		uint64_t	r_offset;
++		uint64_t	r_addend;
++		uint64_t	st_value;
++		uint64_t	st_size;
++		uint32_t	r_type;
++		uint16_t	st_shndx;
++		uint8_t		st_info;
++		uint8_t		st_other;
++#else
++#error unsupported module type
++#endif
++	} __attribute__((packed)) relocation;
++
++	const Elf_Rela *reloc;
++	const Elf_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		int st_shndx;
++
++		reloc = &relatab[loop];
++
++		/* decode the relocation */
++		relocation.r_offset = reloc->r_offset;
++		relocation.r_addend = reloc->r_addend;
++		relocation.r_type = ELF_R_TYPE(reloc->r_info);
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = symbol->st_shndx;
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
++			relocation.st_shndx = mvdata->canonmap[st_shndx];
++
++		crypto_digest_update_val(mvdata, relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = mvdata->strings + symbol->st_name;
++			crypto_digest_update_data(mvdata,
++						  name, strlen(name) + 1);
++		}
++	}
++
++	_debug("%08zx %02x digested the %s section, nrels %zu\n",
++	       mvdata->signed_size, mvdata->csum, sh_name, nrels);
++
++	return 0;
++}
++
++/*
++ * extract an ELF REL table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static int extract_elf_rel(struct module_verify_data *mvdata,
++			   int secix,
++			   const Elf_Rel *reltab, size_t nrels,
++			   const char *sh_name)
++{
++	struct {
++#if defined(MODULES_ARE_ELF32)
++		uint32_t	r_offset;
++		uint32_t	st_value;
++		uint32_t	st_size;
++		uint16_t	st_shndx;
++		uint8_t		r_type;
++		uint8_t		st_info;
++		uint8_t		st_other;
++#elif defined(MODULES_ARE_ELF64)
++		uint64_t	r_offset;
++		uint64_t	st_value;
++		uint64_t	st_size;
++		uint32_t	r_type;
++		uint16_t	st_shndx;
++		uint8_t		st_info;
++		uint8_t		st_other;
++#else
++#error unsupported module type
++#endif
++	} __attribute__((packed)) relocation;
++
++	const Elf_Rel *reloc;
++	const Elf_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		int st_shndx;
++
++		reloc = &reltab[loop];
++
++		/* decode the relocation */
++		relocation.r_offset = reloc->r_offset;
++		relocation.r_type = ELF_R_TYPE(reloc->r_info);
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = symbol->st_shndx;
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
++			relocation.st_shndx = mvdata->canonmap[st_shndx];
++
++		crypto_digest_update_val(mvdata, relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = mvdata->strings + symbol->st_name;
++			crypto_digest_update_data(mvdata,
++						  name, strlen(name) + 1);
++		}
++	}
++
++	_debug("%08zx %02x digested the %s section, nrels %zu\n",
++	       mvdata->signed_size, mvdata->csum, sh_name, nrels);
++
++	return 0;
++}
++
++/*
++ * Load the compiled-in keys
++ */
++static __init int module_verify_init(void)
++{
++	pr_notice("Initialise module verification\n");
++
++	modsign_keyring = key_alloc(&key_type_keyring, ".module_sign",
++				    0, 0, current_cred(),
++				    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
++				    KEY_USR_VIEW | KEY_USR_READ,
++				    KEY_ALLOC_NOT_IN_QUOTA);
++	if (IS_ERR(modsign_keyring))
++		panic("Can't allocate module signing keyring\n");
++
++	if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0)
++		panic("Can't instantiate module signing keyring\n");
++
++	return 0;
++}
++
++/*
++ * Must be initialised before we try and load the keys into the keyring.
++ */
++device_initcall(module_verify_init);
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index 875279f..64c5813 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -16,8 +16,9 @@
+ /*
+  * verify a module's integrity
+  * - check the ELF is viable
++ * - check the module's signature
+  */
+-int module_verify(const Elf_Ehdr *hdr, size_t size)
++int module_verify(const Elf_Ehdr *hdr, size_t size, int *_gpgsig_ok)
+ {
+ 	struct module_verify_data mvdata;
+ 	int ret;
+@@ -34,6 +35,8 @@ int module_verify(const Elf_Ehdr *hdr, size_t size)
+ 		goto error;
+ 	}
+ 
++	ret = module_verify_signature(&mvdata, _gpgsig_ok);
++
+ error:
+ 	kfree(mvdata.secsizes);
+ 	kfree(mvdata.canonlist);
+diff --git a/kernel/module-verify.h b/kernel/module-verify.h
+index 20884fc..0ccdb71 100644
+--- a/kernel/module-verify.h
++++ b/kernel/module-verify.h
+@@ -10,10 +10,13 @@
+  */
+ 
+ #include <linux/types.h>
++#include <linux/elf.h>
++#include <keys/crypto-type.h>
+ #include <asm/module.h>
+ 
+ #ifdef CONFIG_MODULE_VERIFY
+ struct module_verify_data {
++	struct crypto_key_verify_context *mod_sig; /* Module signing context */
+ 	const void		*buffer;	/* module buffer */
+ 	const Elf_Ehdr		*hdr;		/* ELF header */
+ 	const Elf_Shdr		*sections;	/* ELF section table */
+@@ -37,7 +40,7 @@ struct module_verify_data {
+ /*
+  * module-verify.c
+  */
+-extern int module_verify(const Elf_Ehdr *hdr, size_t size);
++extern int module_verify(const Elf_Ehdr *hdr, size_t size, int *_gpgsig_ok);
+ 
+ /*
+  * module-verify-elf.c
+@@ -48,6 +51,18 @@ extern int module_verify_elf(struct module_verify_data *mvdata);
+ #define module_verify_elf(m) (0)
+ #endif
+ 
++/*
++ * module-verify-sig.c
++ */
++#ifdef CONFIG_MODULE_SIG
++extern struct key *modsign_keyring;
++
++extern int module_verify_signature(struct module_verify_data *mvdata,
++				   int *_gpgsig_ok);
++#else
++#define module_verify_signature(m, g) (0)
++#endif
++
+ #else
+-#define module_verify(h, s) (0)
++#define module_verify(h, s, g) (0)
+ #endif
+diff --git a/kernel/module.c b/kernel/module.c
+index 54d6910..bb38584 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -2372,7 +2372,8 @@ static inline void kmemleak_load_module(const struct module *mod,
+ /* Sets info->hdr and info->len. */
+ static int copy_and_check(struct load_info *info,
+ 			  const void __user *umod, unsigned long len,
+-			  const char __user *uargs)
++			  const char __user *uargs,
++			  int *_gpgsig_ok)
+ {
+ 	int err;
+ 	Elf_Ehdr *hdr;
+@@ -2406,7 +2407,7 @@ static int copy_and_check(struct load_info *info,
+ 	}
+ 
+ 	/* Verify the module's contents */
+-	err = module_verify(hdr, len);
++	err = module_verify(hdr, len, _gpgsig_ok);
+ 	if (err < 0)
+ 		goto free_hdr;
+ 
+@@ -2752,7 +2753,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
+ 	return 0;
+ }
+ 
+-static struct module *layout_and_allocate(struct load_info *info)
++static struct module *layout_and_allocate(struct load_info *info,
++					  int gpgsig_ok)
+ {
+ 	/* Module within temporary copy. */
+ 	struct module *mod;
+@@ -2762,6 +2764,7 @@ static struct module *layout_and_allocate(struct load_info *info)
+ 	mod = setup_load_info(info);
+ 	if (IS_ERR(mod))
+ 		return mod;
++	mod->gpgsig_ok = gpgsig_ok;
+ 
+ 	err = check_modinfo(mod, info);
+ 	if (err)
+@@ -2845,17 +2848,18 @@ static struct module *load_module(void __user *umod,
+ 	struct load_info info = { NULL, };
+ 	struct module *mod;
+ 	long err;
++	int gpgsig_ok;
+ 
+ 	pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
+ 	       umod, len, uargs);
+ 
+ 	/* Copy in the blobs from userspace, check they are vaguely sane. */
+-	err = copy_and_check(&info, umod, len, uargs);
++	err = copy_and_check(&info, umod, len, uargs, &gpgsig_ok);
+ 	if (err)
+ 		return ERR_PTR(err);
+ 
+ 	/* Figure out module layout, and allocate all the memory. */
+-	mod = layout_and_allocate(&info);
++	mod = layout_and_allocate(&info, gpgsig_ok);
+ 	if (IS_ERR(mod)) {
+ 		err = PTR_ERR(mod);
+ 		goto free_copy;
+@@ -3491,8 +3495,13 @@ void print_modules(void)
+ 	printk(KERN_DEFAULT "Modules linked in:");
+ 	/* Most callers should already have preempt disabled, but make sure */
+ 	preempt_disable();
+-	list_for_each_entry_rcu(mod, &modules, list)
++	list_for_each_entry_rcu(mod, &modules, list) {
+ 		printk(" %s%s", mod->name, module_flags(mod, buf));
++#ifdef CONFIG_MODULE_SIG
++		if (!mod->gpgsig_ok)
++			printk("(U)");
++#endif
++	}
+ 	preempt_enable();
+ 	if (last_unloaded_module[0])
+ 		printk(" [last unloaded: %s]", last_unloaded_module);
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index 08dce14..b436b04 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -14,7 +14,8 @@
+ # 3)  create one <module>.mod.c file pr. module
+ # 4)  create one Module.symvers file with CRC for all exported symbols
+ # 5) compile all <module>.mod.c files
+-# 6) final link of the module to a <module.ko> file
++# 6) final link of the module to a <module.ko> (or <module.unsigned>) file
++# 7) signs the modules to a <module.ko> file
+ 
+ # Step 3 is used to place certain information in the module's ELF
+ # section, including information such as:
+@@ -32,6 +33,8 @@
+ # Step 4 is solely used to allow module versioning in external modules,
+ # where the CRC of each module is retrieved from the Module.symvers file.
+ 
++# Step 7 is dependent on CONFIG_MODULE_SIG being enabled.
++
+ # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
+ # symbols in the final module linking stage
+ # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
+@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
+ targets += $(modules:.ko=.mod.o)
+ 
+ # Step 6), final link of the modules
++ifneq ($(CONFIG_MODULE_SIG),y)
+ quiet_cmd_ld_ko_o = LD [M]  $@
+       cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
+                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+@@ -125,7 +129,86 @@ $(modules): %.ko :%.o %.mod.o FORCE
+ 	$(call if_changed,ld_ko_o)
+ 
+ targets += $(modules)
++else
++quiet_cmd_ld_ko_unsigned_o = LD [M]  $@
++      cmd_ld_ko_unsigned_o =						\
++		$(LD) -r $(LDFLAGS)					\
++			 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)	\
++			 -o $@ $(filter-out FORCE,$^)			\
++		$(if $(AFTER_LINK),; $(AFTER_LINK))
++
++$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
++	$(call if_changed,ld_ko_unsigned_o)
++
++targets += $(modules:.ko=.ko.unsigned)
++
++# Step 7), sign the modules
++MODSECKEY = ./kernel.sec
++MODPUBKEY = ./kernel.pub
++KEYFLAGS = --no-default-keyring --secret-keyring $(MODSECKEY) --keyring $(MODPUBKEY) --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning
++
++ifdef CONFIG_MODULE_SIG_SHA1
++KEYFLAGS += --digest-algo=SHA1
++else
++ifdef CONFIG_MODULE_SIG_SHA224
++KEYFLAGS += --digest-algo=SHA224
++else
++ifdef CONFIG_MODULE_SIG_SHA256
++KEYFLAGS += --digest-algo=SHA256
++else
++ifdef CONFIG_MODULE_SIG_SHA384
++KEYFLAGS += --digest-algo=SHA384
++else
++ifdef CONFIG_MODULE_SIG_SHA512
++KEYFLAGS += --digest-algo=SHA512
++else
++endif
++endif
++endif
++endif
++endif
++
++ifdef MODKEYNAME
++KEYFLAGS += --default-key $(MODKEYNAME)
++endif
+ 
++ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
++ifeq ($(KBUILD_SRC),)
++	# no O= is being used
++	SCRIPTS_DIR := scripts
++else
++	SCRIPTS_DIR := $(KBUILD_SRC)/scripts
++endif
++SIGN_MODULES := 1
++else
++SIGN_MODULES := 0
++endif
++
++# only sign if it's an in-tree module
++ifneq ($(KBUILD_EXTMOD),)
++SIGN_MODULES := 0
++endif
++
++ifeq ($(SIGN_MODULES),1)
++quiet_cmd_sign_ko_ko_unsigned = SIGN [M] $@
++      cmd_sign_ko_ko_unsigned = \
++		scripts/mod/mod-extract $< $@.digest && \
++		rm -f $@.digest.sig && \
++		gpg --batch --no-greeting $(KEYFLAGS) -b $@.digest && \
++		sh $(SCRIPTS_DIR)/mod/modsign-note.sh $@.digest.sig | \
++		  $(CC) -x assembler-with-cpp $(c_flags) $(CFLAGS_MODULE) -c -o $@.note.o - && \
++		$(LD) -r $(LDFLAGS) -o $@ $< $@.note.o
++else
++quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
++      cmd_sign_ko_ko_unsigned = \
++		cp $< $@
++endif
++
++$(modules): %.ko :%.ko.unsigned FORCE
++	$(call if_changed,sign_ko_ko_unsigned)
++
++targets += $(modules)
++endif
+ 
+ # Add FORCE to the prequisites of a target to force it to be always rebuilt.
+ # ---------------------------------------------------------------------------
+diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
+index e9b7abe..223dfd6 100644
+--- a/scripts/mod/.gitignore
++++ b/scripts/mod/.gitignore
+@@ -1,4 +1,5 @@
+ elfconfig.h
+ mk_elfconfig
+ modpost
++mod-extract
+ 
+diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
+index ff954f8..4654e3b 100644
+--- a/scripts/mod/Makefile
++++ b/scripts/mod/Makefile
+@@ -1,4 +1,4 @@
+-hostprogs-y	:= modpost mk_elfconfig
++hostprogs-y	:= modpost mk_elfconfig mod-extract
+ always		:= $(hostprogs-y) empty.o
+ 
+ modpost-objs	:= modpost.o file2alias.o sumversion.o
+diff --git a/scripts/mod/mod-extract.c b/scripts/mod/mod-extract.c
+new file mode 100644
+index 0000000..0c0e3e3
+--- /dev/null
++++ b/scripts/mod/mod-extract.c
+@@ -0,0 +1,913 @@
++/* mod-extract.c: module extractor for signing
++ *
++ * Copyright (C) 2004 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 License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdarg.h>
++#include <string.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <sys/mman.h>
++#include <sys/stat.h>
++#include <elf.h>
++#include <asm/byteorder.h>
++
++static void extract_elf64(void *buffer, size_t size, Elf64_Ehdr *hdr);
++static void extract_elf32(void *buffer, size_t size, Elf32_Ehdr *hdr);
++
++struct byteorder {
++	uint16_t (*get16)(const uint16_t *);
++	uint32_t (*get32)(const uint32_t *);
++	uint64_t (*get64)(const uint64_t *);
++	void (*set16)(uint16_t *, uint16_t);
++	void (*set32)(uint32_t *, uint32_t);
++	void (*set64)(uint64_t *, uint64_t);
++};
++
++static uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); }
++static uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); }
++static uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); }
++static uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); }
++static uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); }
++static uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); }
++
++static void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); }
++static void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); }
++static void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); }
++static void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); }
++static void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); }
++static void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); }
++
++static const struct byteorder byteorder_le = {
++	get16_le, get32_le, get64_le,
++	set16_le, set32_le, set64_le
++};
++static const struct byteorder byteorder_be = {
++	get16_be, get32_be, get64_be,
++	set16_be, set32_be, set64_be
++};
++static const struct byteorder *order;
++
++static inline uint16_t get16(const uint16_t *p) { return order->get16(p); }
++static inline uint32_t get32(const uint32_t *p) { return order->get32(p); }
++static inline uint64_t get64(const uint64_t *p) { return order->get64(p); }
++static inline void set16(uint16_t *p, uint16_t n) { order->set16(p, n); }
++static inline void set32(uint32_t *p, uint32_t n) { order->set32(p, n); }
++static inline void set64(uint64_t *p, uint64_t n) { order->set64(p, n); }
++
++static FILE *outfd;
++static uint8_t csum, xcsum;
++
++static void write_out(const void *data, size_t size)
++{
++	const uint8_t *p = data;
++	size_t loop;
++
++	for (loop = 0; loop < size; loop++) {
++		csum += p[loop];
++		xcsum += p[loop];
++	}
++
++	if (fwrite(data, 1, size, outfd) != size) {
++		perror("write");
++		exit(1);
++	}
++}
++
++#define write_out_val(VAL) write_out(&(VAL), sizeof(VAL))
++
++static int is_verbose;
++
++static __attribute__((format(printf, 1, 2)))
++void verbose(const char *fmt, ...)
++{
++	va_list va;
++
++	if (is_verbose) {
++		va_start(va, fmt);
++		vprintf(fmt, va);
++		va_end(va);
++	}
++}
++
++static __attribute__((noreturn))
++void usage(void)
++{
++	fprintf(stderr, "Usage: mod-extract [-v] <modulefile> <extractfile>\n");
++	exit(2);
++}
++
++/*
++ *
++ */
++int main(int argc, char **argv)
++{
++	struct stat st;
++	Elf32_Ehdr *hdr32;
++	Elf64_Ehdr *hdr64;
++	size_t len;
++	void *buffer;
++	int fd, be, b64;
++
++	while (argc > 1 && strcmp("-v", argv[1]) == 0) {
++		argv++;
++		argc--;
++		is_verbose++;
++	}
++
++	if (argc != 3)
++		usage();
++
++	/* map the module into memory */
++	fd = open(argv[1], O_RDONLY);
++	if (fd < 0) {
++		perror("open input");
++		exit(1);
++	}
++
++	if (fstat(fd, &st) < 0) {
++		perror("fstat");
++		exit(1);
++	}
++
++	len = st.st_size;
++
++	buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
++	if (buffer == MAP_FAILED) {
++		perror("mmap");
++		exit(1);
++	}
++
++	if (close(fd) < 0) {
++		perror("close input");
++		exit(1);
++	}
++
++	/* check it's an ELF object */
++	hdr32 = buffer;
++	hdr64 = buffer;
++
++	if (hdr32->e_ident[EI_MAG0] != ELFMAG0 ||
++	    hdr32->e_ident[EI_MAG1] != ELFMAG1 ||
++	    hdr32->e_ident[EI_MAG2] != ELFMAG2 ||
++	    hdr32->e_ident[EI_MAG3] != ELFMAG3
++	    ) {
++		fprintf(stderr, "Module does not appear to be ELF\n");
++		exit(3);
++	}
++
++	/* determine endianness and word size */
++	b64 = (hdr32->e_ident[EI_CLASS] == ELFCLASS64);
++	be = (hdr32->e_ident[EI_DATA] == ELFDATA2MSB);
++	order = be ? &byteorder_be : &byteorder_le;
++
++	verbose("Module is %s-bit %s-endian\n",
++		b64 ? "64" : "32",
++		be ? "big" : "little");
++
++	/* open the output file */
++	outfd = fopen(argv[2], "w");
++	if (!outfd) {
++		perror("open output");
++		exit(1);
++	}
++
++	/* perform the extraction */
++	if (b64)
++		extract_elf64(buffer, len, hdr64);
++	else
++		extract_elf32(buffer, len, hdr32);
++
++	/* done */
++	if (fclose(outfd) == EOF) {
++		perror("close output");
++		exit(1);
++	}
++
++	return 0;
++}
++
++/*
++ * extract a RELA table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static void extract_elf64_rela(const void *buffer, int secix, int targetix,
++			       const Elf64_Rela *relatab, size_t nrels,
++			       const Elf64_Sym *symbols, size_t nsyms,
++			       const Elf64_Shdr *sections, size_t nsects, int *canonmap,
++			       const char *strings, size_t nstrings,
++			       const char *sh_name)
++{
++	struct {
++		uint64_t	r_offset;
++		uint64_t	r_addend;
++		uint64_t	st_value;
++		uint64_t	st_size;
++		uint32_t	r_type;
++		uint16_t	st_shndx;
++		uint8_t		st_info;
++		uint8_t		st_other;
++
++	} __attribute__((packed)) relocation;
++
++	const Elf64_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		Elf64_Section st_shndx;
++		Elf64_Xword r_info;
++
++		/* decode the relocation */
++		r_info = get64(&relatab[loop].r_info);
++		relocation.r_offset = relatab[loop].r_offset;
++		relocation.r_addend = relatab[loop].r_addend;
++		set32(&relocation.r_type, ELF64_R_TYPE(r_info));
++
++		if (ELF64_R_SYM(r_info) >= nsyms) {
++			fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
++				(size_t)ELF64_R_SYM(r_info), loop);
++			exit(1);
++		}
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &symbols[ELF64_R_SYM(r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = get16(&symbol->st_shndx);
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < nsects)
++			set16(&relocation.st_shndx, canonmap[st_shndx]);
++
++		write_out_val(relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = strings + get32(&symbol->st_name);
++			write_out(name, strlen(name) + 1);
++		}
++	}
++
++	verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
++}
++
++/*
++ * extract a REL table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static void extract_elf64_rel(const void *buffer, int secix, int targetix,
++			      const Elf64_Rel *relatab, size_t nrels,
++			      const Elf64_Sym *symbols, size_t nsyms,
++			      const Elf64_Shdr *sections, size_t nsects, int *canonmap,
++			      const char *strings, size_t nstrings,
++			      const char *sh_name)
++{
++	struct {
++		uint64_t	r_offset;
++		uint64_t	st_value;
++		uint64_t	st_size;
++		uint32_t	r_type;
++		uint16_t	st_shndx;
++		uint8_t		st_info;
++		uint8_t		st_other;
++
++	} __attribute__((packed)) relocation;
++
++	const Elf64_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		Elf64_Section st_shndx;
++		Elf64_Xword r_info;
++
++		/* decode the relocation */
++		r_info = get64(&relatab[loop].r_info);
++		relocation.r_offset = relatab[loop].r_offset;
++		set32(&relocation.r_type, ELF64_R_TYPE(r_info));
++
++		if (ELF64_R_SYM(r_info) >= nsyms) {
++			fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
++				(size_t)ELF64_R_SYM(r_info), loop);
++			exit(1);
++		}
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &symbols[ELF64_R_SYM(r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = get16(&symbol->st_shndx);
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < nsects)
++			set16(&relocation.st_shndx, canonmap[st_shndx]);
++
++		write_out_val(relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = strings + get32(&symbol->st_name);
++			write_out(name, strlen(name) + 1);
++		}
++	}
++
++	verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
++}
++
++/*
++ * extract the data from a 64-bit module
++ */
++static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
++{
++	const Elf64_Sym *symbols;
++	Elf64_Shdr *sections;
++	const char *secstrings, *strings;
++	size_t nsyms, nstrings;
++	int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
++
++	sections = buffer + get64(&hdr->e_shoff);
++	secstrings = buffer + get64(&sections[get16(&hdr->e_shstrndx)].sh_offset);
++	shnum = get16(&hdr->e_shnum);
++
++	/* find the symbol table and the string table and produce a list of
++	 * index numbers of sections that contribute to the kernel's module
++	 * image
++	 */
++	canonlist = calloc(sizeof(int), shnum * 2);
++	if (!canonlist) {
++		perror("calloc");
++		exit(1);
++	}
++	canonmap = canonlist + shnum;
++	canon = 0;
++
++	symbols = NULL;
++	strings = NULL;
++	nstrings = 0;
++	nsyms = 0;
++
++	for (loop = 1; loop < shnum; loop++) {
++		const char *sh_name = secstrings + get32(&sections[loop].sh_name);
++		Elf64_Word  sh_type	= get32(&sections[loop].sh_type);
++		Elf64_Xword sh_size	= get64(&sections[loop].sh_size);
++		Elf64_Xword sh_flags	= get64(&sections[loop].sh_flags);
++		Elf64_Word  sh_info	= get32(&sections[loop].sh_info);
++		Elf64_Off   sh_offset	= get64(&sections[loop].sh_offset);
++		void *data = buffer + sh_offset;
++
++		/* quick sanity check */
++		if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
++			fprintf(stderr, "Section goes beyond EOF\n");
++			exit(3);
++		}
++
++		/* we only need to canonicalise allocatable sections */
++		if (sh_flags & SHF_ALLOC)
++			canonlist[canon++] = loop;
++		else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
++			 get64(&sections[sh_info].sh_flags) & SHF_ALLOC)
++			canonlist[canon++] = loop;
++
++		/* keep track of certain special sections */
++		switch (sh_type) {
++		case SHT_SYMTAB:
++			if (strcmp(sh_name, ".symtab") == 0) {
++				symbols = data;
++				nsyms = sh_size / sizeof(Elf64_Sym);
++			}
++			break;
++
++		case SHT_STRTAB:
++			if (strcmp(sh_name, ".strtab") == 0) {
++				strings = data;
++				nstrings = sh_size;
++			}
++			break;
++
++		default:
++			break;
++		}
++	}
++
++	if (!symbols) {
++		fprintf(stderr, "Couldn't locate symbol table\n");
++		exit(3);
++	}
++
++	if (!strings) {
++		fprintf(stderr, "Couldn't locate strings table\n");
++		exit(3);
++	}
++
++	/* canonicalise the index numbers of the contributing section */
++	do {
++		changed = 0;
++
++		for (loop = 0; loop < canon - 1; loop++) {
++			const char *x = secstrings + get32(&sections[canonlist[loop + 0]].sh_name);
++			const char *y = secstrings + get32(&sections[canonlist[loop + 1]].sh_name);
++			if (strcmp(x, y) > 0) {
++				tmp = canonlist[loop + 0];
++				canonlist[loop + 0] = canonlist[loop + 1];
++				canonlist[loop + 1] = tmp;
++				changed = 1;
++			}
++		}
++
++	} while (changed);
++
++	for (loop = 0; loop < canon; loop++)
++		canonmap[canonlist[loop]] = loop + 1;
++
++	if (is_verbose > 1) {
++		printf("\nSection canonicalisation map:\n");
++		for (loop = 1; loop < shnum; loop++) {
++			const char *x = secstrings + get32(&sections[loop].sh_name);
++			printf("%4d %s\n", canonmap[loop], x);
++		}
++
++		printf("\nAllocated section list in canonical order:\n");
++		for (loop = 0; loop < canon; loop++) {
++			const char *x = secstrings + get32(&sections[canonlist[loop]].sh_name);
++			printf("%4d %s\n", canonlist[loop], x);
++		}
++	}
++
++	/* iterate through the section table looking for sections we want to
++	 * contribute to the signature */
++	verbose("\n");
++	verbose("CAN FILE POS CS SECT NAME\n");
++	verbose("=== ======== == ==== ==============================\n");
++
++	for (loop = 0; loop < canon; loop++) {
++		int sect = canonlist[loop];
++		const char *sh_name = secstrings + get32(&sections[sect].sh_name);
++		Elf64_Word  sh_type	= get32(&sections[sect].sh_type);
++		Elf64_Xword sh_size	= get64(&sections[sect].sh_size);
++		Elf64_Xword sh_flags	= get64(&sections[sect].sh_flags);
++		Elf64_Word  sh_info	= get32(&sections[sect].sh_info);
++		Elf64_Off   sh_offset	= get64(&sections[sect].sh_offset);
++		void *data = buffer + sh_offset;
++
++		csum = 0;
++
++		/* include canonicalised relocation sections */
++		if (sh_type == SHT_REL || sh_type == SHT_RELA) {
++			Elf32_Word canon_sh_info;
++
++			if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
++				fprintf(stderr,
++					"Invalid ELF - REL/RELA sh_info does"
++					" not refer to a valid section\n");
++				exit(3);
++			}
++
++			verbose("%3u %08lx ", loop, ftell(outfd));
++
++			set32(&canon_sh_info, canonmap[sh_info]);
++
++			/* write out selected portions of the section header */
++			write_out(sh_name, strlen(sh_name));
++			write_out_val(sections[sect].sh_type);
++			write_out_val(sections[sect].sh_flags);
++			write_out_val(sections[sect].sh_size);
++			write_out_val(sections[sect].sh_addralign);
++			write_out_val(canon_sh_info);
++
++			if (sh_type == SHT_RELA)
++				extract_elf64_rela(buffer, sect, sh_info,
++						   data, sh_size / sizeof(Elf64_Rela),
++						   symbols, nsyms,
++						   sections, shnum, canonmap,
++						   strings, nstrings,
++						   sh_name);
++			else
++				extract_elf64_rel(buffer, sect, sh_info,
++						  data, sh_size / sizeof(Elf64_Rel),
++						  symbols, nsyms,
++						  sections, shnum, canonmap,
++						  strings, nstrings,
++						  sh_name);
++			continue;
++		}
++
++		/* include the headers of BSS sections */
++		if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
++			verbose("%3u %08lx ", loop, ftell(outfd));
++
++			/* write out selected portions of the section header */
++			write_out(sh_name, strlen(sh_name));
++			write_out_val(sections[sect].sh_type);
++			write_out_val(sections[sect].sh_flags);
++			write_out_val(sections[sect].sh_size);
++			write_out_val(sections[sect].sh_addralign);
++
++			verbose("%02x %4d %s\n", csum, sect, sh_name);
++		}
++
++		/* include allocatable loadable sections */
++		if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
++			goto include_section;
++
++		/* not this section */
++		continue;
++
++	include_section:
++		verbose("%3u %08lx ", loop, ftell(outfd));
++
++		/* write out selected portions of the section header */
++		write_out(sh_name, strlen(sh_name));
++		write_out_val(sections[sect].sh_type);
++		write_out_val(sections[sect].sh_flags);
++		write_out_val(sections[sect].sh_size);
++		write_out_val(sections[sect].sh_addralign);
++
++		/* write out the section data */
++		write_out(data, sh_size);
++
++		verbose("%02x %4d %s\n", csum, sect, sh_name);
++	}
++
++	verbose("%08lx         (%lu bytes csum 0x%02x)\n",
++		ftell(outfd), ftell(outfd), xcsum);
++}
++
++/*
++ * extract a RELA table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static void extract_elf32_rela(const void *buffer, int secix, int targetix,
++			       const Elf32_Rela *relatab, size_t nrels,
++			       const Elf32_Sym *symbols, size_t nsyms,
++			       const Elf32_Shdr *sections, size_t nsects,
++			       int *canonmap,
++			       const char *strings, size_t nstrings,
++			       const char *sh_name)
++{
++	struct {
++		uint32_t	r_offset;
++		uint32_t	r_addend;
++		uint32_t	st_value;
++		uint32_t	st_size;
++		uint16_t	st_shndx;
++		uint8_t		r_type;
++		uint8_t		st_info;
++		uint8_t		st_other;
++
++	} __attribute__((packed)) relocation;
++
++	const Elf32_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		Elf32_Section st_shndx;
++		Elf32_Word r_info;
++
++		/* decode the relocation */
++		r_info = get32(&relatab[loop].r_info);
++		relocation.r_offset = relatab[loop].r_offset;
++		relocation.r_addend = relatab[loop].r_addend;
++		relocation.r_type = ELF32_R_TYPE(r_info);
++
++		if (ELF32_R_SYM(r_info) >= nsyms) {
++			fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
++				ELF32_R_SYM(r_info), loop);
++			exit(1);
++		}
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &symbols[ELF32_R_SYM(r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = get16(&symbol->st_shndx);
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < nsects)
++			set16(&relocation.st_shndx, canonmap[st_shndx]);
++
++		write_out_val(relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = strings + get32(&symbol->st_name);
++			write_out(name, strlen(name) + 1);
++		}
++	}
++
++	verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
++}
++
++/*
++ * extract a REL table
++ * - need to canonicalise the entries in case section addition/removal has
++ *   rearranged the symbol table and the section table
++ */
++static void extract_elf32_rel(const void *buffer, int secix, int targetix,
++			      const Elf32_Rel *relatab, size_t nrels,
++			      const Elf32_Sym *symbols, size_t nsyms,
++			      const Elf32_Shdr *sections, size_t nsects,
++			      int *canonmap,
++			      const char *strings, size_t nstrings,
++			      const char *sh_name)
++{
++	struct {
++		uint32_t	r_offset;
++		uint32_t	st_value;
++		uint32_t	st_size;
++		uint16_t	st_shndx;
++		uint8_t		r_type;
++		uint8_t		st_info;
++		uint8_t		st_other;
++
++	} __attribute__((packed)) relocation;
++
++	const Elf32_Sym *symbol;
++	size_t loop;
++
++	/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++	for (loop = 0; loop < nrels; loop++) {
++		Elf32_Section st_shndx;
++		Elf32_Word r_info;
++
++		/* decode the relocation */
++		r_info = get32(&relatab[loop].r_info);
++		relocation.r_offset = relatab[loop].r_offset;
++		relocation.r_type = ELF32_R_TYPE(r_info);
++
++		if (ELF32_R_SYM(r_info) >= nsyms) {
++			fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
++				ELF32_R_SYM(r_info), loop);
++			exit(1);
++		}
++
++		/* decode the symbol referenced by the relocation */
++		symbol = &symbols[ELF32_R_SYM(r_info)];
++		relocation.st_info = symbol->st_info;
++		relocation.st_other = symbol->st_other;
++		relocation.st_value = symbol->st_value;
++		relocation.st_size = symbol->st_size;
++		relocation.st_shndx = symbol->st_shndx;
++		st_shndx = get16(&symbol->st_shndx);
++
++		/* canonicalise the section used by the symbol */
++		if (st_shndx > SHN_UNDEF && st_shndx < nsects)
++			set16(&relocation.st_shndx, canonmap[st_shndx]);
++
++		write_out_val(relocation);
++
++		/* undefined symbols must be named if referenced */
++		if (st_shndx == SHN_UNDEF) {
++			const char *name = strings + get32(&symbol->st_name);
++			write_out(name, strlen(name) + 1);
++		}
++	}
++
++	verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
++}
++
++/*
++ * extract the data from a 32-bit module
++ */
++static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
++{
++	const Elf32_Sym *symbols;
++	Elf32_Shdr *sections;
++	const char *secstrings, *strings;
++	size_t nsyms, nstrings;
++	int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
++
++	sections = buffer + get32(&hdr->e_shoff);
++	secstrings = buffer + get32(&sections[get16(&hdr->e_shstrndx)].sh_offset);
++	shnum = get16(&hdr->e_shnum);
++
++	/* find the symbol table and the string table and produce a list of
++	 * index numbers of sections that contribute to the kernel's module
++	 * image
++	 */
++	canonlist = calloc(sizeof(int), shnum * 2);
++	if (!canonlist) {
++		perror("calloc");
++		exit(1);
++	}
++	canonmap = canonlist + shnum;
++	canon = 0;
++
++	symbols = NULL;
++	strings = NULL;
++	nstrings = 0;
++	nsyms = 0;
++
++	for (loop = 1; loop < shnum; loop++) {
++		const char *sh_name = secstrings + get32(&sections[loop].sh_name);
++		Elf32_Word  sh_type	= get32(&sections[loop].sh_type);
++		Elf32_Xword sh_size	= get32(&sections[loop].sh_size);
++		Elf32_Xword sh_flags	= get32(&sections[loop].sh_flags);
++		Elf64_Word  sh_info	= get32(&sections[loop].sh_info);
++		Elf32_Off   sh_offset	= get32(&sections[loop].sh_offset);
++		void *data = buffer + sh_offset;
++
++		/* quick sanity check */
++		if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
++			fprintf(stderr, "Section goes beyond EOF\n");
++			exit(3);
++		}
++
++		/* we only need to canonicalise allocatable sections */
++		if (sh_flags & SHF_ALLOC)
++			canonlist[canon++] = loop;
++		else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
++			 get32(&sections[sh_info].sh_flags) & SHF_ALLOC)
++			canonlist[canon++] = loop;
++
++		/* keep track of certain special sections */
++		switch (sh_type) {
++		case SHT_SYMTAB:
++			if (strcmp(sh_name, ".symtab") == 0) {
++				symbols = data;
++				nsyms = sh_size / sizeof(Elf32_Sym);
++			}
++			break;
++
++		case SHT_STRTAB:
++			if (strcmp(sh_name, ".strtab") == 0) {
++				strings = data;
++				nstrings = sh_size;
++			}
++			break;
++
++		default:
++			break;
++		}
++	}
++
++	if (!symbols) {
++		fprintf(stderr, "Couldn't locate symbol table\n");
++		exit(3);
++	}
++
++	if (!strings) {
++		fprintf(stderr, "Couldn't locate strings table\n");
++		exit(3);
++	}
++
++	/* canonicalise the index numbers of the contributing section */
++	do {
++		changed = 0;
++
++		for (loop = 0; loop < canon - 1; loop++) {
++			const char *x = secstrings + get32(&sections[canonlist[loop + 0]].sh_name);
++			const char *y = secstrings + get32(&sections[canonlist[loop + 1]].sh_name);
++			if (strcmp(x, y) > 0) {
++				tmp = canonlist[loop + 0];
++				canonlist[loop + 0] = canonlist[loop + 1];
++				canonlist[loop + 1] = tmp;
++				changed = 1;
++			}
++		}
++
++	} while (changed);
++
++	for (loop = 0; loop < canon; loop++)
++		canonmap[canonlist[loop]] = loop + 1;
++
++	if (is_verbose > 1) {
++		printf("\nSection canonicalisation map:\n");
++		for (loop = 1; loop < shnum; loop++) {
++			const char *x = secstrings + get32(&sections[loop].sh_name);
++			printf("%4d %s\n", canonmap[loop], x);
++		}
++
++		printf("\nAllocated section list in canonical order:\n");
++		for (loop = 0; loop < canon; loop++) {
++			const char *x = secstrings + get32(&sections[canonlist[loop]].sh_name);
++			printf("%4d %s\n", canonlist[loop], x);
++		}
++	}
++
++	/* iterate through the section table looking for sections we want to
++	 * contribute to the signature */
++	verbose("\n");
++	verbose("CAN FILE POS CS SECT NAME\n");
++	verbose("=== ======== == ==== ==============================\n");
++
++	for (loop = 0; loop < canon; loop++) {
++		int sect = canonlist[loop];
++		const char *sh_name = secstrings + get32(&sections[sect].sh_name);
++		Elf32_Word  sh_type	= get32(&sections[sect].sh_type);
++		Elf32_Xword sh_size	= get32(&sections[sect].sh_size);
++		Elf32_Xword sh_flags	= get32(&sections[sect].sh_flags);
++		Elf32_Word  sh_info	= get32(&sections[sect].sh_info);
++		Elf32_Off   sh_offset	= get32(&sections[sect].sh_offset);
++		void *data = buffer + sh_offset;
++
++		csum = 0;
++
++		/* quick sanity check */
++		if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
++			fprintf(stderr, "section goes beyond EOF\n");
++			exit(3);
++		}
++
++		/* include canonicalised relocation sections */
++		if (sh_type == SHT_REL || sh_type == SHT_RELA) {
++			Elf32_Word canon_sh_info;
++
++			if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
++				fprintf(stderr,
++					"Invalid ELF - REL/RELA sh_info does"
++					" not refer to a valid section\n");
++				exit(3);
++			}
++
++			verbose("%3u %08lx ", loop, ftell(outfd));
++
++			set32(&canon_sh_info, canonmap[sh_info]);
++
++			/* write out selected portions of the section header */
++			write_out(sh_name, strlen(sh_name));
++			write_out_val(sections[sect].sh_type);
++			write_out_val(sections[sect].sh_flags);
++			write_out_val(sections[sect].sh_size);
++			write_out_val(sections[sect].sh_addralign);
++			write_out_val(canon_sh_info);
++
++			if (sh_type == SHT_RELA)
++				extract_elf32_rela(buffer, sect, sh_info,
++						   data, sh_size / sizeof(Elf32_Rela),
++						   symbols, nsyms,
++						   sections, shnum, canonmap,
++						   strings, nstrings,
++						   sh_name);
++			else
++				extract_elf32_rel(buffer, sect, sh_info,
++						  data, sh_size / sizeof(Elf32_Rel),
++						  symbols, nsyms,
++						  sections, shnum, canonmap,
++						  strings, nstrings,
++						  sh_name);
++			continue;
++		}
++
++		/* include the headers of BSS sections */
++		if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
++			verbose("%3u %08lx ", loop, ftell(outfd));
++
++			/* write out selected portions of the section header */
++			write_out(sh_name, strlen(sh_name));
++			write_out_val(sections[sect].sh_type);
++			write_out_val(sections[sect].sh_flags);
++			write_out_val(sections[sect].sh_size);
++			write_out_val(sections[sect].sh_addralign);
++
++			verbose("%02x %4d %s\n", csum, sect, sh_name);
++		}
++
++		/* include allocatable loadable sections */
++		if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
++			goto include_section;
++
++		/* not this section */
++		continue;
++
++	include_section:
++		verbose("%3u %08lx ", loop, ftell(outfd));
++
++		/* write out selected portions of the section header */
++		write_out(sh_name, strlen(sh_name));
++		write_out_val(sections[sect].sh_type);
++		write_out_val(sections[sect].sh_flags);
++		write_out_val(sections[sect].sh_size);
++		write_out_val(sections[sect].sh_addralign);
++
++		/* write out the section data */
++		write_out(data, sh_size);
++
++		verbose("%02x %4d %s\n", csum, sect, sh_name);
++	}
++
++	verbose("%08lx         (%lu bytes csum 0x%02x)\n",
++		ftell(outfd), ftell(outfd), xcsum);
++}
+diff --git a/scripts/mod/modsign-note.sh b/scripts/mod/modsign-note.sh
+new file mode 100644
+index 0000000..bca67c0
+--- /dev/null
++++ b/scripts/mod/modsign-note.sh
+@@ -0,0 +1,16 @@
++#!/bin/sh
++#
++# Generate a module signature note source file
++#
++# mod-sign.sh <sig-file> ><note-src-file>
++#
++
++SIG=$1
++
++cat <<EOF
++#include <linux/modsign.h>
++
++ELFNOTE(MODSIGN_NOTE_NAME, MODSIGN_NOTE_TYPE, .incbin "$SIG")
++EOF
++
++exit 0
+-- 
+1.7.9.1
+
+From 31e77b71e584a702c8e44b83f6af03bb8511cf8d Mon Sep 17 00:00:00 2001
+From: Josh Boyer <jwboyer at redhat.com>
+Date: Tue, 6 Mar 2012 12:56:49 -0500
+Subject: [PATCH] Make sure MPILIB is selected for stuff that uses it...
+
+security/built-in.o: In function `public_key_destroy':
+/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/public_key.c:41: undefined reference to `mpi_free'
+security/built-in.o: In function `RSA_verify_signature':
+/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:222: undefined reference to `mpi_get_nbits'
+/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:224: undefined reference to `mpi_get_nbits'
+
+security/built-in.o: In function `RSAVP1':
+/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:93: undefined reference to `mpi_cmp_ui'
+/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:97: undefined reference to `mpi_cmp'
+
+Signed-off-by: Josh Boyer <jwboyer at redhat.com>
+---
+ security/keys/Kconfig |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/security/keys/Kconfig b/security/keys/Kconfig
+index 5e77c2a..e40f9b68 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -89,12 +89,14 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+ 
+ config CRYPTO_KEY_PKEY_ALGO_RSA
+ 	tristate "RSA public-key algorithm"
++	select MPILIB_EXTRA
+ 	depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+ 	help
+ 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
+ 
+ config PGP_LIBRARY
+ 	tristate "PGP parsing library"
++	select MPILIB
+ 	help
+ 	  This option enables a library that provides a number of simple
+ 	  utility functions for parsing PGP (RFC 4880) packet-based messages.
+-- 
+1.7.9.1
+


More information about the scm-commits mailing list