summaryrefslogtreecommitdiffstats
path: root/modsign-20120510.patch
diff options
context:
space:
mode:
Diffstat (limited to 'modsign-20120510.patch')
-rw-r--r--modsign-20120510.patch8096
1 files changed, 8096 insertions, 0 deletions
diff --git a/modsign-20120510.patch b/modsign-20120510.patch
new file mode 100644
index 000000000..d9aabf83a
--- /dev/null
+++ b/modsign-20120510.patch
@@ -0,0 +1,8096 @@
+From d093caa39460495390c94556f0680218223168c2 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 15:55:49 +0100
+Subject: [PATCH 01/36] MPILIB: Export some more symbols
+
+Export some more symbols for use by the DSA key subtype.
+
+Signed-off-by: David Howells <dhowells@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(+)
+
+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 f68cbbb..fed3405 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 7328d0d..b8b22e5 100644
+--- a/lib/mpi/mpi-mpow.c
++++ b/lib/mpi/mpi-mpow.c
+@@ -132,3 +132,4 @@ nomem:
+ err_out:
+ 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.10.2
+
+
+From 335abcad2d9fa26198c8e99bae2bb9b3185dce22 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 15:55:50 +0100
+Subject: [PATCH 02/36] 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@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 ccc61f8..e9c6ac7 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.10.2
+
+
+From 6569015cb5801f36324c76dee156a3e880fcf9be Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 15:55:50 +0100
+Subject: [PATCH 03/36] 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@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 c73bba3..14b2c3d 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
+ *
+@@ -301,8 +298,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 06783cf..dc62894 100644
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -980,6 +980,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:
+@@ -1002,6 +1004,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.10.2
+
+
+From 13628af46a92a030fdb7dc33976b46cfcc4b3f31 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 15:55:51 +0100
+Subject: [PATCH 04/36] 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@redhat.com>
+---
+ security/keys/Makefile | 12 +++++++++---
+ 1 file 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.10.2
+
+
+From 8c5366bc5c1c9ecaa1104d769f60c7b83ed342a9 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:15:09 +0100
+Subject: [PATCH 05/36] 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@redhat.com>
+---
+ Documentation/security/keys-crypto.txt | 181 +++++++++++++++++++++++++
+ include/keys/crypto-subtype.h | 56 ++++++++
+ include/keys/crypto-type.h | 25 ++++
+ security/keys/Kconfig | 2 +
+ security/keys/Makefile | 1 +
+ security/keys/crypto/Kconfig | 7 +
+ security/keys/crypto/Makefile | 7 +
+ security/keys/crypto/crypto_keys.h | 28 ++++
+ security/keys/crypto/crypto_type.c | 228 ++++++++++++++++++++++++++++++++
+ 9 files changed, 535 insertions(+)
+ 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/Kconfig
+ create mode 100644 security/keys/crypto/Makefile
+ create mode 100644 security/keys/crypto/crypto_keys.h
+ create mode 100644 security/keys/crypto/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@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@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..992fe52 100644
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -69,3 +69,5 @@ config KEYS_DEBUG_PROC_KEYS
+ the resulting table.
+
+ If you are unsure as to whether this is required, answer N.
++
++source security/keys/crypto/Kconfig
+diff --git a/security/keys/Makefile b/security/keys/Makefile
+index 504aaa0..67dae73 100644
+--- a/security/keys/Makefile
++++ b/security/keys/Makefile
+@@ -24,3 +24,4 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
+ #
+ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
+ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
++obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto/
+diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
+new file mode 100644
+index 0000000..3d15710
+--- /dev/null
++++ b/security/keys/crypto/Kconfig
+@@ -0,0 +1,7 @@
++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/crypto/Makefile b/security/keys/crypto/Makefile
+new file mode 100644
+index 0000000..36db1d5
+--- /dev/null
++++ b/security/keys/crypto/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for cryptographic keys
++#
++
++obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
++
++crypto_keys-y := crypto_type.o
+diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h
+new file mode 100644
+index 0000000..a339ce0
+--- /dev/null
++++ b/security/keys/crypto/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@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/crypto_type.c b/security/keys/crypto/crypto_type.c
+new file mode 100644
+index 0000000..33d279b
+--- /dev/null
++++ b/security/keys/crypto/crypto_type.c
+@@ -0,0 +1,228 @@
++/* Cryptographic key type
++ *
++ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ *
++ * 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.10.2
+
+
+From e8d4b12988cd23815f1a5f4654d819f5a0a2194b Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:15:57 +0100
+Subject: [PATCH 06/36] 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@redhat.com>
+---
+ Documentation/security/keys-crypto.txt | 101 +++++++++++++++++++++++++++++
+ include/keys/crypto-subtype.h | 21 ++++++
+ include/keys/crypto-type.h | 9 +++
+ security/keys/crypto/Makefile | 2 +-
+ security/keys/crypto/crypto_verify.c | 111 ++++++++++++++++++++++++++++++++
+ 5 files changed, 243 insertions(+), 1 deletion(-)
+ create mode 100644 security/keys/crypto/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/crypto/Makefile b/security/keys/crypto/Makefile
+index 36db1d5..67001bc 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -4,4 +4,4 @@
+
+ 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/crypto_verify.c b/security/keys/crypto/crypto_verify.c
+new file mode 100644
+index 0000000..65f734c
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From db170ec4f4df7d8f188134c9c9a3e2736ec0dbff Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:16:46 +0100
+Subject: [PATCH 07/36] 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@redhat.com>
+---
+ security/keys/crypto/Kconfig | 10 ++++
+ security/keys/crypto/Makefile | 3 +-
+ security/keys/crypto/public_key.c | 55 +++++++++++++++++++
+ security/keys/crypto/public_key.h | 106 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 173 insertions(+), 1 deletion(-)
+ create mode 100644 security/keys/crypto/public_key.c
+ create mode 100644 security/keys/crypto/public_key.h
+
+diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
+index 3d15710..5f2b8ac 100644
+--- a/security/keys/crypto/Kconfig
++++ b/security/keys/crypto/Kconfig
+@@ -5,3 +5,13 @@ 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
++ select MPILIB
++ 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/crypto/Makefile b/security/keys/crypto/Makefile
+index 67001bc..6384306 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -3,5 +3,6 @@
+ #
+
+ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+-
+ crypto_keys-y := crypto_type.o crypto_verify.o
++
++obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
+diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c
+new file mode 100644
+index 0000000..c00ddac
+--- /dev/null
++++ b/security/keys/crypto/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@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/crypto/public_key.h b/security/keys/crypto/public_key.h
+new file mode 100644
+index 0000000..81ed603
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 07f1001d10c926d28b92f0a32dbb57131a0f0942 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:30:18 +0100
+Subject: [PATCH 08/36] 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@redhat.com>
+---
+ security/keys/crypto/Kconfig | 7 +
+ security/keys/crypto/Makefile | 1 +
+ security/keys/crypto/crypto_rsa.c | 282 +++++++++++++++++++++++++++++++++++++
+ security/keys/crypto/public_key.h | 2 +
+ 4 files changed, 292 insertions(+)
+ create mode 100644 security/keys/crypto/crypto_rsa.c
+
+diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
+index 5f2b8ac..4e3777e 100644
+--- a/security/keys/crypto/Kconfig
++++ b/security/keys/crypto/Kconfig
+@@ -15,3 +15,10 @@ 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
++ select MPILIB_EXTRA
++ help
++ This option enables support for the RSA algorithm (PKCS#1, RFC3447).
+diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
+index 6384306..b6b1a5a 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
+ crypto_keys-y := crypto_type.o crypto_verify.o
+
+ obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
++obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
+diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
+new file mode 100644
+index 0000000..beb5181
+--- /dev/null
++++ b/security/keys/crypto/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@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/crypto/public_key.h b/security/keys/crypto/public_key.h
+index 81ed603..7913615 100644
+--- a/security/keys/crypto/public_key.h
++++ b/security/keys/crypto/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.10.2
+
+
+From a1ac402f327ab537a629c4d365b3f5461eaecb82 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:30:20 +0100
+Subject: [PATCH 09/36] Fix signature verification for shorter signatures
+
+gpg can produce a signature file where length of signature is less than the
+modulus size because the amount of space an MPI takes up is kept as low as
+possible by discarding leading zeros. This regularly happens for several
+modules during the build.
+
+Fix it by relaxing check in RSA verification code.
+
+Thanks to Tomas Mraz and Miloslav Trmac for help.
+
+Signed-off-by: Milan Broz <mbroz@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/crypto_rsa.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
+index beb5181..cc5cd95 100644
+--- a/security/keys/crypto/crypto_rsa.c
++++ b/security/keys/crypto/crypto_rsa.c
+@@ -219,15 +219,23 @@ static int RSA_verify_signature(const struct public_key *key,
+ kenter("");
+
+ /* (1) Check the signature size against the public key modulus size */
+- k = (mpi_get_nbits(key->rsa.n) + 7) / 8;
++ k = mpi_get_nbits(key->rsa.n);
++ tsize = mpi_get_nbits(sig->rsa.s);
+
+- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8;
++ /* According to RFC 4880 sec 3.2, length of MPI is computed starting
++ * from most significant bit. So the RFC 3447 sec 8.2.2 size check
++ * must be relaxed to conform with shorter signatures - so we fail here
++ * only if signature length is longer than modulus size.
++ */
+ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
+- if (tsize != k) {
++ if (k < tsize) {
+ ret = -EBADMSG;
+ goto error;
+ }
+
++ /* Round up and convert to octets */
++ k = (k + 7) / 8;
++
+ /* (2b) Apply the RSAVP1 verification primitive to the public key */
+ ret = RSAVP1(key, sig->rsa.s, &m);
+ if (ret < 0)
+--
+1.7.10.2
+
+
+From d682ea629a2494aab705468d1479058a03fd7879 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:30:23 +0100
+Subject: [PATCH 10/36] 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@redhat.com>
+---
+ include/linux/pgp.h | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 206 insertions(+)
+ 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@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.10.2
+
+
+From 651d6e549374b13b2d0473db17df90ab66abf855 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:33:28 +0100
+Subject: [PATCH 11/36] 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@redhat.com>
+---
+ include/linux/pgp.h | 25 ++++
+ security/keys/crypto/Kconfig | 6 +
+ security/keys/crypto/Makefile | 1 +
+ security/keys/crypto/pgp_library.c | 254 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 286 insertions(+)
+ create mode 100644 security/keys/crypto/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/crypto/Kconfig b/security/keys/crypto/Kconfig
+index 4e3777e..88ce0e2 100644
+--- a/security/keys/crypto/Kconfig
++++ b/security/keys/crypto/Kconfig
+@@ -22,3 +22,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA
+ select MPILIB_EXTRA
+ 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/crypto/Makefile b/security/keys/crypto/Makefile
+index b6b1a5a..5fbe54e 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -7,3 +7,4 @@ crypto_keys-y := crypto_type.o crypto_verify.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
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+new file mode 100644
+index 0000000..685660f
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 1123a360effa696546dbce1273c680b45c5cf946 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:33:30 +0100
+Subject: [PATCH 12/36] 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@redhat.com>
+---
+ include/linux/pgp.h | 24 ++++
+ security/keys/crypto/pgp_library.c | 277 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 301 insertions(+)
+
+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/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index 685660f..f6b831f 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/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.10.2
+
+
+From 53f01a04d44b822af15cd31bb451ca13695bdf1c Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:36:35 +0100
+Subject: [PATCH 13/36] 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@redhat.com>
+---
+ security/keys/crypto/Kconfig | 12 ++
+ security/keys/crypto/Makefile | 4 +
+ security/keys/crypto/pgp_key_parser.c | 343 +++++++++++++++++++++++++++++++++
+ security/keys/crypto/pgp_parser.h | 23 +++
+ 4 files changed, 382 insertions(+)
+ create mode 100644 security/keys/crypto/pgp_key_parser.c
+ create mode 100644 security/keys/crypto/pgp_parser.h
+
+diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
+index 88ce0e2..1c2ae55 100644
+--- a/security/keys/crypto/Kconfig
++++ b/security/keys/crypto/Kconfig
+@@ -28,3 +28,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/crypto/Makefile b/security/keys/crypto/Makefile
+index 5fbe54e..3bb2e61 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.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
++pgp_parser-y := \
++ pgp_key_parser.o
+diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c
+new file mode 100644
+index 0000000..4efc4de
+--- /dev/null
++++ b/security/keys/crypto/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@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/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
+new file mode 100644
+index 0000000..1cda231
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 3e401cdc0ae1768ecbc301a631a2a34f56834313 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:40:17 +0100
+Subject: [PATCH 14/36] 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@redhat.com>
+---
+ security/keys/crypto/Makefile | 3 +-
+ security/keys/crypto/pgp_parser.h | 6 +
+ security/keys/crypto/pgp_pubkey_sig.c | 323 +++++++++++++++++++++++++++++++++
+ 3 files changed, 331 insertions(+), 1 deletion(-)
+ create mode 100644 security/keys/crypto/pgp_pubkey_sig.c
+
+diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
+index 3bb2e61..d4ac8ac 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -11,4 +11,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
+
+ obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o
+ pgp_parser-y := \
+- pgp_key_parser.o
++ pgp_key_parser.o \
++ pgp_pubkey_sig.o
+diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
+index 1cda231..a6192ce 100644
+--- a/security/keys/crypto/pgp_parser.h
++++ b/security/keys/crypto/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/crypto/pgp_pubkey_sig.c b/security/keys/crypto/pgp_pubkey_sig.c
+new file mode 100644
+index 0000000..b4b7cb0
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 55e67eca050ff43915912e50dda49ecafdc816aa Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:40:39 +0100
+Subject: [PATCH 15/36] 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@redhat.com>
+---
+ security/keys/crypto/Makefile | 1 +
+ security/keys/crypto/pgp_key_parser.c | 1 +
+ security/keys/crypto/pgp_parser.h | 6 ++
+ security/keys/crypto/pgp_sig_parser.c | 104 +++++++++++++++++++++++++++++++++
+ 4 files changed, 112 insertions(+)
+ create mode 100644 security/keys/crypto/pgp_sig_parser.c
+
+diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
+index d4ac8ac..fa7746d 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -12,4 +12,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
+ obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o
+ pgp_parser-y := \
+ pgp_key_parser.o \
++ pgp_sig_parser.o \
+ pgp_pubkey_sig.o
+diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c
+index 4efc4de..1407e2e 100644
+--- a/security/keys/crypto/pgp_key_parser.c
++++ b/security/keys/crypto/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/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
+index a6192ce..73c900e 100644
+--- a/security/keys/crypto/pgp_parser.h
++++ b/security/keys/crypto/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/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c
+new file mode 100644
+index 0000000..b72c505
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 0760cf6519e184298944df0d9f6fe5a097fb16ff Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 4 May 2012 16:41:12 +0100
+Subject: [PATCH 16/36] 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@redhat.com>
+---
+ Documentation/security/keys-crypto.txt | 20 +++++++
+ include/keys/crypto-type.h | 3 ++
+ security/keys/crypto/Kconfig | 9 ++++
+ security/keys/crypto/Makefile | 1 +
+ security/keys/crypto/pgp_preload.c | 90 ++++++++++++++++++++++++++++++++
+ 5 files changed, 123 insertions(+)
+ create mode 100644 security/keys/crypto/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/crypto/Kconfig b/security/keys/crypto/Kconfig
+index 1c2ae55..8af0155 100644
+--- a/security/keys/crypto/Kconfig
++++ b/security/keys/crypto/Kconfig
+@@ -40,3 +40,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/crypto/Makefile b/security/keys/crypto/Makefile
+index fa7746d..4162ecb 100644
+--- a/security/keys/crypto/Makefile
++++ b/security/keys/crypto/Makefile
+@@ -8,6 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.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
+ pgp_parser-y := \
+diff --git a/security/keys/crypto/pgp_preload.c b/security/keys/crypto/pgp_preload.c
+new file mode 100644
+index 0000000..25154e3
+--- /dev/null
++++ b/security/keys/crypto/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@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.10.2
+
+
+From 8f7d6b082b6b7357e44f9345c8c040f53aa60a7f Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:46:56 +0100
+Subject: [PATCH 17/36] Provide macros for forming the name of an ELF note and
+ its section
+
+Provide macros for stringifying the name of an ELF note and its section
+appropriately so that the macro can be used in both C and assembly.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ include/linux/elfnote.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+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 */
+--
+1.7.10.2
+
+
+From b37a512b3d6593d541e05550316bd407515c1ec2 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:44 +0100
+Subject: [PATCH 18/36] Guard check in module loader against integer overflow
+
+The check:
+
+ if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr))
+
+may not work if there's an overflow in the right-hand side of the condition.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/module.c b/kernel/module.c
+index 78ac6ec..377cb06 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -2429,7 +2429,8 @@ static int copy_and_check(struct load_info *info,
+ goto free_hdr;
+ }
+
+- if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
++ if (hdr->e_shoff >= len ||
++ hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) {
+ err = -ENOEXEC;
+ goto free_hdr;
+ }
+--
+1.7.10.2
+
+
+From a7f2ec2a77490ed84bf8020cd5b41d7c7ea3f3cb Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:52 +0100
+Subject: [PATCH 19/36] 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@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 +++
+ arch/x86/include/asm/module.h | 6 ++++++
+ include/asm-generic/module.h | 10 ++++++++++
+ 13 files changed, 80 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 7467d1d..4404cca 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\",@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\",@nobits; .align 3; .previous");
+ asm(".section .init.plt,\"ax\",@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/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
+index 9eae775..724f173 100644
+--- a/arch/x86/include/asm/module.h
++++ b/arch/x86/include/asm/module.h
+@@ -63,4 +63,10 @@
+ # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
+ #endif
+
++#ifdef CONFIG_X86_32
++#define MODULE_HAS_ELF_REL_ONLY
++#else
++#define MODULE_HAS_ELF_RELA_ONLY
++#endif
++
+ #endif /* _ASM_X86_MODULE_H */
+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.10.2
+
+
+From b31d1ea8afb0b63e872a1bed3a3c88d7696bf2e7 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:53 +0100
+Subject: [PATCH 20/36] MODSIGN: Provide gitignore and make clean rules for
+ extra files
+
+Provide gitignore and make clean rules for extra files to hide and clean up the
+extra files produced by module signing stuff once it is added. Also add a
+clean up rule for the module content extractor program used to extract the data
+to be signed.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ .gitignore | 12 ++++++++++++
+ Makefile | 1 +
+ scripts/mod/.gitignore | 1 +
+ 3 files changed, 14 insertions(+)
+
+diff --git a/.gitignore b/.gitignore
+index 57af07c..7948eeb 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,12 @@ GTAGS
+ *.orig
+ *~
+ \#*#
++
++#
++# GPG leavings from module signing
++#
++genkey
++modsign.pub
++modsign.sec
++random_seed
++trustdb.gpg
+diff --git a/Makefile b/Makefile
+index a06ee9f..1df8b14 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/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
+
+--
+1.7.10.2
+
+
+From dce3a6eca8dda09a28cb2f45b87e70e1c2d52139 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:53 +0100
+Subject: [PATCH 21/36] MODSIGN: Provide Documentation and Kconfig options
+
+Provide documentation and kernel configuration options for module signing.
+
+The documentation can be found in:
+
+ Documentation/module-signing.txt
+
+The following configuration options are added:
+
+ (1) CONFIG_MODULE_SIG
+
+ Enable module signing. This will both cause the build process to sign
+ modules and the kernel to check modules when they're loaded.
+
+ (2) CONFIG_MODULE_SIG_SHA1
+ CONFIG_MODULE_SIG_SHA224
+ CONFIG_MODULE_SIG_SHA256
+ CONFIG_MODULE_SIG_SHA384
+ CONFIG_MODULE_SIG_SHA512
+
+ Select the cryptographic hash used to digest the data prior to signing.
+ Additionally, the crypto module selected will be built into the kernel as
+ it won't be possible to load it as a module without incurring a circular
+ dependency when the kernel tries to check its signature.
+
+ (3) CONFIG_MODULE_SIG_FORCE
+
+ Require that any module loaded must be signed with a key compiled into
+ the kernel. All other modules are rejected with EKEYREJECTED.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ Documentation/module-signing.txt | 194 ++++++++++++++++++++++++++++++++++++++
+ include/linux/modsign.h | 27 ++++++
+ init/Kconfig | 53 +++++++++++
+ 3 files changed, 274 insertions(+)
+ create mode 100644 Documentation/module-signing.txt
+ create mode 100644 include/linux/modsign.h
+
+diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
+new file mode 100644
+index 0000000..d75d473
+--- /dev/null
++++ b/Documentation/module-signing.txt
+@@ -0,0 +1,194 @@
++ ==============================
++ 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 modsign.pub.
++
++For example, a throwaway key could be generated automatically by something like
++the following:
++
++ cat >genkey <<EOF
++ %pubring modsign.pub
++ %secring modsign.sec
++ Key-Type: RSA
++ Key-Length: 4096
++ 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 using the rngd program if there's a
++hardware random number generator available.
++
++Note that no GPG password is used in the above scriptlet.
++
++The modsign.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 "./modsign.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 "./modsign.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 with any of the following:
++
++ strip -x
++ strip -g
++ eu-strip
++
++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.
++
++Note that "strip" and "strip -s" may not be used on a module, signed or
++otherwise, as they remove the symbol table and render the relocation tables
++unusable.
++
++
++======================
++LOADING SIGNED MODULES
++======================
++
++Modules are loaded with insmod, exactly as for unsigned modules. The signature
++is inserted into the module object file during the build process as an ELF note
++called "module.sig" in an ELF section called ".note.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/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@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/init/Kconfig b/init/Kconfig
+index 6cfd71d..7cda3e6 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1409,6 +1409,59 @@ 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_SIG
++ bool "Module signature verification"
++ depends on MODULES
++ select CRYPTO_KEY_TYPE
++ select CRYPTO_KEY_PKEY_ALGO_DSA
++ select CRYPTO_KEY_PKEY_ALGO_RSA
++ select PGP_PARSER
++ select PGP_PRELOAD
++ 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.
++
+ endif # MODULES
+
+ config INIT_ALL_POSSIBLE
+--
+1.7.10.2
+
+
+From f9980a27c5d2d02af2feb578957145a206088fff Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:54 +0100
+Subject: [PATCH 22/36] MODSIGN: Sign modules during the build process
+
+If CONFIG_MODULE_SIG is set, then this patch will cause the module to get a
+signature installed. The following steps will occur:
+
+ (1) The module will be linked to foo.ko.unsigned instead of foo.ko
+
+ (2) The module's signable content will be extracted to foo.ko.digest by the
+ mod-extract program.
+
+ (3) The signature will be generated on foo.ko.digest by gpg and placed in
+ foo.ko.digest.sig
+
+ (4) The signature will be encapsulated into an ELF note and placed into a file
+ called foo.ko.note.o using the output from modsign-note.sh piped into the
+ assembler.
+
+ (5) The unsigned module from (1) and the signature ELF note from (4) will be
+ linked together to produce foo.ko
+
+Step (3) requires private and public keys to be available. By default these
+are expected to be found in PGP keyring files called modsign.sec (the secret
+key) and modsign.pub (the public key) in the build root.
+
+If the secret key is not found then signing will be skipped and the unsigned
+module from (1) will just be copied to foo.ko.
+
+If signing occurs, lines like the following will be seen:
+
+ LD [M] fs/foo/foo.ko.unsigned
+ SIGN [M] fs/foo/foo.ko
+
+will appear in the build log. If it is skipped, the following will be seen:
+
+ LD [M] fs/foo/foo.ko.unsigned
+ NO SIGN [M] fs/foo/foo.ko
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ scripts/Makefile.modpost | 87 ++++-
+ scripts/mod/Makefile | 2 +-
+ scripts/mod/mod-extract.c | 913 +++++++++++++++++++++++++++++++++++++++++++
+ scripts/mod/modsign-note.sh | 16 +
+ 4 files changed, 1016 insertions(+), 2 deletions(-)
+ create mode 100644 scripts/mod/mod-extract.c
+ create mode 100644 scripts/mod/modsign-note.sh
+
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index 08dce14..17465d8 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,88 @@ $(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 = ./modsign.sec
++MODPUBKEY = ./modsign.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)
++KEYRING_DEP := modsign.sec modsign.pub
++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
++KEYRING_DEP :=
++quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
++ cmd_sign_ko_ko_unsigned = \
++ cp $< $@
++endif
++
++$(modules): %.ko :%.ko.unsigned $(KEYRING_DEP) 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/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@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.10.2
+
+
+From 38ddca03060502e8134320b732758fd6b6a98247 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:55 +0100
+Subject: [PATCH 23/36] MODSIGN: Module signature verification stub
+
+Create a stub for the module signature verifier and link it into module.c so
+that it gets called. A field is added to struct module to record whether or
+not a valid module signature was detected.
+
+The stub also implements the policy for handling unsigned modules and the
+printing of error messages to indicate various problems with the module.
+
+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.
+
+This table indicates the behaviours in 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
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ include/linux/module.h | 3 ++
+ kernel/Makefile | 1 +
+ kernel/module-verify-defs.h | 77 ++++++++++++++++++++++++++++++
+ kernel/module-verify.c | 109 +++++++++++++++++++++++++++++++++++++++++++
+ kernel/module-verify.h | 19 ++++++++
+ kernel/module.c | 26 +++++++++--
+ 6 files changed, 230 insertions(+), 5 deletions(-)
+ create mode 100644 kernel/module-verify-defs.h
+ create mode 100644 kernel/module-verify.c
+ create mode 100644 kernel/module-verify.h
+
+diff --git a/include/linux/module.h b/include/linux/module.h
+index fbcafe2..7391833 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -227,6 +227,9 @@ struct module
+ /* Unique handle for this module */
+ char name[MODULE_NAME_LEN];
+
++ /* Is this module GPG signed */
++ bool gpgsig_ok;
++
+ /* Sysfs stuff. */
+ struct module_kobject mkobj;
+ struct module_attribute *modinfo_attrs;
+diff --git a/kernel/Makefile b/kernel/Makefile
+index cb41b95..7608053 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -51,6 +51,7 @@ 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_SIG) += module-verify.o
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+ obj-$(CONFIG_KEXEC) += kexec.o
+diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h
+new file mode 100644
+index 0000000..292d2ba
+--- /dev/null
++++ b/kernel/module-verify-defs.h
+@@ -0,0 +1,77 @@
++/* Module verification internal definitions
++ *
++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++#ifdef CONFIG_MODULE_SIG
++
++/*
++ * Internal state
++ */
++struct module_verify_data {
++ struct crypto_key_verify_context *mod_sig; /* Module signing context */
++ union {
++ const void *buffer; /* module buffer */
++ const Elf_Ehdr *hdr; /* ELF header */
++ };
++ const Elf_Shdr *sections; /* ELF section table */
++ const char *secstrings; /* ELF section string table */
++ const void *sig; /* Signature note content */
++ size_t size; /* module object size */
++ size_t nsects; /* number of sections */
++ size_t sig_size; /* Size of signature */
++ size_t signed_size; /* count of bytes contributed to digest */
++ unsigned *canonlist; /* list of canonicalised sections */
++ unsigned *canonmap; /* section canonicalisation map */
++ unsigned ncanon; /* number of canonicalised sections */
++ unsigned sig_index; /* module signature section index */
++ uint8_t xcsum; /* checksum of bytes contributed to digest */
++ uint8_t csum; /* checksum of bytes representing a section */
++};
++
++/*
++ * Whether or not we support various types of ELF relocation record
++ */
++#if defined(MODULE_HAS_ELF_REL_ONLY)
++#define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
++#define is_elf_rela(sh_type) (0)
++#elif defined(MODULE_HAS_ELF_RELA_ONLY)
++#define is_elf_rel(sh_type) (0)
++#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
++#else
++#define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
++#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
++#endif
++
++/*
++ * Debugging. Define DEBUG to enable.
++ */
++#define _debug(FMT, ...) \
++ do { \
++ if (unlikely(modsign_debug)) \
++ pr_debug(FMT, ##__VA_ARGS__); \
++ } while(0)
++
++#ifdef 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 { \
++} while (0)
++#endif
++
++#endif /* CONFIG_MODULE_SIG */
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+new file mode 100644
+index 0000000..0a3eb4b
+--- /dev/null
++++ b/kernel/module-verify.c
+@@ -0,0 +1,109 @@
++/* Module signature verification
++ *
++ * The code in this file examines a signed kernel module and attempts to
++ * determine if the PGP signature inside the module matches a digest of the
++ * allocatable sections and the canonicalised relocation tables for those
++ * allocatable sections.
++ *
++ * The module signature is included in an ELF note within the ELF structure of
++ * the module blob. This, combined with the minimal canonicalisation performed
++ * here, permits the module to pass through "strip -x", "strip -g" and
++ * "eu-strip" without becoming corrupt. "strip" and "strip -s" will render a
++ * module unusable by removing the symbol table.
++ *
++ * Copyright (C) 2004, 2011, 2012 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@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.
++ */
++
++#undef DEBUG
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/elf.h>
++#include <linux/elfnote.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <linux/modsign.h>
++#include <linux/moduleparam.h>
++#include <keys/crypto-type.h>
++#include "module-verify.h"
++#include "module-verify-defs.h"
++
++#ifdef DEBUG
++static int modsign_debug;
++core_param(modsign_debug, modsign_debug, int, 0644);
++#else
++#define modsign_debug false
++#endif
++
++#ifdef CONFIG_MODULE_SIG_FORCE
++#define modsign_signedonly true
++#else
++static bool modsign_signedonly;
++#endif
++
++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 integrity
++ */
++int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
++{
++ struct module_verify_data mvdata;
++ int ret;
++
++ memset(&mvdata, 0, sizeof(mvdata));
++ mvdata.buffer = hdr;
++ mvdata.size = size;
++
++ if (mvdata.sig_index <= 0) {
++ /* Deal with an unsigned module */
++ if (modsign_signedonly) {
++ pr_err("An attempt to load unsigned module was rejected\n");
++ return -EKEYREJECTED;
++ } else {
++ return 0;
++ }
++ goto out;
++ }
++
++ ret = 0;
++
++out:
++ switch (ret) {
++ case 0: /* Good signature */
++ *_gpgsig_ok = true;
++ break;
++ case -ELIBBAD:
++ pr_err("Module format error encountered\n");
++ break;
++ case -EBADMSG:
++ pr_err("Module signature error encountered\n");
++ 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;
++}
++
++static int __init sign_setup(char *str)
++{
++#ifndef CONFIG_MODULE_SIG_FORCE
++ modsign_signedonly = true;
++#endif
++ return 0;
++}
++__setup("enforcemodulesig", sign_setup);
+diff --git a/kernel/module-verify.h b/kernel/module-verify.h
+new file mode 100644
+index 0000000..6bb6b56
+--- /dev/null
++++ b/kernel/module-verify.h
+@@ -0,0 +1,19 @@
++/* Module verification definitions
++ *
++ * Copyright (C) 2004, 2012 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++
++#ifdef CONFIG_MODULE_SIG
++extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok);
++#else
++static inline int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
++{
++ return 0;
++}
++#endif
+diff --git a/kernel/module.c b/kernel/module.c
+index 377cb06..c3797f7 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>
+@@ -2402,7 +2403,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,
++ bool *_gpgsig_ok)
+ {
+ int err;
+ Elf_Ehdr *hdr;
+@@ -2435,6 +2437,12 @@ static int copy_and_check(struct load_info *info,
+ goto free_hdr;
+ }
+
++ /* Verify the module's contents */
++ *_gpgsig_ok = false;
++ err = module_verify(hdr, len, _gpgsig_ok);
++ if (err < 0)
++ goto free_hdr;
++
+ info->hdr = hdr;
+ info->len = len;
+ return 0;
+@@ -2777,7 +2785,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,
++ bool gpgsig_ok)
+ {
+ /* Module within temporary copy. */
+ struct module *mod;
+@@ -2787,6 +2796,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)
+@@ -2870,17 +2880,18 @@ static struct module *load_module(void __user *umod,
+ struct load_info info = { NULL, };
+ struct module *mod;
+ long err;
++ bool 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;
+@@ -3517,8 +3528,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);
+--
+1.7.10.2
+
+
+From 6f5323e52cdc37969939ef82036783da67afe69f Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:55 +0100
+Subject: [PATCH 24/36] MODSIGN: Provide module signing public keys to the
+ kernel
+
+Include a PGP keyring containing the public keys required to perform module
+verification in the kernel image during build and create a special keyring
+during boot which is then populated with keys of crypto type holding the public
+keys found in the PGP keyring.
+
+These can be seen by root:
+
+[root@andromeda ~]# cat /proc/keys
+07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd []
+15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4
+...
+
+It is probably worth permitting root to invalidate these keys, resulting in
+their removal and preventing further modules from being loaded with that key.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/Makefile | 3 +-
+ kernel/modsign-pubkey.c | 74 +++++++++++++++++++++++++++++++++++++++++++
+ kernel/module-verify-defs.h | 4 +++
+ kernel/module-verify.c | 2 --
+ 4 files changed, 80 insertions(+), 3 deletions(-)
+ create mode 100644 kernel/modsign-pubkey.c
+
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 7608053..986ed7f 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -51,7 +51,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_SIG) += module-verify.o
++obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o
++kernel/modsign-pubkey.o: modsign.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..2ada460
+--- /dev/null
++++ b/kernel/modsign-pubkey.c
+@@ -0,0 +1,74 @@
++/* Public keys for module signature verification
++ *
++ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <keys/crypto-type.h>
++#include "module-verify-defs.h"
++
++struct key *modsign_keyring;
++
++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 \"modsign.pub\"\n"
++ "modsign_public_keys_end:"
++ );
++
++/*
++ * We need to make sure ccache doesn't cache the .o file as it doesn't notice
++ * if modsign.pub changes.
++ */
++static __initdata const char annoy_ccache[] = __TIME__ "foo";
++
++/*
++ * Load the compiled-in keys
++ */
++static __init int module_verify_init(void)
++{
++ pr_notice("Initialise module verification\n");
++
++ modsign_keyring = 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);
++
++/*
++ * 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-defs.h b/kernel/module-verify-defs.h
+index 292d2ba..45bea45 100644
+--- a/kernel/module-verify-defs.h
++++ b/kernel/module-verify-defs.h
+@@ -11,6 +11,10 @@
+
+ #ifdef CONFIG_MODULE_SIG
+
++#include <linux/module.h>
++
++extern struct key *modsign_keyring;
++
+ /*
+ * Internal state
+ */
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index 0a3eb4b..b1c1d4c 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -27,8 +27,6 @@
+ #include <linux/slab.h>
+ #include <linux/elf.h>
+ #include <linux/elfnote.h>
+-#include <linux/sched.h>
+-#include <linux/cred.h>
+ #include <linux/modsign.h>
+ #include <linux/moduleparam.h>
+ #include <keys/crypto-type.h>
+--
+1.7.10.2
+
+
+From 5727333d123ef9d7fa2666069306bf3ec2d7f110 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:56 +0100
+Subject: [PATCH 25/36] MODSIGN: Check the ELF container
+
+Check the ELF container of the kernel module to prevent the kernel from
+crashing or getting corrupted whilst trying to use it and locate the module
+signature note if present.
+
+We try to check as little as possible. We check the metadata that the
+signature checker actually has to use, and leave anything that it doesn't
+actually need to the signature to catch.
+
+The stuff we need to check is:
+
+ (1) The locations and offsets in the ELF header of important parts like the
+ section table.
+
+ (2) The section table. Note that we only check sh_info for section types that
+ we're actually interested in (string, symbol and relocation tables). We
+ also check that alignments are what we expect for those tables.
+
+ (3) That non-empty string tables have the required NUL at the end so that we
+ can be sure that all strings therein are NUL-terminated. We don't bother
+ checking for the required NUL at the beginning as it shouldn't cause a
+ problem to us.
+
+ (4) The name offset and section index in each symbol. We could defer this to
+ when we deal with the relocation tables so that we only check symbols that
+ are used by relocations - but we would then end up checking some symbols
+ multiple times.
+
+ (5) The module signature note section and the first note in it if present.
+
+ (6) That relocations applied to an allocatable section only refer to
+ symbols in allocatable sections and absolute symbols (done in the module
+ signing code rather than here).
+
+Note that these checks survive "strip -x", "strip -g" and "eu-strip" being
+applied to a module and detect if the module was given to "strip" or "strip -s"
+and report an error.
+
+We can skip some direct checks that turn out unnecessary or redundant:
+
+ (1) That sh_link has a greater than 0 value for symbol tables and relocation
+ tables. These require the index of a string table and a symbol table
+ respectively - and since we have already checked section 0 is of SHT_NULL
+ type, checking the symbol type renders the sh_link > 0 check redundant.
+
+ (2) That a non-empty string table begins with a NUL. Since we check the
+ string table ends with a NUL, any string in there will be NUL-terminated
+ and shouldn't cause us to transgress beyond the bounds of the string table
+ when using strlen().
+
+ (3) That strings in a string table actually make sense. We don't care, so
+ long as it is NUL terminated. Any string that refers to an undefined
+ symbol is added to the crypto digest and will be checked that way.
+ Strings that we directly look for (such as ".modinfo") will be validated
+ by that.
+
+ (4) That sections don't overlap. We don't actually care if sections overlap
+ in the file, provided we don't see bad metadata. If the sections holding
+ the allocatable content overlap, then the signature check is likely to
+ fail.
+
+ (5) That symbol values and relocation offsets and addends make sense. We just
+ add this data to the digest if it pertains to an allocatable section.
+
+ (6) That allocatable note sections, other than the signature note, make sense.
+ The contents of these get added to the digest in their entirety, so we
+ don't need to check them manually.
+
+If bad ELF is detected, ELIBBAD is indicated.
+
+Note! The "noinline" attribute on the module_verify_elf() function results in
+somewhat smaller code. Similarly, having separate loops to check basic section
+parameters and to check type-specific features of sections results in smaller
+code, presumably because some local variables can be discarded.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module-verify.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 226 insertions(+)
+
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index b1c1d4c..5711aeb 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -50,6 +50,224 @@ static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
+ static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
+
+ /*
++ * Verify the minimum amount of ELF structure of a module needed to check the
++ * module's signature without bad ELF crashing the kernel.
++ */
++static noinline int module_verify_elf(struct module_verify_data *mvdata)
++{
++ const struct elf_note *note;
++ const Elf_Ehdr *hdr = mvdata->hdr;
++ const Elf_Shdr *section, *secstop;
++ const Elf_Sym *symbols, *symbol, *symstop;
++ const char *strtab;
++ size_t size, secsize, secstrsize, strsize, notesize, notemetasize;
++ unsigned line;
++
++ size = mvdata->size;
++
++#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)
++
++ /* Validate the ELF header */
++ elfcheck(size > sizeof(Elf_Ehdr));
++ elfcheck(hdr->e_ehsize < size);
++
++ elfcheck(hdr->e_shnum < SHN_LORESERVE);
++ elfcheck(hdr->e_shstrndx < hdr->e_shnum);
++ elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
++ elfcheck(hdr->e_shoff < size);
++ elfcheck(hdr->e_shoff >= hdr->e_ehsize);
++ elfcheck(hdr->e_shoff % sizeof(long) == 0);
++ elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff);
++
++ /* Validate the section table contents */
++ mvdata->nsects = hdr->e_shnum;
++ mvdata->sections = mvdata->buffer + hdr->e_shoff;
++ secstop = mvdata->sections + mvdata->nsects;
++
++ /* Section 0 is special, usually indicating an undefined symbol */
++ seccheck(mvdata->sections[SHN_UNDEF].sh_type == SHT_NULL);
++
++ /* We also want access to the section name table */
++ seccheck(mvdata->sections[hdr->e_shstrndx].sh_type == SHT_STRTAB);
++ secstrsize = mvdata->sections[hdr->e_shstrndx].sh_size;
++
++ for (section = mvdata->sections + 1; section < secstop; section++) {
++ seccheck(section->sh_name < secstrsize);
++ seccheck(section->sh_link < hdr->e_shnum);
++
++ /* Section file offsets must reside within the file, though
++ * they don't have to actually consume file space (.bss for
++ * example).
++ */
++ seccheck(section->sh_offset >= hdr->e_ehsize);
++ seccheck((section->sh_offset & (section->sh_addralign - 1)) == 0);
++ seccheck(section->sh_offset <= size);
++ if (section->sh_type != SHT_NOBITS)
++ seccheck(section->sh_size <= size - section->sh_offset);
++
++ /* Some types of section should contain arrays of fixed-length
++ * records of a predetermined size and mustn't contain partial
++ * records. Also, records we're going to access directly must
++ * have appropriate alignment that we don't get a misalignment
++ * exception.
++ */
++ if (section->sh_entsize > 1)
++ seccheck(section->sh_size % section->sh_entsize == 0);
++
++ switch (section->sh_type) {
++ case SHT_SYMTAB:
++ seccheck(section->sh_entsize == sizeof(Elf_Sym));
++ seccheck(section->sh_addralign % sizeof(long) == 0);
++ break;
++ case SHT_REL:
++#ifndef MODULE_HAS_ELF_RELA_ONLY
++ seccheck(section->sh_entsize == sizeof(Elf_Rel));
++ seccheck(section->sh_addralign % sizeof(long) == 0);
++ break;
++#else
++ seccheck(false);
++ break;
++#endif
++ case SHT_RELA:
++#ifndef MODULE_HAS_ELF_REL_ONLY
++ seccheck(section->sh_entsize == sizeof(Elf_Rela));
++ seccheck(section->sh_addralign % sizeof(long) == 0);
++ break;
++#else
++ seccheck(false);
++ break;
++#endif
++ case SHT_NOTE:
++ seccheck(section->sh_addralign % 4 == 0);
++ break;
++ case SHT_STRTAB:
++ /* We require all string tables to be non-empty. If
++ * not empty, a string table must end in a NUL (it
++ * should also begin with a NUL, but it's not a problem
++ * for us if it doesn't).
++ */
++ seccheck(section->sh_size >= 2);
++ strtab = mvdata->buffer + section->sh_offset;
++ seccheck(strtab[section->sh_size - 1] == '\0');
++ break;
++ }
++ }
++
++ /* Check features specific to the type of each section.
++ *
++ * Note that having a separate loop here allows the compiler to discard
++ * some local variables used in the above loop thus making the code
++ * smaller.
++ */
++ for (section = mvdata->sections + 1; section < secstop; section++) {
++ switch (section->sh_type) {
++ case SHT_SYMTAB:
++ /* Symbol tables nominate a string table. */
++ seccheck(mvdata->sections[section->sh_link].sh_type ==
++ SHT_STRTAB);
++
++ /* Validate the symbols in the table. The first symbol
++ * (STN_UNDEF) is special.
++ */
++ symbol = symbols = mvdata->buffer + section->sh_offset;
++ symstop = mvdata->buffer +
++ (section->sh_offset + section->sh_size);
++
++ symcheck(ELF_ST_TYPE(symbols[0].st_info) == STT_NOTYPE);
++ symcheck(symbol[0].st_shndx == SHN_UNDEF);
++
++ strsize = mvdata->sections[section->sh_link].sh_size;
++ for (symbol++; symbol < symstop; symbol++) {
++ symcheck(symbol->st_name < strsize);
++ symcheck(symbol->st_shndx < hdr->e_shnum ||
++ symbol->st_shndx >= SHN_LORESERVE);
++ }
++ break;
++
++#ifndef MODULE_HAS_ELF_RELA_ONLY
++ case SHT_REL:
++#endif
++#ifndef MODULE_HAS_ELF_REL_ONLY
++ case SHT_RELA:
++#endif
++ /* Relocation tables nominate a symbol table and a
++ * target section to which the relocations will be
++ * applied.
++ */
++ seccheck(mvdata->sections[section->sh_link].sh_type ==
++ SHT_SYMTAB);
++ seccheck(section->sh_info > 0);
++ seccheck(section->sh_info < hdr->e_shnum);
++ break;
++ }
++ }
++
++ /* We can now use section name string table section as we checked its
++ * bounds in the loop above.
++ *
++ * Each name is NUL-terminated, and the table as a whole should have a
++ * NUL at either end as there to be at least one named section for the
++ * module information.
++ */
++ section = &mvdata->sections[hdr->e_shstrndx];
++ mvdata->secstrings = mvdata->buffer + section->sh_offset;
++
++ for (section = mvdata->sections + 1; section < secstop; section++) {
++ const char *name = mvdata->secstrings + section->sh_name;
++
++ switch (section->sh_type) {
++ case SHT_NOTE:
++ if (strcmp(name, modsign_note_section) != 0)
++ continue;
++
++ /* We've found a note purporting to contain a signature
++ * so we should check the structure of that.
++ */
++ notemetasize = sizeof(struct elf_note) +
++ roundup(sizeof(modsign_note_name), 4);
++
++ seccheck(mvdata->sig_index == 0);
++ seccheck(section->sh_size > notemetasize);
++ note = mvdata->buffer + section->sh_offset;
++ seccheck(note->n_type == MODSIGN_NOTE_TYPE);
++ seccheck(note->n_namesz == sizeof(modsign_note_name));
++
++ notesize = section->sh_size - notemetasize;
++ seccheck(note->n_descsz <= notesize);
++
++ seccheck(memcmp(note + 1, modsign_note_name,
++ note->n_namesz) == 0);
++
++ mvdata->sig_size = note->n_descsz;
++ mvdata->sig = (void *)note + notemetasize;
++ mvdata->sig_index = section - mvdata->sections;
++ break;
++ }
++ }
++
++ return 0;
++
++elfcheck_error:
++ _debug("Verify ELF error (check %u)\n", line);
++ return -ELIBBAD;
++seccheck_error:
++ _debug("Verify ELF error [sec %ld] (check %u)\n",
++ (long)(section - mvdata->sections), line);
++ return -ELIBBAD;
++symcheck_error:
++ _debug("Verify ELF error [sym %ld] (check %u)\n",
++ (long)(symbol - symbols), line);
++ return -ELIBBAD;
++}
++
++/*
+ * Verify a module's integrity
+ */
+ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+@@ -61,6 +279,14 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+ mvdata.buffer = hdr;
+ mvdata.size = size;
+
++ /* Minimally check the ELF to make sure building the signature digest
++ * won't crash the kernel.
++ */
++ ret = module_verify_elf(&mvdata);
++ if (ret < 0)
++ goto out;
++
++ /* The ELF checker found the sig for us if it exists */
+ if (mvdata.sig_index <= 0) {
+ /* Deal with an unsigned module */
+ if (modsign_signedonly) {
+--
+1.7.10.2
+
+
+From 21a28e681f53685960f2780b7884e8b391122259 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:56 +0100
+Subject: [PATCH 26/36] MODSIGN: Produce a filtered and canonicalised section
+ list
+
+Build a list of the sections in which we're interested and canonicalise the
+section indices to avoid the problems of the section table being altered by ld
+when the signature is linked into the binary and by strip.
+
+The only sections in which we're actually interested are those that are marked
+allocatable (which will be kept in memory) and relocation tables that are
+applicable to those sections.
+
+Canonicalisation is done by sorting the filtered list in order of section name.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module-verify.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 80 insertions(+)
+
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index 5711aeb..13c60c2 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -268,6 +268,80 @@ symcheck_error:
+ }
+
+ /*
++ * Canonicalise the section table index numbers.
++ *
++ * We build a list of the sections we want to add to the digest and sort it by
++ * name. We're only interested in adding two types of section:
++ *
++ * (1) Allocatable sections. These should have no references to other
++ * sections.
++ *
++ * (2) Relocation tables for allocatable sections. The section table entry
++ * has a reference to the target section to which the relocations will be
++ * applied. The relocation entries have references to symbols in
++ * non-allocatable sections. Symbols can be replaced by their contents,
++ * but do include a further reference to a section - which must be
++ * canonicalised.
++ *
++ * We also build a map of raw section index to canonical section index.
++ */
++static int module_verify_canonicalise(struct module_verify_data *mvdata)
++{
++ const Elf_Shdr *sechdrs = mvdata->sections;
++ unsigned *canonlist, canon, loop, tmp;
++ bool changed;
++
++ canonlist = kmalloc(sizeof(unsigned) * mvdata->nsects * 2, GFP_KERNEL);
++ if (!canonlist)
++ return -ENOMEM;
++
++ mvdata->canonlist = canonlist;
++ mvdata->canonmap = 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 want allocatable sections and relocation tables */
++ if (section->sh_flags & SHF_ALLOC)
++ canonlist[canon++] = loop;
++ else if ((is_elf_rel(section->sh_type) ||
++ is_elf_rela(section->sh_type)) &&
++ mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC)
++ canonlist[canon++] = loop;
++ }
++
++ /* Sort the canonicalisation list */
++ do {
++ changed = false;
++
++ for (loop = 0; loop < canon - 1; loop++) {
++ const char *x, *y;
++
++ x = mvdata->secstrings + sechdrs[canonlist[loop + 0]].sh_name;
++ y = mvdata->secstrings + sechdrs[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 = true;
++ }
++ }
++ } while (changed);
++
++ /* What we really want is a raw-to-canon lookup table */
++ memset(mvdata->canonmap, 0xff, mvdata->nsects * sizeof(unsigned));
++ for (loop = 0; loop < canon; loop++)
++ mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
++ mvdata->ncanon = canon;
++ return 0;
++}
++
++/*
+ * Verify a module's integrity
+ */
+ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+@@ -298,7 +372,13 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+ goto out;
+ }
+
++ /* Produce a canonicalisation map for the sections */
++ ret = module_verify_canonicalise(&mvdata);
++ if (ret < 0)
++ goto out;
++
+ ret = 0;
++ kfree(mvdata.canonlist);
+
+ out:
+ switch (ret) {
+--
+1.7.10.2
+
+
+From 92fb97859c50a0dd63886baf057477a7a336b2a1 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:56 +0100
+Subject: [PATCH 27/36] MODSIGN: Create digest of module content and check
+ signature
+
+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.
+
+There are several reasons why these patches are useful, amongst which are:
+
+ (1) to prevent accidentally corrupted modules from causing damage;
+
+ (2) to prevent maliciously modified modules from 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.
+
+Note that 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. To protect the kernel image
+would be the responsibility of the boot loader or the system BIOS.
+
+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).
+
+Note! The "noinline" attribute on module_verify_signature() results in
+somewhat smaller code.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module-verify.c | 321 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 320 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index 13c60c2..a31b39c 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -49,6 +49,22 @@ static bool modsign_signedonly;
+ static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
+ static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
+
++#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)
++
+ /*
+ * Verify the minimum amount of ELF structure of a module needed to check the
+ * module's signature without bad ELF crashing the kernel.
+@@ -342,6 +358,309 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata)
+ }
+
+ /*
++ * Extract an ELF REL table
++ *
++ * We need to canonicalise the entries in case section/symbol addition/removal
++ * has rearranged the symbol table and the section table.
++ */
++static int extract_elf_rel(struct module_verify_data *mvdata,
++ unsigned 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 *symbols, *symbol;
++ const char *strings;
++ unsigned long r_sym;
++ size_t nsyms, loop;
++
++ nsyms = mvdata->sections[secix].sh_size / sizeof(Elf_Sym);
++ symbols = mvdata->buffer + mvdata->sections[secix].sh_offset;
++ strings = mvdata->buffer +
++ mvdata->sections[mvdata->sections[secix].sh_link].sh_offset;
++
++ /* Contribute the relevant bits from a join of { REL, SYMBOL, SECTION } */
++ for (loop = 0; loop < nrels; loop++) {
++ unsigned 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 */
++ r_sym = ELF_R_SYM(reloc->r_info);
++ if (r_sym >= nsyms)
++ return -ELIBBAD;
++ symbol = &symbols[r_sym];
++ 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) {
++ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC))
++ return -ELIBBAD;
++ 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 = 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 RELA table
++ *
++ * We need to canonicalise the entries in case section/symbol addition/removal
++ * has rearranged the symbol table and the section table.
++ */
++static int extract_elf_rela(struct module_verify_data *mvdata,
++ unsigned 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_Shdr *relsec, *symsec, *strsec;
++ const Elf_Rela *reloc;
++ const Elf_Sym *symbols, *symbol;
++ unsigned long r_sym;
++ const char *strings;
++ size_t nsyms, loop;
++
++ relsec = &mvdata->sections[secix];
++ symsec = &mvdata->sections[relsec->sh_link];
++ strsec = &mvdata->sections[symsec->sh_link];
++ nsyms = symsec->sh_size / sizeof(Elf_Sym);
++ symbols = mvdata->buffer + symsec->sh_offset;
++ strings = mvdata->buffer + strsec->sh_offset;
++
++ /* Contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++ for (loop = 0; loop < nrels; loop++) {
++ unsigned 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 */
++ r_sym = ELF_R_SYM(reloc->r_info);
++ if (r_sym >= nsyms)
++ return -ELIBBAD;
++ symbol = &symbols[r_sym];
++ 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 = 0;
++ st_shndx = symbol->st_shndx;
++
++ /* Canonicalise the section used by the symbol */
++ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) {
++ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC))
++ return -ELIBBAD;
++ 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 = 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;
++}
++
++/*
++ * Verify a module's signature
++ */
++static noinline int module_verify_signature(struct module_verify_data *mvdata)
++{
++ struct crypto_key_verify_context *mod_sig;
++ const Elf_Shdr *sechdrs = mvdata->sections;
++ const char *secstrings = mvdata->secstrings;
++ const u8 *sig = mvdata->sig;
++ size_t sig_size = mvdata->sig_size;
++ int loop, ret;
++
++ _debug("sig in section %u (size %zu)\n",
++ mvdata->sig_index, mvdata->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]);
++
++ /* 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 DEBUG
++ mvdata->xcsum = 0;
++#endif
++
++ /* Load data from each relevant section into the digest. Note that
++ * canonlist[] is a filtered list and only contains the sections we
++ * actually want.
++ */
++ 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;
++ const char *sh_name = secstrings + sechdrs[sect].sh_name;
++ const void *data = mvdata->buffer + sechdrs[sect].sh_offset;
++
++#ifdef DEBUG
++ mvdata->csum = 0;
++#endif
++
++ /* Digest the headers of any section we include. */
++ 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);
++
++ /* Relocation record sections refer to the section to be
++ * relocated, but this needs to be canonicalised to survive
++ * stripping.
++ */
++ if (is_elf_rel(sh_type) || is_elf_rela(sh_type))
++ crypto_digest_update_val(mvdata,
++ mvdata->canonmap[sh_info]);
++
++ /* Since relocation records give details of how we have to
++ * alter the allocatable sections, we need to digest these too.
++ *
++ * These, however, refer to metadata (symbols and sections)
++ * that may have been altered by the process of adding the
++ * signature section or the process of being stripped.
++ *
++ * To deal with this, we substitute the referenced metadata for
++ * the references to that metadata. So, for instance, the
++ * symbol ref from the relocation record is replaced with the
++ * contents of the symbol to which it refers, and the symbol's
++ * section ref is replaced with a canonicalised section number.
++ */
++ if (is_elf_rel(sh_type)) {
++ ret = extract_elf_rel(mvdata, sect,
++ data,
++ sh_size / sizeof(Elf_Rel),
++ sh_name);
++ if (ret < 0)
++ goto format_error;
++ continue;
++ }
++
++ if (is_elf_rela(sh_type)) {
++ ret = extract_elf_rela(mvdata, sect,
++ data,
++ sh_size / sizeof(Elf_Rela),
++ sh_name);
++ if (ret < 0)
++ goto format_error;
++ continue;
++ }
++
++ /* Include allocatable loadable sections */
++ if (sh_type != SHT_NOBITS)
++ crypto_digest_update_data(mvdata, data, sh_size);
++
++ _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);
++ _debug("verify-sig : %d\n", ret);
++ return ret;
++
++format_error:
++ verify_sig_cancel(mvdata->mod_sig);
++ return -ELIBBAD;
++}
++
++/*
+ * Verify a module's integrity
+ */
+ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+@@ -377,7 +696,7 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
+ if (ret < 0)
+ goto out;
+
+- ret = 0;
++ ret = module_verify_signature(&mvdata);
+ kfree(mvdata.canonlist);
+
+ out:
+--
+1.7.10.2
+
+
+From 2e9f557c1235027c0c7223a8a072333758905066 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:57 +0100
+Subject: [PATCH 28/36] MODSIGN: Automatically generate module signing keys if
+ missing
+
+Automatically generate keys for module signing if they're absent so that
+allyesconfig doesn't break. The builder should consider generating their own
+keyrings, however, so that the keys are appropriately named and any extra keys
+required get imported.
+
+Also change the names of the keyring files to modsign.pub and modsign.sec so
+that they are then a more obvious what they're about and add a dependency for
+the signing rules on the keyring files so that the signatures get regenerated
+if the keyrings change.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/Makefile | 42 +++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 41 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/Makefile b/kernel/Makefile
+index 986ed7f..d8139bb 100644
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -52,7 +52,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
+ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += module.o
+ obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o
+-kernel/modsign-pubkey.o: modsign.pub
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+ obj-$(CONFIG_KEXEC) += kexec.o
+@@ -129,3 +128,44 @@ quiet_cmd_timeconst = TIMEC $@
+ targets += timeconst.h
+ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE
+ $(call if_changed,timeconst)
++
++###############################################################################
++#
++# If module signing is requested, say by allyesconfig, but a key has not been
++# supplied, then one will need to be generated to make sure the build does not
++# fail and that the kernel may be used afterwards.
++#
++###############################################################################
++ifeq ($(CONFIG_MODULE_SIG),y)
++kernel/modsign-pubkey.o: modsign.pub
++
++modsign.pub modsign.sec: genkey
++ @echo "###"
++ @echo "### Now generating a PGP key pair to be used for signing modules."
++ @echo "###"
++ @echo "### If this takes a long time, you might wish to run rngd in the"
++ @echo "### background to keep the supply of entropy topped up. It"
++ @echo "### needs to be run as root, and should use a hardware random"
++ @echo "### number generator if one is available, eg:"
++ @echo "###"
++ @echo "### rngd -r /dev/hwrandom"
++ @echo "###"
++ gpg --homedir . --batch --gen-key genkey
++ @echo "###"
++ @echo "### Key pair generated."
++ @echo "###"
++ rm -f pubring.gpg secring.gpg trustdb.gpg
++
++genkey:
++ echo "%pubring modsign.pub" >genkey
++ echo "%secring modsign.sec" >>genkey
++ echo "%no-protection: yes" >> genkey
++ echo "%transient-key: yes" >>genkey
++ echo "Key-Type: RSA" >>genkey
++ echo "Key-Length: 4096" >>genkey
++ echo "Name-Real: Sample kernel key" >>genkey
++ echo "Name-Comment: Sample kernel module signing key" >>genkey
++ echo "%commit" >>genkey
++
++endif
++CLEAN_FILES += modsign.pub modsign.sec genkey random_seed
+--
+1.7.10.2
+
+
+From 958049a9def253735019a5acf19b4c2aeec9f01c Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:55:35 +0100
+Subject: [PATCH 29/36] MODSIGN: Suppress some redundant ELF checks
+
+Suppress some redundant ELF checks in module_verify_elf() that are also done
+by copy_and_check() in the core module loader code prior to calling
+module_verify().
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module-verify.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index a31b39c..e1bfd28 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -76,7 +76,7 @@ static noinline int module_verify_elf(struct module_verify_data *mvdata)
+ const Elf_Shdr *section, *secstop;
+ const Elf_Sym *symbols, *symbol, *symstop;
+ const char *strtab;
+- size_t size, secsize, secstrsize, strsize, notesize, notemetasize;
++ size_t size, secstrsize, strsize, notesize, notemetasize;
+ unsigned line;
+
+ size = mvdata->size;
+@@ -96,11 +96,11 @@ do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0)
+
+ elfcheck(hdr->e_shnum < SHN_LORESERVE);
+ elfcheck(hdr->e_shstrndx < hdr->e_shnum);
+- elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
+- elfcheck(hdr->e_shoff < size);
++ /* elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); */
++ /* elfcheck(hdr->e_shoff < size); */
+ elfcheck(hdr->e_shoff >= hdr->e_ehsize);
+ elfcheck(hdr->e_shoff % sizeof(long) == 0);
+- elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff);
++ /* elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); */
+
+ /* Validate the section table contents */
+ mvdata->nsects = hdr->e_shnum;
+--
+1.7.10.2
+
+
+From b5df4e7900852395a1ccb70190827cccc0c0de2d Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 11 May 2012 16:56:05 +0100
+Subject: [PATCH 30/36] MODSIGN: Fix some checkpatch noise
+
+Fix some warnings and errors produced by checkpatch.
+
+Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ kernel/module-verify-defs.h | 24 ++++++++++++------------
+ kernel/module-verify.c | 18 +++++++++++-------
+ kernel/module-verify.h | 3 ++-
+ security/keys/crypto/pgp_key_parser.c | 2 +-
+ 4 files changed, 26 insertions(+), 21 deletions(-)
+
+diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h
+index 45bea45..2fe31e1 100644
+--- a/kernel/module-verify-defs.h
++++ b/kernel/module-verify-defs.h
+@@ -60,22 +60,22 @@ struct module_verify_data {
+ do { \
+ if (unlikely(modsign_debug)) \
+ pr_debug(FMT, ##__VA_ARGS__); \
+- } while(0)
++ } while (0)
+
+ #ifdef 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)
++#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 { \
+-} while (0)
++ do { \
++ } while (0)
+ #endif
+
+ #endif /* CONFIG_MODULE_SIG */
+diff --git a/kernel/module-verify.c b/kernel/module-verify.c
+index e1bfd28..161cf3e 100644
+--- a/kernel/module-verify.c
++++ b/kernel/module-verify.c
+@@ -82,13 +82,13 @@ static noinline int module_verify_elf(struct module_verify_data *mvdata)
+ size = mvdata->size;
+
+ #define elfcheck(X) \
+-do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0)
++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)
++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)
++do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0)
+
+ /* Validate the ELF header */
+ elfcheck(size > sizeof(Elf_Ehdr));
+@@ -388,7 +388,7 @@ static int extract_elf_rel(struct module_verify_data *mvdata,
+ #else
+ #error unsupported module type
+ #endif
+- } __attribute__((packed)) relocation;
++ } __packed relocation;
+
+ const Elf_Rel *reloc;
+ const Elf_Sym *symbols, *symbol;
+@@ -401,7 +401,9 @@ static int extract_elf_rel(struct module_verify_data *mvdata,
+ strings = mvdata->buffer +
+ mvdata->sections[mvdata->sections[secix].sh_link].sh_offset;
+
+- /* Contribute the relevant bits from a join of { REL, SYMBOL, SECTION } */
++ /* Contribute the relevant bits from a join of
++ * { REL, SYMBOL, SECTION }
++ */
+ for (loop = 0; loop < nrels; loop++) {
+ unsigned st_shndx;
+
+@@ -479,7 +481,7 @@ static int extract_elf_rela(struct module_verify_data *mvdata,
+ #else
+ #error unsupported module type
+ #endif
+- } __attribute__((packed)) relocation;
++ } __packed relocation;
+
+ const Elf_Shdr *relsec, *symsec, *strsec;
+ const Elf_Rela *reloc;
+@@ -495,7 +497,9 @@ static int extract_elf_rela(struct module_verify_data *mvdata,
+ symbols = mvdata->buffer + symsec->sh_offset;
+ strings = mvdata->buffer + strsec->sh_offset;
+
+- /* Contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
++ /* Contribute the relevant bits from a join of
++ * { RELA, SYMBOL, SECTION }
++ */
+ for (loop = 0; loop < nrels; loop++) {
+ unsigned st_shndx;
+
+diff --git a/kernel/module-verify.h b/kernel/module-verify.h
+index 6bb6b56..c640634 100644
+--- a/kernel/module-verify.h
++++ b/kernel/module-verify.h
+@@ -12,7 +12,8 @@
+ #ifdef CONFIG_MODULE_SIG
+ extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok);
+ #else
+-static inline int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
++static inline int module_verify(const Elf_Ehdr *hdr, size_t size,
++ bool *_gpgsig_ok)
+ {
+ return 0;
+ }
+diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c
+index 1407e2e..d913538 100644
+--- a/security/keys/crypto/pgp_key_parser.c
++++ b/security/keys/crypto/pgp_key_parser.c
+@@ -94,7 +94,7 @@ static int pgp_calc_pkey_keyid(struct shash_desc *digest,
+ if (pgp->version < PGP_KEY_VERSION_4) {
+ u16 a16;
+
+- if( pgp->expires_at)
++ if (pgp->expires_at)
+ a16 = (pgp->expires_at - pgp->creation_time) / 86400UL;
+ else
+ a16 = 0;
+--
+1.7.10.2
+
+
+From 27ecab7d7ee104299133c9ffd51d00ea378ed56b Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Wed, 16 May 2012 15:13:41 +0100
+Subject: [PATCH 31/36] PGPLIB: Preclear array on stack
+
+Preclear an array on the stack so that the error handling that frees what the
+array might point to won't crash.
+
+Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/pgp_key_parser.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c
+index d913538..84ce457 100644
+--- a/security/keys/crypto/pgp_key_parser.c
++++ b/security/keys/crypto/pgp_key_parser.c
+@@ -71,6 +71,9 @@ static int pgp_calc_pkey_keyid(struct shash_desc *digest,
+
+ kenter("");
+
++ for (i = 0; i < ARRAY_SIZE(pp); i++)
++ pp[i] = NULL;
++
+ n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6;
+ for (i = 0; i < npkey; i++) {
+ nb[i] = mpi_get_nbits(key->mpi[i]);
+--
+1.7.10.2
+
+
+From a382a46fe70ee35cfb6fe97faa8abffd82368cbe Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Wed, 16 May 2012 15:19:24 +0100
+Subject: [PATCH 32/36] PGPLIB: Check the length in a packet or subpacket
+
+Check the length in a packet or subpacket to make sure there isn't an overflow
+should the length not fit into the lower 31 bits of an integer.
+
+It is possible that both pgp_parse_packet_header() and
+pgp_parse_sig_subpkt_header() could see packets that purport to be >2G in size.
+Normally this will not be a problem because EBADMSG is indicated if the size
+indicated is greater than the remnant size of the data - but just in case we do
+end up parsing a >2G blob, a couple of simple checks can prevent an overflow
+from occurring.
+
+Reported-by: Stephan Mueller <stephan.mueller@atsec.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/pgp_library.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index f6b831f..a9462f5 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/pgp_library.c
+@@ -137,6 +137,8 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
+ pr_devel("datalen=%zu size=%zu", datalen, size);
+ if (datalen < size)
+ goto short_packet;
++ if ((int)size < 0)
++ goto too_big;
+
+ *_data = data;
+ *_datalen = datalen;
+@@ -147,6 +149,9 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
+ short_packet:
+ pr_debug("Attempt to parse short packet\n");
+ return -EBADMSG;
++too_big:
++ pr_debug("Signature subpacket size >2G\n");
++ return -EMSGSIZE;
+ }
+
+ /**
+@@ -312,6 +317,8 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
+ pr_debug("Signature subpacket size can't be zero\n");
+ return -EBADMSG;
+ }
++ if ((int)size < 0)
++ goto too_big;
+
+ type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK;
+ datalen--;
+@@ -330,6 +337,9 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
+ short_subpacket:
+ pr_debug("Attempt to parse short signature subpacket\n");
+ return -EBADMSG;
++too_big:
++ pr_debug("Signature subpacket size >2G\n");
++ return -EMSGSIZE;
+ }
+
+ /**
+--
+1.7.10.2
+
+
+From a577fc904c197d97b028863989d9a891c3e1ea17 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 17 May 2012 17:41:36 +0100
+Subject: [PATCH 33/36] PGPLIB: Remnant length should be decreased in
+ pgp_parse_sig_params()
+
+The remnant length of the signature packet should be decreased rather than
+being increased as we parse in pgp_parse_sig_params().
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/pgp_library.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index a9462f5..1ff3628 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/pgp_library.c
+@@ -503,7 +503,7 @@ int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
+ if (ret < 0)
+ return ret;
+ data += subdatalen;
+- datalen += subdatalen;
++ datalen -= subdatalen;
+ }
+
+ subdatalen = *data++ << 8;
+@@ -521,7 +521,7 @@ int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
+ if (ret < 0)
+ return ret;
+ data += subdatalen;
+- datalen += subdatalen;
++ datalen -= subdatalen;
+ }
+
+ if (!ctx.got_the_issuer) {
+--
+1.7.10.2
+
+
+From ab7204f60a1cedecb24bb2888db5d03bdcf20488 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 17 May 2012 17:41:36 +0100
+Subject: [PATCH 34/36] PGPLIB: Parse 5-octet length new-format packet headers
+
+Parse 5-octet length new-format packet headers to extract the 32-bit length
+encoded therein [RFC4880 4.2.2.3].
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/pgp_library.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index 1ff3628..310ee2f 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/pgp_library.c
+@@ -86,8 +86,17 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
+ *_headerlen = 3;
+ break;
+ case 0xff:
+- pr_debug("Five-byte packet length not supported\n");
+- return -EBADMSG;
++ /* Five-byte length */
++ if (datalen < 5)
++ goto short_packet;
++ size = data[1] << 24;
++ size |= data[2] << 16;
++ size |= data[3] << 8;
++ size |= data[4];
++ data += 5;
++ datalen -= 5;
++ *_headerlen = 6;
++ break;
+ default:
+ pr_debug("Error parsing packet length\n");
+ return -EBADMSG;
+--
+1.7.10.2
+
+
+From df233b65b833e085f39d80dc6f77c383b32786ce Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 17 May 2012 17:41:36 +0100
+Subject: [PATCH 35/36] PGPLIB: Change the debug message for Partial Body
+ Length specifier
+
+Change the debug message displayed if we encounter a Partial Body Length
+specifier whilst parsing a PGP stream [RFC4880 4.2.2.4].
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ security/keys/crypto/pgp_library.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index 310ee2f..111cbd7 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/pgp_library.c
+@@ -98,7 +98,7 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
+ *_headerlen = 6;
+ break;
+ default:
+- pr_debug("Error parsing packet length\n");
++ pr_debug("Partial body length packet not supported\n");
+ return -EBADMSG;
+ }
+ } else {
+--
+1.7.10.2
+
+
+From 3ac676c62cceabdbf814bbc3495f36abd1848a97 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 18 May 2012 16:44:14 +0100
+Subject: [PATCH 36/36] PGPLIB: Adjust error handling
+
+Adjust the error handling in the following ways:
+
+ (1) When parsing signature subpacket header, do the size checks before
+ accessing the subpacket type (which is in the subpacket payload governed
+ by the size).
+
+ (2) Indicate ENOPKG when we are asked to use a public key algorithm we don't
+ support rather than returning ENOKEY.
+
+ (3) Indicate EKEYREJECTED if the key that matches the signature demands a
+ different key algorithm to the signature.
+
+ (4) Indicate ENOMSG if the signature blob does not contain a signature
+ packet. Possibly this should be EBADMSG - though that causes the next
+ packet parser to be tried if available.
+
+ (5) Give a better debug message in the case of an unsupported hash.
+
+ (6) Don't return keyring-related errors when searching for a key containing
+ the public key (EACCES, ENOTDIR, EAGAIN), but rather map them to ENOKEY.
+ Possibly EACCES should be passed through as you also get that if there
+ *is* a matching key, but it cannot be accessed.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ Documentation/module-signing.txt | 2 ++
+ security/keys/crypto/pgp_library.c | 16 ++++++++--------
+ security/keys/crypto/pgp_pubkey_sig.c | 9 +++++----
+ security/keys/crypto/pgp_sig_parser.c | 15 ++++++++++++---
+ 4 files changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
+index d75d473..d3beb1e 100644
+--- a/Documentation/module-signing.txt
++++ b/Documentation/module-signing.txt
+@@ -185,10 +185,12 @@ This table indicates the behaviours of the various situations:
+ MODULE STATE PERMISSIVE MODE ENFORCING MODE
+ ======================================= =============== ===============
+ Unsigned Ok EKEYREJECTED
++ No signature packet in the signature ENOMSG ENOMSG
+ 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, pubkey algorithm unavailable ENOPKG ENOPKG
+ Signed, hash algorithm unavailable ENOPKG ENOPKG
+ Corrupt signature EBADMSG EBADMSG
+ Corrupt ELF ELIBBAD ELIBBAD
+diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
+index 111cbd7..ee08b86 100644
+--- a/security/keys/crypto/pgp_library.c
++++ b/security/keys/crypto/pgp_library.c
+@@ -322,10 +322,11 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
+ }
+
+ /* The type octet is included in the size */
+- if (size == 0) {
+- pr_debug("Signature subpacket size can't be zero\n");
+- return -EBADMSG;
+- }
++ pr_devel("datalen=%zu size=%zu", datalen, size);
++ if (datalen < size)
++ goto short_subpacket;
++ if (size == 0)
++ goto very_short_subpacket;
+ if ((int)size < 0)
+ goto too_big;
+
+@@ -333,16 +334,15 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
+ 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;
+
++very_short_subpacket:
++ pr_debug("Signature subpacket size can't be zero\n");
++ return -EBADMSG;
+ short_subpacket:
+ pr_debug("Attempt to parse short signature subpacket\n");
+ return -EBADMSG;
+diff --git a/security/keys/crypto/pgp_pubkey_sig.c b/security/keys/crypto/pgp_pubkey_sig.c
+index b4b7cb0..bc02dfa 100644
+--- a/security/keys/crypto/pgp_pubkey_sig.c
++++ b/security/keys/crypto/pgp_pubkey_sig.c
+@@ -86,12 +86,12 @@ struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
+ !pgp_public_key_algorithms[p.params.pubkey_algo]) {
+ pr_debug("Unsupported public key algorithm %u\n",
+ p.params.pubkey_algo);
+- return ERR_PTR(-ENOKEY);
++ return ERR_PTR(-ENOPKG);
+ }
+
+ if (pgp_public_key_algorithms[p.params.pubkey_algo] != key->algo) {
+- kleave(" = -ENOKEY [wrong pk algo]");
+- return ERR_PTR(-ENOKEY);
++ kleave(" = -EKEYREJECTED [wrong pk algo]");
++ return ERR_PTR(-EKEYREJECTED);
+ }
+
+ if (!(key->capabilities & PKEY_CAN_VERIFY)) {
+@@ -101,7 +101,8 @@ struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
+
+ if (p.params.hash_algo >= PGP_HASH__LAST ||
+ !pgp_hash_algorithms[p.params.hash_algo]) {
+- kleave(" = -ENOPKG [hash]");
++ pr_debug("Unsupported hash algorithm %u\n",
++ p.params.hash_algo);
+ return ERR_PTR(-ENOPKG);
+ }
+
+diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c
+index b72c505..3dd223f 100644
+--- a/security/keys/crypto/pgp_sig_parser.c
++++ b/security/keys/crypto/pgp_sig_parser.c
+@@ -66,7 +66,7 @@ static struct key *find_key_for_pgp_sig(struct key *keyring,
+ return ERR_PTR(ret);
+
+ if (!p.found_sig)
+- return ERR_PTR(-EINVAL);
++ return ERR_PTR(-ENOMSG);
+
+ sprintf(criterion, "id:%08x%08x",
+ be32_to_cpu(p.params.issuer32[0]),
+@@ -76,8 +76,17 @@ static struct key *find_key_for_pgp_sig(struct key *keyring,
+
+ key = keyring_search(make_key_ref(keyring, 1),
+ &key_type_crypto, criterion);
+- if (IS_ERR(key))
+- return ERR_CAST(key);
++ if (IS_ERR(key)) {
++ switch (PTR_ERR(key)) {
++ /* Hide some search errors */
++ case -EACCES:
++ case -ENOTDIR:
++ case -EAGAIN:
++ return ERR_PTR(-ENOKEY);
++ default:
++ return ERR_CAST(key);
++ }
++ }
+
+ pr_debug("Found key %x\n", key_serial(key_ref_to_ptr(key)));
+ return key_ref_to_ptr(key);
+--
+1.7.10.2
+