[kernel] re-enable modsign and secure boot

Justin M. Forbes jforbes at fedoraproject.org
Mon Oct 15 14:45:55 UTC 2012


commit be7ac52af682ed133aa613ed21c756d1459ff3aa
Author: Justin M. Forbes <jforbes at redhat.com>
Date:   Mon Oct 15 09:42:26 2012 -0500

    re-enable modsign and secure boot

 kernel.spec                |    7 +-
 modsign-post-KS-jwb.patch  | 9293 ++------------------------------------------
 secure-boot-20120924.patch |    6 +-
 3 files changed, 256 insertions(+), 9050 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index ea4a8b5..cb52e45 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -1390,10 +1390,10 @@ ApplyPatch linux-2.6-crash-driver.patch
 ApplyPatch linux-2.6-e1000-ich9-montevina.patch
 
 # crypto/
-# ApplyPatch modsign-post-KS-jwb.patch
+ApplyPatch modsign-post-KS-jwb.patch
 
 # secure boot
-# ApplyPatch secure-boot-20120924.patch
+ApplyPatch secure-boot-20120924.patch
 
 # Improved PCI support for UEFI
 ApplyPatch handle-efi-roms.patch
@@ -2301,6 +2301,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Mon Oct 15 2012 Justin M. Forbes <jforbes at redhat.com>
+- re-enable modsign and secure boot
+
 * Mon Oct 15 2012 Justin M. Forbes <jforbes at redhat.com> - 3.7.0-0.rc1.git0.1
 - Linux 3.7-rc1
 - Disable debugging options.
diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch
index e8a86af..5900332 100644
--- a/modsign-post-KS-jwb.patch
+++ b/modsign-post-KS-jwb.patch
@@ -1,8791 +1,254 @@
-From 2cdfd353ac1a5b9f62398ef59b4a08b5b55ac089 Mon Sep 17 00:00:00 2001
-From: Rusty Russell <rusty at rustcorp.com.au>
-Date: Wed, 5 Sep 2012 12:32:17 +0930
-Subject: [PATCH 01/26] module: signature checking hook
-
-We do a very simple search for a particular string appended to the module
-(which is cache-hot and about to be SHA'd anyway).  There's both a config
-option and a boot parameter which control whether we accept (and taint) or
-fail with unsigned modules.
-
-Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
----
- Documentation/kernel-parameters.txt |  6 +++
- include/linux/module.h              |  8 ++++
- init/Kconfig                        | 14 ++++++
- kernel/module.c                     | 88 ++++++++++++++++++++++++++++++++++++-
- 4 files changed, 115 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index ad7e2e5..9b2b8d3 100644
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
- 			log everything. Information is printed at KERN_DEBUG
- 			so loglevel=8 may also need to be specified.
- 
-+	module.sig_enforce
-+			[KNL] When CONFIG_MODULE_SIG is set, this means that
-+			modules without (valid) signatures will fail to load.
-+			Note that if CONFIG_MODULE_SIG_ENFORCE is set, that
-+			is always true, so this option does nothing.
-+
- 	mousedev.tap_time=
- 			[MOUSE] Maximum time between finger touching and
- 			leaving touchpad surface for touch to be considered
-diff --git a/include/linux/module.h b/include/linux/module.h
-index fbcafe2..7760c6d 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -21,6 +21,9 @@
- #include <linux/percpu.h>
- #include <asm/module.h>
- 
-+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
-+#define MODULE_SIG_STRING "~Module signature appended~\n"
-+
- /* Not Yet Implemented */
- #define MODULE_SUPPORTED_DEVICE(name)
- 
-@@ -260,6 +263,11 @@ struct module
- 	const unsigned long *unused_gpl_crcs;
- #endif
- 
-+#ifdef CONFIG_MODULE_SIG
-+	/* Signature was verified. */
-+	bool sig_ok;
-+#endif
-+
- 	/* symbols that will be GPL-only in the near future. */
- 	const struct kernel_symbol *gpl_future_syms;
- 	const unsigned long *gpl_future_crcs;
-diff --git a/init/Kconfig b/init/Kconfig
-index af6c7f8..7452e19 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1585,6 +1585,20 @@ 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
-+	help
-+	  Check modules for valid signatures upon load: the signature
-+	  is simply appended to the module. For more information see
-+	  Documentation/module-signing.txt.
-+
-+config MODULE_SIG_FORCE
-+	bool "Require modules to be validly signed"
-+	depends on MODULE_SIG
-+	help
-+	  Reject unsigned modules or signed modules for which we don't have a
-+	  key.  Without this, such modules will simply taint the kernel.
- endif # MODULES
- 
- config INIT_ALL_POSSIBLE
-diff --git a/kernel/module.c b/kernel/module.c
-index 4edbd9c..5c6f65c 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -102,6 +102,43 @@ static LIST_HEAD(modules);
- struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
- #endif /* CONFIG_KGDB_KDB */
- 
-+#ifdef CONFIG_MODULE_SIG
-+#ifdef CONFIG_MODULE_SIG_FORCE
-+static bool sig_enforce = true;
-+#else
-+static bool sig_enforce = false;
-+
-+static int param_set_bool_enable_only(const char *val,
-+				      const struct kernel_param *kp)
-+{
-+	int err;
-+	bool test;
-+	struct kernel_param dummy_kp = *kp;
-+
-+	dummy_kp.arg = &test;
-+
-+	err = param_set_bool(val, &dummy_kp);
-+	if (err)
-+		return err;
-+
-+	/* Don't let them unset it once it's set! */
-+	if (!test && sig_enforce)
-+		return -EROFS;
-+
-+	if (test)
-+		sig_enforce = true;
-+	return 0;
-+}
-+
-+static const struct kernel_param_ops param_ops_bool_enable_only = {
-+	.set = param_set_bool_enable_only,
-+	.get = param_get_bool,
-+};
-+#define param_check_bool_enable_only param_check_bool
-+
-+module_param(sig_enforce, bool_enable_only, 0644);
-+#endif /* !CONFIG_MODULE_SIG_FORCE */
-+#endif /* CONFIG_MODULE_SIG */
- 
- /* Block module loading/unloading? */
- int modules_disabled = 0;
-@@ -136,6 +173,7 @@ struct load_info {
- 	unsigned long symoffs, stroffs;
- 	struct _ddebug *debug;
- 	unsigned int num_debug;
-+	bool sig_ok;
- 	struct {
- 		unsigned int sym, str, mod, vers, info, pcpu;
- 	} index;
-@@ -2399,7 +2437,45 @@ static inline void kmemleak_load_module(const struct module *mod,
- }
- #endif
- 
--/* Sets info->hdr and info->len. */
-+#ifdef CONFIG_MODULE_SIG
-+static int module_sig_check(struct load_info *info,
-+			    const void *mod, unsigned long *len)
-+{
-+	int err = 0;
-+	const unsigned long markerlen = strlen(MODULE_SIG_STRING);
-+	const void *p = mod, *end = mod + *len;
-+
-+	/* Poor man's memmem. */
-+	while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
-+		if (p + markerlen > end)
-+			break;
-+
-+		if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
-+			const void *sig = p + markerlen;
-+			/* Truncate module up to signature. */
-+			*len = p - mod;
-+			err = mod_verify_sig(mod, *len,
-+					     sig, end - sig,
-+					     &info->sig_ok);
-+			break;
-+		}
-+		p++;
-+	}
-+
-+	/* Not having a signature is only an error if we're strict. */
-+	if (!err && !info->sig_ok && sig_enforce)
-+		err = -EKEYREJECTED;
-+	return err;
-+}
-+#else /* !CONFIG_MODULE_SIG */
-+static int module_sig_check(struct load_info *info,
-+			    void *mod, unsigned long *len)
-+{
-+	return 0;
-+}
-+#endif /* !CONFIG_MODULE_SIG */
-+
-+/* Sets info->hdr, info->len and info->sig_ok. */
- static int copy_and_check(struct load_info *info,
- 			  const void __user *umod, unsigned long len,
- 			  const char __user *uargs)
-@@ -2419,6 +2495,10 @@ static int copy_and_check(struct load_info *info,
- 		goto free_hdr;
- 	}
- 
-+	err = module_sig_check(info, hdr, &len);
-+	if (err)
-+		goto free_hdr;
-+
- 	/* Sanity checks against insmoding binaries or wrong arch,
- 	   weird elf version */
- 	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
-@@ -2886,6 +2966,12 @@ static struct module *load_module(void __user *umod,
- 		goto free_copy;
- 	}
- 
-+#ifdef CONFIG_MODULE_SIG
-+	mod->sig_ok = info.sig_ok;
-+	if (!mod->sig_ok)
-+		add_taint_module(mod, TAINT_FORCED_MODULE);
-+#endif
-+
- 	/* Now module is in final location, initialize linked lists, etc. */
- 	err = module_unload_init(mod);
- 	if (err)
--- 
-1.7.11.4
-
-
-From d4f65b5d2497b2fd9c45f06b71deb4ab084a5b66 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Thu, 13 Sep 2012 13:06:29 +0100
-Subject: [PATCH 02/26] KEYS: Add payload preparsing opportunity prior to key
- instantiate or update
-
-Give the key type the opportunity to preparse the payload prior to the
-instantiation and update routines being called.  This is done with the
-provision of two new key type operations:
-
-	int (*preparse)(struct key_preparsed_payload *prep);
-	void (*free_preparse)(struct key_preparsed_payload *prep);
-
-If the first operation is present, then it is called before key creation (in
-the add/update case) or before the key semaphore is taken (in the update and
-instantiate cases).  The second operation is called to clean up if the first
-was called.
-
-preparse() is given the opportunity to fill in the following structure:
-
-	struct key_preparsed_payload {
-		char		*description;
-		void		*type_data[2];
-		void		*payload;
-		const void	*data;
-		size_t		datalen;
-		size_t		quotalen;
-	};
-
-Before the preparser is called, the first three fields will have been cleared,
-the payload pointer and size will be stored in data and datalen and the default
-quota size from the key_type struct will be stored into quotalen.
-
-The preparser may parse the payload in any way it likes and may store data in
-the type_data[] and payload fields for use by the instantiate() and update()
-ops.
-
-The preparser may also propose a description for the key by attaching it as a
-string to the description field.  This can be used by passing a NULL or ""
-description to the add_key() system call or the key_create_or_update()
-function.  This cannot work with request_key() as that required the description
-to tell the upcall about the key to be created.
-
-This, for example permits keys that store PGP public keys to generate their own
-name from the user ID and public key fingerprint in the key.
-
-The instantiate() and update() operations are then modified to look like this:
-
-	int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
-	int (*update)(struct key *key, struct key_preparsed_payload *prep);
-
-and the new payload data is passed in *prep, whether or not it was preparsed.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- Documentation/security/keys.txt          |  50 +++++++++++++-
- fs/cifs/cifs_spnego.c                    |   6 +-
- fs/cifs/cifsacl.c                        |   8 +--
- include/keys/user-type.h                 |   6 +-
- include/linux/key-type.h                 |  35 +++++++++-
- net/ceph/crypto.c                        |   9 +--
- net/dns_resolver/dns_key.c               |   6 +-
- net/rxrpc/ar-key.c                       |  40 +++++------
- security/keys/encrypted-keys/encrypted.c |  16 +++--
- security/keys/key.c                      | 114 ++++++++++++++++++++++---------
- security/keys/keyctl.c                   |  18 +++--
- security/keys/keyring.c                  |   6 +-
- security/keys/request_key_auth.c         |   8 +--
- security/keys/trusted.c                  |  16 +++--
- security/keys/user_defined.c             |  14 ++--
- 15 files changed, 250 insertions(+), 102 deletions(-)
-
-diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
-index aa0dbd7..7d9ca92 100644
---- a/Documentation/security/keys.txt
-+++ b/Documentation/security/keys.txt
-@@ -412,6 +412,10 @@ The main syscalls are:
-      to the keyring. In this case, an error will be generated if the process
-      does not have permission to write to the keyring.
- 
-+     If the key type supports it, if the description is NULL or an empty
-+     string, the key type will try and generate a description from the content
-+     of the payload.
-+
-      The payload is optional, and the pointer can be NULL if not required by
-      the type. The payload is plen in size, and plen can be zero for an empty
-      payload.
-@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory:
-      it should return 0.
- 
- 
-- (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
-+ (*) int (*preparse)(struct key_preparsed_payload *prep);
-+
-+     This optional method permits the key type to attempt to parse payload
-+     before a key is created (add key) or the key semaphore is taken (update or
-+     instantiate key).  The structure pointed to by prep looks like:
-+
-+	struct key_preparsed_payload {
-+		char		*description;
-+		void		*type_data[2];
-+		void		*payload;
-+		const void	*data;
-+		size_t		datalen;
-+		size_t		quotalen;
-+	};
-+
-+     Before calling the method, the caller will fill in data and datalen with
-+     the payload blob parameters; quotalen will be filled in with the default
-+     quota size from the key type and the rest will be cleared.
-+
-+     If a description can be proposed from the payload contents, that should be
-+     attached as a string to the description field.  This will be used for the
-+     key description if the caller of add_key() passes NULL or "".
-+
-+     The method can attach anything it likes to type_data[] and payload.  These
-+     are merely passed along to the instantiate() or update() operations.
-+
-+     The method should return 0 if success ful or a negative error code
-+     otherwise.
-+
-+     
-+ (*) void (*free_preparse)(struct key_preparsed_payload *prep);
-+
-+     This method is only required if the preparse() method is provided,
-+     otherwise it is unused.  It cleans up anything attached to the
-+     description, type_data and payload fields of the key_preparsed_payload
-+     struct as filled in by the preparse() method.
-+
-+
-+ (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
- 
-      This method is called to attach a payload to a key during construction.
-      The payload attached need not bear any relation to the data passed to this
-      function.
- 
-+     The prep->data and prep->datalen fields will define the original payload
-+     blob.  If preparse() was supplied then other fields may be filled in also.
-+
-      If the amount of data attached to the key differs from the size in
-      keytype->def_datalen, then key_payload_reserve() should be called.
- 
-@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory:
-      If this type of key can be updated, then this method should be provided.
-      It is called to update a key's payload from the blob of data provided.
- 
-+     The prep->data and prep->datalen fields will define the original payload
-+     blob.  If preparse() was supplied then other fields may be filled in also.
-+
-      key_payload_reserve() should be called if the data length might change
-      before any changes are actually made. Note that if this succeeds, the type
-      is committed to changing the key because it's already been altered, so all
-diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
-index e622863..086f381 100644
---- a/fs/cifs/cifs_spnego.c
-+++ b/fs/cifs/cifs_spnego.c
-@@ -31,18 +31,18 @@
- 
- /* create a new cifs key */
- static int
--cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
-+cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	char *payload;
- 	int ret;
- 
- 	ret = -ENOMEM;
--	payload = kmalloc(datalen, GFP_KERNEL);
-+	payload = kmalloc(prep->datalen, GFP_KERNEL);
- 	if (!payload)
- 		goto error;
- 
- 	/* attach the data */
--	memcpy(payload, data, datalen);
-+	memcpy(payload, prep->data, prep->datalen);
- 	key->payload.data = payload;
- 	ret = 0;
- 
-diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
-index 05f4dc2..f3c60e2 100644
---- a/fs/cifs/cifsacl.c
-+++ b/fs/cifs/cifsacl.c
-@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = {
- };
- 
- static int
--cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
-+cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	char *payload;
- 
--	payload = kmalloc(datalen, GFP_KERNEL);
-+	payload = kmalloc(prep->datalen, GFP_KERNEL);
- 	if (!payload)
- 		return -ENOMEM;
- 
--	memcpy(payload, data, datalen);
-+	memcpy(payload, prep->data, prep->datalen);
- 	key->payload.data = payload;
--	key->datalen = datalen;
-+	key->datalen = prep->datalen;
- 	return 0;
- }
- 
-diff --git a/include/keys/user-type.h b/include/keys/user-type.h
-index bc9ec1d..5e452c8 100644
---- a/include/keys/user-type.h
-+++ b/include/keys/user-type.h
-@@ -35,8 +35,10 @@ struct user_key_payload {
- extern struct key_type key_type_user;
- extern struct key_type key_type_logon;
- 
--extern int user_instantiate(struct key *key, const void *data, size_t datalen);
--extern int user_update(struct key *key, const void *data, size_t datalen);
-+struct key_preparsed_payload;
-+
-+extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep);
-+extern int user_update(struct key *key, struct key_preparsed_payload *prep);
- extern int user_match(const struct key *key, const void *criterion);
- extern void user_revoke(struct key *key);
- extern void user_destroy(struct key *key);
-diff --git a/include/linux/key-type.h b/include/linux/key-type.h
-index f0c651c..518a53a 100644
---- a/include/linux/key-type.h
-+++ b/include/linux/key-type.h
-@@ -26,6 +26,27 @@ struct key_construction {
- 	struct key	*authkey;/* authorisation for key being constructed */
- };
- 
-+/*
-+ * Pre-parsed payload, used by key add, update and instantiate.
-+ *
-+ * This struct will be cleared and data and datalen will be set with the data
-+ * and length parameters from the caller and quotalen will be set from
-+ * def_datalen from the key type.  Then if the preparse() op is provided by the
-+ * key type, that will be called.  Then the struct will be passed to the
-+ * instantiate() or the update() op.
-+ *
-+ * If the preparse() op is given, the free_preparse() op will be called to
-+ * clear the contents.
-+ */
-+struct key_preparsed_payload {
-+	char		*description;	/* Proposed key description (or NULL) */
-+	void		*type_data[2];	/* Private key-type data */
-+	void		*payload;	/* Proposed payload */
-+	const void	*data;		/* Raw data */
-+	size_t		datalen;	/* Raw datalen */
-+	size_t		quotalen;	/* Quota length for proposed payload */
-+};
-+
- typedef int (*request_key_actor_t)(struct key_construction *key,
- 				   const char *op, void *aux);
- 
-@@ -45,18 +66,28 @@ struct key_type {
- 	/* vet a description */
- 	int (*vet_description)(const char *description);
- 
-+	/* Preparse the data blob from userspace that is to be the payload,
-+	 * generating a proposed description and payload that will be handed to
-+	 * the instantiate() and update() ops.
-+	 */
-+	int (*preparse)(struct key_preparsed_payload *prep);
-+
-+	/* Free a preparse data structure.
-+	 */
-+	void (*free_preparse)(struct key_preparsed_payload *prep);
-+
- 	/* instantiate a key of this type
- 	 * - this method should call key_payload_reserve() to determine if the
- 	 *   user's quota will hold the payload
- 	 */
--	int (*instantiate)(struct key *key, const void *data, size_t datalen);
-+	int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
- 
- 	/* update a key of this type (optional)
- 	 * - this method should call key_payload_reserve() to recalculate the
- 	 *   quota consumption
- 	 * - the key must be locked against read when modifying
- 	 */
--	int (*update)(struct key *key, const void *data, size_t datalen);
-+	int (*update)(struct key *key, struct key_preparsed_payload *prep);
- 
- 	/* match a key against a description */
- 	int (*match)(const struct key *key, const void *desc);
-diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
-index 9da7fdd..af14cb4 100644
---- a/net/ceph/crypto.c
-+++ b/net/ceph/crypto.c
-@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len,
- 	}
- }
- 
--int ceph_key_instantiate(struct key *key, const void *data, size_t datalen)
-+int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct ceph_crypto_key *ckey;
-+	size_t datalen = prep->datalen;
- 	int ret;
- 	void *p;
- 
- 	ret = -EINVAL;
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		goto err;
- 
- 	ret = key_payload_reserve(key, datalen);
-@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen)
- 		goto err;
- 
- 	/* TODO ceph_crypto_key_decode should really take const input */
--	p = (void *)data;
--	ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen);
-+	p = (void *)prep->data;
-+	ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen);
- 	if (ret < 0)
- 		goto err_ckey;
- 
-diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
-index d9507dd..859ab8b 100644
---- a/net/dns_resolver/dns_key.c
-+++ b/net/dns_resolver/dns_key.c
-@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache;
-  *        "ip1,ip2,...#foo=bar"
-  */
- static int
--dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
-+dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct user_key_payload *upayload;
- 	unsigned long derrno;
- 	int ret;
--	size_t result_len = 0;
--	const char *data = _data, *end, *opt;
-+	size_t datalen = prep->datalen, result_len = 0;
-+	const char *data = prep->data, *end, *opt;
- 
- 	kenter("%%%d,%s,'%*.*s',%zu",
- 	       key->serial, key->description,
-diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
-index 8b1f9f4..106c5a6 100644
---- a/net/rxrpc/ar-key.c
-+++ b/net/rxrpc/ar-key.c
-@@ -26,8 +26,8 @@
- #include "ar-internal.h"
- 
- static int rxrpc_vet_description_s(const char *);
--static int rxrpc_instantiate(struct key *, const void *, size_t);
--static int rxrpc_instantiate_s(struct key *, const void *, size_t);
-+static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *);
-+static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *);
- static void rxrpc_destroy(struct key *);
- static void rxrpc_destroy_s(struct key *);
- static void rxrpc_describe(const struct key *, struct seq_file *);
-@@ -678,7 +678,7 @@ error:
-  *
-  * if no data is provided, then a no-security key is made
-  */
--static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
-+static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	const struct rxrpc_key_data_v1 *v1;
- 	struct rxrpc_key_token *token, **pp;
-@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
- 	u32 kver;
- 	int ret;
- 
--	_enter("{%x},,%zu", key_serial(key), datalen);
-+	_enter("{%x},,%zu", key_serial(key), prep->datalen);
- 
- 	/* handle a no-security key */
--	if (!data && datalen == 0)
-+	if (!prep->data && prep->datalen == 0)
- 		return 0;
- 
- 	/* determine if the XDR payload format is being used */
--	if (datalen > 7 * 4) {
--		ret = rxrpc_instantiate_xdr(key, data, datalen);
-+	if (prep->datalen > 7 * 4) {
-+		ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen);
- 		if (ret != -EPROTO)
- 			return ret;
- 	}
- 
- 	/* get the key interface version number */
- 	ret = -EINVAL;
--	if (datalen <= 4 || !data)
-+	if (prep->datalen <= 4 || !prep->data)
- 		goto error;
--	memcpy(&kver, data, sizeof(kver));
--	data += sizeof(kver);
--	datalen -= sizeof(kver);
-+	memcpy(&kver, prep->data, sizeof(kver));
-+	prep->data += sizeof(kver);
-+	prep->datalen -= sizeof(kver);
- 
- 	_debug("KEY I/F VERSION: %u", kver);
- 
-@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
- 
- 	/* deal with a version 1 key */
- 	ret = -EINVAL;
--	if (datalen < sizeof(*v1))
-+	if (prep->datalen < sizeof(*v1))
- 		goto error;
- 
--	v1 = data;
--	if (datalen != sizeof(*v1) + v1->ticket_length)
-+	v1 = prep->data;
-+	if (prep->datalen != sizeof(*v1) + v1->ticket_length)
- 		goto error;
- 
- 	_debug("SCIX: %u", v1->security_index);
-@@ -784,17 +784,17 @@ error:
-  * instantiate a server secret key
-  * data should be a pointer to the 8-byte secret key
-  */
--static int rxrpc_instantiate_s(struct key *key, const void *data,
--			       size_t datalen)
-+static int rxrpc_instantiate_s(struct key *key,
-+			       struct key_preparsed_payload *prep)
- {
- 	struct crypto_blkcipher *ci;
- 
--	_enter("{%x},,%zu", key_serial(key), datalen);
-+	_enter("{%x},,%zu", key_serial(key), prep->datalen);
- 
--	if (datalen != 8)
-+	if (prep->datalen != 8)
- 		return -EINVAL;
- 
--	memcpy(&key->type_data, data, 8);
-+	memcpy(&key->type_data, prep->data, 8);
- 
- 	ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
- 	if (IS_ERR(ci)) {
-@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data,
- 		return PTR_ERR(ci);
- 	}
- 
--	if (crypto_blkcipher_setkey(ci, data, 8) < 0)
-+	if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0)
- 		BUG();
- 
- 	key->payload.data = ci;
-diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
-index 2d1bb8a..9e1e005 100644
---- a/security/keys/encrypted-keys/encrypted.c
-+++ b/security/keys/encrypted-keys/encrypted.c
-@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload,
-  *
-  * On success, return 0. Otherwise return errno.
-  */
--static int encrypted_instantiate(struct key *key, const void *data,
--				 size_t datalen)
-+static int encrypted_instantiate(struct key *key,
-+				 struct key_preparsed_payload *prep)
- {
- 	struct encrypted_key_payload *epayload = NULL;
- 	char *datablob = NULL;
-@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data,
- 	char *master_desc = NULL;
- 	char *decrypted_datalen = NULL;
- 	char *hex_encoded_iv = NULL;
-+	size_t datalen = prep->datalen;
- 	int ret;
- 
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		return -EINVAL;
- 
- 	datablob = kmalloc(datalen + 1, GFP_KERNEL);
- 	if (!datablob)
- 		return -ENOMEM;
- 	datablob[datalen] = 0;
--	memcpy(datablob, data, datalen);
-+	memcpy(datablob, prep->data, datalen);
- 	ret = datablob_parse(datablob, &format, &master_desc,
- 			     &decrypted_datalen, &hex_encoded_iv);
- 	if (ret < 0)
-@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu)
-  *
-  * On success, return 0. Otherwise return errno.
-  */
--static int encrypted_update(struct key *key, const void *data, size_t datalen)
-+static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct encrypted_key_payload *epayload = key->payload.data;
- 	struct encrypted_key_payload *new_epayload;
- 	char *buf;
- 	char *new_master_desc = NULL;
- 	const char *format = NULL;
-+	size_t datalen = prep->datalen;
- 	int ret = 0;
- 
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		return -EINVAL;
- 
- 	buf = kmalloc(datalen + 1, GFP_KERNEL);
-@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
- 		return -ENOMEM;
- 
- 	buf[datalen] = 0;
--	memcpy(buf, data, datalen);
-+	memcpy(buf, prep->data, datalen);
- 	ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL);
- 	if (ret < 0)
- 		goto out;
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 50d96d4..1d039af 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve);
-  * key_construction_mutex.
-  */
- static int __key_instantiate_and_link(struct key *key,
--				      const void *data,
--				      size_t datalen,
-+				      struct key_preparsed_payload *prep,
- 				      struct key *keyring,
- 				      struct key *authkey,
- 				      unsigned long *_prealloc)
-@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key,
- 	/* can't instantiate twice */
- 	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
- 		/* instantiate the key */
--		ret = key->type->instantiate(key, data, datalen);
-+		ret = key->type->instantiate(key, prep);
- 
- 		if (ret == 0) {
- 			/* mark the key as being instantiated */
-@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key,
- 			     struct key *keyring,
- 			     struct key *authkey)
- {
-+	struct key_preparsed_payload prep;
- 	unsigned long prealloc;
- 	int ret;
- 
-+	memset(&prep, 0, sizeof(prep));
-+	prep.data = data;
-+	prep.datalen = datalen;
-+	prep.quotalen = key->type->def_datalen;
-+	if (key->type->preparse) {
-+		ret = key->type->preparse(&prep);
-+		if (ret < 0)
-+			goto error;
-+	}
-+
- 	if (keyring) {
- 		ret = __key_link_begin(keyring, key->type, key->description,
- 				       &prealloc);
- 		if (ret < 0)
--			return ret;
-+			goto error_free_preparse;
- 	}
- 
--	ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey,
-+	ret = __key_instantiate_and_link(key, &prep, keyring, authkey,
- 					 &prealloc);
- 
- 	if (keyring)
- 		__key_link_end(keyring, key->type, prealloc);
- 
-+error_free_preparse:
-+	if (key->type->preparse)
-+		key->type->free_preparse(&prep);
-+error:
- 	return ret;
- }
- 
-@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype)
-  * if we get an error.
-  */
- static inline key_ref_t __key_update(key_ref_t key_ref,
--				     const void *payload, size_t plen)
-+				     struct key_preparsed_payload *prep)
- {
- 	struct key *key = key_ref_to_ptr(key_ref);
- 	int ret;
-@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
- 
- 	down_write(&key->sem);
- 
--	ret = key->type->update(key, payload, plen);
-+	ret = key->type->update(key, prep);
- 	if (ret == 0)
- 		/* updating a negative key instantiates it */
- 		clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
-@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- 			       unsigned long flags)
- {
- 	unsigned long prealloc;
-+	struct key_preparsed_payload prep;
- 	const struct cred *cred = current_cred();
- 	struct key_type *ktype;
- 	struct key *keyring, *key = NULL;
-@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- 	}
- 
- 	key_ref = ERR_PTR(-EINVAL);
--	if (!ktype->match || !ktype->instantiate)
--		goto error_2;
-+	if (!ktype->match || !ktype->instantiate ||
-+	    (!description && !ktype->preparse))
-+		goto error_put_type;
- 
- 	keyring = key_ref_to_ptr(keyring_ref);
- 
-@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- 
- 	key_ref = ERR_PTR(-ENOTDIR);
- 	if (keyring->type != &key_type_keyring)
--		goto error_2;
-+		goto error_put_type;
-+
-+	memset(&prep, 0, sizeof(prep));
-+	prep.data = payload;
-+	prep.datalen = plen;
-+	prep.quotalen = ktype->def_datalen;
-+	if (ktype->preparse) {
-+		ret = ktype->preparse(&prep);
-+		if (ret < 0) {
-+			key_ref = ERR_PTR(ret);
-+			goto error_put_type;
-+		}
-+		if (!description)
-+			description = prep.description;
-+		key_ref = ERR_PTR(-EINVAL);
-+		if (!description)
-+			goto error_free_prep;
-+	}
- 
- 	ret = __key_link_begin(keyring, ktype, description, &prealloc);
--	if (ret < 0)
--		goto error_2;
-+	if (ret < 0) {
-+		key_ref = ERR_PTR(ret);
-+		goto error_free_prep;
-+	}
- 
- 	/* if we're going to allocate a new key, we're going to have
- 	 * to modify the keyring */
- 	ret = key_permission(keyring_ref, KEY_WRITE);
- 	if (ret < 0) {
- 		key_ref = ERR_PTR(ret);
--		goto error_3;
-+		goto error_link_end;
- 	}
- 
- 	/* if it's possible to update this type of key, search for an existing
-@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- 			perm, flags);
- 	if (IS_ERR(key)) {
- 		key_ref = ERR_CAST(key);
--		goto error_3;
-+		goto error_link_end;
- 	}
- 
- 	/* instantiate it and link it into the target keyring */
--	ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL,
--					 &prealloc);
-+	ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc);
- 	if (ret < 0) {
- 		key_put(key);
- 		key_ref = ERR_PTR(ret);
--		goto error_3;
-+		goto error_link_end;
- 	}
- 
- 	key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
- 
-- error_3:
-+error_link_end:
- 	__key_link_end(keyring, ktype, prealloc);
-- error_2:
-+error_free_prep:
-+	if (ktype->preparse)
-+		ktype->free_preparse(&prep);
-+error_put_type:
- 	key_type_put(ktype);
-- error:
-+error:
- 	return key_ref;
- 
-  found_matching_key:
-@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- 	 * - we can drop the locks first as we have the key pinned
- 	 */
- 	__key_link_end(keyring, ktype, prealloc);
--	key_type_put(ktype);
- 
--	key_ref = __key_update(key_ref, payload, plen);
--	goto error;
-+	key_ref = __key_update(key_ref, &prep);
-+	goto error_free_prep;
- }
- EXPORT_SYMBOL(key_create_or_update);
- 
-@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update);
-  */
- int key_update(key_ref_t key_ref, const void *payload, size_t plen)
- {
-+	struct key_preparsed_payload prep;
- 	struct key *key = key_ref_to_ptr(key_ref);
- 	int ret;
- 
-@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
- 
- 	/* attempt to update it if supported */
- 	ret = -EOPNOTSUPP;
--	if (key->type->update) {
--		down_write(&key->sem);
--
--		ret = key->type->update(key, payload, plen);
--		if (ret == 0)
--			/* updating a negative key instantiates it */
--			clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
-+	if (!key->type->update)
-+		goto error;
- 
--		up_write(&key->sem);
-+	memset(&prep, 0, sizeof(prep));
-+	prep.data = payload;
-+	prep.datalen = plen;
-+	prep.quotalen = key->type->def_datalen;
-+	if (key->type->preparse) {
-+		ret = key->type->preparse(&prep);
-+		if (ret < 0)
-+			goto error;
- 	}
- 
-- error:
-+	down_write(&key->sem);
-+
-+	ret = key->type->update(key, &prep);
-+	if (ret == 0)
-+		/* updating a negative key instantiates it */
-+		clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
-+
-+	up_write(&key->sem);
-+
-+	if (key->type->preparse)
-+		key->type->free_preparse(&prep);
-+error:
- 	return ret;
- }
- EXPORT_SYMBOL(key_update);
-diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
-index 3364fbf..505d40b 100644
---- a/security/keys/keyctl.c
-+++ b/security/keys/keyctl.c
-@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type,
-  * Extract the description of a new key from userspace and either add it as a
-  * new key to the specified keyring or update a matching key in that keyring.
-  *
-+ * If the description is NULL or an empty string, the key type is asked to
-+ * generate one from the payload.
-+ *
-  * The keyring must be writable so that we can attach the key to it.
-  *
-  * If successful, the new key's serial number is returned, otherwise an error
-@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
- 	if (ret < 0)
- 		goto error;
- 
--	description = strndup_user(_description, PAGE_SIZE);
--	if (IS_ERR(description)) {
--		ret = PTR_ERR(description);
--		goto error;
-+	description = NULL;
-+	if (_description) {
-+		description = strndup_user(_description, PAGE_SIZE);
-+		if (IS_ERR(description)) {
-+			ret = PTR_ERR(description);
-+			goto error;
-+		}
-+		if (!*description) {
-+			kfree(description);
-+			description = NULL;
-+		}
- 	}
- 
- 	/* pull the payload in if one was supplied */
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 81e7852..f04d8cf 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc)
-  * operations.
-  */
- static int keyring_instantiate(struct key *keyring,
--			       const void *data, size_t datalen);
-+			       struct key_preparsed_payload *prep);
- static int keyring_match(const struct key *keyring, const void *criterion);
- static void keyring_revoke(struct key *keyring);
- static void keyring_destroy(struct key *keyring);
-@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring)
-  * Returns 0 on success, -EINVAL if given any data.
-  */
- static int keyring_instantiate(struct key *keyring,
--			       const void *data, size_t datalen)
-+			       struct key_preparsed_payload *prep)
- {
- 	int ret;
- 
- 	ret = -EINVAL;
--	if (datalen == 0) {
-+	if (prep->datalen == 0) {
- 		/* make the keyring available by name if it has one */
- 		keyring_publish_name(keyring);
- 		ret = 0;
-diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
-index 60d4e3f..85730d5 100644
---- a/security/keys/request_key_auth.c
-+++ b/security/keys/request_key_auth.c
-@@ -19,7 +19,8 @@
- #include <asm/uaccess.h>
- #include "internal.h"
- 
--static int request_key_auth_instantiate(struct key *, const void *, size_t);
-+static int request_key_auth_instantiate(struct key *,
-+					struct key_preparsed_payload *);
- static void request_key_auth_describe(const struct key *, struct seq_file *);
- static void request_key_auth_revoke(struct key *);
- static void request_key_auth_destroy(struct key *);
-@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = {
-  * Instantiate a request-key authorisation key.
-  */
- static int request_key_auth_instantiate(struct key *key,
--					const void *data,
--					size_t datalen)
-+					struct key_preparsed_payload *prep)
- {
--	key->payload.data = (struct request_key_auth *) data;
-+	key->payload.data = (struct request_key_auth *)prep->data;
- 	return 0;
- }
- 
-diff --git a/security/keys/trusted.c b/security/keys/trusted.c
-index 2d5d041..42036c7 100644
---- a/security/keys/trusted.c
-+++ b/security/keys/trusted.c
-@@ -927,22 +927,23 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
-  *
-  * On success, return 0. Otherwise return errno.
-  */
--static int trusted_instantiate(struct key *key, const void *data,
--			       size_t datalen)
-+static int trusted_instantiate(struct key *key,
-+			       struct key_preparsed_payload *prep)
- {
- 	struct trusted_key_payload *payload = NULL;
- 	struct trusted_key_options *options = NULL;
-+	size_t datalen = prep->datalen;
- 	char *datablob;
- 	int ret = 0;
- 	int key_cmd;
- 	size_t key_len;
-
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		return -EINVAL;
- 
- 	datablob = kmalloc(datalen + 1, GFP_KERNEL);
- 	if (!datablob)
- 		return -ENOMEM;
--	memcpy(datablob, data, datalen);
-+	memcpy(datablob, prep->data, datalen);
- 	datablob[datalen] = '\0';
- 
- 	options = trusted_options_alloc();
-@@ -1011,17 +1012,18 @@ static void trusted_rcu_free(struct rcu_head *rcu)
- /*
-  * trusted_update - reseal an existing key with new PCR values
-  */
--static int trusted_update(struct key *key, const void *data, size_t datalen)
-+static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct trusted_key_payload *p = key->payload.data;
- 	struct trusted_key_payload *new_p;
- 	struct trusted_key_options *new_o;
-+	size_t datalen = prep->datalen;
- 	char *datablob;
- 	int ret = 0;
- 
- 	if (!p->migratable)
- 		return -EPERM;
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		return -EINVAL;
- 
- 	datablob = kmalloc(datalen + 1, GFP_KERNEL);
-@@ -1038,7 +1040,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen)
- 		goto out;
- 	}
- 
--	memcpy(datablob, data, datalen);
-+	memcpy(datablob, prep->data, datalen);
- 	datablob[datalen] = '\0';
- 	ret = datablob_parse(datablob, new_p, new_o);
- 	if (ret != Opt_update) {
-diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
-index c7660a2..55dc889 100644
---- a/security/keys/user_defined.c
-+++ b/security/keys/user_defined.c
-@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon);
- /*
-  * instantiate a user defined key
-  */
--int user_instantiate(struct key *key, const void *data, size_t datalen)
-+int user_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct user_key_payload *upayload;
-+	size_t datalen = prep->datalen;
- 	int ret;
- 
- 	ret = -EINVAL;
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		goto error;
- 
- 	ret = key_payload_reserve(key, datalen);
-@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen)
- 
- 	/* attach the data */
- 	upayload->datalen = datalen;
--	memcpy(upayload->data, data, datalen);
-+	memcpy(upayload->data, prep->data, datalen);
- 	rcu_assign_keypointer(key, upayload);
- 	ret = 0;
- 
-@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate);
-  * update a user defined key
-  * - the key's semaphore is write-locked
-  */
--int user_update(struct key *key, const void *data, size_t datalen)
-+int user_update(struct key *key, struct key_preparsed_payload *prep)
- {
- 	struct user_key_payload *upayload, *zap;
-+	size_t datalen = prep->datalen;
- 	int ret;
- 
- 	ret = -EINVAL;
--	if (datalen <= 0 || datalen > 32767 || !data)
-+	if (datalen <= 0 || datalen > 32767 || !prep->data)
- 		goto error;
- 
- 	/* construct a replacement payload */
-@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
- 		goto error;
- 
- 	upayload->datalen = datalen;
--	memcpy(upayload->data, data, datalen);
-+	memcpy(upayload->data, prep->data, datalen);
- 
- 	/* check the quota and attach the new data */
- 	zap = upayload;
--- 
-1.7.11.4
-
-
-From a3f7dff6cbc2eb6be871a58fef34cacf7f78abf8 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Thu, 13 Sep 2012 13:09:33 +0100
-Subject: [PATCH 03/26] MPILIB: Provide count_leading/trailing_zeros() based
- on arch functions
-
-Provide count_leading/trailing_zeros() macros based on extant arch bit scanning
-functions rather than reimplementing from scratch in MPILIB.
-
-Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x).
-
-Also move the definition to asm-generic as other people may be interested in
-using it.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
-Cc: David S. Miller <davem at davemloft.net>
-Cc: Dmitry Kasatkin <dmitry.kasatkin at intel.com>
-Cc: Arnd Bergmann <arnd at arndb.com>
----
- include/asm-generic/bitops/count_zeros.h |  57 +++++++++++++
- lib/mpi/longlong.h                       | 138 +------------------------------
- lib/mpi/mpi-bit.c                        |   2 +-
- lib/mpi/mpi-pow.c                        |   4 +-
- 4 files changed, 62 insertions(+), 139 deletions(-)
- create mode 100644 include/asm-generic/bitops/count_zeros.h
-
-diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h
-new file mode 100644
-index 0000000..97520d2
---- /dev/null
-+++ b/include/asm-generic/bitops/count_zeros.h
-@@ -0,0 +1,57 @@
-+/* Count leading and trailing zeros functions
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_
-+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_
-+
-+#include <asm/bitops.h>
-+
-+/**
-+ * count_leading_zeros - Count the number of zeros from the MSB back
-+ * @x: The value
-+ *
-+ * Count the number of leading zeros from the MSB going towards the LSB in @x.
-+ *
-+ * If the MSB of @x is set, the result is 0.
-+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1.
-+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0.
-+ */
-+static inline int count_leading_zeros(unsigned long x)
-+{
-+	if (sizeof(x) == 4)
-+		return BITS_PER_LONG - fls(x);
-+	else
-+		return BITS_PER_LONG - fls64(x);
-+}
-+
-+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG
-+
-+/**
-+ * count_trailing_zeros - Count the number of zeros from the LSB forwards
-+ * @x: The value
-+ *
-+ * Count the number of trailing zeros from the LSB going towards the MSB in @x.
-+ *
-+ * If the LSB of @x is set, the result is 0.
-+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1.
-+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0.
-+ */
-+static inline int count_trailing_zeros(unsigned long x)
-+{
-+#define COUNT_TRAILING_ZEROS_0 (-1)
-+
-+	if (sizeof(x) == 4)
-+		return ffs(x);
-+	else
-+		return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0;
-+}
-+
-+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */
-diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
-index 29f9862..678ce4f 100644
---- a/lib/mpi/longlong.h
-+++ b/lib/mpi/longlong.h
-@@ -19,6 +19,8 @@
-  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-  * MA 02111-1307, USA. */
- 
-+#include <asm-generic/bitops/count_zeros.h>
-+
- /* You have to define the following before including this file:
-  *
-  * UWtype -- An unsigned type, default type for operations (typically a "word")
-@@ -146,12 +148,6 @@ do { \
- 	: "1" ((USItype)(n1)), \
- 		"r" ((USItype)(n0)), \
- 		"r" ((USItype)(d)))
--
--#define count_leading_zeros(count, x) \
--	__asm__ ("clz %0,%1" \
--	: "=r" ((USItype)(count)) \
--	: "r" ((USItype)(x)))
--#define COUNT_LEADING_ZEROS_0 32
- #endif /* __a29k__ */
- 
- #if defined(__alpha) && W_TYPE_SIZE == 64
-@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd();
- 	: "1" ((USItype)(nh)), \
- 		"0" ((USItype)(nl)), \
- 		"g" ((USItype)(d)))
--#define count_leading_zeros(count, x) \
--	__asm__ ("bsch/1 %1,%0" \
--	: "=g" (count) \
--	: "g" ((USItype)(x)), \
--	     "0" ((USItype)0))
- #endif
- 
- /***************************************
-@@ -354,27 +345,6 @@ do { USItype __r; \
- } while (0)
- extern USItype __udiv_qrnnd();
- #endif /* LONGLONG_STANDALONE */
--#define count_leading_zeros(count, x) \
--do { \
--	USItype __tmp; \
--	__asm__ ( \
--	"ldi             1,%0\n" \
--	"extru,=	%1,15,16,%%r0  ; Bits 31..16 zero?\n" \
--	"extru,tr	%1,15,16,%1    ; No.  Shift down, skip add.\n" \
--	"ldo		16(%0),%0      ; Yes.	Perform add.\n" \
--	"extru,=	%1,23,8,%%r0   ; Bits 15..8 zero?\n" \
--	"extru,tr	%1,23,8,%1     ; No.  Shift down, skip add.\n" \
--	"ldo		8(%0),%0       ; Yes.	Perform add.\n" \
--	"extru,=	%1,27,4,%%r0   ; Bits 7..4 zero?\n" \
--	"extru,tr	%1,27,4,%1     ; No.  Shift down, skip add.\n" \
--	"ldo		4(%0),%0       ; Yes.	Perform add.\n" \
--	"extru,=	%1,29,2,%%r0   ; Bits 3..2 zero?\n" \
--	"extru,tr	%1,29,2,%1     ; No.  Shift down, skip add.\n" \
--	"ldo		2(%0),%0       ; Yes.	Perform add.\n" \
--	"extru		%1,30,1,%1     ; Extract bit 1.\n" \
--	"sub		%0,%1,%0       ; Subtract it.              " \
--	: "=r" (count), "=r" (__tmp) : "1" (x)); \
--} while (0)
- #endif /* hppa */
- 
- /***************************************
-@@ -457,15 +427,6 @@ do { \
- 	: "0" ((USItype)(n0)), \
- 	     "1" ((USItype)(n1)), \
- 	     "rm" ((USItype)(d)))
--#define count_leading_zeros(count, x) \
--do { \
--	USItype __cbtmp; \
--	__asm__ ("bsrl %1,%0" \
--	: "=r" (__cbtmp) : "rm" ((USItype)(x))); \
--	(count) = __cbtmp ^ 31; \
--} while (0)
--#define count_trailing_zeros(count, x) \
--	__asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
- #ifndef UMUL_TIME
- #define UMUL_TIME 40
- #endif
-@@ -536,15 +497,6 @@ do { \
- 	     "dI" ((USItype)(d))); \
- 	(r) = __rq.__i.__l; (q) = __rq.__i.__h; \
- } while (0)
--#define count_leading_zeros(count, x) \
--do { \
--	USItype __cbtmp; \
--	__asm__ ("scanbit %1,%0" \
--	: "=r" (__cbtmp) \
--	: "r" ((USItype)(x))); \
--	(count) = __cbtmp ^ 31; \
--} while (0)
--#define COUNT_LEADING_ZEROS_0 (-32)	/* sic */
- #if defined(__i960mx)		/* what is the proper symbol to test??? */
- #define rshift_rhlc(r, h, l, c) \
- do { \
-@@ -603,11 +555,6 @@ do { \
- 	: "0" ((USItype)(n0)), \
- 	     "1" ((USItype)(n1)), \
- 	     "dmi" ((USItype)(d)))
--#define count_leading_zeros(count, x) \
--	__asm__ ("bfffo %1{%b2:%b2},%0" \
--	: "=d" ((USItype)(count)) \
--	: "od" ((USItype)(x)), "n" (0))
--#define COUNT_LEADING_ZEROS_0 32
- #else /* not mc68020 */
- #define umul_ppmm(xh, xl, a, b) \
- do { USItype __umul_tmp1, __umul_tmp2; \
-@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \
- 	     "rJ" ((USItype)(bh)), \
- 	     "rJ" ((USItype)(al)), \
- 	     "rJ" ((USItype)(bl)))
--#define count_leading_zeros(count, x) \
--do { \
--	USItype __cbtmp; \
--	__asm__ ("ff1 %0,%1" \
--	: "=r" (__cbtmp) \
--	: "r" ((USItype)(x))); \
--	(count) = __cbtmp ^ 31; \
--} while (0)
--#define COUNT_LEADING_ZEROS_0 63	/* sic */
- #if defined(__m88110__)
- #define umul_ppmm(wh, wl, u, v) \
- do { \
-@@ -779,12 +717,6 @@ do { \
- 	: "0" (__xx.__ll), \
- 	     "g" ((USItype)(d))); \
- 	(r) = __xx.__i.__l; (q) = __xx.__i.__h; })
--#define count_trailing_zeros(count, x) \
--do { \
--	__asm__("ffsd      %2,%0" \
--	: "=r"((USItype) (count)) \
--	: "0"((USItype) 0), "r"((USItype) (x))); \
--	} while (0)
- #endif /* __ns32000__ */
- 
- /***************************************
-@@ -855,11 +787,6 @@ do { \
- 		"rI" ((USItype)(al)), \
- 		"r" ((USItype)(bl))); \
- } while (0)
--#define count_leading_zeros(count, x) \
--	__asm__ ("{cntlz|cntlzw} %0,%1" \
--	: "=r" ((USItype)(count)) \
--	: "r" ((USItype)(x)))
--#define COUNT_LEADING_ZEROS_0 32
- #if defined(_ARCH_PPC)
- #define umul_ppmm(ph, pl, m0, m1) \
- do { \
-@@ -1001,19 +928,6 @@ do { \
- } while (0)
- #define UMUL_TIME 20
- #define UDIV_TIME 200
--#define count_leading_zeros(count, x) \
--do { \
--	if ((x) >= 0x10000) \
--		__asm__ ("clz     %0,%1" \
--		: "=r" ((USItype)(count)) \
--		: "r" ((USItype)(x) >> 16)); \
--	else { \
--		__asm__ ("clz   %0,%1" \
--		: "=r" ((USItype)(count)) \
--		: "r" ((USItype)(x))); \
--		(count) += 16; \
--	} \
--} while (0)
- #endif /* RT/ROMP */
- 
- /***************************************
-@@ -1142,13 +1056,6 @@ do { \
- 	"rI" ((USItype)(d)) \
- 	: "%g1" __AND_CLOBBER_CC)
- #define UDIV_TIME 37
--#define count_leading_zeros(count, x) \
--	__asm__ ("scan %1,0,%0" \
--	: "=r" ((USItype)(x)) \
--	: "r" ((USItype)(count)))
--/* Early sparclites return 63 for an argument of 0, but they warn that future
--	implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
--	undefined.  */
- #endif /* __sparclite__ */
- #endif /* __sparc_v8__ */
- 	/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd.  */
-@@ -1454,47 +1361,6 @@ do { \
- #define udiv_qrnnd __udiv_qrnnd_c
- #endif
- 
--#undef count_leading_zeros
--#if !defined(count_leading_zeros)
--	extern
--#ifdef __STDC__
--			const
--#endif
--			unsigned char __clz_tab[];
--#define count_leading_zeros(count, x) \
--do { \
--	UWtype __xr = (x); \
--	UWtype __a; \
--	\
--	if (W_TYPE_SIZE <= 32) { \
--		__a = __xr < ((UWtype) 1 << 2*__BITS4) \
--		? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \
--		: (__xr < ((UWtype) 1 << 3*__BITS4) ?  2*__BITS4 : 3*__BITS4); \
--	} \
--	else { \
--		for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
--			if (((__xr >> __a) & 0xff) != 0) \
--				break; \
--	} \
--	\
--	(count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
--} while (0)
--	/* This version gives a well-defined value for zero. */
--#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
--#endif
--
--#if !defined(count_trailing_zeros)
--/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
--	defined in asm, but if it is not, the C version above is good enough.  */
--#define count_trailing_zeros(count, x) \
--do { \
--	UWtype __ctz_x = (x); \
--	UWtype __ctz_c; \
--	count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \
--	(count) = W_TYPE_SIZE - 1 - __ctz_c; \
--} while (0)
--#endif
--
- #ifndef UDIV_NEEDS_NORMALIZATION
- #define UDIV_NEEDS_NORMALIZATION 0
- #endif
-diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c
-index 5687248..503537e 100644
---- a/lib/mpi/mpi-bit.c
-+++ b/lib/mpi/mpi-bit.c
-@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a)
- 	if (a->nlimbs) {
- 		mpi_limb_t alimb = a->d[a->nlimbs - 1];
- 		if (alimb)
--			count_leading_zeros(n, alimb);
-+			n = count_leading_zeros(alimb);
- 		else
- 			n = BITS_PER_MPI_LIMB;
- 		n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB;
-diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
-index 67f3e79..5464c87 100644
---- a/lib/mpi/mpi-pow.c
-+++ b/lib/mpi/mpi-pow.c
-@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
- 	mp = mp_marker = mpi_alloc_limb_space(msize);
- 	if (!mp)
- 		goto enomem;
--	count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]);
-+	mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]);
- 	if (mod_shift_cnt)
- 		mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt);
- 	else
-@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
- 
- 		i = esize - 1;
- 		e = ep[i];
--		count_leading_zeros(c, e);
-+		c = count_leading_zeros(e);
- 		e = (e << c) << 1;	/* shift the exp bits to the left, lose msb */
- 		c = BITS_PER_MPI_LIMB - 1 - c;
- 
--- 
-1.7.11.4
-
-
-From 79e4c942f35117b405402acf0f075ff79260e546 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Thu, 13 Sep 2012 15:17:21 +0100
-Subject: [PATCH 04/26] KEYS: Document asymmetric key type
-
-In-source documentation for the asymmetric key type.  This will be located in:
-
-	Documentation/crypto/asymmetric-keys.txt
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- Documentation/crypto/asymmetric-keys.txt | 312 +++++++++++++++++++++++++++++++
- 1 file changed, 312 insertions(+)
- create mode 100644 Documentation/crypto/asymmetric-keys.txt
-
-diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt
-new file mode 100644
-index 0000000..b767590
---- /dev/null
-+++ b/Documentation/crypto/asymmetric-keys.txt
-@@ -0,0 +1,312 @@
-+		=============================================
-+		ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE
-+		=============================================
-+
-+Contents:
-+
-+  - Overview.
-+  - Key identification.
-+  - Accessing asymmetric keys.
-+    - Signature verification.
-+  - Asymmetric key subtypes.
-+  - Instantiation data parsers.
-+
-+
-+========
-+OVERVIEW
-+========
-+
-+The "asymmetric" key type is designed to be a container for the keys used in
-+public-key cryptography, without imposing any particular restrictions on the
-+form or mechanism of the cryptography or form of the key.
-+
-+The asymmetric 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 stored in the
-+key.
-+
-+A completely in-kernel key retention and operation subtype 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 asymmetric key would then
-+merely be an interface to the TPM driver.
-+
-+Also provided is the concept of a data parser.  Data parsers are responsible
-+for extracting information from the blobs of data passed to the instantiation
-+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.
-+
-+A data parser may interpret the data blob as containing the bits representing a
-+key, or it may interpret it as a reference to a key held somewhere else in the
-+system (for example, a TPM).
-+
-+
-+==================
-+KEY IDENTIFICATION
-+==================
-+
-+If a key is added with an empty name, the instantiation data parsers are given
-+the opportunity to pre-parse a key and to determine the description the key
-+should be given from the content of the key.
-+
-+This can then be used to refer to the key, either by complete match or by
-+partial match.  The key type may also use other criteria to refer to a key.
-+
-+The asymmetric key type's match function can then perform a wider range of
-+comparisons 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 asymmetric 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. tpm) will be matched.  For
-+     instance:
-+
-+	keyctl search @s asymmetric tpm: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 asymmetri modsign.0: DSA 5acc2142 []
-+
-+
-+=========================
-+ACCESSING ASYMMETRIC KEYS
-+=========================
-+
-+For general access to asymmetric keys from within the kernel, the following
-+inclusion is required:
-+
-+	#include <crypto/public_key.h>
-+
-+This gives access to functions for dealing with asymmetric / public keys.
-+Three enums are defined there for representing public-key cryptography
-+algorithms:
-+
-+	enum pkey_algo
-+
-+digest algorithms used by those:
-+
-+	enum pkey_hash_algo
-+
-+and key identifier representations:
-+
-+	enum pkey_id_type
-+
-+Note that the key type representation types are required because key
-+identifiers from different standards aren't necessarily compatible.  For
-+instance, PGP generates key identifiers by hashing the key data plus some
-+PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers.
-+
-+The operations defined upon a key are:
-+
-+ (1) Signature verification.
-+
-+Other operations are possible (such as encryption) with the same key data
-+required for verification, but not currently supported, and others
-+(eg. decryption and signature generation) require extra key data.
-+
-+
-+SIGNATURE VERIFICATION
-+----------------------
-+
-+An operation is provided to perform cryptographic signature verification, using
-+an asymmetric key to provide or to provide access to the public key.
-+
-+	int verify_signature(const struct key *key,
-+			     const struct public_key_signature *sig);
-+
-+The caller must have already obtained the key from some source and can then use
-+it to check the signature.  The caller must have parsed the signature and
-+transferred the relevant bits to the structure pointed to by sig.
-+
-+	struct public_key_signature {
-+		u8 *digest;
-+		u8 digest_size;
-+		enum pkey_hash_algo pkey_hash_algo : 8;
-+		u8 nr_mpi;
-+		union {
-+			MPI mpi[2];
-+			...
-+		};
-+	};
-+
-+The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that
-+make up the actual signature must be stored in sig->mpi[] and the count of MPIs
-+placed in sig->nr_mpi.
-+
-+In addition, the data must have been digested by the caller and the resulting
-+hash must be pointed to by sig->digest and the size of the hash be placed in
-+sig->digest_size.
-+
-+The function will return 0 upon success or -EKEYREJECTED if the signature
-+doesn't match.
-+
-+The function may also return -ENOTSUPP if an unsupported public-key algorithm
-+or public-key/hash algorithm combination is specified or the key doesn't
-+support the operation; -EBADMSG or -ERANGE if some of the parameters have weird
-+data; or -ENOMEM if an allocation can't be performed.  -EINVAL can be returned
-+if the key argument is the wrong type or is incompletely set up.
-+
-+
-+=======================
-+ASYMMETRIC KEY SUBTYPES
-+=======================
-+
-+Asymmetric keys have a subtype that defines the set of operations that can be
-+performed on that key and that determines what data is attached as the key
-+payload.  The payload format is entirely at the whim of the subtype.
-+
-+The subtype is selected by the key data parser and the parser must initialise
-+the data required for it.  The asymmetric key retains a reference on the
-+subtype module.
-+
-+The subtype definition structure can be found in:
-+
-+	#include <keys/asymmetric-subtype.h>
-+
-+and looks like the following:
-+
-+	struct asymmetric_key_subtype {
-+		struct module		*owner;
-+		const char		*name;
-+
-+		void (*describe)(const struct key *key, struct seq_file *m);
-+		void (*destroy)(void *payload);
-+		int (*verify_signature)(const struct key *key,
-+					const struct public_key_signature *sig);
-+	};
-+
-+Asymmetric keys point to this with their type_data[0] member.
-+
-+The owner and name fields should be set to the owning module and the name of
-+the subtype.  Currently, the name is only used for print statements.
-+
-+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
-+     asymmetric key will look after freeing the fingerprint and releasing the
-+     reference on the subtype module.
-+
-+ (3) verify_signature().
-+
-+     Optional.  These are the entry points for the key usage operations.
-+     Currently there is only the one defined.  If not set, the caller will be
-+     given -ENOTSUPP.  The subtype may do anything it likes to implement an
-+     operation, including offloading to hardware.
-+
-+
-+==========================
-+INSTANTIATION DATA PARSERS
-+==========================
-+
-+The asymmetric key type doesn't generally want to store or to deal with a raw
-+blob of data that holds the key data.  It would have to parse it and error
-+check it each time it wanted to use it.  Further, the contents of the blob may
-+have various checks that can be performed on it (eg. self-signatures, validity
-+dates) and may contain useful data about the key (identifiers, capabilities).
-+
-+Also, the blob may represent a pointer to some hardware containing the key
-+rather than the key itself.
-+
-+Examples of blob formats for which parsers could be implemented include:
-+
-+ - OpenPGP packet stream [RFC 4880].
-+ - X.509 ASN.1 stream.
-+ - Pointer to TPM key.
-+ - Pointer to UEFI key.
-+
-+During key instantiation each parser in the list is tried until one doesn't
-+return -EBADMSG.
-+
-+The parser definition structure can be found in:
-+
-+	#include <keys/asymmetric-parser.h>
-+
-+and looks like the following:
-+
-+	struct asymmetric_key_parser {
-+		struct module	*owner;
-+		const char	*name;
-+
-+		int (*parse)(struct key_preparsed_payload *prep);
-+	};
-+
-+The owner and name fields should be set to the owning module and the name of
-+the parser.
-+
-+There is currently only a single operation defined by the parser, and it is
-+mandatory:
-+
-+ (1) parse().
-+
-+     This is called to preparse the key from the key creation and update paths.
-+     In particular, it is called during the key creation _before_ a key is
-+     allocated, and as such, is permitted to provide the key's description in
-+     the case that the caller declines to do so.
-+
-+     The caller passes a pointer to the following struct with all of the fields
-+     cleared, except for data, datalen and quotalen [see
-+     Documentation/security/keys.txt].
-+
-+	struct key_preparsed_payload {
-+		char		*description;
-+		void		*type_data[2];
-+		void		*payload;
-+		const void	*data;
-+		size_t		datalen;
-+		size_t		quotalen;
-+	};
-+
-+     The instantiation data is in a blob pointed to by data and is datalen in
-+     size.  The parse() function is not permitted to change these two values at
-+     all, and shouldn't change any of the other values _unless_ they are
-+     recognise the blob format and will not return -EBADMSG to indicate it is
-+     not theirs.
-+
-+     If the parser is happy with the blob, it should propose a description for
-+     the key and attach it to ->description, ->type_data[0] should be set to
-+     point to the subtype to be used, ->payload should be set to point to the
-+     initialised data for that subtype, ->type_data[1] should point to a hex
-+     fingerprint and quotalen should be updated to indicate how much quota this
-+     key should account for.
-+
-+     When clearing up, the data attached to ->type_data[1] and ->description
-+     will be kfree()'d and the data attached to ->payload will be passed to the
-+     subtype's ->destroy() method to be disposed of.  A module reference for
-+     the subtype pointed to by ->type_data[0] will be put.
-+
-+
-+     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.  On success, 0 should be returned.
-+
-+     The key's fingerprint 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_asymmetric_key_parser(struct asymmetric_key_parser *parser);
-+	void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype);
-+
-+Parsers may not have the same name.  The names are otherwise only used for
-+displaying in debugging messages.
--- 
-1.7.11.4
-
-
-From 2fb78e0d337ac41f2cddad18fc5c34374e5298ab Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Thu, 13 Sep 2012 15:17:21 +0100
-Subject: [PATCH 05/26] KEYS: Implement asymmetric key type
-
-Create a key type that can be used to represent an asymmetric key type for use
-in appropriate cryptographic operations, such as encryption, decryption,
-signature generation and signature verification.
-
-The key type is "asymmetric" and can provide access to a variety of
-cryptographic algorithms.
-
-Possibly, this would be better as "public_key" - but that has the disadvantage
-that "public key" is an overloaded term.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/Kconfig                           |   1 +
- crypto/Makefile                          |   1 +
- crypto/asymmetric_keys/Kconfig           |  13 +++
- crypto/asymmetric_keys/Makefile          |   7 ++
- crypto/asymmetric_keys/asymmetric_keys.h |  15 +++
- crypto/asymmetric_keys/asymmetric_type.c | 156 +++++++++++++++++++++++++++++++
- include/keys/asymmetric-subtype.h        |  55 +++++++++++
- include/keys/asymmetric-type.h           |  25 +++++
- 8 files changed, 273 insertions(+)
- create mode 100644 crypto/asymmetric_keys/Kconfig
- create mode 100644 crypto/asymmetric_keys/Makefile
- create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h
- create mode 100644 crypto/asymmetric_keys/asymmetric_type.c
- create mode 100644 include/keys/asymmetric-subtype.h
- create mode 100644 include/keys/asymmetric-type.h
-
-diff --git a/crypto/Kconfig b/crypto/Kconfig
-index a323805..1ca0b24 100644
---- a/crypto/Kconfig
-+++ b/crypto/Kconfig
-@@ -1043,5 +1043,6 @@ config CRYPTO_USER_API_SKCIPHER
- 	  key cipher algorithms.
- 
- source "drivers/crypto/Kconfig"
-+source crypto/asymmetric_keys/Kconfig
- 
- endif	# if CRYPTO
-diff --git a/crypto/Makefile b/crypto/Makefile
-index 30f33d6..ced472e 100644
---- a/crypto/Makefile
-+++ b/crypto/Makefile
-@@ -96,3 +96,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
- #
- obj-$(CONFIG_XOR_BLOCKS) += xor.o
- obj-$(CONFIG_ASYNC_CORE) += async_tx/
-+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
-diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-new file mode 100644
-index 0000000..cad29b3
---- /dev/null
-+++ b/crypto/asymmetric_keys/Kconfig
-@@ -0,0 +1,13 @@
-+menuconfig ASYMMETRIC_KEY_TYPE
-+	tristate "Asymmetric (public-key cryptographic) key type"
-+	depends on KEYS
-+	help
-+	  This option provides support for a key type that holds the data for
-+	  the asymmetric keys used for public key cryptographic operations such
-+	  as encryption, decryption, signature generation and signature
-+	  verification.
-+
-+if ASYMMETRIC_KEY_TYPE
-+
-+
-+endif # ASYMMETRIC_KEY_TYPE
-diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
-new file mode 100644
-index 0000000..b725bcc
---- /dev/null
-+++ b/crypto/asymmetric_keys/Makefile
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for asymmetric cryptographic keys
-+#
-+
-+obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
-+
-+asymmetric_keys-y := asymmetric_type.o
-diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h
-new file mode 100644
-index 0000000..515b634
---- /dev/null
-+++ b/crypto/asymmetric_keys/asymmetric_keys.h
-@@ -0,0 +1,15 @@
-+/* Internal definitions for asymmetric key type
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+static inline const char *asymmetric_key_id(const struct key *key)
-+{
-+	return key->type_data.p[1];
-+}
-diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
-new file mode 100644
-index 0000000..bfb0424
---- /dev/null
-+++ b/crypto/asymmetric_keys/asymmetric_type.c
-@@ -0,0 +1,156 @@
-+/* Asymmetric public-key cryptography key type
-+ *
-+ * See Documentation/security/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+#include <keys/asymmetric-subtype.h>
-+#include <linux/seq_file.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include "asymmetric_keys.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * Match asymmetric 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 asymmetric_key_match(const struct key *key, const void *description)
-+{
-+	const struct asymmetric_key_subtype *subtype = asymmetric_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 = asymmetric_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 asymmetric key
-+ */
-+static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
-+{
-+	const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
-+	const char *kid = asymmetric_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 asymmetric_key defined key.  The key was preparsed, so we just
-+ * have to transfer the data here.
-+ */
-+static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+/*
-+ * dispose of the data dangling from the corpse of a asymmetric key
-+ */
-+static void asymmetric_key_destroy(struct key *key)
-+{
-+	struct asymmetric_key_subtype *subtype = asymmetric_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_asymmetric = {
-+	.name		= "asymmetric",
-+	.instantiate	= asymmetric_key_instantiate,
-+	.match		= asymmetric_key_match,
-+	.destroy	= asymmetric_key_destroy,
-+	.describe	= asymmetric_key_describe,
-+};
-+EXPORT_SYMBOL_GPL(key_type_asymmetric);
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init asymmetric_key_init(void)
-+{
-+	return register_key_type(&key_type_asymmetric);
-+}
-+
-+static void __exit asymmetric_key_cleanup(void)
-+{
-+	unregister_key_type(&key_type_asymmetric);
-+}
-+
-+module_init(asymmetric_key_init);
-+module_exit(asymmetric_key_cleanup);
-diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h
-new file mode 100644
-index 0000000..4b840e8
---- /dev/null
-+++ b/include/keys/asymmetric-subtype.h
-@@ -0,0 +1,55 @@
-+/* Asymmetric public-key cryptography key subtype
-+ *
-+ * See Documentation/security/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _KEYS_ASYMMETRIC_SUBTYPE_H
-+#define _KEYS_ASYMMETRIC_SUBTYPE_H
-+
-+#include <linux/seq_file.h>
-+#include <keys/asymmetric-type.h>
-+
-+struct public_key_signature;
-+
-+/*
-+ * Keys of this type declare a subtype that indicates the handlers and
-+ * capabilities.
-+ */
-+struct asymmetric_key_subtype {
-+	struct module		*owner;
-+	const char		*name;
-+	unsigned short		name_len;	/* length of name */
-+
-+	/* Describe a key of this subtype for /proc/keys */
-+	void (*describe)(const struct key *key, struct seq_file *m);
-+
-+	/* Destroy a key of this subtype */
-+	void (*destroy)(void *payload);
-+
-+	/* Verify the signature on a key of this subtype (optional) */
-+	int (*verify_signature)(const struct key *key,
-+				const struct public_key_signature *sig);
-+};
-+
-+/**
-+ * asymmetric_key_subtype - Get the subtype from an asymmetric key
-+ * @key: The key of interest.
-+ *
-+ * Retrieves and returns the subtype pointer of the asymmetric key from the
-+ * type-specific data attached to the key.
-+ */
-+static inline
-+struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key)
-+{
-+	return key->type_data.p[0];
-+}
-+
-+#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */
-diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h
-new file mode 100644
-index 0000000..7dd4734
---- /dev/null
-+++ b/include/keys/asymmetric-type.h
-@@ -0,0 +1,25 @@
-+/* Asymmetric Public-key cryptography key type interface
-+ *
-+ * See Documentation/security/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _KEYS_ASYMMETRIC_TYPE_H
-+#define _KEYS_ASYMMETRIC_TYPE_H
-+
-+#include <linux/key-type.h>
-+
-+extern struct key_type key_type_asymmetric;
-+
-+/*
-+ * The payload is at the discretion of the subtype.
-+ */
-+
-+#endif /* _KEYS_ASYMMETRIC_TYPE_H */
--- 
-1.7.11.4
-
-
-From d28ffd9e0c8987e5af59ae38bb48779b0d221f00 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Thu, 13 Sep 2012 15:17:32 +0100
-Subject: [PATCH 06/26] KEYS: Asymmetric key pluggable data parsers
-
-The instantiation data passed to the asymmetric key type are expected to be
-formatted in some way, and there are several possible standard ways to format
-the data.
-
-The two obvious standards are OpenPGP keys and X.509 certificates.  The latter
-is especially useful when dealing with UEFI, and the former might be useful
-when dealing with, say, eCryptfs.
-
-Further, it might be desirable to provide formatted blobs that indicate
-hardware is to be accessed to retrieve the keys or that the keys live
-unretrievably in a hardware store, but that the keys can be used by means of
-the hardware.
-
-From userspace, the keys can be loaded using the keyctl command, for example,
-an X.509 binary certificate:
-
-	keyctl padd asymmetric foo @s <dhowells.pem
-
-or a PGP key:
-
-	keyctl padd asymmetric bar @s <dhowells.pub
-
-or a pointer into the contents of the TPM:
-
-	keyctl add asymmetric zebra "TPM:04982390582905f8" @s
-
-Inside the kernel, pluggable parsers register themselves and then get to
-examine the payload data to see if they can handle it.  If they can, they get
-to:
-
-  (1) Propose a name for the key, to be used it the name is "" or NULL.
-
-  (2) Specify the key subtype.
-
-  (3) Provide the data for the subtype.
-
-The key type asks the parser to do its stuff before a key is allocated and thus
-before the name is set.  If successful, the parser stores the suggested data
-into the key_preparsed_payload struct, which will be either used (if the key is
-successfully created and instantiated or updated) or discarded.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/asymmetric_type.c | 120 ++++++++++++++++++++++++++++++-
- include/keys/asymmetric-parser.h         |  37 ++++++++++
- 2 files changed, 156 insertions(+), 1 deletion(-)
- create mode 100644 include/keys/asymmetric-parser.h
-
-diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
-index bfb0424..cf80765 100644
---- a/crypto/asymmetric_keys/asymmetric_type.c
-+++ b/crypto/asymmetric_keys/asymmetric_type.c
-@@ -11,6 +11,7 @@
-  * 2 of the Licence, or (at your option) any later version.
-  */
- #include <keys/asymmetric-subtype.h>
-+#include <keys/asymmetric-parser.h>
- #include <linux/seq_file.h>
- #include <linux/module.h>
- #include <linux/slab.h>
-@@ -18,6 +19,9 @@
- 
- MODULE_LICENSE("GPL");
- 
-+static LIST_HEAD(asymmetric_key_parsers);
-+static DECLARE_RWSEM(asymmetric_key_parsers_sem);
-+
- /*
-  * Match asymmetric keys on (part of) their name
-  * We have some shorthand methods for matching keys.  We allow:
-@@ -107,12 +111,79 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
- }
- 
- /*
-+ * Preparse a asymmetric payload to get format the contents appropriately for the
-+ * internal payload to cut down on the number of scans of the data performed.
-+ *
-+ * We also generate a proposed description from the contents of the key that
-+ * can be used to name the key if the user doesn't want to provide one.
-+ */
-+static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
-+{
-+	struct asymmetric_key_parser *parser;
-+	int ret;
-+
-+	pr_devel("==>%s()\n", __func__);
-+
-+	if (prep->datalen == 0)
-+		return -EINVAL;
-+
-+	down_read(&asymmetric_key_parsers_sem);
-+
-+	ret = -EBADMSG;
-+	list_for_each_entry(parser, &asymmetric_key_parsers, link) {
-+		pr_debug("Trying parser '%s'\n", parser->name);
-+
-+		ret = parser->parse(prep);
-+		if (ret != -EBADMSG) {
-+			pr_debug("Parser recognised the format (ret %d)\n",
-+				 ret);
-+			break;
-+		}
-+	}
-+
-+	up_read(&asymmetric_key_parsers_sem);
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ret;
-+}
-+
-+/*
-+ * Clean up the preparse data
-+ */
-+static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
-+{
-+	struct asymmetric_key_subtype *subtype = prep->type_data[0];
-+
-+	pr_devel("==>%s()\n", __func__);
-+
-+	if (subtype) {
-+		subtype->destroy(prep->payload);
-+		module_put(subtype->owner);
-+	}
-+	kfree(prep->type_data[1]);
-+	kfree(prep->description);
-+}
-+
-+/*
-  * Instantiate a asymmetric_key defined key.  The key was preparsed, so we just
-  * have to transfer the data here.
-  */
- static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- {
--	return -EOPNOTSUPP;
-+	int ret;
-+
-+	pr_devel("==>%s()\n", __func__);
-+
-+	ret = key_payload_reserve(key, prep->quotalen);
-+	if (ret == 0) {
-+		key->type_data.p[0] = prep->type_data[0];
-+		key->type_data.p[1] = prep->type_data[1];
-+		key->payload.data = prep->payload;
-+		prep->type_data[0] = NULL;
-+		prep->type_data[1] = NULL;
-+		prep->payload = NULL;
-+	}
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ret;
- }
- 
- /*
-@@ -132,6 +203,8 @@ static void asymmetric_key_destroy(struct key *key)
- 
- struct key_type key_type_asymmetric = {
- 	.name		= "asymmetric",
-+	.preparse	= asymmetric_key_preparse,
-+	.free_preparse	= asymmetric_key_free_preparse,
- 	.instantiate	= asymmetric_key_instantiate,
- 	.match		= asymmetric_key_match,
- 	.destroy	= asymmetric_key_destroy,
-@@ -139,6 +212,51 @@ struct key_type key_type_asymmetric = {
- };
- EXPORT_SYMBOL_GPL(key_type_asymmetric);
- 
-+/**
-+ * register_asymmetric_key_parser - Register a asymmetric key blob parser
-+ * @parser: The parser to register
-+ */
-+int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
-+{
-+	struct asymmetric_key_parser *cursor;
-+	int ret;
-+
-+	down_write(&asymmetric_key_parsers_sem);
-+
-+	list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
-+		if (strcmp(cursor->name, parser->name) == 0) {
-+			pr_err("Asymmetric key parser '%s' already registered\n",
-+			       parser->name);
-+			ret = -EEXIST;
-+			goto out;
-+		}
-+	}
-+
-+	list_add_tail(&parser->link, &asymmetric_key_parsers);
-+
-+	pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
-+	ret = 0;
-+
-+out:
-+	up_write(&asymmetric_key_parsers_sem);
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
-+
-+/**
-+ * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
-+ * @parser: The parser to unregister
-+ */
-+void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
-+{
-+	down_write(&asymmetric_key_parsers_sem);
-+	list_del(&parser->link);
-+	up_write(&asymmetric_key_parsers_sem);
-+
-+	pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
-+}
-+EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
-+
- /*
-  * Module stuff
-  */
-diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h
-new file mode 100644
-index 0000000..09b3b48
---- /dev/null
-+++ b/include/keys/asymmetric-parser.h
-@@ -0,0 +1,37 @@
-+/* Asymmetric public-key cryptography data parser
-+ *
-+ * See Documentation/crypto/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _KEYS_ASYMMETRIC_PARSER_H
-+#define _KEYS_ASYMMETRIC_PARSER_H
-+
-+/*
-+ * Key data parser.  Called during key instantiation.
-+ */
-+struct asymmetric_key_parser {
-+	struct list_head	link;
-+	struct module		*owner;
-+	const char		*name;
-+
-+	/* Attempt to parse a key from the data blob passed to add_key() or
-+	 * keyctl_instantiate().  Should also generate a proposed description
-+	 * that the caller can optionally use for the key.
-+	 *
-+	 * Return EBADMSG if not recognised.
-+	 */
-+	int (*parse)(struct key_preparsed_payload *prep);
-+};
-+
-+extern int register_asymmetric_key_parser(struct asymmetric_key_parser *);
-+extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *);
-+
-+#endif /* _KEYS_ASYMMETRIC_PARSER_H */
--- 
-1.7.11.4
-
-
-From 171881bb3693176db4d0f85f78066fcdb6266525 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:24:55 +0100
-Subject: [PATCH 07/26] KEYS: Asymmetric public-key algorithm crypto key
- subtype
-
-Add a subtype for supporting asymmetric public-key encryption algorithms such
-as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337).
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/Kconfig      |   8 +++
- crypto/asymmetric_keys/Makefile     |   2 +
- crypto/asymmetric_keys/public_key.c | 108 ++++++++++++++++++++++++++++++++++++
- crypto/asymmetric_keys/public_key.h |  28 ++++++++++
- include/crypto/public_key.h         | 104 ++++++++++++++++++++++++++++++++++
- 5 files changed, 250 insertions(+)
- create mode 100644 crypto/asymmetric_keys/public_key.c
- create mode 100644 crypto/asymmetric_keys/public_key.h
- create mode 100644 include/crypto/public_key.h
-
-diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-index cad29b3..bbfccaa 100644
---- a/crypto/asymmetric_keys/Kconfig
-+++ b/crypto/asymmetric_keys/Kconfig
-@@ -9,5 +9,13 @@ menuconfig ASYMMETRIC_KEY_TYPE
- 
- if ASYMMETRIC_KEY_TYPE
- 
-+config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-+	tristate "Asymmetric public-key crypto algorithm subtype"
-+	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.
- 
- endif # ASYMMETRIC_KEY_TYPE
-diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
-index b725bcc..5ed46ee 100644
---- a/crypto/asymmetric_keys/Makefile
-+++ b/crypto/asymmetric_keys/Makefile
-@@ -5,3 +5,5 @@
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
- 
- asymmetric_keys-y := asymmetric_type.o
-+
-+obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
-diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
-new file mode 100644
-index 0000000..cb2e291
---- /dev/null
-+++ b/crypto/asymmetric_keys/public_key.c
-@@ -0,0 +1,108 @@
-+/* In-software asymmetric public-key crypto subtype
-+ *
-+ * See Documentation/crypto/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "PKEY: "fmt
-+#include <linux/module.h>
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/seq_file.h>
-+#include <keys/asymmetric-subtype.h>
-+#include "public_key.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+const char *const pkey_algo[PKEY_ALGO__LAST] = {
-+	[PKEY_ALGO_DSA]		= "DSA",
-+	[PKEY_ALGO_RSA]		= "RSA",
-+};
-+EXPORT_SYMBOL_GPL(pkey_algo);
-+
-+const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
-+	[PKEY_HASH_MD4]		= "md4",
-+	[PKEY_HASH_MD5]		= "md5",
-+	[PKEY_HASH_SHA1]	= "sha1",
-+	[PKEY_HASH_RIPE_MD_160]	= "rmd160",
-+	[PKEY_HASH_SHA256]	= "sha256",
-+	[PKEY_HASH_SHA384]	= "sha384",
-+	[PKEY_HASH_SHA512]	= "sha512",
-+	[PKEY_HASH_SHA224]	= "sha224",
-+};
-+EXPORT_SYMBOL_GPL(pkey_hash_algo);
-+
-+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = {
-+	[PKEY_ID_PGP]		= "PGP",
-+	[PKEY_ID_X509]		= "X509",
-+};
-+EXPORT_SYMBOL_GPL(pkey_id_type);
-+
-+/*
-+ * Provide a part of a description of the key for /proc/keys.
-+ */
-+static void public_key_describe(const struct key *asymmetric_key,
-+				struct seq_file *m)
-+{
-+	struct public_key *key = asymmetric_key->payload.data;
-+
-+	if (key)
-+		seq_printf(m, "%s.%s",
-+			   pkey_id_type[key->id_type], key->algo->name);
-+}
-+
-+/*
-+ * Destroy a public key algorithm key.
-+ */
-+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);
-+	}
-+}
-+EXPORT_SYMBOL_GPL(public_key_destroy);
-+
-+/*
-+ * Verify a signature using a public key.
-+ */
-+static int public_key_verify_signature(const struct key *key,
-+				       const struct public_key_signature *sig)
-+{
-+	const struct public_key *pk = key->payload.data;
-+
-+	if (!pk->algo->verify_signature)
-+		return -ENOTSUPP;
-+
-+	if (sig->nr_mpi != pk->algo->n_sig_mpi) {
-+		pr_debug("Signature has %u MPI not %u\n",
-+			 sig->nr_mpi, pk->algo->n_sig_mpi);
-+		return -EINVAL;
-+	}
-+
-+	return pk->algo->verify_signature(pk, sig);
-+}
-+
-+/*
-+ * Public key algorithm asymmetric key subtype
-+ */
-+struct asymmetric_key_subtype public_key_subtype = {
-+	.owner			= THIS_MODULE,
-+	.name			= "public_key",
-+	.describe		= public_key_describe,
-+	.destroy		= public_key_destroy,
-+	.verify_signature	= public_key_verify_signature,
-+};
-+EXPORT_SYMBOL_GPL(public_key_subtype);
-diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
-new file mode 100644
-index 0000000..1f86aad
---- /dev/null
-+++ b/crypto/asymmetric_keys/public_key.h
-@@ -0,0 +1,28 @@
-+/* Public key algorithm internals
-+ *
-+ * See Documentation/crypto/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <crypto/public_key.h>
-+
-+extern struct asymmetric_key_subtype public_key_subtype;
-+
-+/*
-+ * Public key algorithm 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_signature)(const struct public_key *key,
-+				const struct public_key_signature *sig);
-+};
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-new file mode 100644
-index 0000000..4b8b6c1
---- /dev/null
-+++ b/include/crypto/public_key.h
-@@ -0,0 +1,104 @@
-+/* Asymmetric public-key algorithm definitions
-+ *
-+ * See Documentation/crypto/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_PUBLIC_KEY_H
-+#define _LINUX_PUBLIC_KEY_H
-+
-+#include <linux/mpi.h>
-+
-+enum pkey_algo {
-+	PKEY_ALGO_DSA,
-+	PKEY_ALGO_RSA,
-+	PKEY_ALGO__LAST
-+};
-+
-+extern const char *const pkey_algo[PKEY_ALGO__LAST];
-+
-+enum pkey_hash_algo {
-+	PKEY_HASH_MD4,
-+	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
-+};
-+
-+extern const char *const pkey_hash_algo[PKEY_HASH__LAST];
-+
-+enum pkey_id_type {
-+	PKEY_ID_PGP,		/* OpenPGP generated key ID */
-+	PKEY_ID_X509,		/* X.509 arbitrary subjectKeyIdentifier */
-+	PKEY_ID_TYPE__LAST
-+};
-+
-+extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST];
-+
-+/*
-+ * Cryptographic data for the public-key subtype of the asymmetric key type.
-+ *
-+ * Note that this may include private part of the key as well as the public
-+ * part.
-+ */
-+struct public_key {
-+	const struct public_key_algorithm *algo;
-+	u8	capabilities;
-+#define PKEY_CAN_ENCRYPT	0x01
-+#define PKEY_CAN_DECRYPT	0x02
-+#define PKEY_CAN_SIGN		0x04
-+#define PKEY_CAN_VERIFY		0x08
-+	enum pkey_id_type id_type : 8;
-+	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;
-+	};
-+};
-+
-+extern void public_key_destroy(void *payload);
-+
-+/*
-+ * Public key cryptography signature data
-+ */
-+struct public_key_signature {
-+	u8 *digest;
-+	u8 digest_size;			/* Number of bytes in digest */
-+	u8 nr_mpi;			/* Occupancy of mpi[] */
-+	enum pkey_hash_algo pkey_hash_algo : 8;
-+	union {
-+		MPI mpi[2];
-+		struct {
-+			MPI s;		/* m^d mod n */
-+		} rsa;
-+		struct {
-+			MPI r;
-+			MPI s;
-+		} dsa;
-+	};
-+};
-+
-+#endif /* _LINUX_PUBLIC_KEY_H */
--- 
-1.7.11.4
-
-
-From 8e45e274bb3f8bb90306e0102a2c48ea1ef179fb Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:25:04 +0100
-Subject: [PATCH 08/26] KEYS: Provide signature verification with an
- asymmetric key
-
-Provide signature verification using an asymmetric-type key to indicate the
-public key to be used.
-
-The API is a single function that can be found in crypto/public_key.h:
-
-	int verify_signature(const struct key *key,
-			     const struct public_key_signature *sig)
-
-The first argument is the appropriate key to be used and the second argument
-is the parsed signature data:
-
-	struct public_key_signature {
-		u8 *digest;
-		u16 digest_size;
-		enum pkey_hash_algo pkey_hash_algo : 8;
-		union {
-			MPI mpi[2];
-			struct {
-				MPI s;		/* m^d mod n */
-			} rsa;
-			struct {
-				MPI r;
-				MPI s;
-			} dsa;
-		};
-	};
-
-This should be filled in prior to calling the function.  The hash algorithm
-should already have been called and the hash finalised and the output should
-be in a buffer pointed to by the 'digest' member.
-
-Any extra data to be added to the hash by the hash format (eg. PGP) should
-have been added by the caller prior to finalising the hash.
-
-It is assumed that the signature is made up of a number of MPI values.  If an
-algorithm becomes available for which this is not the case, the above structure
-will have to change.
-
-It is also assumed that it will have been checked that the signature algorithm
-matches the key algorithm.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/Makefile    |  2 +-
- crypto/asymmetric_keys/signature.c | 49 ++++++++++++++++++++++++++++++++++++++
- include/crypto/public_key.h        |  4 ++++
- 3 files changed, 54 insertions(+), 1 deletion(-)
- create mode 100644 crypto/asymmetric_keys/signature.c
-
-diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
-index 5ed46ee..8dcdf0c 100644
---- a/crypto/asymmetric_keys/Makefile
-+++ b/crypto/asymmetric_keys/Makefile
-@@ -4,6 +4,6 @@
- 
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
- 
--asymmetric_keys-y := asymmetric_type.o
-+asymmetric_keys-y := asymmetric_type.o signature.o
- 
- obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
-diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
-new file mode 100644
-index 0000000..50b3f88
---- /dev/null
-+++ b/crypto/asymmetric_keys/signature.c
-@@ -0,0 +1,49 @@
-+/* Signature verification with an asymmetric key
-+ *
-+ * See Documentation/security/asymmetric-keys.txt
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <keys/asymmetric-subtype.h>
-+#include <linux/module.h>
-+#include <linux/err.h>
-+#include <crypto/public_key.h>
-+#include "asymmetric_keys.h"
-+
-+/**
-+ * verify_signature - Initiate the use of an asymmetric key to verify a signature
-+ * @key: The asymmetric key to verify against
-+ * @sig: The signature to check
-+ *
-+ * Returns 0 if successful or else an error.
-+ */
-+int verify_signature(const struct key *key,
-+		     const struct public_key_signature *sig)
-+{
-+	const struct asymmetric_key_subtype *subtype;
-+	int ret;
-+
-+	pr_devel("==>%s()\n", __func__);
-+
-+	if (key->type != &key_type_asymmetric)
-+		return -EINVAL;
-+	subtype = asymmetric_key_subtype(key);
-+	if (!subtype ||
-+	    !key->payload.data)
-+		return -EINVAL;
-+	if (!subtype->verify_signature)
-+		return -ENOTSUPP;
-+
-+	ret = subtype->verify_signature(key, sig);
-+
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(verify_signature);
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-index 4b8b6c1..f5b0224 100644
---- a/include/crypto/public_key.h
-+++ b/include/crypto/public_key.h
-@@ -101,4 +101,8 @@ struct public_key_signature {
- 	};
- };
- 
-+struct key;
-+extern int verify_signature(const struct key *key,
-+			    const struct public_key_signature *sig);
-+
- #endif /* _LINUX_PUBLIC_KEY_H */
--- 
-1.7.11.4
-
-
-From 941e72448fc68f41a56798112a6f20df6bcd0ad0 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:25:22 +0100
-Subject: [PATCH 09/26] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA
- signature verification
-
-Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by
-RSA signature verification as per RFC3447 section 5.2.2 step 1.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- lib/mpi/Makefile  |  1 +
- lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 71 insertions(+)
- create mode 100644 lib/mpi/mpi-cmp.c
-
-diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile
-index 45ca90a..019a68c 100644
---- a/lib/mpi/Makefile
-+++ b/lib/mpi/Makefile
-@@ -14,6 +14,7 @@ mpi-y = \
- 	generic_mpih-add1.o		\
- 	mpicoder.o			\
- 	mpi-bit.o			\
-+	mpi-cmp.o			\
- 	mpih-cmp.o			\
- 	mpih-div.o			\
- 	mpih-mul.o			\
-diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
-new file mode 100644
-index 0000000..1871e7b
---- /dev/null
-+++ b/lib/mpi/mpi-cmp.c
-@@ -0,0 +1,70 @@
-+/* mpi-cmp.c  -  MPI functions
-+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
-+ *
-+ * This file is part of GnuPG.
-+ *
-+ * GnuPG 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.
-+ *
-+ * GnuPG is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-+ */
-+
-+#include "mpi-internal.h"
-+
-+int mpi_cmp_ui(MPI u, unsigned long v)
-+{
-+	mpi_limb_t limb = v;
-+
-+	mpi_normalize(u);
-+	if (!u->nlimbs && !limb)
-+		return 0;
-+	if (u->sign)
-+		return -1;
-+	if (u->nlimbs > 1)
-+		return 1;
-+
-+	if (u->d[0] == limb)
-+		return 0;
-+	else if (u->d[0] > limb)
-+		return 1;
-+	else
-+		return -1;
-+}
-+EXPORT_SYMBOL_GPL(mpi_cmp_ui);
-+
-+int mpi_cmp(MPI u, MPI v)
-+{
-+	mpi_size_t usize, vsize;
-+	int cmp;
-+
-+	mpi_normalize(u);
-+	mpi_normalize(v);
-+	usize = u->nlimbs;
-+	vsize = v->nlimbs;
-+	if (!u->sign && v->sign)
-+		return 1;
-+	if (u->sign && !v->sign)
-+		return -1;
-+	if (usize != vsize && !u->sign && !v->sign)
-+		return usize - vsize;
-+	if (usize != vsize && u->sign && v->sign)
-+		return vsize + usize;
-+	if (!usize)
-+		return 0;
-+	cmp = mpihelp_cmp(u->d, v->d, usize);
-+	if (!cmp)
-+		return 0;
-+	if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0))
-+		return 1;
-+	return -1;
-+}
-+EXPORT_SYMBOL_GPL(mpi_cmp);
--- 
-1.7.11.4
-
-
-From ca876ff8fde3c6febb8a8578ca0e1608576071bf Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:25:40 +0100
-Subject: [PATCH 10/26] RSA: Implement signature verification algorithm
- [PKCS#1 / RFC3447]
-
-Implement RSA public key cryptography [PKCS#1 / RFC3447].  At this time, only
-the signature verification algorithm is supported.  This uses the asymmetric
-public key subtype to hold its key data.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/Kconfig      |   7 +
- crypto/asymmetric_keys/Makefile     |   1 +
- crypto/asymmetric_keys/public_key.h |   2 +
- crypto/asymmetric_keys/rsa.c        | 269 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 279 insertions(+)
- create mode 100644 crypto/asymmetric_keys/rsa.c
-
-diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-index bbfccaa..561759d 100644
---- a/crypto/asymmetric_keys/Kconfig
-+++ b/crypto/asymmetric_keys/Kconfig
-@@ -18,4 +18,11 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
- 	  appropriate hash algorithms (such as SHA-1) must be available.
- 	  ENOPKG will be reported if the requisite algorithm is unavailable.
- 
-+config PUBLIC_KEY_ALGO_RSA
-+	tristate "RSA public-key algorithm"
-+	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-+	select MPILIB_EXTRA
-+	help
-+	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
-+
- endif # ASYMMETRIC_KEY_TYPE
-diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
-index 8dcdf0c..7c92691 100644
---- a/crypto/asymmetric_keys/Makefile
-+++ b/crypto/asymmetric_keys/Makefile
-@@ -7,3 +7,4 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
- asymmetric_keys-y := asymmetric_type.o signature.o
- 
- obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
-+obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
-diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
-index 1f86aad..5e5e356 100644
---- a/crypto/asymmetric_keys/public_key.h
-+++ b/crypto/asymmetric_keys/public_key.h
-@@ -26,3 +26,5 @@ struct public_key_algorithm {
- 	int (*verify_signature)(const struct public_key *key,
- 				const struct public_key_signature *sig);
- };
-+
-+extern const struct public_key_algorithm RSA_public_key_algorithm;
-diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
-new file mode 100644
-index 0000000..9b31ee2
---- /dev/null
-+++ b/crypto/asymmetric_keys/rsa.c
-@@ -0,0 +1,269 @@
-+/* RSA asymmetric public-key algorithm [RFC3447]
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "RSA: "fmt
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include "public_key.h"
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("RSA Public Key Algorithm");
-+
-+#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 *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("");
-+
-+	if (!RSA_ASN1_templates[sig->pkey_hash_algo].data)
-+		return -ENOTSUPP;
-+
-+	/* (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;
-+
-+	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_signature = RSA_verify_signature,
-+};
-+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
--- 
-1.7.11.4
-
-
-From e179a9b04469ea018a8fdb53f11c57222ba540a0 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:28:05 +0100
-Subject: [PATCH 11/26] RSA: 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 at redhat.com>
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/rsa.c | 14 +++++++++++---
- 1 file changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
-index 9b31ee2..4a6a069 100644
---- a/crypto/asymmetric_keys/rsa.c
-+++ b/crypto/asymmetric_keys/rsa.c
-@@ -224,15 +224,23 @@ static int RSA_verify_signature(const struct public_key *key,
- 		return -ENOTSUPP;
- 
- 	/* (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.11.4
-
-
-From d412c256ea6170b6aeceb9f1eb1737d991473634 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:30:46 +0100
-Subject: [PATCH 12/26] X.509: Implement simple static OID registry
-
-Implement a simple static OID registry that allows the mapping of an encoded
-OID to an enum value for ease of use.
-
-The OID registry index enum appears in the:
-
-	linux/oid_registry.h
-
-header file.  A script generates the registry from lines in the header file
-that look like:
-
-	<sp*>OID_foo,<sp*>/*<sp*>1.2.3.4<sp*>*/
-
-The actual OID is taken to be represented by the numbers with interpolated
-dots in the comment.
-
-All other lines in the header are ignored.
-
-The registry is queries by calling:
-
-	OID look_up_oid(const void *data, size_t datasize);
-
-This returns a number from the registry enum representing the OID if found or
-OID__NR if not.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- include/linux/oid_registry.h |  90 +++++++++++++++++++
- lib/.gitignore               |   2 +-
- lib/Kconfig                  |   5 ++
- lib/Makefile                 |  16 ++++
- lib/build_OID_registry       | 209 +++++++++++++++++++++++++++++++++++++++++++
- lib/oid_registry.c           |  89 ++++++++++++++++++
- 6 files changed, 410 insertions(+), 1 deletion(-)
- create mode 100644 include/linux/oid_registry.h
- create mode 100755 lib/build_OID_registry
- create mode 100644 lib/oid_registry.c
-
-diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
-new file mode 100644
-index 0000000..5928546
---- /dev/null
-+++ b/include/linux/oid_registry.h
-@@ -0,0 +1,90 @@
-+/* ASN.1 Object identifier (OID) registry
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_OID_REGISTRY_H
-+#define _LINUX_OID_REGISTRY_H
-+
-+#include <linux/types.h>
-+
-+/*
-+ * OIDs are turned into these values if possible, or OID__NR if not held here.
-+ *
-+ * NOTE!  Do not mess with the format of each line as this is read by
-+ *	  build_OID_registry.pl to generate the data for look_up_OID().
-+ */
-+enum OID {
-+	OID_id_dsa_with_sha1,		/* 1.2.840.10030.4.3 */
-+	OID_id_dsa,			/* 1.2.840.10040.4.1 */
-+	OID_id_ecdsa_with_sha1,		/* 1.2.840.10045.4.1 */
-+	OID_id_ecPublicKey,		/* 1.2.840.10045.2.1 */
-+
-+	/* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */
-+	OID_rsaEncryption,		/* 1.2.840.113549.1.1.1 */
-+	OID_md2WithRSAEncryption,	/* 1.2.840.113549.1.1.2 */
-+	OID_md3WithRSAEncryption,	/* 1.2.840.113549.1.1.3 */
-+	OID_md4WithRSAEncryption,	/* 1.2.840.113549.1.1.4 */
-+	OID_sha1WithRSAEncryption,	/* 1.2.840.113549.1.1.5 */
-+	OID_sha256WithRSAEncryption,	/* 1.2.840.113549.1.1.11 */
-+	OID_sha384WithRSAEncryption,	/* 1.2.840.113549.1.1.12 */
-+	OID_sha512WithRSAEncryption,	/* 1.2.840.113549.1.1.13 */
-+	OID_sha224WithRSAEncryption,	/* 1.2.840.113549.1.1.14 */
-+	/* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */
-+	OID_data,			/* 1.2.840.113549.1.7.1 */
-+	OID_signed_data,		/* 1.2.840.113549.1.7.2 */
-+	/* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */
-+	OID_email_address,		/* 1.2.840.113549.1.9.1 */
-+	OID_content_type,		/* 1.2.840.113549.1.9.3 */
-+	OID_messageDigest,		/* 1.2.840.113549.1.9.4 */
-+	OID_signingTime,		/* 1.2.840.113549.1.9.5 */
-+	OID_smimeCapabilites,		/* 1.2.840.113549.1.9.15 */
-+	OID_smimeAuthenticatedAttrs,	/* 1.2.840.113549.1.9.16.2.11 */
-+
-+	/* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */
-+	OID_md2,			/* 1.2.840.113549.2.2 */
-+	OID_md4,			/* 1.2.840.113549.2.4 */
-+	OID_md5,			/* 1.2.840.113549.2.5 */
-+
-+	OID_certAuthInfoAccess,		/* 1.3.6.1.5.5.7.1.1 */
-+	OID_msOutlookExpress,		/* 1.3.6.1.4.1.311.16.4 */
-+	OID_sha1,			/* 1.3.14.3.2.26 */
-+
-+	/* Distinguished Name attribute IDs [RFC 2256] */
-+	OID_commonName,			/* 2.5.4.3 */
-+	OID_surname,			/* 2.5.4.4 */
-+	OID_countryName,		/* 2.5.4.6 */
-+	OID_locality,			/* 2.5.4.7 */
-+	OID_stateOrProvinceName,	/* 2.5.4.8 */
-+	OID_organizationName,		/* 2.5.4.10 */
-+	OID_organizationUnitName,	/* 2.5.4.11 */
-+	OID_title,			/* 2.5.4.12 */
-+	OID_description,		/* 2.5.4.13 */
-+	OID_name,			/* 2.5.4.41 */
-+	OID_givenName,			/* 2.5.4.42 */
-+	OID_initials,			/* 2.5.4.43 */
-+	OID_generationalQualifier,	/* 2.5.4.44 */
-+
-+	/* Certificate extension IDs */
-+	OID_subjectKeyIdentifier,	/* 2.5.29.14 */
-+	OID_keyUsage,			/* 2.5.29.15 */
-+	OID_subjectAltName,		/* 2.5.29.17 */
-+	OID_issuerAltName,		/* 2.5.29.18 */
-+	OID_basicConstraints,		/* 2.5.29.19 */
-+	OID_crlDistributionPoints,	/* 2.5.29.31 */
-+	OID_certPolicies,		/* 2.5.29.32 */
-+	OID_authorityKeyIdentifier,	/* 2.5.29.35 */
-+	OID_extKeyUsage,		/* 2.5.29.37 */
-+
-+	OID__NR
-+};
-+
-+extern enum OID look_up_OID(const void *data, size_t datasize);
-+
-+#endif /* _LINUX_OID_REGISTRY_H */
-diff --git a/lib/Kconfig b/lib/Kconfig
-index bb94c1b..4b31a46 100644
---- a/lib/Kconfig
-+++ b/lib/Kconfig
-@@ -396,4 +396,9 @@ config SIGNATURE
- config LIBFDT
- 	bool
- 
-+config OID_REGISTRY
-+	tristate
-+	help
-+	  Enable fast lookup object identifier registry.
-+
- endmenu
-diff --git a/lib/Makefile b/lib/Makefile
-index 42d283e..b042896 100644
---- a/lib/Makefile
-+++ b/lib/Makefile
-@@ -150,3 +150,19 @@ quiet_cmd_crc32 = GEN     $@
- 
- $(obj)/crc32table.h: $(obj)/gen_crc32table
- 	$(call cmd,crc32)
-+
-+#
-+# Build a fast OID lookip registry from include/linux/oid_registry.h
-+#
-+obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
-+
-+$(obj)/oid_registry.c: $(obj)/oid_registry_data.c
-+
-+$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \
-+			    $(src)/build_OID_registry
-+	$(call cmd,build_OID_registry)
-+
-+quiet_cmd_build_OID_registry = GEN     $@
-+      cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@
-+
-+clean-files	+= oid_registry_data.c
-diff --git a/lib/build_OID_registry b/lib/build_OID_registry
-new file mode 100755
-index 0000000..dfbdaab
---- /dev/null
-+++ b/lib/build_OID_registry
-@@ -0,0 +1,209 @@
-+#!/usr/bin/perl -w
-+#
-+# Build a static ASN.1 Object Identified (OID) registry
-+#
-+# Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+# Written by David Howells (dhowells at redhat.com)
-+#
-+# This program is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU General Public Licence
-+# as published by the Free Software Foundation; either version
-+# 2 of the Licence, or (at your option) any later version.
-+#
-+
-+use strict;
-+
-+my @names = ();
-+my @oids = ();
-+
-+if ($#ARGV != 1) {
-+    print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n";
-+    exit(2);
-+}
-+
-+#
-+# Open the file to read from
-+#
-+open IN_FILE, "<$ARGV[0]" || die;
-+while (<IN_FILE>) {
-+    chomp;
-+    if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) {
-+	push @names, $1;
-+	push @oids, $2;
-+    }
-+}
-+close IN_FILE || die;
-+
-+#
-+# Open the files to write into
-+#
-+open C_FILE, ">$ARGV[1]" or die;
-+print C_FILE "/*\n";
-+print C_FILE " * Automatically generated by ", $0, ".  Do not edit\n";
-+print C_FILE " */\n";
-+
-+#
-+# Split the data up into separate lists and also determine the lengths of the
-+# encoded data arrays.
-+#
-+my @indices = ();
-+my @lengths = ();
-+my $total_length = 0;
-+
-+print "Compiling ", $#names + 1, " OIDs\n";
-+
-+for (my $i = 0; $i <= $#names; $i++) {
-+    my $name = $names[$i];
-+    my $oid = $oids[$i];
-+
-+    my @components = split(/[.]/, $oid);
-+
-+    # Determine the encoded length of this OID
-+    my $size = $#components;
-+    for (my $loop = 2; $loop <= $#components; $loop++) {
-+	my $c = $components[$loop];
-+
-+	# We will base128 encode the number
-+	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));
-+	$tmp = int($tmp / 7);
-+	$size += $tmp;
-+    }
-+    push @lengths, $size;
-+    push @indices, $total_length;
-+    $total_length += $size;
-+}
-+
-+#
-+# Emit the look-up-by-OID index table
-+#
-+print C_FILE "\n";
-+if ($total_length <= 255) {
-+    print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n";
-+} else {
-+    print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n";
-+}
-+for (my $i = 0; $i <= $#names; $i++) {
-+    print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n"
-+}
-+print C_FILE "\t[OID__NR] = ", $total_length, "\n";
-+print C_FILE "};\n";
-+
-+#
-+# Encode the OIDs
-+#
-+my @encoded_oids = ();
-+
-+for (my $i = 0; $i <= $#names; $i++) {
-+    my @octets = ();
-+
-+    my @components = split(/[.]/, $oids[$i]);
-+
-+    push @octets, $components[0] * 40 + $components[1];
-+
-+    for (my $loop = 2; $loop <= $#components; $loop++) {
-+	my $c = $components[$loop];
-+
-+	# Base128 encode the number
-+	my $tmp = ($c == 0) ? 0 : int(log($c)/log(2));
-+	$tmp = int($tmp / 7);
-+
-+	for (; $tmp > 0; $tmp--) {
-+	    push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80;
-+	}
-+	push @octets, $c & 0x7f;
-+    }
-+
-+    push @encoded_oids, \@octets;
-+}
-+
-+#
-+# Create a hash value for each OID
-+#
-+my @hash_values = ();
-+for (my $i = 0; $i <= $#names; $i++) {
-+    my @octets = @{$encoded_oids[$i]};
-+
-+    my $hash = $#octets;
-+    foreach (@octets) {
-+	$hash += $_ * 33;
-+    }
-+
-+    $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash);
-+
-+    push @hash_values, $hash & 0xff;
-+}
-+
-+#
-+# Emit the OID data
-+#
-+print C_FILE "\n";
-+print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n";
-+for (my $i = 0; $i <= $#names; $i++) {
-+    my @octets = @{$encoded_oids[$i]};
-+    print C_FILE "\t";
-+    print C_FILE $_, ", " foreach (@octets);
-+    print C_FILE "\t// ", $names[$i];
-+    print C_FILE "\n";
-+}
-+print C_FILE "};\n";
-+
-+#
-+# Build the search index table (ordered by length then hash then content)
-+#
-+my @index_table = ( 0 .. $#names );
-+
-+ at index_table = sort {
-+    my @octets_a = @{$encoded_oids[$a]};
-+    my @octets_b = @{$encoded_oids[$b]};
-+
-+    return $hash_values[$a] <=> $hash_values[$b]
-+	if ($hash_values[$a] != $hash_values[$b]);
-+    return $#octets_a <=> $#octets_b
-+	if ($#octets_a != $#octets_b);
-+    for (my $i = $#octets_a; $i >= 0; $i--) {
-+	return $octets_a[$i] <=> $octets_b[$i]
-+	    if ($octets_a[$i] != $octets_b[$i]);
-+    }
-+    return 0;
-+
-+} @index_table;
-+
-+#
-+# Emit the search index and hash value table
-+#
-+print C_FILE "\n";
-+print C_FILE "static const struct {\n";
-+print C_FILE "\tunsigned char hash;\n";
-+if ($#names <= 255) {
-+    print C_FILE "\tenum OID oid : 8;\n";
-+} else {
-+    print C_FILE "\tenum OID oid : 16;\n";
-+}
-+print C_FILE "} oid_search_table[OID__NR] = {\n";
-+for (my $i = 0; $i <= $#names; $i++) {
-+    my @octets = @{$encoded_oids[$index_table[$i]]};
-+    printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ",
-+	   $i,
-+	   $hash_values[$index_table[$i]],
-+	   $names[$index_table[$i]]);
-+    printf C_FILE "%02x", $_ foreach (@octets);
-+    print C_FILE "\n";
-+}
-+print C_FILE "};\n";
-+
-+#
-+# Emit the OID debugging name table
-+#
-+#print C_FILE "\n";
-+#print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n";
-+#
-+#for (my $i = 0; $i <= $#names; $i++) {
-+#    print C_FILE "\t\"", $names[$i], "\",\n"
-+#}
-+#print C_FILE "\t\"Unknown-OID\"\n";
-+#print C_FILE "};\n";
-+
-+#
-+# Polish off
-+#
-+close C_FILE or die;
-diff --git a/lib/oid_registry.c b/lib/oid_registry.c
-new file mode 100644
-index 0000000..33cfd17
---- /dev/null
-+++ b/lib/oid_registry.c
-@@ -0,0 +1,89 @@
-+/* ASN.1 Object identifier (OID) registry
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/export.h>
-+#include <linux/oid_registry.h>
-+#include "oid_registry_data.c"
-+
-+/**
-+ * look_up_OID - Find an OID registration for the specified data
-+ * @data: Binary representation of the OID
-+ * @datasize: Size of the binary representation
-+ */
-+enum OID look_up_OID(const void *data, size_t datasize)
-+{
-+	const unsigned char *octets = data;
-+	enum OID oid;
-+	unsigned char xhash;
-+	unsigned i, j, k, hash;
-+	size_t len;
-+
-+	/* Hash the OID data */
-+	hash = datasize - 1;
-+
-+	for (i = 0; i < datasize; i++)
-+		hash += octets[i] * 33;
-+	hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash;
-+	hash &= 0xff;
-+
-+	/* Binary search the OID registry.  OIDs are stored in ascending order
-+	 * of hash value then ascending order of size and then in ascending
-+	 * order of reverse value.
-+	 */
-+	i = 0;
-+	k = OID__NR;
-+	while (i < k) {
-+		j = (i + k) / 2;
-+
-+		xhash = oid_search_table[j].hash;
-+		if (xhash > hash) {
-+			k = j;
-+			continue;
-+		}
-+		if (xhash < hash) {
-+			i = j + 1;
-+			continue;
-+		}
-+
-+		oid = oid_search_table[j].oid;
-+		len = oid_index[oid + 1] - oid_index[oid];
-+		if (len > datasize) {
-+			k = j;
-+			continue;
-+		}
-+		if (len < datasize) {
-+			i = j + 1;
-+			continue;
-+		}
-+
-+		/* Variation is most likely to be at the tail end of the
-+		 * OID, so do the comparison in reverse.
-+		 */
-+		while (len > 0) {
-+			unsigned char a = oid_data[oid_index[oid] + --len];
-+			unsigned char b = octets[len];
-+			if (a > b) {
-+				k = j;
-+				goto next;
-+			}
-+			if (a < b) {
-+				i = j + 1;
-+				goto next;
-+			}
-+		}
-+		return oid;
-+	next:
-+		;
-+	}
-+
-+	return OID__NR;
-+}
-+EXPORT_SYMBOL_GPL(look_up_OID);
--- 
-1.7.11.4
-
-
-From 098335ed1edc5ec7ae7a346416654e12bb9bcd65 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:30:51 +0100
-Subject: [PATCH 13/26] X.509: Add utility functions to render OIDs as strings
-
-Add a pair of utility functions to render OIDs as strings.  The first takes an
-encoded OID and turns it into a "a.b.c.d" form string:
-
-	int sprint_oid(const void *data, size_t datasize,
-		       char *buffer, size_t bufsize);
-
-The second takes an OID enum index and calls the first on the data held
-therein:
-
-	int sprint_OID(enum OID oid, char *buffer, size_t bufsize);
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- include/linux/oid_registry.h |  2 ++
- lib/oid_registry.c           | 81 ++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 83 insertions(+)
-
-diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
-index 5928546..6926db7 100644
---- a/include/linux/oid_registry.h
-+++ b/include/linux/oid_registry.h
-@@ -86,5 +86,7 @@ enum OID {
- };
- 
- extern enum OID look_up_OID(const void *data, size_t datasize);
-+extern int sprint_oid(const void *, size_t, char *, size_t);
-+extern int sprint_OID(enum OID, char *, size_t);
- 
- #endif /* _LINUX_OID_REGISTRY_H */
-diff --git a/lib/oid_registry.c b/lib/oid_registry.c
-index 33cfd17..d8de11f 100644
---- a/lib/oid_registry.c
-+++ b/lib/oid_registry.c
-@@ -11,6 +11,9 @@
- 
- #include <linux/export.h>
- #include <linux/oid_registry.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/bug.h>
- #include "oid_registry_data.c"
- 
- /**
-@@ -87,3 +90,81 @@ enum OID look_up_OID(const void *data, size_t datasize)
- 	return OID__NR;
- }
- EXPORT_SYMBOL_GPL(look_up_OID);
-+
-+/*
-+ * sprint_OID - Print an Object Identifier into a buffer
-+ * @data: The encoded OID to print
-+ * @datasize: The size of the encoded OID
-+ * @buffer: The buffer to render into
-+ * @bufsize: The size of the buffer
-+ *
-+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of
-+ * bytes is returned.  -EBADMSG is returned if the data could not be intepreted
-+ * and -ENOBUFS if the buffer was too small.
-+ */
-+int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
-+{
-+	const unsigned char *v = data, *end = v + datasize;
-+	unsigned long num;
-+	unsigned char n;
-+	size_t ret;
-+	int count;
-+
-+	if (v >= end)
-+		return -EBADMSG;
-+
-+	n = *v++;
-+	ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
-+	buffer += count;
-+	bufsize -= count;
-+	if (bufsize == 0)
-+		return -ENOBUFS;
-+
-+	while (v < end) {
-+		num = 0;
-+		n = *v++;
-+		if (!(n & 0x80)) {
-+			num = n;
-+		} else {
-+			num = n & 0x7f;
-+			do {
-+				if (v >= end)
-+					return -EBADMSG;
-+				n = *v++;
-+				num <<= 7;
-+				num |= n & 0x7f;
-+			} while (n & 0x80);
-+		}
-+		ret += count = snprintf(buffer, bufsize, ".%lu", num);
-+		buffer += count;
-+		bufsize -= count;
-+		if (bufsize == 0)
-+			return -ENOBUFS;
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(sprint_oid);
-+
-+/**
-+ * sprint_OID - Print an Object Identifier into a buffer
-+ * @oid: The OID to print
-+ * @buffer: The buffer to render into
-+ * @bufsize: The size of the buffer
-+ *
-+ * The OID is rendered into the buffer in "a.b.c.d" format and the number of
-+ * bytes is returned.
-+ */
-+int sprint_OID(enum OID oid, char *buffer, size_t bufsize)
-+{
-+	int ret;
-+
-+	BUG_ON(oid >= OID__NR);
-+
-+	ret = sprint_oid(oid_data + oid_index[oid],
-+			 oid_index[oid + 1] - oid_index[oid],
-+			 buffer, bufsize);
-+	BUG_ON(ret == -EBADMSG);
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(sprint_OID);
--- 
-1.7.11.4
-
-
-From 3ddb8a2f1fe420777491641d39328741d9a28565 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Fri, 21 Sep 2012 23:31:13 +0100
-Subject: [PATCH 14/26] X.509: Add simple ASN.1 grammar compiler
-
-Add a simple ASN.1 grammar compiler.  This produces a bytecode output that can
-be fed to a decoder to inform the decoder how to interpret the ASN.1 stream it
-is trying to parse.
-
-Action functions can be specified in the grammar by interpolating:
-
-	({ foo })
-
-after a type, for example:
-
-	SubjectPublicKeyInfo ::= SEQUENCE {
-		algorithm		AlgorithmIdentifier,
-		subjectPublicKey	BIT STRING ({ do_key_data })
-		}
-
-The decoder is expected to call these after matching this type and parsing the
-contents if it is a constructed type.
-
-The grammar compiler does not currently support the SET type (though it does
-support SET OF) as I can't see a good way of tracking which members have been
-encountered yet without using up extra stack space.
-
-Currently, the grammar compiler will fail if more than 256 bytes of bytecode
-would be produced or more than 256 actions have been specified as it uses
-8-bit jump values and action indices to keep space usage down.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- include/linux/asn1.h              |   67 ++
- include/linux/asn1_ber_bytecode.h |   87 +++
- init/Kconfig                      |    8 +
- scripts/.gitignore                |    1 +
- scripts/Makefile                  |    2 +
- scripts/Makefile.build            |   11 +
- scripts/asn1_compiler.c           | 1545 +++++++++++++++++++++++++++++++++++++
- 7 files changed, 1721 insertions(+)
- create mode 100644 include/linux/asn1.h
- create mode 100644 include/linux/asn1_ber_bytecode.h
- create mode 100644 scripts/asn1_compiler.c
-
-diff --git a/include/linux/asn1.h b/include/linux/asn1.h
-new file mode 100644
-index 0000000..5c3f4e4
---- /dev/null
-+++ b/include/linux/asn1.h
-@@ -0,0 +1,67 @@
-+/* ASN.1 BER/DER/CER encoding definitions
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_ASN1_H
-+#define _LINUX_ASN1_H
-+
-+/* Class */
-+enum asn1_class {
-+	ASN1_UNIV	= 0,	/* Universal */
-+	ASN1_APPL	= 1,	/* Application */
-+	ASN1_CONT	= 2,	/* Context */
-+	ASN1_PRIV	= 3	/* Private */
-+};
-+#define ASN1_CLASS_BITS	0xc0
-+
-+
-+enum asn1_method {
-+	ASN1_PRIM	= 0,	/* Primitive */
-+	ASN1_CONS	= 1	/* Constructed */
-+};
-+#define ASN1_CONS_BIT	0x20
-+
-+/* Tag */
-+enum asn1_tag {
-+	ASN1_EOC	= 0,	/* End Of Contents or N/A */
-+	ASN1_BOOL	= 1,	/* Boolean */
-+	ASN1_INT	= 2,	/* Integer */
-+	ASN1_BTS	= 3,	/* Bit String */
-+	ASN1_OTS	= 4,	/* Octet String */
-+	ASN1_NULL	= 5,	/* Null */
-+	ASN1_OID	= 6,	/* Object Identifier  */
-+	ASN1_ODE	= 7,	/* Object Description */
-+	ASN1_EXT	= 8,	/* External */
-+	ASN1_REAL	= 9,	/* Real float */
-+	ASN1_ENUM	= 10,	/* Enumerated */
-+	ASN1_EPDV	= 11,	/* Embedded PDV */
-+	ASN1_UTF8STR	= 12,	/* UTF8 String */
-+	ASN1_RELOID	= 13,	/* Relative OID */
-+	/* 14 - Reserved */
-+	/* 15 - Reserved */
-+	ASN1_SEQ	= 16,	/* Sequence and Sequence of */
-+	ASN1_SET	= 17,	/* Set and Set of */
-+	ASN1_NUMSTR	= 18,	/* Numerical String */
-+	ASN1_PRNSTR	= 19,	/* Printable String */
-+	ASN1_TEXSTR	= 20,	/* T61 String / Teletext String */
-+	ASN1_VIDSTR	= 21,	/* Videotex String */
-+	ASN1_IA5STR	= 22,	/* IA5 String */
-+	ASN1_UNITIM	= 23,	/* Universal Time */
-+	ASN1_GENTIM	= 24,	/* General Time */
-+	ASN1_GRASTR	= 25,	/* Graphic String */
-+	ASN1_VISSTR	= 26,	/* Visible String */
-+	ASN1_GENSTR	= 27,	/* General String */
-+	ASN1_UNISTR	= 28,	/* Universal String */
-+	ASN1_CHRSTR	= 29,	/* Character String */
-+	ASN1_BMPSTR	= 30,	/* BMP String */
-+	ASN1_LONG_TAG	= 31	/* Long form tag */
-+};
-+
-+#endif /* _LINUX_ASN1_H */
-diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h
-new file mode 100644
-index 0000000..945d44a
---- /dev/null
-+++ b/include/linux/asn1_ber_bytecode.h
-@@ -0,0 +1,87 @@
-+/* ASN.1 BER/DER/CER parsing state machine internal definitions
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_ASN1_BER_BYTECODE_H
-+#define _LINUX_ASN1_BER_BYTECODE_H
-+
-+#ifdef __KERNEL__
-+#include <linux/types.h>
-+#endif
-+#include <linux/asn1.h>
-+
-+typedef int (*asn1_action_t)(void *context,
-+			     size_t hdrlen, /* In case of ANY type */
-+			     unsigned char tag, /* In case of ANY type */
-+			     const void *value, size_t vlen);
-+
-+struct asn1_decoder {
-+	const unsigned char *machine;
-+	size_t machlen;
-+	const asn1_action_t *actions;
-+};
-+
-+enum asn1_opcode {
-+	/* The tag-matching ops come first and the odd-numbered slots
-+	 * are for OR_SKIP ops.
-+	 */
-+#define ASN1_OP_MATCH__SKIP		  0x01
-+#define ASN1_OP_MATCH__ACT		  0x02
-+#define ASN1_OP_MATCH__JUMP		  0x04
-+#define ASN1_OP_MATCH__ANY		  0x08
-+#define ASN1_OP_MATCH__COND		  0x10
-+
-+	ASN1_OP_MATCH			= 0x00,
-+	ASN1_OP_MATCH_OR_SKIP		= 0x01,
-+	ASN1_OP_MATCH_ACT		= 0x02,
-+	ASN1_OP_MATCH_ACT_OR_SKIP	= 0x03,
-+	ASN1_OP_MATCH_JUMP		= 0x04,
-+	ASN1_OP_MATCH_JUMP_OR_SKIP	= 0x05,
-+	ASN1_OP_MATCH_ANY		= 0x08,
-+	ASN1_OP_MATCH_ANY_ACT		= 0x0a,
-+	/* Everything before here matches unconditionally */
-+
-+	ASN1_OP_COND_MATCH_OR_SKIP	= 0x11,
-+	ASN1_OP_COND_MATCH_ACT_OR_SKIP	= 0x13,
-+	ASN1_OP_COND_MATCH_JUMP_OR_SKIP	= 0x15,
-+	ASN1_OP_COND_MATCH_ANY		= 0x18,
-+	ASN1_OP_COND_MATCH_ANY_ACT	= 0x1a,
-+
-+	/* Everything before here will want a tag from the data */
-+#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT
-+
-+	/* These are here to help fill up space */
-+	ASN1_OP_COND_FAIL		= 0x1b,
-+	ASN1_OP_COMPLETE		= 0x1c,
-+	ASN1_OP_ACT			= 0x1d,
-+	ASN1_OP_RETURN			= 0x1e,
-+
-+	/* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */
-+	ASN1_OP_END_SEQ			= 0x20,
-+	ASN1_OP_END_SET			= 0x21,
-+	ASN1_OP_END_SEQ_OF		= 0x22,
-+	ASN1_OP_END_SET_OF		= 0x23,
-+	ASN1_OP_END_SEQ_ACT		= 0x24,
-+	ASN1_OP_END_SET_ACT		= 0x25,
-+	ASN1_OP_END_SEQ_OF_ACT		= 0x26,
-+	ASN1_OP_END_SET_OF_ACT		= 0x27,
-+#define ASN1_OP_END__SET		  0x01
-+#define ASN1_OP_END__OF			  0x02
-+#define ASN1_OP_END__ACT		  0x04
-+
-+	ASN1_OP__NR
-+};
-+
-+#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG)
-+#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG)
-+#define _jump_target(N) (N)
-+#define _action(N) (N)
-+
-+#endif /* _LINUX_ASN1_BER_BYTECODE_H */
-diff --git a/init/Kconfig b/init/Kconfig
-index af6c7f8..66cc885 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1612,4 +1612,12 @@ config PADATA
- 	depends on SMP
- 	bool
- 
-+config ASN1
-+	tristate
-+	help
-+	  Build a simple ASN.1 grammar compiler that produces a bytecode output
-+	  that can be interpreted by the ASN.1 stream decoder and used to
-+	  inform it as to what tags are to be expected in a stream and what
-+	  functions to call on what tags.
-+
- source "kernel/Kconfig.locks"
-diff --git a/scripts/.gitignore b/scripts/.gitignore
-index 65f362d..fb070fa 100644
---- a/scripts/.gitignore
-+++ b/scripts/.gitignore
-@@ -10,3 +10,4 @@ ihex2fw
- recordmcount
- docproc
- sortextable
-+asn1_compiler
-diff --git a/scripts/Makefile b/scripts/Makefile
-index a55b006..01e7adb 100644
---- a/scripts/Makefile
-+++ b/scripts/Makefile
-@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT)           += conmakehash
- hostprogs-$(CONFIG_IKCONFIG)     += bin2c
- hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
- hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
-+hostprogs-$(CONFIG_ASN1)	 += asn1_compiler
- 
- HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
-+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
- 
- always		:= $(hostprogs-y) $(hostprogs-m)
- 
-diff --git a/scripts/Makefile.build b/scripts/Makefile.build
-index ff1720d..0e801c3 100644
---- a/scripts/Makefile.build
-+++ b/scripts/Makefile.build
-@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS     $@
- $(obj)/%.lds: $(src)/%.lds.S FORCE
- 	$(call if_changed_dep,cpp_lds_S)
- 
-+# ASN.1 grammar
-+# ---------------------------------------------------------------------------
-+quiet_cmd_asn1_compiler = ASN.1   $@
-+      cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
-+				$(subst .h,.c,$@) $(subst .c,.h,$@)
-+
-+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
-+
-+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
-+	$(call cmd,asn1_compiler)
-+
- # Build the compiled-in targets
- # ---------------------------------------------------------------------------
- 
-diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
-new file mode 100644
-index 0000000..db0e5cd
---- /dev/null
-+++ b/scripts/asn1_compiler.c
-@@ -0,0 +1,1545 @@
-+/* Simplified ASN.1 notation parser
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <string.h>
-+#include <ctype.h>
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <sys/stat.h>
-+#include <linux/asn1_ber_bytecode.h>
-+
-+enum token_type {
-+	DIRECTIVE_ABSENT,
-+	DIRECTIVE_ALL,
-+	DIRECTIVE_ANY,
-+	DIRECTIVE_APPLICATION,
-+	DIRECTIVE_AUTOMATIC,
-+	DIRECTIVE_BEGIN,
-+	DIRECTIVE_BIT,
-+	DIRECTIVE_BMPString,
-+	DIRECTIVE_BOOLEAN,
-+	DIRECTIVE_BY,
-+	DIRECTIVE_CHARACTER,
-+	DIRECTIVE_CHOICE,
-+	DIRECTIVE_CLASS,
-+	DIRECTIVE_COMPONENT,
-+	DIRECTIVE_COMPONENTS,
-+	DIRECTIVE_CONSTRAINED,
-+	DIRECTIVE_CONTAINING,
-+	DIRECTIVE_DEFAULT,
-+	DIRECTIVE_DEFINED,
-+	DIRECTIVE_DEFINITIONS,
-+	DIRECTIVE_EMBEDDED,
-+	DIRECTIVE_ENCODED,
-+	DIRECTIVE_ENCODING_CONTROL,
-+	DIRECTIVE_END,
-+	DIRECTIVE_ENUMERATED,
-+	DIRECTIVE_EXCEPT,
-+	DIRECTIVE_EXPLICIT,
-+	DIRECTIVE_EXPORTS,
-+	DIRECTIVE_EXTENSIBILITY,
-+	DIRECTIVE_EXTERNAL,
-+	DIRECTIVE_FALSE,
-+	DIRECTIVE_FROM,
-+	DIRECTIVE_GeneralString,
-+	DIRECTIVE_GeneralizedTime,
-+	DIRECTIVE_GraphicString,
-+	DIRECTIVE_IA5String,
-+	DIRECTIVE_IDENTIFIER,
-+	DIRECTIVE_IMPLICIT,
-+	DIRECTIVE_IMPLIED,
-+	DIRECTIVE_IMPORTS,
-+	DIRECTIVE_INCLUDES,
-+	DIRECTIVE_INSTANCE,
-+	DIRECTIVE_INSTRUCTIONS,
-+	DIRECTIVE_INTEGER,
-+	DIRECTIVE_INTERSECTION,
-+	DIRECTIVE_ISO646String,
-+	DIRECTIVE_MAX,
-+	DIRECTIVE_MIN,
-+	DIRECTIVE_MINUS_INFINITY,
-+	DIRECTIVE_NULL,
-+	DIRECTIVE_NumericString,
-+	DIRECTIVE_OBJECT,
-+	DIRECTIVE_OCTET,
-+	DIRECTIVE_OF,
-+	DIRECTIVE_OPTIONAL,
-+	DIRECTIVE_ObjectDescriptor,
-+	DIRECTIVE_PATTERN,
-+	DIRECTIVE_PDV,
-+	DIRECTIVE_PLUS_INFINITY,
-+	DIRECTIVE_PRESENT,
-+	DIRECTIVE_PRIVATE,
-+	DIRECTIVE_PrintableString,
-+	DIRECTIVE_REAL,
-+	DIRECTIVE_RELATIVE_OID,
-+	DIRECTIVE_SEQUENCE,
-+	DIRECTIVE_SET,
-+	DIRECTIVE_SIZE,
-+	DIRECTIVE_STRING,
-+	DIRECTIVE_SYNTAX,
-+	DIRECTIVE_T61String,
-+	DIRECTIVE_TAGS,
-+	DIRECTIVE_TRUE,
-+	DIRECTIVE_TeletexString,
-+	DIRECTIVE_UNION,
-+	DIRECTIVE_UNIQUE,
-+	DIRECTIVE_UNIVERSAL,
-+	DIRECTIVE_UTCTime,
-+	DIRECTIVE_UTF8String,
-+	DIRECTIVE_UniversalString,
-+	DIRECTIVE_VideotexString,
-+	DIRECTIVE_VisibleString,
-+	DIRECTIVE_WITH,
-+	NR__DIRECTIVES,
-+	TOKEN_ASSIGNMENT = NR__DIRECTIVES,
-+	TOKEN_OPEN_CURLY,
-+	TOKEN_CLOSE_CURLY,
-+	TOKEN_OPEN_SQUARE,
-+	TOKEN_CLOSE_SQUARE,
-+	TOKEN_OPEN_ACTION,
-+	TOKEN_CLOSE_ACTION,
-+	TOKEN_COMMA,
-+	TOKEN_NUMBER,
-+	TOKEN_TYPE_NAME,
-+	TOKEN_ELEMENT_NAME,
-+	NR__TOKENS
-+};
-+
-+static const unsigned char token_to_tag[NR__TOKENS] = {
-+	/* EOC goes first */
-+	[DIRECTIVE_BOOLEAN]		= ASN1_BOOL,
-+	[DIRECTIVE_INTEGER]		= ASN1_INT,
-+	[DIRECTIVE_BIT]			= ASN1_BTS,
-+	[DIRECTIVE_OCTET]		= ASN1_OTS,
-+	[DIRECTIVE_NULL]		= ASN1_NULL,
-+	[DIRECTIVE_OBJECT]		= ASN1_OID,
-+	[DIRECTIVE_ObjectDescriptor]	= ASN1_ODE,
-+	[DIRECTIVE_EXTERNAL]		= ASN1_EXT,
-+	[DIRECTIVE_REAL]		= ASN1_REAL,
-+	[DIRECTIVE_ENUMERATED]		= ASN1_ENUM,
-+	[DIRECTIVE_EMBEDDED]		= 0,
-+	[DIRECTIVE_UTF8String]		= ASN1_UTF8STR,
-+	[DIRECTIVE_RELATIVE_OID]	= ASN1_RELOID,
-+	/* 14 */
-+	/* 15 */
-+	[DIRECTIVE_SEQUENCE]		= ASN1_SEQ,
-+	[DIRECTIVE_SET]			= ASN1_SET,
-+	[DIRECTIVE_NumericString]	= ASN1_NUMSTR,
-+	[DIRECTIVE_PrintableString]	= ASN1_PRNSTR,
-+	[DIRECTIVE_T61String]		= ASN1_TEXSTR,
-+	[DIRECTIVE_TeletexString]	= ASN1_TEXSTR,
-+	[DIRECTIVE_VideotexString]	= ASN1_VIDSTR,
-+	[DIRECTIVE_IA5String]		= ASN1_IA5STR,
-+	[DIRECTIVE_UTCTime]		= ASN1_UNITIM,
-+	[DIRECTIVE_GeneralizedTime]	= ASN1_GENTIM,
-+	[DIRECTIVE_GraphicString]	= ASN1_GRASTR,
-+	[DIRECTIVE_VisibleString]	= ASN1_VISSTR,
-+	[DIRECTIVE_GeneralString]	= ASN1_GENSTR,
-+	[DIRECTIVE_UniversalString]	= ASN1_UNITIM,
-+	[DIRECTIVE_CHARACTER]		= ASN1_CHRSTR,
-+	[DIRECTIVE_BMPString]		= ASN1_BMPSTR,
-+};
-+
-+static const char asn1_classes[4][5] = {
-+	[ASN1_UNIV]	= "UNIV",
-+	[ASN1_APPL]	= "APPL",
-+	[ASN1_CONT]	= "CONT",
-+	[ASN1_PRIV]	= "PRIV"
-+};
-+
-+static const char asn1_methods[2][5] = {
-+	[ASN1_UNIV]	= "PRIM",
-+	[ASN1_APPL]	= "CONS"
-+};
-+
-+static const char *const asn1_universal_tags[32] = {
-+	"EOC",
-+	"BOOL",
-+	"INT",
-+	"BTS",
-+	"OTS",
-+	"NULL",
-+	"OID",
-+	"ODE",
-+	"EXT",
-+	"REAL",
-+	"ENUM",
-+	"EPDV",
-+	"UTF8STR",
-+	"RELOID",
-+	NULL,		/* 14 */
-+	NULL,		/* 15 */
-+	"SEQ",
-+	"SET",
-+	"NUMSTR",
-+	"PRNSTR",
-+	"TEXSTR",
-+	"VIDSTR",
-+	"IA5STR",
-+	"UNITIM",
-+	"GENTIM",
-+	"GRASTR",
-+	"VISSTR",
-+	"GENSTR",
-+	"UNISTR",
-+	"CHRSTR",
-+	"BMPSTR",
-+	NULL		/* 31 */
-+};
-+
-+static const char *filename;
-+static const char *grammar_name;
-+static const char *outputname;
-+static const char *headername;
-+
-+static const char *const directives[NR__DIRECTIVES] = {
-+#define _(X) [DIRECTIVE_##X] = #X
-+	_(ABSENT),
-+	_(ALL),
-+	_(ANY),
-+	_(APPLICATION),
-+	_(AUTOMATIC),
-+	_(BEGIN),
-+	_(BIT),
-+	_(BMPString),
-+	_(BOOLEAN),
-+	_(BY),
-+	_(CHARACTER),
-+	_(CHOICE),
-+	_(CLASS),
-+	_(COMPONENT),
-+	_(COMPONENTS),
-+	_(CONSTRAINED),
-+	_(CONTAINING),
-+	_(DEFAULT),
-+	_(DEFINED),
-+	_(DEFINITIONS),
-+	_(EMBEDDED),
-+	_(ENCODED),
-+	[DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
-+	_(END),
-+	_(ENUMERATED),
-+	_(EXCEPT),
-+	_(EXPLICIT),
-+	_(EXPORTS),
-+	_(EXTENSIBILITY),
-+	_(EXTERNAL),
-+	_(FALSE),
-+	_(FROM),
-+	_(GeneralString),
-+	_(GeneralizedTime),
-+	_(GraphicString),
-+	_(IA5String),
-+	_(IDENTIFIER),
-+	_(IMPLICIT),
-+	_(IMPLIED),
-+	_(IMPORTS),
-+	_(INCLUDES),
-+	_(INSTANCE),
-+	_(INSTRUCTIONS),
-+	_(INTEGER),
-+	_(INTERSECTION),
-+	_(ISO646String),
-+	_(MAX),
-+	_(MIN),
-+	[DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
-+	[DIRECTIVE_NULL] = "NULL",
-+	_(NumericString),
-+	_(OBJECT),
-+	_(OCTET),
-+	_(OF),
-+	_(OPTIONAL),
-+	_(ObjectDescriptor),
-+	_(PATTERN),
-+	_(PDV),
-+	[DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
-+	_(PRESENT),
-+	_(PRIVATE),
-+	_(PrintableString),
-+	_(REAL),
-+	[DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
-+	_(SEQUENCE),
-+	_(SET),
-+	_(SIZE),
-+	_(STRING),
-+	_(SYNTAX),
-+	_(T61String),
-+	_(TAGS),
-+	_(TRUE),
-+	_(TeletexString),
-+	_(UNION),
-+	_(UNIQUE),
-+	_(UNIVERSAL),
-+	_(UTCTime),
-+	_(UTF8String),
-+	_(UniversalString),
-+	_(VideotexString),
-+	_(VisibleString),
-+	_(WITH)
-+};
-+
-+struct action {
-+	struct action	*next;
-+	unsigned char	index;
-+	char		name[];
-+};
-+
-+static struct action *action_list;
-+static unsigned nr_actions;
-+
-+struct token {
-+	unsigned short	line;
-+	enum token_type	token_type : 8;
-+	unsigned char	size;
-+	struct action	*action;
-+	const char	*value;
-+	struct type	*type;
-+};
-+
-+static struct token *token_list;
-+static unsigned nr_tokens;
-+
-+static int directive_compare(const void *_key, const void *_pdir)
-+{
-+	const struct token *token = _key;
-+	const char *const *pdir = _pdir, *dir = *pdir;
-+	size_t dlen, clen;
-+	int val;
-+
-+	dlen = strlen(dir);
-+	clen = (dlen < token->size) ? dlen : token->size;
-+
-+	//printf("cmp(%*.*s,%s) = ",
-+	//       (int)token->size, (int)token->size, token->value,
-+	//       dir);
-+
-+	val = memcmp(token->value, dir, clen);
-+	if (val != 0) {
-+		//printf("%d [cmp]\n", val);
-+		return val;
-+	}
-+
-+	if (dlen == token->size) {
-+		//printf("0\n");
-+		return 0;
-+	}
-+	//printf("%d\n", (int)dlen - (int)token->size);
-+	return dlen - token->size; /* shorter -> negative */
-+}
-+
-+/*
-+ * Tokenise an ASN.1 grammar
-+ */
-+static void tokenise(char *buffer, char *end)
-+{
-+	struct token *tokens;
-+	char *line, *nl, *p, *q;
-+	unsigned tix, lineno;
-+
-+	/* Assume we're going to have half as many tokens as we have
-+	 * characters
-+	 */
-+	token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
-+	if (!tokens) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+	tix = 0;
-+
-+	lineno = 0;
-+	while (buffer < end) {
-+		/* First of all, break out a line */
-+		lineno++;
-+		line = buffer;
-+		nl = memchr(line, '\n', end - buffer);
-+		if (!nl) {
-+			buffer = nl = end;
-+		} else {
-+			buffer = nl + 1;
-+			*nl = '\0';
-+		}
-+
-+		/* Remove "--" comments */
-+		p = line;
-+	next_comment:
-+		while ((p = memchr(p, '-', nl - p))) {
-+			if (p[1] == '-') {
-+				/* Found a comment; see if there's a terminator */
-+				q = p + 2;
-+				while ((q = memchr(q, '-', nl - q))) {
-+					if (q[1] == '-') {
-+						/* There is - excise the comment */
-+						q += 2;
-+						memmove(p, q, nl - q);
-+						goto next_comment;
-+					}
-+					q++;
-+				}
-+				*p = '\0';
-+				nl = p;
-+				break;
-+			} else {
-+				p++;
-+			}
-+		}
-+
-+		p = line;
-+		while (p < nl) {
-+			/* Skip white space */
-+			while (p < nl && isspace(*p))
-+				*(p++) = 0;
-+			if (p >= nl)
-+				break;
-+
-+			tokens[tix].line = lineno;
-+			tokens[tix].value = p;
-+
-+			/* Handle string tokens */
-+			if (isalpha(*p)) {
-+				const char **dir;
-+
-+				/* Can be a directive, type name or element
-+				 * name.  Find the end of the name.
-+				 */
-+				q = p + 1;
-+				while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
-+					q++;
-+				tokens[tix].size = q - p;
-+				p = q;
-+
-+				/* If it begins with a lowercase letter then
-+				 * it's an element name
-+				 */
-+				if (islower(tokens[tix].value[0])) {
-+					tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
-+					continue;
-+				}
-+
-+				/* Otherwise we need to search the directive
-+				 * table
-+				 */
-+				dir = bsearch(&tokens[tix], directives,
-+					      sizeof(directives) / sizeof(directives[1]),
-+					      sizeof(directives[1]),
-+					      directive_compare);
-+				if (dir) {
-+					tokens[tix++].token_type = dir - directives;
-+					continue;
-+				}
-+
-+				tokens[tix++].token_type = TOKEN_TYPE_NAME;
-+				continue;
-+			}
-+
-+			/* Handle numbers */
-+			if (isdigit(*p)) {
-+				/* Find the end of the number */
-+				q = p + 1;
-+				while (q < nl && (isdigit(*q)))
-+					q++;
-+				tokens[tix].size = q - p;
-+				p = q;
-+				tokens[tix++].token_type = TOKEN_NUMBER;
-+				continue;
-+			}
-+
-+			if (nl - p >= 3) {
-+				if (memcmp(p, "::=", 3) == 0) {
-+					p += 3;
-+					tokens[tix].size = 3;
-+					tokens[tix++].token_type = TOKEN_ASSIGNMENT;
-+					continue;
-+				}
-+			}
-+
-+			if (nl - p >= 2) {
-+				if (memcmp(p, "({", 2) == 0) {
-+					p += 2;
-+					tokens[tix].size = 2;
-+					tokens[tix++].token_type = TOKEN_OPEN_ACTION;
-+					continue;
-+				}
-+				if (memcmp(p, "})", 2) == 0) {
-+					p += 2;
-+					tokens[tix].size = 2;
-+					tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
-+					continue;
-+				}
-+			}
-+
-+			if (nl - p >= 1) {
-+				tokens[tix].size = 1;
-+				switch (*p) {
-+				case '{':
-+					p += 1;
-+					tokens[tix++].token_type = TOKEN_OPEN_CURLY;
-+					continue;
-+				case '}':
-+					p += 1;
-+					tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
-+					continue;
-+				case '[':
-+					p += 1;
-+					tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
-+					continue;
-+				case ']':
-+					p += 1;
-+					tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
-+					continue;
-+				case ',':
-+					p += 1;
-+					tokens[tix++].token_type = TOKEN_COMMA;
-+					continue;
-+				default:
-+					break;
-+				}
-+			}
-+
-+			fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
-+				filename, lineno, *p);
-+			exit(1);
-+		}
-+	}
-+
-+	nr_tokens = tix;
-+	printf("Extracted %u tokens\n", nr_tokens);
-+
-+#if 0
-+	{
-+		int n;
-+		for (n = 0; n < nr_tokens; n++)
-+			printf("Token %3u: '%*.*s'\n",
-+			       n,
-+			       (int)token_list[n].size, (int)token_list[n].size,
-+			       token_list[n].value);
-+	}
-+#endif
-+}
-+
-+static void build_type_list(void);
-+static void parse(void);
-+static void render(FILE *out, FILE *hdr);
-+
-+/*
-+ *
-+ */
-+int main(int argc, char **argv)
-+{
-+	struct stat st;
-+	ssize_t readlen;
-+	FILE *out, *hdr;
-+	char *buffer, *p;
-+	int fd;
-+
-+	if (argc != 4) {
-+		fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
-+			argv[0]);
-+		exit(2);
-+	}
-+
-+	filename = argv[1];
-+	outputname = argv[2];
-+	headername = argv[3];
-+
-+	fd = open(filename, O_RDONLY);
-+	if (fd < 0) {
-+		perror(filename);
-+		exit(1);
-+	}
-+
-+	if (fstat(fd, &st) < 0) {
-+		perror(filename);
-+		exit(1);
-+	}
-+
-+	if (!(buffer = malloc(st.st_size + 1))) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+
-+	if ((readlen = read(fd, buffer, st.st_size)) < 0) {
-+		perror(filename);
-+		exit(1);
-+	}
-+
-+	if (close(fd) < 0) {
-+		perror(filename);
-+		exit(1);
-+	}
-+
-+	if (readlen != st.st_size) {
-+		fprintf(stderr, "%s: Short read\n", filename);
-+		exit(1);
-+	}
-+
-+	p = strrchr(argv[1], '/');
-+	p = p ? p + 1 : argv[1];
-+	grammar_name = strdup(p);
-+	if (!p) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+	p = strchr(grammar_name, '.');
-+	if (p)
-+		*p = '\0';
-+
-+	buffer[readlen] = 0;
-+	tokenise(buffer, buffer + readlen);
-+	build_type_list();
-+	parse();
-+
-+	out = fopen(outputname, "w");
-+	if (!out) {
-+		perror(outputname);
-+		exit(1);
-+	}
-+
-+	hdr = fopen(headername, "w");
-+	if (!out) {
-+		perror(headername);
-+		exit(1);
-+	}
-+
-+	render(out, hdr);
-+
-+	if (fclose(out) < 0) {
-+		perror(outputname);
-+		exit(1);
-+	}
-+
-+	if (fclose(hdr) < 0) {
-+		perror(headername);
-+		exit(1);
-+	}
-+
-+	return 0;
-+}
-+
-+enum compound {
-+	NOT_COMPOUND,
-+	SET,
-+	SET_OF,
-+	SEQUENCE,
-+	SEQUENCE_OF,
-+	CHOICE,
-+	ANY,
-+	TYPE_REF,
-+	TAG_OVERRIDE
-+};
-+
-+struct element {
-+	struct type	*type_def;
-+	struct token	*name;
-+	struct token	*type;
-+	struct action	*action;
-+	struct element	*children;
-+	struct element	*next;
-+	struct element	*render_next;
-+	struct element	*list_next;
-+	uint8_t		n_elements;
-+	enum compound	compound : 8;
-+	enum asn1_class	class : 8;
-+	enum asn1_method method : 8;
-+	uint8_t		tag;
-+	unsigned	entry_index;
-+	unsigned	flags;
-+#define ELEMENT_IMPLICIT	0x0001
-+#define ELEMENT_EXPLICIT	0x0002
-+#define ELEMENT_MARKED		0x0004
-+#define ELEMENT_RENDERED	0x0008
-+#define ELEMENT_SKIPPABLE	0x0010
-+#define ELEMENT_CONDITIONAL	0x0020
-+};
-+
-+struct type {
-+	struct token	*name;
-+	struct token	*def;
-+	struct element	*element;
-+	unsigned	ref_count;
-+	unsigned	flags;
-+#define TYPE_STOP_MARKER	0x0001
-+#define TYPE_BEGIN		0x0002
-+};
-+
-+static struct type *type_list;
-+static struct type **type_index;
-+static unsigned nr_types;
-+
-+static int type_index_compare(const void *_a, const void *_b)
-+{
-+	const struct type *const *a = _a, *const *b = _b;
-+
-+	if ((*a)->name->size != (*b)->name->size)
-+		return (*a)->name->size - (*b)->name->size;
-+	else
-+		return memcmp((*a)->name->value, (*b)->name->value,
-+			      (*a)->name->size);
-+}
-+
-+static int type_finder(const void *_key, const void *_ti)
-+{
-+	const struct token *token = _key;
-+	const struct type *const *ti = _ti;
-+	const struct type *type = *ti;
-+
-+	if (token->size != type->name->size)
-+		return token->size - type->name->size;
-+	else
-+		return memcmp(token->value, type->name->value,
-+			      token->size);
-+}
-+
-+/*
-+ * Build up a list of types and a sorted index to that list.
-+ */
-+static void build_type_list(void)
-+{
-+	struct type *types;
-+	unsigned nr, t, n;
-+
-+	nr = 0;
-+	for (n = 0; n < nr_tokens - 1; n++)
-+		if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
-+		    token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
-+			nr++;
-+
-+	if (nr == 0) {
-+		fprintf(stderr, "%s: No defined types\n", filename);
-+		exit(1);
-+	}
-+
-+	nr_types = nr;
-+	types = type_list = calloc(nr + 1, sizeof(type_list[0]));
-+	if (!type_list) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+	type_index = calloc(nr, sizeof(type_index[0]));
-+	if (!type_index) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+
-+	t = 0;
-+	types[t].flags |= TYPE_BEGIN;
-+	for (n = 0; n < nr_tokens - 1; n++) {
-+		if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
-+		    token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
-+			types[t].name = &token_list[n];
-+			type_index[t] = &types[t];
-+			t++;
-+		}
-+	}
-+	types[t].name = &token_list[n + 1];
-+	types[t].flags |= TYPE_STOP_MARKER;
-+
-+	qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
-+
-+	printf("Extracted %u types\n", nr_types);
-+#if 0
-+	for (n = 0; n < nr_types; n++) {
-+		struct type *type = type_index[n];
-+		printf("- %*.*s\n",
-+		       (int)type->name->size,
-+		       (int)type->name->size,
-+		       type->name->value);
-+	}
-+#endif
-+}
-+
-+static struct element *parse_type(struct token **_cursor, struct token *stop,
-+				  struct token *name);
-+
-+/*
-+ * Parse the token stream
-+ */
-+static void parse(void)
-+{
-+	struct token *cursor;
-+	struct type *type;
-+
-+	/* Parse one type definition statement at a time */
-+	type = type_list;
-+	do {
-+		cursor = type->name;
-+
-+		if (cursor[0].token_type != TOKEN_TYPE_NAME ||
-+		    cursor[1].token_type != TOKEN_ASSIGNMENT)
-+			abort();
-+		cursor += 2;
-+
-+		type->element = parse_type(&cursor, type[1].name, NULL);
-+		type->element->type_def = type;
-+
-+		if (cursor != type[1].name) {
-+			fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+
-+	} while (type++, !(type->flags & TYPE_STOP_MARKER));
-+
-+	printf("Extracted %u actions\n", nr_actions);
-+}
-+
-+static struct element *element_list;
-+
-+static struct element *alloc_elem(struct token *type)
-+{
-+	struct element *e = calloc(1, sizeof(*e));
-+	if (!e) {
-+		perror(NULL);
-+		exit(1);
-+	}
-+	e->list_next = element_list;
-+	element_list = e;
-+	return e;
-+}
-+
-+static struct element *parse_compound(struct token **_cursor, struct token *end,
-+				      int alternates);
-+
-+/*
-+ * Parse one type definition statement
-+ */
-+static struct element *parse_type(struct token **_cursor, struct token *end,
-+				  struct token *name)
-+{
-+	struct element *top, *element;
-+	struct action *action, **ppaction;
-+	struct token *cursor = *_cursor;
-+	struct type **ref;
-+	char *p;
-+	int labelled = 0, implicit = 0;
-+
-+	top = element = alloc_elem(cursor);
-+	element->class = ASN1_UNIV;
-+	element->method = ASN1_PRIM;
-+	element->tag = token_to_tag[cursor->token_type];
-+	element->name = name;
-+
-+	/* Extract the tag value if one given */
-+	if (cursor->token_type == TOKEN_OPEN_SQUARE) {
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		switch (cursor->token_type) {
-+		case DIRECTIVE_UNIVERSAL:
-+			element->class = ASN1_UNIV;
-+			cursor++;
-+			break;
-+		case DIRECTIVE_APPLICATION:
-+			element->class = ASN1_APPL;
-+			cursor++;
-+			break;
-+		case TOKEN_NUMBER:
-+			element->class = ASN1_CONT;
-+			break;
-+		case DIRECTIVE_PRIVATE:
-+			element->class = ASN1_PRIV;
-+			cursor++;
-+			break;
-+		default:
-+			fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != TOKEN_NUMBER) {
-+			fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+
-+		element->tag &= ~0x1f;
-+		element->tag |= strtoul(cursor->value, &p, 10);
-+		if (p - cursor->value != cursor->size)
-+			abort();
-+		cursor++;
-+
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
-+			fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		labelled = 1;
-+	}
-+
-+	/* Handle implicit and explicit markers */
-+	if (cursor->token_type == DIRECTIVE_IMPLICIT) {
-+		element->flags |= ELEMENT_IMPLICIT;
-+		implicit = 1;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+	} else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
-+		element->flags |= ELEMENT_EXPLICIT;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+	}
-+
-+	if (labelled) {
-+		if (!implicit)
-+			element->method |= ASN1_CONS;
-+		element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
-+		element->children = alloc_elem(cursor);
-+		element = element->children;
-+		element->class = ASN1_UNIV;
-+		element->method = ASN1_PRIM;
-+		element->tag = token_to_tag[cursor->token_type];
-+		element->name = name;
-+	}
-+
-+	/* Extract the type we're expecting here */
-+	element->type = cursor;
-+	switch (cursor->token_type) {
-+	case DIRECTIVE_ANY:
-+		element->compound = ANY;
-+		cursor++;
-+		break;
-+
-+	case DIRECTIVE_NULL:
-+	case DIRECTIVE_BOOLEAN:
-+	case DIRECTIVE_ENUMERATED:
-+	case DIRECTIVE_INTEGER:
-+		element->compound = NOT_COMPOUND;
-+		cursor++;
-+		break;
-+
-+	case DIRECTIVE_EXTERNAL:
-+		element->method = ASN1_CONS;
-+
-+	case DIRECTIVE_BMPString:
-+	case DIRECTIVE_GeneralString:
-+	case DIRECTIVE_GraphicString:
-+	case DIRECTIVE_IA5String:
-+	case DIRECTIVE_ISO646String:
-+	case DIRECTIVE_NumericString:
-+	case DIRECTIVE_PrintableString:
-+	case DIRECTIVE_T61String:
-+	case DIRECTIVE_TeletexString:
-+	case DIRECTIVE_UniversalString:
-+	case DIRECTIVE_UTF8String:
-+	case DIRECTIVE_VideotexString:
-+	case DIRECTIVE_VisibleString:
-+	case DIRECTIVE_ObjectDescriptor:
-+	case DIRECTIVE_GeneralizedTime:
-+	case DIRECTIVE_UTCTime:
-+		element->compound = NOT_COMPOUND;
-+		cursor++;
-+		break;
-+
-+	case DIRECTIVE_BIT:
-+	case DIRECTIVE_OCTET:
-+		element->compound = NOT_COMPOUND;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != DIRECTIVE_STRING)
-+			goto parse_error;
-+		cursor++;
-+		break;
-+
-+	case DIRECTIVE_OBJECT:
-+		element->compound = NOT_COMPOUND;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != DIRECTIVE_IDENTIFIER)
-+			goto parse_error;
-+		cursor++;
-+		break;
-+
-+	case TOKEN_TYPE_NAME:
-+		element->compound = TYPE_REF;
-+		ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
-+			      type_finder);
-+		if (!ref) {
-+			fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+		cursor->type = *ref;
-+		(*ref)->ref_count++;
-+		cursor++;
-+		break;
-+
-+	case DIRECTIVE_CHOICE:
-+		element->compound = CHOICE;
-+		cursor++;
-+		element->children = parse_compound(&cursor, end, 1);
-+		break;
-+
-+	case DIRECTIVE_SEQUENCE:
-+		element->compound = SEQUENCE;
-+		element->method = ASN1_CONS;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type == DIRECTIVE_OF) {
-+			element->compound = SEQUENCE_OF;
-+			cursor++;
-+			if (cursor >= end)
-+				goto overrun_error;
-+			element->children = parse_type(&cursor, end, NULL);
-+		} else {
-+			element->children = parse_compound(&cursor, end, 0);
-+		}
-+		break;
-+
-+	case DIRECTIVE_SET:
-+		element->compound = SET;
-+		element->method = ASN1_CONS;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type == DIRECTIVE_OF) {
-+			element->compound = SET_OF;
-+			cursor++;
-+			if (cursor >= end)
-+				goto parse_error;
-+			element->children = parse_type(&cursor, end, NULL);
-+		} else {
-+			element->children = parse_compound(&cursor, end, 1);
-+		}
-+		break;
-+
-+	default:
-+		fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
-+			filename, cursor->line,
-+			(int)cursor->size, (int)cursor->size, cursor->value);
-+		exit(1);
-+	}
-+
-+	/* Handle elements that are optional */
-+	if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
-+			     cursor->token_type == DIRECTIVE_DEFAULT)
-+	    ) {
-+		cursor++;
-+		top->flags |= ELEMENT_SKIPPABLE;
-+	}
-+
-+	if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != TOKEN_ELEMENT_NAME) {
-+			fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+
-+		action = malloc(sizeof(struct action) + cursor->size + 1);
-+		if (!action) {
-+			perror(NULL);
-+			exit(1);
-+		}
-+		action->index = 0;
-+		memcpy(action->name, cursor->value, cursor->size);
-+		action->name[cursor->size] = 0;
-+
-+		for (ppaction = &action_list;
-+		     *ppaction;
-+		     ppaction = &(*ppaction)->next
-+		     ) {
-+			int cmp = strcmp(action->name, (*ppaction)->name);
-+			if (cmp == 0) {
-+				free(action);
-+				action = *ppaction;
-+				goto found;
-+			}
-+			if (cmp < 0) {
-+				action->next = *ppaction;
-+				*ppaction = action;
-+				nr_actions++;
-+				goto found;
-+			}
-+		}
-+		action->next = NULL;
-+		*ppaction = action;
-+		nr_actions++;
-+	found:
-+
-+		element->action = action;
-+		cursor->action = action;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != TOKEN_CLOSE_ACTION) {
-+			fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
-+				filename, cursor->line,
-+				(int)cursor->size, (int)cursor->size, cursor->value);
-+			exit(1);
-+		}
-+		cursor++;
-+	}
-+
-+	*_cursor = cursor;
-+	return top;
-+
-+parse_error:
-+	fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
-+		filename, cursor->line,
-+		(int)cursor->size, (int)cursor->size, cursor->value);
-+	exit(1);
-+
-+overrun_error:
-+	fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
-+	exit(1);
-+}
-+
-+/*
-+ * Parse a compound type list
-+ */
-+static struct element *parse_compound(struct token **_cursor, struct token *end,
-+				      int alternates)
-+{
-+	struct element *children, **child_p = &children, *element;
-+	struct token *cursor = *_cursor, *name;
-+
-+	if (cursor->token_type != TOKEN_OPEN_CURLY) {
-+		fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
-+			filename, cursor->line,
-+			(int)cursor->size, (int)cursor->size, cursor->value);
-+		exit(1);
-+	}
-+	cursor++;
-+	if (cursor >= end)
-+		goto overrun_error;
-+
-+	if (cursor->token_type == TOKEN_OPEN_CURLY) {
-+		fprintf(stderr, "%s:%d: Empty compound\n",
-+			filename, cursor->line);
-+		exit(1);
-+	}
-+
-+	for (;;) {
-+		name = NULL;
-+		if (cursor->token_type == TOKEN_ELEMENT_NAME) {
-+			name = cursor;
-+			cursor++;
-+			if (cursor >= end)
-+				goto overrun_error;
-+		}
-+
-+		element = parse_type(&cursor, end, name);
-+		if (alternates)
-+			element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
-+
-+		*child_p = element;
-+		child_p = &element->next;
-+
-+		if (cursor >= end)
-+			goto overrun_error;
-+		if (cursor->token_type != TOKEN_COMMA)
-+			break;
-+		cursor++;
-+		if (cursor >= end)
-+			goto overrun_error;
-+	}
-+
-+	children->flags &= ~ELEMENT_CONDITIONAL;
-+
-+	if (cursor->token_type != TOKEN_CLOSE_CURLY) {
-+		fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
-+			filename, cursor->line,
-+			(int)cursor->size, (int)cursor->size, cursor->value);
-+		exit(1);
-+	}
-+	cursor++;
-+
-+	*_cursor = cursor;
-+	return children;
-+
-+overrun_error:
-+	fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
-+	exit(1);
-+}
-+
-+static void render_element(FILE *out, struct element *e, struct element *tag);
-+static void render_out_of_line_list(FILE *out);
-+
-+static int nr_entries;
-+static int render_depth = 1;
-+static struct element *render_list, **render_list_p = &render_list;
-+
-+__attribute__((format(printf, 2, 3)))
-+static void render_opcode(FILE *out, const char *fmt, ...)
-+{
-+	va_list va;
-+
-+	if (out) {
-+		fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
-+		va_start(va, fmt);
-+		vfprintf(out, fmt, va);
-+		va_end(va);
-+	}
-+	nr_entries++;
-+}
-+
-+__attribute__((format(printf, 2, 3)))
-+static void render_more(FILE *out, const char *fmt, ...)
-+{
-+	va_list va;
-+
-+	if (out) {
-+		va_start(va, fmt);
-+		vfprintf(out, fmt, va);
-+		va_end(va);
-+	}
-+}
-+
-+/*
-+ * Render the grammar into a state machine definition.
-+ */
-+static void render(FILE *out, FILE *hdr)
-+{
-+	struct element *e;
-+	struct action *action;
-+	struct type *root;
-+	int index;
-+
-+	fprintf(hdr, "/*\n");
-+	fprintf(hdr, " * Automatically generated by asn1_compiler.  Do not edit\n");
-+	fprintf(hdr, " *\n");
-+	fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
-+	fprintf(hdr, " */\n");
-+	fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
-+	fprintf(hdr, "\n");
-+	fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
-+	if (ferror(hdr)) {
-+		perror(headername);
-+		exit(1);
-+	}
-+
-+	fprintf(out, "/*\n");
-+	fprintf(out, " * Automatically generated by asn1_compiler.  Do not edit\n");
-+	fprintf(out, " *\n");
-+	fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
-+	fprintf(out, " */\n");
-+	fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
-+	fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
-+	fprintf(out, "\n");
-+	if (ferror(out)) {
-+		perror(outputname);
-+		exit(1);
-+	}
-+
-+	/* Tabulate the action functions we might have to call */
-+	fprintf(hdr, "\n");
-+	index = 0;
-+	for (action = action_list; action; action = action->next) {
-+		action->index = index++;
-+		fprintf(hdr,
-+			"extern int %s(void *, size_t, unsigned char,"
-+			" const void *, size_t);\n",
-+			action->name);
-+	}
-+	fprintf(hdr, "\n");
-+
-+	fprintf(out, "enum %s_actions {\n", grammar_name);
-+	for (action = action_list; action; action = action->next)
-+		fprintf(out, "\tACT_%s = %u,\n",
-+			action->name, action->index);
-+	fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
-+	fprintf(out, "};\n");
-+
-+	fprintf(out, "\n");
-+	fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
-+		grammar_name, grammar_name);
-+	for (action = action_list; action; action = action->next)
-+		fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
-+	fprintf(out, "};\n");
-+
-+	if (ferror(out)) {
-+		perror(outputname);
-+		exit(1);
-+	}
-+
-+	/* We do two passes - the first one calculates all the offsets */
-+	printf("Pass 1\n");
-+	nr_entries = 0;
-+	root = &type_list[0];
-+	render_element(NULL, root->element, NULL);
-+	render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
-+	render_out_of_line_list(NULL);
-+
-+	for (e = element_list; e; e = e->list_next)
-+		e->flags &= ~ELEMENT_RENDERED;
-+
-+	/* And then we actually render */
-+	printf("Pass 2\n");
-+	fprintf(out, "\n");
-+	fprintf(out, "static const unsigned char %s_machine[] = {\n",
-+		grammar_name);
-+
-+	nr_entries = 0;
-+	root = &type_list[0];
-+	render_element(out, root->element, NULL);
-+	render_opcode(out, "ASN1_OP_COMPLETE,\n");
-+	render_out_of_line_list(out);
-+
-+	fprintf(out, "};\n");
-+
-+	fprintf(out, "\n");
-+	fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
-+	fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
-+	fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
-+	fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
-+	fprintf(out, "};\n");
-+}
-+
-+/*
-+ * Render the out-of-line elements
-+ */
-+static void render_out_of_line_list(FILE *out)
-+{
-+	struct element *e, *ce;
-+	const char *act;
-+	int entry;
-+
-+	while ((e = render_list)) {
-+		render_list = e->render_next;
-+		if (!render_list)
-+			render_list_p = &render_list;
-+
-+		render_more(out, "\n");
-+		e->entry_index = entry = nr_entries;
-+		render_depth++;
-+		for (ce = e->children; ce; ce = ce->next)
-+			render_element(out, ce, NULL);
-+		render_depth--;
-+
-+		act = e->action ? "_ACT" : "";
-+		switch (e->compound) {
-+		case SEQUENCE:
-+			render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
-+			break;
-+		case SEQUENCE_OF:
-+			render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
-+			render_opcode(out, "_jump_target(%u),\n", entry);
-+			break;
-+		case SET:
-+			render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
-+			break;
-+		case SET_OF:
-+			render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
-+			render_opcode(out, "_jump_target(%u),\n", entry);
-+			break;
-+		}
-+		if (e->action)
-+			render_opcode(out, "_action(ACT_%s),\n",
-+				      e->action->name);
-+		render_opcode(out, "ASN1_OP_RETURN,\n");
-+	}
-+}
-+
-+/*
-+ * Render an element.
-+ */
-+static void render_element(FILE *out, struct element *e, struct element *tag)
-+{
-+	struct element *ec;
-+	const char *cond, *act;
-+	int entry, skippable = 0, outofline = 0;
-+
-+	if (e->flags & ELEMENT_SKIPPABLE ||
-+	    (tag && tag->flags & ELEMENT_SKIPPABLE))
-+		skippable = 1;
-+
-+	if ((e->type_def && e->type_def->ref_count > 1) ||
-+	    skippable)
-+		outofline = 1;
-+
-+	if (e->type_def && out) {
-+		render_more(out, "\t// %*.*s\n",
-+			    (int)e->type_def->name->size, (int)e->type_def->name->size,
-+			    e->type_def->name->value);
-+	}
-+
-+	/* Render the operation */
-+	cond = (e->flags & ELEMENT_CONDITIONAL ||
-+		(tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
-+	act = e->action ? "_ACT" : "";
-+	switch (e->compound) {
-+	case ANY:
-+		render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
-+		if (e->name)
-+			render_more(out, "\t\t// %*.*s",
-+				    (int)e->name->size, (int)e->name->size,
-+				    e->name->value);
-+		render_more(out, "\n");
-+		goto dont_render_tag;
-+
-+	case TAG_OVERRIDE:
-+		render_element(out, e->children, e);
-+		return;
-+
-+	case SEQUENCE:
-+	case SEQUENCE_OF:
-+	case SET:
-+	case SET_OF:
-+		render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
-+			      cond,
-+			      outofline ? "_JUMP" : "",
-+			      skippable ? "_OR_SKIP" : "");
-+		break;
-+
-+	case CHOICE:
-+		goto dont_render_tag;
-+
-+	case TYPE_REF:
-+		if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
-+			goto dont_render_tag;
-+	default:
-+		render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
-+			      cond, act,
-+			      skippable ? "_OR_SKIP" : "");
-+		break;
-+	}
-+
-+	if (e->name)
-+		render_more(out, "\t\t// %*.*s",
-+			    (int)e->name->size, (int)e->name->size,
-+			    e->name->value);
-+	render_more(out, "\n");
-+
-+	/* Render the tag */
-+	if (!tag)
-+		tag = e;
-+	if (tag->class == ASN1_UNIV &&
-+	    tag->tag != 14 &&
-+	    tag->tag != 15 &&
-+	    tag->tag != 31)
-+		render_opcode(out, "_tag(%s, %s, %s),\n",
-+			      asn1_classes[tag->class],
-+			      asn1_methods[tag->method | e->method],
-+			      asn1_universal_tags[tag->tag]);
-+	else
-+		render_opcode(out, "_tagn(%s, %s, %2u),\n",
-+			      asn1_classes[tag->class],
-+			      asn1_methods[tag->method | e->method],
-+			      tag->tag);
-+	tag = NULL;
-+dont_render_tag:
-+
-+	/* Deal with compound types */
-+	switch (e->compound) {
-+	case TYPE_REF:
-+		render_element(out, e->type->type->element, tag);
-+		if (e->action)
-+			render_opcode(out, "ASN1_OP_ACT,\n");
-+		break;
-+
-+	case SEQUENCE:
-+		if (outofline) {
-+			/* Render out-of-line for multiple use or
-+			 * skipability */
-+			render_opcode(out, "_jump_target(%u),", e->entry_index);
-+			if (e->type_def && e->type_def->name)
-+				render_more(out, "\t\t// --> %*.*s",
-+					    (int)e->type_def->name->size,
-+					    (int)e->type_def->name->size,
-+					    e->type_def->name->value);
-+			render_more(out, "\n");
-+			if (!(e->flags & ELEMENT_RENDERED)) {
-+				e->flags |= ELEMENT_RENDERED;
-+				*render_list_p = e;
-+				render_list_p = &e->render_next;
-+			}
-+			return;
-+		} else {
-+			/* Render inline for single use */
-+			render_depth++;
-+			for (ec = e->children; ec; ec = ec->next)
-+				render_element(out, ec, NULL);
-+			render_depth--;
-+			render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
-+		}
-+		break;
-+
-+	case SEQUENCE_OF:
-+	case SET_OF:
-+		if (outofline) {
-+			/* Render out-of-line for multiple use or
-+			 * skipability */
-+			render_opcode(out, "_jump_target(%u),", e->entry_index);
-+			if (e->type_def && e->type_def->name)
-+				render_more(out, "\t\t// --> %*.*s",
-+					    (int)e->type_def->name->size,
-+					    (int)e->type_def->name->size,
-+					    e->type_def->name->value);
-+			render_more(out, "\n");
-+			if (!(e->flags & ELEMENT_RENDERED)) {
-+				e->flags |= ELEMENT_RENDERED;
-+				*render_list_p = e;
-+				render_list_p = &e->render_next;
-+			}
-+			return;
-+		} else {
-+			/* Render inline for single use */
-+			entry = nr_entries;
-+			render_depth++;
-+			render_element(out, e->children, NULL);
-+			render_depth--;
-+			if (e->compound == SEQUENCE_OF)
-+				render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
-+			else
-+				render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
-+			render_opcode(out, "_jump_target(%u),\n", entry);
-+		}
-+		break;
-+
-+	case SET:
-+		/* I can't think of a nice way to do SET support without having
-+		 * a stack of bitmasks to make sure no element is repeated.
-+		 * The bitmask has also to be checked that no non-optional
-+		 * elements are left out whilst not preventing optional
-+		 * elements from being left out.
-+		 */
-+		fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
-+		exit(1);
-+
-+	case CHOICE:
-+		for (ec = e->children; ec; ec = ec->next)
-+			render_element(out, ec, NULL);
-+		if (!skippable)
-+			render_opcode(out, "ASN1_OP_COND_FAIL,\n");
-+		if (e->action)
-+			render_opcode(out, "ASN1_OP_ACT,\n");
-+		break;
-+
-+	default:
-+		break;
-+	}
-+
-+	if (e->action)
-+		render_opcode(out, "_action(ACT_%s),\n", e->action->name);
-+}
--- 
-1.7.11.4
-
-
-From 8ea3f94cc16a23e3edbebf12f4223e654eb8219d Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:11:16 +0100
-Subject: [PATCH 15/26] X.509: Add an ASN.1 decoder
-
-Add an ASN.1 BER/DER/CER decoder.  This uses the bytecode from the ASN.1
-compiler in the previous patch to inform it as to what to expect to find in the
-encoded byte stream.  The output from the compiler also tells it what functions
-to call on what tags, thus allowing the caller to retrieve information.
-
-The decoder is called as follows:
-
-	int asn1_decoder(const struct asn1_decoder *decoder,
-			 void *context,
-			 const unsigned char *data,
-			 size_t datalen);
-
-The decoder argument points to the bytecode from the ASN.1 compiler.  context
-is the caller's context and is passed to the action functions.  data and
-datalen define the byte stream to be decoded.
-
-
-Note that the decoder is currently limited to datalen being less than 64K.
-This reduces the amount of stack space used by the decoder because ASN.1 is a
-nested construct.  Similarly, the decoder is limited to a maximum of 10 levels
-of constructed data outside of a leaf node also in an effort to keep stack
-usage down.
-
-These restrictions can be raised if necessary.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- include/linux/asn1_decoder.h |  24 +++
- lib/Makefile                 |   2 +
- lib/asn1_decoder.c           | 477 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 503 insertions(+)
- create mode 100644 include/linux/asn1_decoder.h
- create mode 100644 lib/asn1_decoder.c
-
-diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h
-new file mode 100644
-index 0000000..fa2ff5b
---- /dev/null
-+++ b/include/linux/asn1_decoder.h
-@@ -0,0 +1,24 @@
-+/* ASN.1 decoder
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_ASN1_DECODER_H
-+#define _LINUX_ASN1_DECODER_H
-+
-+#include <linux/asn1.h>
-+
-+struct asn1_decoder;
-+
-+extern int asn1_ber_decoder(const struct asn1_decoder *decoder,
-+			    void *context,
-+			    const unsigned char *data,
-+			    size_t datalen);
-+
-+#endif /* _LINUX_ASN1_DECODER_H */
-diff --git a/lib/Makefile b/lib/Makefile
-index b042896..ca856b6 100644
---- a/lib/Makefile
-+++ b/lib/Makefile
-@@ -140,6 +140,8 @@ $(foreach file, $(libfdt_files), \
- 	$(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt))
- lib-$(CONFIG_LIBFDT) += $(libfdt_files)
- 
-+obj-$(CONFIG_ASN1) += asn1_decoder.o
-+
- obj-$(CONFIG_RBTREE_TEST) += rbtree_test.o
- obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o
- 
-diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c
-new file mode 100644
-index 0000000..2e4196d
---- /dev/null
-+++ b/lib/asn1_decoder.c
-@@ -0,0 +1,477 @@
-+/* Decoder for ASN.1 BER/DER/CER encoded bytestream
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+#include <linux/errno.h>
-+#include <linux/asn1_decoder.h>
-+#include <linux/asn1_ber_bytecode.h>
-+
-+static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
-+	/*					OPC TAG JMP ACT */
-+	[ASN1_OP_MATCH]				= 1 + 1,
-+	[ASN1_OP_MATCH_OR_SKIP]			= 1 + 1,
-+	[ASN1_OP_MATCH_ACT]			= 1 + 1     + 1,
-+	[ASN1_OP_MATCH_ACT_OR_SKIP]		= 1 + 1     + 1,
-+	[ASN1_OP_MATCH_JUMP]			= 1 + 1 + 1,
-+	[ASN1_OP_MATCH_JUMP_OR_SKIP]		= 1 + 1 + 1,
-+	[ASN1_OP_MATCH_ANY]			= 1,
-+	[ASN1_OP_MATCH_ANY_ACT]			= 1         + 1,
-+	[ASN1_OP_COND_MATCH_OR_SKIP]		= 1 + 1,
-+	[ASN1_OP_COND_MATCH_ACT_OR_SKIP]	= 1 + 1     + 1,
-+	[ASN1_OP_COND_MATCH_JUMP_OR_SKIP]	= 1 + 1 + 1,
-+	[ASN1_OP_COND_MATCH_ANY]		= 1,
-+	[ASN1_OP_COND_MATCH_ANY_ACT]		= 1         + 1,
-+	[ASN1_OP_COND_FAIL]			= 1,
-+	[ASN1_OP_COMPLETE]			= 1,
-+	[ASN1_OP_ACT]				= 1         + 1,
-+	[ASN1_OP_RETURN]			= 1,
-+	[ASN1_OP_END_SEQ]			= 1,
-+	[ASN1_OP_END_SEQ_OF]			= 1     + 1,
-+	[ASN1_OP_END_SET]			= 1,
-+	[ASN1_OP_END_SET_OF]			= 1     + 1,
-+	[ASN1_OP_END_SEQ_ACT]			= 1         + 1,
-+	[ASN1_OP_END_SEQ_OF_ACT]		= 1     + 1 + 1,
-+	[ASN1_OP_END_SET_ACT]			= 1         + 1,
-+	[ASN1_OP_END_SET_OF_ACT]		= 1     + 1 + 1,
-+};
-+
-+/*
-+ * Find the length of an indefinite length object
-+ */
-+static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
-+				       const char **_errmsg, size_t *_err_dp)
-+{
-+	unsigned char tag, tmp;
-+	size_t dp = 0, len, n;
-+	int indef_level = 1;
-+
-+next_tag:
-+	if (unlikely(datalen - dp < 2)) {
-+		if (datalen == dp)
-+			goto missing_eoc;
-+		goto data_overrun_error;
-+	}
-+
-+	/* Extract a tag from the data */
-+	tag = data[dp++];
-+	if (tag == 0) {
-+		/* It appears to be an EOC. */
-+		if (data[dp++] != 0)
-+			goto invalid_eoc;
-+		if (--indef_level <= 0)
-+			return dp;
-+		goto next_tag;
-+	}
-+
-+	if (unlikely((tag & 0x1f) == 0x1f)) {
-+		do {
-+			if (unlikely(datalen - dp < 2))
-+				goto data_overrun_error;
-+			tmp = data[dp++];
-+		} while (tmp & 0x80);
-+	}
-+
-+	/* Extract the length */
-+	len = data[dp++];
-+	if (len < 0x7f) {
-+		dp += len;
-+		goto next_tag;
-+	}
-+
-+	if (unlikely(len == 0x80)) {
-+		/* Indefinite length */
-+		if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
-+			goto indefinite_len_primitive;
-+		indef_level++;
-+		goto next_tag;
-+	}
-+
-+	n = len - 0x80;
-+	if (unlikely(n > sizeof(size_t) - 1))
-+		goto length_too_long;
-+	if (unlikely(n > datalen - dp))
-+		goto data_overrun_error;
-+	for (len = 0; n > 0; n--) {
-+		len <<= 8;
-+		len |= data[dp++];
-+	}
-+	dp += len;
-+	goto next_tag;
-+
-+length_too_long:
-+	*_errmsg = "Unsupported length";
-+	goto error;
-+indefinite_len_primitive:
-+	*_errmsg = "Indefinite len primitive not permitted";
-+	goto error;
-+invalid_eoc:
-+	*_errmsg = "Invalid length EOC";
-+	goto error;
-+data_overrun_error:
-+	*_errmsg = "Data overrun error";
-+	goto error;
-+missing_eoc:
-+	*_errmsg = "Missing EOC in indefinite len cons";
-+error:
-+	*_err_dp = dp;
-+	return -1;
-+}
-+
-+/**
-+ * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern
-+ * @decoder: The decoder definition (produced by asn1_compiler)
-+ * @context: The caller's context (to be passed to the action functions)
-+ * @data: The encoded data
-+ * @datasize: The size of the encoded data
-+ *
-+ * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern
-+ * produced by asn1_compiler.  Action functions are called on marked tags to
-+ * allow the caller to retrieve significant data.
-+ *
-+ * LIMITATIONS:
-+ *
-+ * To keep down the amount of stack used by this function, the following limits
-+ * have been imposed:
-+ *
-+ *  (1) This won't handle datalen > 65535 without increasing the size of the
-+ *	cons stack elements and length_too_long checking.
-+ *
-+ *  (2) The stack of constructed types is 10 deep.  If the depth of non-leaf
-+ *	constructed types exceeds this, the decode will fail.
-+ *
-+ *  (3) The SET type (not the SET OF type) isn't really supported as tracking
-+ *	what members of the set have been seen is a pain.
-+ */
-+int asn1_ber_decoder(const struct asn1_decoder *decoder,
-+		     void *context,
-+		     const unsigned char *data,
-+		     size_t datalen)
-+{
-+	const unsigned char *machine = decoder->machine;
-+	const asn1_action_t *actions = decoder->actions;
-+	size_t machlen = decoder->machlen;
-+	enum asn1_opcode op;
-+	unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0;
-+	const char *errmsg;
-+	size_t pc = 0, dp = 0, tdp = 0, len = 0;
-+	int ret;
-+
-+	unsigned char flags = 0;
-+#define FLAG_INDEFINITE_LENGTH	0x01
-+#define FLAG_MATCHED		0x02
-+#define FLAG_CONS		0x20 /* Corresponds to CONS bit in the opcode tag
-+				      * - ie. whether or not we are going to parse
-+				      *   a compound type.
-+				      */
-+
-+#define NR_CONS_STACK 10
-+	unsigned short cons_dp_stack[NR_CONS_STACK];
-+	unsigned short cons_datalen_stack[NR_CONS_STACK];
-+	unsigned char cons_hdrlen_stack[NR_CONS_STACK];
-+#define NR_JUMP_STACK 10
-+	unsigned char jump_stack[NR_JUMP_STACK];
-+
-+	if (datalen > 65535)
-+		return -EMSGSIZE;
-+
-+next_op:
-+	pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n",
-+		 pc, machlen, dp, datalen, csp, jsp);
-+	if (unlikely(pc >= machlen))
-+		goto machine_overrun_error;
-+	op = machine[pc];
-+	if (unlikely(pc + asn1_op_lengths[op] > machlen))
-+		goto machine_overrun_error;
-+
-+	/* If this command is meant to match a tag, then do that before
-+	 * evaluating the command.
-+	 */
-+	if (op <= ASN1_OP__MATCHES_TAG) {
-+		unsigned char tmp;
-+
-+		/* Skip conditional matches if possible */
-+		if ((op & ASN1_OP_MATCH__COND &&
-+		     flags & FLAG_MATCHED) ||
-+		    dp == datalen) {
-+			pc += asn1_op_lengths[op];
-+			goto next_op;
-+		}
-+
-+		flags = 0;
-+		hdr = 2;
-+
-+		/* Extract a tag from the data */
-+		if (unlikely(dp >= datalen - 1))
-+			goto data_overrun_error;
-+		tag = data[dp++];
-+		if (unlikely((tag & 0x1f) == 0x1f))
-+			goto long_tag_not_supported;
-+
-+		if (op & ASN1_OP_MATCH__ANY) {
-+			pr_debug("- any %02x\n", tag);
-+		} else {
-+			/* Extract the tag from the machine
-+			 * - Either CONS or PRIM are permitted in the data if
-+			 *   CONS is not set in the op stream, otherwise CONS
-+			 *   is mandatory.
-+			 */
-+			optag = machine[pc + 1];
-+			flags |= optag & FLAG_CONS;
-+
-+			/* Determine whether the tag matched */
-+			tmp = optag ^ tag;
-+			tmp &= ~(optag & ASN1_CONS_BIT);
-+			pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp);
-+			if (tmp != 0) {
-+				/* All odd-numbered tags are MATCH_OR_SKIP. */
-+				if (op & ASN1_OP_MATCH__SKIP) {
-+					pc += asn1_op_lengths[op];
-+					dp--;
-+					goto next_op;
-+				}
-+				goto tag_mismatch;
-+			}
-+		}
-+		flags |= FLAG_MATCHED;
-+
-+		len = data[dp++];
-+		if (len > 0x7f) {
-+			if (unlikely(len == 0x80)) {
-+				/* Indefinite length */
-+				if (unlikely(!(tag & ASN1_CONS_BIT)))
-+					goto indefinite_len_primitive;
-+				flags |= FLAG_INDEFINITE_LENGTH;
-+				if (unlikely(2 > datalen - dp))
-+					goto data_overrun_error;
-+			} else {
-+				int n = len - 0x80;
-+				if (unlikely(n > 2))
-+					goto length_too_long;
-+				if (unlikely(dp >= datalen - n))
-+					goto data_overrun_error;
-+				hdr += n;
-+				for (len = 0; n > 0; n--) {
-+					len <<= 8;
-+					len |= data[dp++];
-+				}
-+				if (unlikely(len > datalen - dp))
-+					goto data_overrun_error;
-+			}
-+		}
-+
-+		if (flags & FLAG_CONS) {
-+			/* For expected compound forms, we stack the positions
-+			 * of the start and end of the data.
-+			 */
-+			if (unlikely(csp >= NR_CONS_STACK))
-+				goto cons_stack_overflow;
-+			cons_dp_stack[csp] = dp;
-+			cons_hdrlen_stack[csp] = hdr;
-+			if (!(flags & FLAG_INDEFINITE_LENGTH)) {
-+				cons_datalen_stack[csp] = datalen;
-+				datalen = dp + len;
-+			} else {
-+				cons_datalen_stack[csp] = 0;
-+			}
-+			csp++;
-+		}
-+
-+		pr_debug("- TAG: %02x %zu%s\n",
-+			 tag, len, flags & FLAG_CONS ? " CONS" : "");
-+		tdp = dp;
-+	}
-+
-+	/* Decide how to handle the operation */
-+	switch (op) {
-+	case ASN1_OP_MATCH_ANY_ACT:
-+	case ASN1_OP_COND_MATCH_ANY_ACT:
-+		ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
-+		if (ret < 0)
-+			return ret;
-+		goto skip_data;
-+
-+	case ASN1_OP_MATCH_ACT:
-+	case ASN1_OP_MATCH_ACT_OR_SKIP:
-+	case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
-+		ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len);
-+		if (ret < 0)
-+			return ret;
-+		goto skip_data;
-+
-+	case ASN1_OP_MATCH:
-+	case ASN1_OP_MATCH_OR_SKIP:
-+	case ASN1_OP_MATCH_ANY:
-+	case ASN1_OP_COND_MATCH_OR_SKIP:
-+	case ASN1_OP_COND_MATCH_ANY:
-+	skip_data:
-+		if (!(flags & FLAG_CONS)) {
-+			if (flags & FLAG_INDEFINITE_LENGTH) {
-+				len = asn1_find_indefinite_length(
-+					data + dp, datalen - dp, &errmsg, &dp);
-+				if (len < 0)
-+					goto error;
-+			}
-+			pr_debug("- LEAF: %zu\n", len);
-+			dp += len;
-+		}
-+		pc += asn1_op_lengths[op];
-+		goto next_op;
-+
-+	case ASN1_OP_MATCH_JUMP:
-+	case ASN1_OP_MATCH_JUMP_OR_SKIP:
-+	case ASN1_OP_COND_MATCH_JUMP_OR_SKIP:
-+		pr_debug("- MATCH_JUMP\n");
-+		if (unlikely(jsp == NR_JUMP_STACK))
-+			goto jump_stack_overflow;
-+		jump_stack[jsp++] = pc + asn1_op_lengths[op];
-+		pc = machine[pc + 2];
-+		goto next_op;
-+
-+	case ASN1_OP_COND_FAIL:
-+		if (unlikely(!(flags & FLAG_MATCHED)))
-+			goto tag_mismatch;
-+		pc += asn1_op_lengths[op];
-+		goto next_op;
-+
-+	case ASN1_OP_COMPLETE:
-+		if (unlikely(jsp != 0 || csp != 0)) {
-+			pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n",
-+			       jsp, csp);
-+			return -EBADMSG;
-+		}
-+		return 0;
-+
-+	case ASN1_OP_END_SET:
-+	case ASN1_OP_END_SET_ACT:
-+		if (unlikely(!(flags & FLAG_MATCHED)))
-+			goto tag_mismatch;
-+	case ASN1_OP_END_SEQ:
-+	case ASN1_OP_END_SET_OF:
-+	case ASN1_OP_END_SEQ_OF:
-+	case ASN1_OP_END_SEQ_ACT:
-+	case ASN1_OP_END_SET_OF_ACT:
-+	case ASN1_OP_END_SEQ_OF_ACT:
-+		if (unlikely(csp <= 0))
-+			goto cons_stack_underflow;
-+		csp--;
-+		tdp = cons_dp_stack[csp];
-+		hdr = cons_hdrlen_stack[csp];
-+		len = datalen;
-+		datalen = cons_datalen_stack[csp];
-+		pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n",
-+			 tdp, dp, len, datalen);
-+		if (datalen == 0) {
-+			/* Indefinite length - check for the EOC. */
-+			datalen = len;
-+			if (unlikely(datalen - dp < 2))
-+				goto data_overrun_error;
-+			if (data[dp++] != 0) {
-+				if (op & ASN1_OP_END__OF) {
-+					dp--;
-+					csp++;
-+					pc = machine[pc + 1];
-+					pr_debug("- continue\n");
-+					goto next_op;
-+				}
-+				goto missing_eoc;
-+			}
-+			if (data[dp++] != 0)
-+				goto invalid_eoc;
-+			len = dp - tdp - 2;
-+		} else {
-+			if (dp < len && (op & ASN1_OP_END__OF)) {
-+				datalen = len;
-+				csp++;
-+				pc = machine[pc + 1];
-+				pr_debug("- continue\n");
-+				goto next_op;
-+			}
-+			if (dp != len)
-+				goto cons_length_error;
-+			len -= tdp;
-+			pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp);
-+		}
-+
-+		if (op & ASN1_OP_END__ACT) {
-+			unsigned char act;
-+			if (op & ASN1_OP_END__OF)
-+				act = machine[pc + 2];
-+			else
-+				act = machine[pc + 1];
-+			ret = actions[act](context, hdr, 0, data + tdp, len);
-+		}
-+		pc += asn1_op_lengths[op];
-+		goto next_op;
-+
-+	case ASN1_OP_ACT:
-+		ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
-+		pc += asn1_op_lengths[op];
-+		goto next_op;
-+
-+	case ASN1_OP_RETURN:
-+		if (unlikely(jsp <= 0))
-+			goto jump_stack_underflow;
-+		pc = jump_stack[--jsp];
-+		goto next_op;
-+
-+	default:
-+		break;
-+	}
-+
-+	/* Shouldn't reach here */
-+	pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op);
-+	return -EBADMSG;
-+
-+data_overrun_error:
-+	errmsg = "Data overrun error";
-+	goto error;
-+machine_overrun_error:
-+	errmsg = "Machine overrun error";
-+	goto error;
-+jump_stack_underflow:
-+	errmsg = "Jump stack underflow";
-+	goto error;
-+jump_stack_overflow:
-+	errmsg = "Jump stack overflow";
-+	goto error;
-+cons_stack_underflow:
-+	errmsg = "Cons stack underflow";
-+	goto error;
-+cons_stack_overflow:
-+	errmsg = "Cons stack overflow";
-+	goto error;
-+cons_length_error:
-+	errmsg = "Cons length error";
-+	goto error;
-+missing_eoc:
-+	errmsg = "Missing EOC in indefinite len cons";
-+	goto error;
-+invalid_eoc:
-+	errmsg = "Invalid length EOC";
-+	goto error;
-+length_too_long:
-+	errmsg = "Unsupported length";
-+	goto error;
-+indefinite_len_primitive:
-+	errmsg = "Indefinite len primitive not permitted";
-+	goto error;
-+tag_mismatch:
-+	errmsg = "Unexpected tag";
-+	goto error;
-+long_tag_not_supported:
-+	errmsg = "Long tag not supported";
-+error:
-+	pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n",
-+		 errmsg, pc, dp, optag, tag, len);
-+	return -EBADMSG;
-+}
-+EXPORT_SYMBOL_GPL(asn1_ber_decoder);
--- 
-1.7.11.4
-
-
-From f055a9091c35be0171d39ca8e76bb4677d89eef1 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:11:27 +0100
-Subject: [PATCH 16/26] MPILIB: Provide a function to read raw data into an
- MPI
-
-Provide a function to read raw data of a predetermined size into an MPI rather
-than expecting the size to be encoded within the data.  The data is assumed to
-represent an unsigned integer, and the resulting MPI will be positive.
-
-The function looks like this:
-
-	MPI mpi_read_raw_data(const void *, size_t);
-
-This is useful for reading ASN.1 integer primitives where the length is encoded
-in the ASN.1 metadata.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- include/linux/mpi.h |  1 +
- lib/mpi/mpicoder.c  | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 56 insertions(+)
-
-diff --git a/include/linux/mpi.h b/include/linux/mpi.h
-index d02cca6..5af1b81 100644
---- a/include/linux/mpi.h
-+++ b/include/linux/mpi.h
-@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b);
- 
- /*-- mpicoder.c --*/
- MPI do_encode_md(const void *sha_buffer, unsigned nbits);
-+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes);
- MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread);
- int mpi_fromstr(MPI val, const char *str);
- u32 mpi_get_keyid(MPI a, u32 *keyid);
-diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
-index f0fa659..3962b7f 100644
---- a/lib/mpi/mpicoder.c
-+++ b/lib/mpi/mpicoder.c
-@@ -18,10 +18,65 @@
-  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-  */
- 
-+#include <linux/bitops.h>
-+#include <asm-generic/bitops/count_zeros.h>
- #include "mpi-internal.h"
- 
- #define MAX_EXTERN_MPI_BITS 16384
- 
-+/**
-+ * mpi_read_raw_data - Read a raw byte stream as a positive integer
-+ * @xbuffer: The data to read
-+ * @nbytes: The amount of data to read
-+ */
-+MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
-+{
-+	const uint8_t *buffer = xbuffer;
-+	int i, j;
-+	unsigned nbits, nlimbs;
-+	mpi_limb_t a;
-+	MPI val = NULL;
-+
-+	while (nbytes >= 0 && buffer[0] == 0) {
-+		buffer++;
-+		nbytes--;
-+	}
-+
-+	nbits = nbytes * 8;
-+	if (nbits > MAX_EXTERN_MPI_BITS) {
-+		pr_info("MPI: mpi too large (%u bits)\n", nbits);
-+		return NULL;
-+	}
-+	if (nbytes > 0)
-+		nbits -= count_leading_zeros(buffer[0]);
-+	else
-+		nbits = 0;
-+
-+	nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
-+	val = mpi_alloc(nlimbs);
-+	if (!val)
-+		return NULL;
-+	val->nbits = nbits;
-+	val->sign = 0;
-+	val->nlimbs = nlimbs;
-+
-+	if (nbytes > 0) {
-+		i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
-+		i %= BYTES_PER_MPI_LIMB;
-+		for (j = nlimbs; j > 0; j--) {
-+			a = 0;
-+			for (; i < BYTES_PER_MPI_LIMB; i++) {
-+				a <<= 8;
-+				a |= *buffer++;
-+			}
-+			i = 0;
-+			val->d[j - 1] = a;
-+		}
-+	}
-+	return val;
-+}
-+EXPORT_SYMBOL_GPL(mpi_read_raw_data);
-+
- MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
- {
- 	const uint8_t *buffer = xbuffer;
--- 
-1.7.11.4
-
-
-From 3d816cdad8cdd5412ecc8f539bb09daef52ba361 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:11:48 +0100
-Subject: [PATCH 17/26] X.509: Add a crypto key parser for binary (DER) X.509
- certificates
-
-Add a crypto key parser for binary (DER) encoded X.509 certificates.  The
-certificate is parsed and, if possible, the signature is verified.
-
-An X.509 key can be added like this:
-
-	# keyctl padd crypto bar @s </tmp/x509.cert
-	15768135
-
-and displayed like this:
-
-	# cat /proc/keys
-	00f09a47 I--Q---     1 perm 39390000     0     0 asymmetri bar: X509.RSA e9fd6d08 []
-
-Note that this only works with binary certificates.  PEM encoded certificates
-are ignored by the parser.
-
-Note also that the X.509 key ID is not congruent with the PGP key ID, but for
-the moment, they will match.
-
-If a NULL or "" name is given to add_key(), then the parser will generate a key
-description from the CertificateSerialNumber and Name fields of the
-TBSCertificate:
-
-	00aefc4e I--Q---     1 perm 39390000     0     0 asymmetri bfbc0cd76d050ea4:/C=GB/L=Cambridge/O=Red Hat/CN=kernel key: X509.RSA 0c688c7b []
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- crypto/asymmetric_keys/.gitignore         |   1 +
- crypto/asymmetric_keys/Kconfig            |  10 +
- crypto/asymmetric_keys/Makefile           |  17 +
- crypto/asymmetric_keys/x509.asn1          |  60 ++++
- crypto/asymmetric_keys/x509_cert_parser.c | 497 ++++++++++++++++++++++++++++++
- crypto/asymmetric_keys/x509_parser.h      |  36 +++
- crypto/asymmetric_keys/x509_public_key.c  | 207 +++++++++++++
- crypto/asymmetric_keys/x509_rsakey.asn1   |   4 +
- 8 files changed, 832 insertions(+)
- create mode 100644 crypto/asymmetric_keys/.gitignore
- create mode 100644 crypto/asymmetric_keys/x509.asn1
- create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c
- create mode 100644 crypto/asymmetric_keys/x509_parser.h
- create mode 100644 crypto/asymmetric_keys/x509_public_key.c
- create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
-
-diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore
-new file mode 100644
-index 0000000..ee32837
---- /dev/null
-+++ b/crypto/asymmetric_keys/.gitignore
-@@ -0,0 +1 @@
-+*-asn1.[ch]
-diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-index 561759d..6d2c2ea 100644
---- a/crypto/asymmetric_keys/Kconfig
-+++ b/crypto/asymmetric_keys/Kconfig
-@@ -25,4 +25,14 @@ config PUBLIC_KEY_ALGO_RSA
- 	help
- 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
- 
-+config X509_CERTIFICATE_PARSER
-+	tristate "X.509 certificate parser"
-+	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-+	select ASN1
-+	select OID_REGISTRY
-+	help
-+	  This option procides support for parsing X.509 format blobs for key
-+	  data and provides the ability to instantiate a crypto key from a
-+	  public key packet found inside the certificate.
-+
- endif # ASYMMETRIC_KEY_TYPE
-diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
-index 7c92691..0727204 100644
---- a/crypto/asymmetric_keys/Makefile
-+++ b/crypto/asymmetric_keys/Makefile
-@@ -8,3 +8,20 @@ asymmetric_keys-y := asymmetric_type.o signature.o
- 
- obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
- obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
-+
-+#
-+# X.509 Certificate handling
-+#
-+obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
-+x509_key_parser-y := \
-+	x509-asn1.o \
-+	x509_rsakey-asn1.o \
-+	x509_cert_parser.o \
-+	x509_public_key.o
-+
-+$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h
-+$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
-+$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
-+
-+clean-files	+= x509-asn1.c x509-asn1.h
-+clean-files	+= x509_rsakey-asn1.c x509_rsakey-asn1.h
-diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1
-new file mode 100644
-index 0000000..bf32b3d
---- /dev/null
-+++ b/crypto/asymmetric_keys/x509.asn1
-@@ -0,0 +1,60 @@
-+Certificate ::= SEQUENCE {
-+	tbsCertificate		TBSCertificate ({ x509_note_tbs_certificate }),
-+	signatureAlgorithm	AlgorithmIdentifier,
-+	signature		BIT STRING ({ x509_note_signature })
-+	}
-+
-+TBSCertificate ::= SEQUENCE {
-+	version           [ 0 ]	Version DEFAULT,
-+	serialNumber		CertificateSerialNumber,
-+	signature		AlgorithmIdentifier ({ x509_note_pkey_algo }),
-+	issuer			Name ({ x509_note_issuer }),
-+	validity		Validity,
-+	subject			Name ({ x509_note_subject }),
-+	subjectPublicKeyInfo	SubjectPublicKeyInfo,
-+	issuerUniqueID    [ 1 ]	IMPLICIT UniqueIdentifier OPTIONAL,
-+	subjectUniqueID   [ 2 ]	IMPLICIT UniqueIdentifier OPTIONAL,
-+	extensions        [ 3 ]	Extensions OPTIONAL
-+	}
-+
-+Version ::= INTEGER
-+CertificateSerialNumber ::= INTEGER
-+
-+AlgorithmIdentifier ::= SEQUENCE {
-+	algorithm		OBJECT IDENTIFIER ({ x509_note_OID }),
-+	parameters		ANY OPTIONAL
-+}
-+
-+Name ::= SEQUENCE OF RelativeDistinguishedName
-+
-+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
-+
-+AttributeValueAssertion ::= SEQUENCE {
-+	attributeType		OBJECT IDENTIFIER ({ x509_note_OID }),
-+	attributeValue		ANY ({ x509_extract_name_segment })
-+	}
-+
-+Validity ::= SEQUENCE {
-+	notBefore		Time ({ x509_note_not_before }),
-+	notAfter		Time ({ x509_note_not_after })
-+	}
-+
-+Time ::= CHOICE {
-+	utcTime			UTCTime,
-+	generalTime		GeneralizedTime
-+	}
-+
-+SubjectPublicKeyInfo ::= SEQUENCE {
-+	algorithm		AlgorithmIdentifier,
-+	subjectPublicKey	BIT STRING ({ x509_extract_key_data })
-+	}
-+
-+UniqueIdentifier ::= BIT STRING
-+
-+Extensions ::= SEQUENCE OF Extension
-+
-+Extension ::= SEQUENCE {
-+	extnid			OBJECT IDENTIFIER ({ x509_note_OID }),
-+	critical		BOOLEAN DEFAULT,
-+	extnValue		OCTET STRING ({ x509_process_extension })
-+	}
-diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
-new file mode 100644
-index 0000000..8fcac94
---- /dev/null
-+++ b/crypto/asymmetric_keys/x509_cert_parser.c
-@@ -0,0 +1,497 @@
-+/* X.509 certificate parser
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "X.509: "fmt
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/oid_registry.h>
-+#include "public_key.h"
-+#include "x509_parser.h"
-+#include "x509-asn1.h"
-+#include "x509_rsakey-asn1.h"
-+
-+struct x509_parse_context {
-+	struct x509_certificate	*cert;		/* Certificate being constructed */
-+	unsigned long	data;			/* Start of data */
-+	const void	*cert_start;		/* Start of cert content */
-+	const void	*key;			/* Key data */
-+	size_t		key_size;		/* Size of key data */
-+	enum OID	last_oid;		/* Last OID encountered */
-+	enum OID	algo_oid;		/* Algorithm OID */
-+	unsigned char	nr_mpi;			/* Number of MPIs stored */
-+	u8		o_size;			/* Size of organizationName (O) */
-+	u8		cn_size;		/* Size of commonName (CN) */
-+	u8		email_size;		/* Size of emailAddress */
-+	u16		o_offset;		/* Offset of organizationName (O) */
-+	u16		cn_offset;		/* Offset of commonName (CN) */
-+	u16		email_offset;		/* Offset of emailAddress */
-+};
-+
-+/*
-+ * Free an X.509 certificate
-+ */
-+void x509_free_certificate(struct x509_certificate *cert)
-+{
-+	if (cert) {
-+		public_key_destroy(cert->pub);
-+		kfree(cert->issuer);
-+		kfree(cert->subject);
-+		kfree(cert->fingerprint);
-+		kfree(cert->authority);
-+		kfree(cert);
-+	}
-+}
-+
-+/*
-+ * Parse an X.509 certificate
-+ */
-+struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
-+{
-+	struct x509_certificate *cert;
-+	struct x509_parse_context *ctx;
-+	long ret;
-+
-+	ret = -ENOMEM;
-+	cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL);
-+	if (!cert)
-+		goto error_no_cert;
-+	cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
-+	if (!cert->pub)
-+		goto error_no_ctx;
-+	ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
-+	if (!ctx)
-+		goto error_no_ctx;
-+
-+	ctx->cert = cert;
-+	ctx->data = (unsigned long)data;
-+
-+	/* Attempt to decode the certificate */
-+	ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen);
-+	if (ret < 0)
-+		goto error_decode;
-+
-+	/* Decode the public key */
-+	ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
-+			       ctx->key, ctx->key_size);
-+	if (ret < 0)
-+		goto error_decode;
-+
-+	kfree(ctx);
-+	return cert;
-+
-+error_decode:
-+	kfree(ctx);
-+error_no_ctx:
-+	x509_free_certificate(cert);
-+error_no_cert:
-+	return ERR_PTR(ret);
-+}
-+
-+/*
-+ * Note an OID when we find one for later processing when we know how
-+ * to interpret it.
-+ */
-+int x509_note_OID(void *context, size_t hdrlen,
-+	     unsigned char tag,
-+	     const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	ctx->last_oid = look_up_OID(value, vlen);
-+	if (ctx->last_oid == OID__NR) {
-+		char buffer[50];
-+		sprint_oid(value, vlen, buffer, sizeof(buffer));
-+		pr_debug("Unknown OID: [%zu] %s\n",
-+			 (unsigned long)value - ctx->data, buffer);
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * Save the position of the TBS data so that we can check the signature over it
-+ * later.
-+ */
-+int x509_note_tbs_certificate(void *context, size_t hdrlen,
-+			      unsigned char tag,
-+			      const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n",
-+		 hdrlen, tag, (unsigned long)value - ctx->data, vlen);
-+
-+	ctx->cert->tbs = value - hdrlen;
-+	ctx->cert->tbs_size = vlen + hdrlen;
-+	return 0;
-+}
-+
-+/*
-+ * Record the public key algorithm
-+ */
-+int x509_note_pkey_algo(void *context, size_t hdrlen,
-+			unsigned char tag,
-+			const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	pr_debug("PubKey Algo: %u\n", ctx->last_oid);
-+
-+	switch (ctx->last_oid) {
-+	case OID_md2WithRSAEncryption:
-+	case OID_md3WithRSAEncryption:
-+	default:
-+		return -ENOPKG; /* Unsupported combination */
-+
-+	case OID_md4WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_MD5;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+
-+	case OID_sha1WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_SHA1;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+
-+	case OID_sha256WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_SHA256;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+
-+	case OID_sha384WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_SHA384;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+
-+	case OID_sha512WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_SHA512;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+
-+	case OID_sha224WithRSAEncryption:
-+		ctx->cert->sig_hash_algo = PKEY_HASH_SHA224;
-+		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+		break;
-+	}
-+
-+	ctx->algo_oid = ctx->last_oid;
-+	return 0;
-+}
-+
-+/*
-+ * Note the whereabouts and type of the signature.
-+ */
-+int x509_note_signature(void *context, size_t hdrlen,
-+			unsigned char tag,
-+			const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen);
-+
-+	if (ctx->last_oid != ctx->algo_oid) {
-+		pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n",
-+			ctx->algo_oid, ctx->last_oid);
-+		return -EINVAL;
-+	}
-+
-+	ctx->cert->sig = value;
-+	ctx->cert->sig_size = vlen;
-+	return 0;
-+}
-+
-+/*
-+ * Note some of the name segments from which we'll fabricate a name.
-+ */
-+int x509_extract_name_segment(void *context, size_t hdrlen,
-+			      unsigned char tag,
-+			      const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	switch (ctx->last_oid) {
-+	case OID_commonName:
-+		ctx->cn_size = vlen;
-+		ctx->cn_offset = (unsigned long)value - ctx->data;
-+		break;
-+	case OID_organizationName:
-+		ctx->o_size = vlen;
-+		ctx->o_offset = (unsigned long)value - ctx->data;
-+		break;
-+	case OID_email_address:
-+		ctx->email_size = vlen;
-+		ctx->email_offset = (unsigned long)value - ctx->data;
-+		break;
-+	default:
-+		break;
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * Fabricate and save the issuer and subject names
-+ */
-+static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen,
-+			       unsigned char tag,
-+			       char **_name, size_t vlen)
-+{
-+	const void *name, *data = (const void *)ctx->data;
-+	size_t namesize;
-+	char *buffer;
-+
-+	if (*_name)
-+		return -EINVAL;
-+
-+	/* Empty name string if no material */
-+	if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) {
-+		buffer = kmalloc(1, GFP_KERNEL);
-+		if (!buffer)
-+			return -ENOMEM;
-+		buffer[0] = 0;
-+		goto done;
-+	}
-+
-+	if (ctx->cn_size && ctx->o_size) {
-+		/* Consider combining O and CN, but use only the CN if it is
-+		 * prefixed by the O, or a significant portion thereof.
-+		 */
-+		namesize = ctx->cn_size;
-+		name = data + ctx->cn_offset;
-+		if (ctx->cn_size >= ctx->o_size &&
-+		    memcmp(data + ctx->cn_offset, data + ctx->o_offset,
-+			   ctx->o_size) == 0)
-+			goto single_component;
-+		if (ctx->cn_size >= 7 &&
-+		    ctx->o_size >= 7 &&
-+		    memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0)
-+			goto single_component;
-+
-+		buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1,
-+				 GFP_KERNEL);
-+		if (!buffer)
-+			return -ENOMEM;
-+
-+		memcpy(buffer,
-+		       data + ctx->o_offset, ctx->o_size);
-+		buffer[ctx->o_size + 0] = ':';
-+		buffer[ctx->o_size + 1] = ' ';
-+		memcpy(buffer + ctx->o_size + 2,
-+		       data + ctx->cn_offset, ctx->cn_size);
-+		buffer[ctx->o_size + 2 + ctx->cn_size] = 0;
-+		goto done;
-+
-+	} else if (ctx->cn_size) {
-+		namesize = ctx->cn_size;
-+		name = data + ctx->cn_offset;
-+	} else if (ctx->o_size) {
-+		namesize = ctx->o_size;
-+		name = data + ctx->o_offset;
-+	} else {
-+		namesize = ctx->email_size;
-+		name = data + ctx->email_offset;
-+	}
-+
-+single_component:
-+	buffer = kmalloc(namesize + 1, GFP_KERNEL);
-+	if (!buffer)
-+		return -ENOMEM;
-+	memcpy(buffer, name, namesize);
-+	buffer[namesize] = 0;
-+
-+done:
-+	*_name = buffer;
-+	ctx->cn_size = 0;
-+	ctx->o_size = 0;
-+	ctx->email_size = 0;
-+	return 0;
-+}
-+
-+int x509_note_issuer(void *context, size_t hdrlen,
-+		     unsigned char tag,
-+		     const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen);
-+}
-+
-+int x509_note_subject(void *context, size_t hdrlen,
-+		      unsigned char tag,
-+		      const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen);
-+}
-+
-+/*
-+ * Extract the data for the public key algorithm
-+ */
-+int x509_extract_key_data(void *context, size_t hdrlen,
-+			  unsigned char tag,
-+			  const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+
-+	if (ctx->last_oid != OID_rsaEncryption)
-+		return -ENOPKG;
-+
-+	/* There seems to be an extraneous 0 byte on the front of the data */
-+	ctx->cert->pkey_algo = PKEY_ALGO_RSA;
-+	ctx->key = value + 1;
-+	ctx->key_size = vlen - 1;
-+	return 0;
-+}
-+
-+/*
-+ * Extract a RSA public key value
-+ */
-+int rsa_extract_mpi(void *context, size_t hdrlen,
-+		    unsigned char tag,
-+		    const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	MPI mpi;
-+
-+	if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) {
-+		pr_err("Too many public key MPIs in certificate\n");
-+		return -EBADMSG;
-+	}
-+
-+	mpi = mpi_read_raw_data(value, vlen);
-+	if (!mpi)
-+		return -ENOMEM;
-+
-+	ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi;
-+	return 0;
-+}
-+
-+/*
-+ * Process certificate extensions that are used to qualify the certificate.
-+ */
-+int x509_process_extension(void *context, size_t hdrlen,
-+			   unsigned char tag,
-+			   const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	const unsigned char *v = value;
-+	char *f;
-+	int i;
-+
-+	pr_debug("Extension: %u\n", ctx->last_oid);
-+
-+	if (ctx->last_oid == OID_subjectKeyIdentifier) {
-+		/* Get hold of the key fingerprint */
-+		if (vlen < 3)
-+			return -EBADMSG;
-+		if (v[0] != ASN1_OTS || v[1] != vlen - 2)
-+			return -EBADMSG;
-+		v += 2;
-+		vlen -= 2;
-+
-+		f = kmalloc(vlen * 2 + 1, GFP_KERNEL);
-+		if (!f)
-+			return -ENOMEM;
-+		for (i = 0; i < vlen; i++)
-+			sprintf(f + i * 2, "%02x", v[i]);
-+		pr_debug("fingerprint %s\n", f);
-+		ctx->cert->fingerprint = f;
-+		return 0;
-+	}
-+
-+	if (ctx->last_oid == OID_authorityKeyIdentifier) {
-+		/* Get hold of the CA key fingerprint */
-+		if (vlen < 5)
-+			return -EBADMSG;
-+		if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) ||
-+		    v[1] != vlen - 2 ||
-+		    v[2] != (ASN1_CONT << 6) ||
-+		    v[3] != vlen - 4)
-+			return -EBADMSG;
-+		v += 4;
-+		vlen -= 4;
-+
-+		f = kmalloc(vlen * 2 + 1, GFP_KERNEL);
-+		if (!f)
-+			return -ENOMEM;
-+		for (i = 0; i < vlen; i++)
-+			sprintf(f + i * 2, "%02x", v[i]);
-+		pr_debug("authority   %s\n", f);
-+		ctx->cert->authority = f;
-+		return 0;
-+	}
-+
-+	return 0;
-+}
-+
-+/*
-+ * Record a certificate time.
-+ */
-+static int x509_note_time(time_t *_time,  size_t hdrlen,
-+			  unsigned char tag,
-+			  const unsigned char *value, size_t vlen)
-+{
-+	unsigned YY, MM, DD, hh, mm, ss;
-+	const unsigned char *p = value;
-+
-+#define dec2bin(X) ((X) - '0')
-+#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; })
-+
-+	if (tag == ASN1_UNITIM) {
-+		/* UTCTime: YYMMDDHHMMSSZ */
-+		if (vlen != 13)
-+			goto unsupported_time;
-+		YY = DD2bin(p);
-+		if (YY > 50)
-+			YY += 1900;
-+		else
-+			YY += 2000;
-+	} else if (tag == ASN1_GENTIM) {
-+		/* GenTime: YYYYMMDDHHMMSSZ */
-+		if (vlen != 15)
-+			goto unsupported_time;
-+		YY = DD2bin(p) * 100 + DD2bin(p);
-+	} else {
-+		goto unsupported_time;
-+	}
-+
-+	MM = DD2bin(p);
-+	DD = DD2bin(p);
-+	hh = DD2bin(p);
-+	mm = DD2bin(p);
-+	ss = DD2bin(p);
-+
-+	if (*p != 'Z')
-+		goto unsupported_time;
-+
-+	*_time = mktime(YY, MM, DD, hh, mm, ss);
-+	return 0;
-+
-+unsupported_time:
-+	pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n",
-+		 tag, (int)vlen, (int)vlen, value);
-+	return -EBADMSG;
-+}
-+
-+int x509_note_not_before(void *context, size_t hdrlen,
-+			 unsigned char tag,
-+			 const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen);
-+}
-+
-+int x509_note_not_after(void *context, size_t hdrlen,
-+			unsigned char tag,
-+			const void *value, size_t vlen)
-+{
-+	struct x509_parse_context *ctx = context;
-+	return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen);
-+}
-diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
-new file mode 100644
-index 0000000..635053f
---- /dev/null
-+++ b/crypto/asymmetric_keys/x509_parser.h
-@@ -0,0 +1,36 @@
-+/* X.509 certificate parser internal definitions
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <crypto/public_key.h>
-+
-+struct x509_certificate {
-+	struct x509_certificate *next;
-+	struct public_key *pub;			/* Public key details */
-+	char		*issuer;		/* Name of certificate issuer */
-+	char		*subject;		/* Name of certificate subject */
-+	char		*fingerprint;		/* Key fingerprint as hex */
-+	char		*authority;		/* Authority key fingerprint as hex */
-+	time_t		valid_from;
-+	time_t		valid_to;
-+	enum pkey_algo	pkey_algo : 8;		/* Public key algorithm */
-+	enum pkey_algo	sig_pkey_algo : 8;	/* Signature public key algorithm */
-+	enum pkey_hash_algo sig_hash_algo : 8;	/* Signature hash algorithm */
-+	const void	*tbs;			/* Signed data */
-+	size_t		tbs_size;		/* Size of signed data */
-+	const void	*sig;			/* Signature data */
-+	size_t		sig_size;		/* Size of sigature */
-+};
-+
-+/*
-+ * x509_cert_parser.c
-+ */
-+extern void x509_free_certificate(struct x509_certificate *cert);
-+extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-new file mode 100644
-index 0000000..716917c
---- /dev/null
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -0,0 +1,207 @@
-+/* Instantiate a public key crypto key from an X.509 Certificate
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "X.509: "fmt
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/mpi.h>
-+#include <linux/asn1_decoder.h>
-+#include <keys/asymmetric-subtype.h>
-+#include <keys/asymmetric-parser.h>
-+#include <crypto/hash.h>
-+#include "asymmetric_keys.h"
-+#include "public_key.h"
-+#include "x509_parser.h"
-+
-+static const
-+struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = {
-+	[PKEY_ALGO_DSA]		= NULL,
-+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
-+	defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
-+	[PKEY_ALGO_RSA]		= &RSA_public_key_algorithm,
-+#endif
-+};
-+
-+/*
-+ * Check the signature on a certificate using the provided public key
-+ */
-+static int x509_check_signature(const struct public_key *pub,
-+				const struct x509_certificate *cert)
-+{
-+	struct public_key_signature *sig;
-+	struct crypto_shash *tfm;
-+	struct shash_desc *desc;
-+	size_t digest_size, desc_size;
-+	int ret;
-+
-+	pr_devel("==>%s()\n", __func__);
-+	
-+	/* Allocate the hashing algorithm we're going to need and find out how
-+	 * big the hash operational data will be.
-+	 */
-+	tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0);
-+	if (IS_ERR(tfm))
-+		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
-+
-+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
-+	digest_size = crypto_shash_digestsize(tfm);
-+
-+	/* We allocate the hash operational data storage on the end of our
-+	 * context data.
-+	 */
-+	ret = -ENOMEM;
-+	sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL);
-+	if (!sig)
-+		goto error_no_sig;
-+
-+	sig->pkey_hash_algo	= cert->sig_hash_algo;
-+	sig->digest		= (u8 *)sig + sizeof(*sig) + desc_size;
-+	sig->digest_size	= digest_size;
-+
-+	desc = (void *)sig + sizeof(*sig);
-+	desc->tfm	= tfm;
-+	desc->flags	= CRYPTO_TFM_REQ_MAY_SLEEP;
-+
-+	ret = crypto_shash_init(desc);
-+	if (ret < 0)
-+		goto error;
-+
-+	ret = -ENOMEM;
-+	sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size);
-+	if (!sig->rsa.s)
-+		goto error;
-+
-+	ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
-+	if (ret < 0)
-+		goto error_mpi;
-+
-+	ret = pub->algo->verify_signature(pub, sig);
-+
-+	pr_debug("Cert Verification: %d\n", ret);
-+
-+error_mpi:
-+	mpi_free(sig->rsa.s);
-+error:
-+	kfree(sig);
-+error_no_sig:
-+	crypto_free_shash(tfm);
-+
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ret;
-+}
-+
-+/*
-+ * Attempt to parse a data blob for a key as an X509 certificate.
-+ */
-+static int x509_key_preparse(struct key_preparsed_payload *prep)
-+{
-+	struct x509_certificate *cert;
-+	time_t now;
-+	size_t srlen, sulen;
-+	char *desc = NULL;
-+	int ret;
-+
-+	cert = x509_cert_parse(prep->data, prep->datalen);
-+	if (IS_ERR(cert))
-+		return PTR_ERR(cert);
-+
-+	pr_devel("Cert Issuer: %s\n", cert->issuer);
-+	pr_devel("Cert Subject: %s\n", cert->subject);
-+	pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]);
-+	pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to);
-+	pr_devel("Cert Signature: %s + %s\n",
-+		 pkey_algo[cert->sig_pkey_algo],
-+		 pkey_hash_algo[cert->sig_hash_algo]);
-+
-+	if (!cert->fingerprint || !cert->authority) {
-+		pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
-+			cert->subject);
-+		ret = -EKEYREJECTED;
-+		goto error_free_cert;
-+	}
-+
-+	now = CURRENT_TIME.tv_sec;
-+	if (now < cert->valid_from) {
-+		pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
-+		ret = -EKEYREJECTED;
-+		goto error_free_cert;
-+	}
-+	if (now >= cert->valid_to) {
-+		pr_warn("Cert %s has expired\n", cert->fingerprint);
-+		ret = -EKEYEXPIRED;
-+		goto error_free_cert;
-+	}
-+
-+	cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
-+	cert->pub->id_type = PKEY_ID_X509;
-+
-+	/* Check the signature on the key */
-+	if (strcmp(cert->fingerprint, cert->authority) == 0) {
-+		ret = x509_check_signature(cert->pub, cert);
-+		if (ret < 0)
-+			goto error_free_cert;
-+	}
-+
-+	/* Propose a description */
-+	sulen = strlen(cert->subject);
-+	srlen = strlen(cert->fingerprint);
-+	ret = -ENOMEM;
-+	desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL);
-+	if (!desc)
-+		goto error_free_cert;
-+	memcpy(desc, cert->subject, sulen);
-+	desc[sulen] = ':';
-+	desc[sulen + 1] = ' ';
-+	memcpy(desc + sulen + 2, cert->fingerprint, srlen);
-+	desc[sulen + 2 + srlen] = 0;
-+
-+	/* We're pinning the module by being linked against it */
-+	__module_get(public_key_subtype.owner);
-+	prep->type_data[0] = &public_key_subtype;
-+	prep->type_data[1] = cert->fingerprint;
-+	prep->payload = cert->pub;
-+	prep->description = desc;
-+	prep->quotalen = 100;
-+
-+	/* We've finished with the certificate */
-+	cert->pub = NULL;
-+	cert->fingerprint = NULL;
-+	desc = NULL;
-+	ret = 0;
-+
-+error_free_cert:
-+	x509_free_certificate(cert);
-+	return ret;
-+}
-+
-+static struct asymmetric_key_parser x509_key_parser = {
-+	.owner	= THIS_MODULE,
-+	.name	= "x509",
-+	.parse	= x509_key_preparse,
-+};
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init x509_key_init(void)
-+{
-+	return register_asymmetric_key_parser(&x509_key_parser);
-+}
-+
-+static void __exit x509_key_exit(void)
-+{
-+	unregister_asymmetric_key_parser(&x509_key_parser);
-+}
-+
-+module_init(x509_key_init);
-+module_exit(x509_key_exit);
-diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1
-new file mode 100644
-index 0000000..4ec7cc6
---- /dev/null
-+++ b/crypto/asymmetric_keys/x509_rsakey.asn1
-@@ -0,0 +1,4 @@
-+RSAPublicKey ::= SEQUENCE {
-+	modulus			INTEGER ({ rsa_extract_mpi }),	-- n
-+	publicExponent		INTEGER ({ rsa_extract_mpi })	-- e
-+	}
--- 
-1.7.11.4
-
-
-From 955fc6ec995f6bec6c487eb46027e108e240ebe3 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:25 +0100
-Subject: [PATCH 18/26] MOD: Fix Rusty's module_sig_check()
-
-Make the following fixes to Rusty's module_sig_check() function:
-
- (1) mod_verify_sig() is not defined, resulting in a compilation error and
-     thereby breaking git bisect, so provide a dummy that returns an error.
-
- (2) Using strlen() on a static string is a waste of resources.  Further, you
-     may end up with two copies of the string emitted.
-
- (3) Doing a memchr() of the bytes beyond the last position that the marker
-     can be in is a waste of resources.
-
-While we're at it, push responsibility for the return value entirely off to
-mod_verify_sig() if we find a signature.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- kernel/Makefile          |  1 +
- kernel/module-internal.h | 14 ++++++++++++++
- kernel/module.c          | 41 +++++++++++++++++++++++------------------
- kernel/module_signing.c  | 23 +++++++++++++++++++++++
- 4 files changed, 61 insertions(+), 18 deletions(-)
- create mode 100644 kernel/module-internal.h
- create mode 100644 kernel/module_signing.c
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index c0cc67a..08ba8a6 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -55,6 +55,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_signing.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
-diff --git a/kernel/module-internal.h b/kernel/module-internal.h
-new file mode 100644
-index 0000000..14da0ea
---- /dev/null
-+++ b/kernel/module-internal.h
-@@ -0,0 +1,14 @@
-+/* Module internals
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+extern int mod_verify_sig(const void *mod, unsigned long modlen,
-+			  const void *sig, unsigned long siglen,
-+			  bool *_sig_ok);
-diff --git a/kernel/module.c b/kernel/module.c
-index 5c6f65c..ab69599 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-internal.h"
- 
- #define CREATE_TRACE_POINTS
- #include <trace/events/module.h>
-@@ -2438,34 +2439,38 @@ static inline void kmemleak_load_module(const struct module *mod,
- #endif
- 
- #ifdef CONFIG_MODULE_SIG
-+
- static int module_sig_check(struct load_info *info,
- 			    const void *mod, unsigned long *len)
- {
-+	static const char module_sig_string[] = MODULE_SIG_STRING;
- 	int err = 0;
--	const unsigned long markerlen = strlen(MODULE_SIG_STRING);
--	const void *p = mod, *end = mod + *len;
--
--	/* Poor man's memmem. */
--	while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
--		if (p + markerlen > end)
--			break;
--
--		if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
--			const void *sig = p + markerlen;
--			/* Truncate module up to signature. */
--			*len = p - mod;
--			err = mod_verify_sig(mod, *len,
--					     sig, end - sig,
--					     &info->sig_ok);
--			break;
--		}
--		p++;
-+	const unsigned long markerlen = sizeof(module_sig_string) - 1;
-+	const void *p = mod, *end = mod + *len, *sig;
-+	const void *limit = end - markerlen - 1;
-+
-+	if (markerlen < *len) {
-+		/* Poor man's memmem. */
-+		do {
-+			p = memchr(p, MODULE_SIG_STRING[0], limit - p);
-+			if (!p)
-+				break;
-+			if (memcmp(p, module_sig_string, markerlen) != 0)
-+				continue;
-+			goto found_marker;
-+		} while (++p < limit);
- 	}
- 
- 	/* Not having a signature is only an error if we're strict. */
- 	if (!err && !info->sig_ok && sig_enforce)
- 		err = -EKEYREJECTED;
- 	return err;
-+
-+found_marker:
-+	sig = p + markerlen;
-+	/* Truncate module up to signature. */
-+	*len = p - mod;
-+	return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok);
- }
- #else /* !CONFIG_MODULE_SIG */
- static int module_sig_check(struct load_info *info,
-diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-new file mode 100644
-index 0000000..0af10a5
---- /dev/null
-+++ b/kernel/module_signing.c
-@@ -0,0 +1,23 @@
-+/* Module signature checker
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/kernel.h>
-+#include "module-internal.h"
-+
-+/*
-+ * Verify the signature on a module.
-+ */
-+int mod_verify_sig(const void *mod, unsigned long modlen,
-+		   const void *sig, unsigned long siglen,
-+		   bool *_sig_ok)
-+{
-+	return -EKEYREJECTED;
-+}
--- 
-1.7.11.4
-
-
-From 4c31831859550149cdba65a37d72416c87dbbef6 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:25 +0100
-Subject: [PATCH 19/26] 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 at redhat.com>
----
- .gitignore | 13 +++++++++++++
- Makefile   |  1 +
- 2 files changed, 14 insertions(+)
-
-diff --git a/.gitignore b/.gitignore
-index 57af07c..9736304 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -14,6 +14,10 @@
- *.o.*
- *.a
- *.s
-+*.ko.unsigned
-+*.ko.stripped
-+*.ko.stripped.dig
-+*.ko.stripped.sig
- *.ko
- *.so
- *.so.dbg
-@@ -84,3 +88,12 @@ GTAGS
- *.orig
- *~
- \#*#
-+
-+#
-+# Leavings from module signing
-+#
-+extra_certificates
-+signing_key.priv
-+signing_key.x509
-+signing_key.x509.keyid
-+signing_key.x509.signer
-diff --git a/Makefile b/Makefile
-index 371ce88..644048d 100644
---- a/Makefile
-+++ b/Makefile
-@@ -1239,6 +1239,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.*' \
--- 
-1.7.11.4
-
-
-From 6977e69eef4379f34a2ad264856d74ac292284df Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:25 +0100
-Subject: [PATCH 20/26] MODSIGN: Provide Kconfig options
-
-Provide kernel configuration options for module signing.
-
-The following configuration options are added:
-
-     CONFIG_MODULE_SIG_SHA1
-     CONFIG_MODULE_SIG_SHA224
-     CONFIG_MODULE_SIG_SHA256
-     CONFIG_MODULE_SIG_SHA384
-     CONFIG_MODULE_SIG_SHA512
-
-These 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.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- init/Kconfig | 38 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 38 insertions(+)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index fa8ccad..00d4579 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1593,12 +1593,50 @@ config MODULE_SIG
- 	  is simply appended to the module. For more information see
- 	  Documentation/module-signing.txt.
- 
-+	  !!!WARNING!!!  If you enable this option, you MUST make sure that the
-+	  module DOES NOT get stripped after being signed.  This includes the
-+	  debuginfo strip done by some packagers (such as rpmbuild) and
-+	  inclusion into an initramfs that wants the module size reduced.
-+
- config MODULE_SIG_FORCE
- 	bool "Require modules to be validly signed"
- 	depends on MODULE_SIG
- 	help
- 	  Reject unsigned modules or signed modules for which we don't have a
- 	  key.  Without this, such modules will simply taint the kernel.
-+
-+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_SHA256
-+
-+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_SHA512
-+
-+config MODULE_SIG_SHA512
-+	bool "Sign modules with SHA-512"
-+	select CRYPTO_SHA512
-+
-+endchoice
-+
- endif # MODULES
- 
- config INIT_ALL_POSSIBLE
--- 
-1.7.11.4
-
-
-From 60378703cf88ed221ee602727c37ae241565d44a Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:25 +0100
-Subject: [PATCH 21/26] 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
-key and certificate, however, so that the keys are appropriately named.
-
-The private key for the module signer should be placed in signing_key.priv
-(unencrypted!) and the public key in an X.509 certificate as signing_key.x509.
-
-If a transient key is desired for signing the modules, a config file for
-'openssl req' can be placed in x509.genkey, looking something like the
-following:
-
-	[ req ]
-	default_bits = 4096
-	distinguished_name = req_distinguished_name
-	prompt = no
-	x509_extensions = myexts
-
-	[ req_distinguished_name ]
-	O = Magarathea
-	CN = Glacier signing key
-	emailAddress = slartibartfast at magrathea.h2g2
-
-	[ myexts ]
-	basicConstraints=critical,CA:FALSE
-	keyUsage=digitalSignature
-	subjectKeyIdentifier=hash
-	authorityKeyIdentifier=hash
-
-The build process will use this to configure:
-
-	openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \
-		-x509 -config x509.genkey \
-		-outform DER -out signing_key.x509 \
-		-keyout signing_key.priv
-
-to generate the key.
-
-Note that it is required that the X.509 certificate have a subjectKeyIdentifier
-and an authorityKeyIdentifier.  Without those, the certificate will be
-rejected.  These can be used to check the validity of a certificate.
-
-Note that 'make distclean' will remove signing_key.{priv,x509} and x509.genkey,
-whether or not they were generated automatically.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 49 insertions(+)
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 08ba8a6..83f1565 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -132,3 +132,52 @@ quiet_cmd_timeconst  = TIMEC   $@
- targets += timeconst.h
- $(obj)/timeconst.h: $(src)/timeconst.pl FORCE
- 	$(call if_changed,timeconst)
-+
-+ifeq ($(CONFIG_MODULE_SIG),y)
-+
-+###############################################################################
-+#
-+# 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.
-+#
-+###############################################################################
-+signing_key.priv signing_key.x509: x509.genkey
-+	@echo "###"
-+	@echo "### Now generating an X.509 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 "###"
-+	openssl req -new -nodes -utf8 -sha1 -days 36500 -batch \
-+		-x509 -config x509.genkey \
-+		-outform DER -out signing_key.x509 \
-+		-keyout signing_key.priv
-+	@echo "###"
-+	@echo "### Key pair generated."
-+	@echo "###"
-+
-+x509.genkey:
-+	@echo Generating X.509 key generation config
-+	@echo  >x509.genkey "[ req ]"
-+	@echo >>x509.genkey "default_bits = 4096"
-+	@echo >>x509.genkey "distinguished_name = req_distinguished_name"
-+	@echo >>x509.genkey "prompt = no"
-+	@echo >>x509.genkey "x509_extensions = myexts"
-+	@echo >>x509.genkey
-+	@echo >>x509.genkey "[ req_distinguished_name ]"
-+	@echo >>x509.genkey "O = Magarathea"
-+	@echo >>x509.genkey "CN = Glacier signing key"
-+	@echo >>x509.genkey "emailAddress = slartibartfast at magrathea.h2g2"
-+	@echo >>x509.genkey
-+	@echo >>x509.genkey "[ myexts ]"
-+	@echo >>x509.genkey "basicConstraints=critical,CA:FALSE"
-+	@echo >>x509.genkey "keyUsage=digitalSignature"
-+	@echo >>x509.genkey "subjectKeyIdentifier=hash"
-+	@echo >>x509.genkey "authorityKeyIdentifier=keyid"
-+endif
-+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey
--- 
-1.7.11.4
-
-
-From 798049d9df83c8fd87fd5ddb97a77054558f4361 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:25 +0100
-Subject: [PATCH 22/26] 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 at 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 at redhat.com>
----
- kernel/Makefile          |  11 ++++-
- kernel/modsign_pubkey.c  | 112 +++++++++++++++++++++++++++++++++++++++++++++++
- kernel/module-internal.h |   2 +
- 3 files changed, 123 insertions(+), 2 deletions(-)
- create mode 100644 kernel/modsign_pubkey.c
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 83f1565..63f8386 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -55,7 +55,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_signing.o
-+obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
-@@ -134,6 +134,13 @@ $(obj)/timeconst.h: $(src)/timeconst.pl FORCE
- 	$(call if_changed,timeconst)
- 
- ifeq ($(CONFIG_MODULE_SIG),y)
-+#
-+# Pull the signing certificate and any extra certificates into the kernel
-+#
-+extra_certificates:
-+	touch $@
-+
-+kernel/modsign_pubkey.o: signing_key.x509 extra_certificates
- 
- ###############################################################################
- #
-@@ -180,4 +187,4 @@ x509.genkey:
- 	@echo >>x509.genkey "subjectKeyIdentifier=hash"
- 	@echo >>x509.genkey "authorityKeyIdentifier=keyid"
- endif
--CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey
-+CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates
-diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
-new file mode 100644
-index 0000000..f504d9f
---- /dev/null
-+++ b/kernel/modsign_pubkey.c
-@@ -0,0 +1,112 @@
-+/* Public keys for module signature verification
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells at redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/cred.h>
-+#include <linux/err.h>
-+#include <keys/asymmetric-type.h>
-+#include "module-internal.h"
-+
-+struct key *modsign_keyring;
-+
-+extern __initdata const u8 modsign_certificate_list[];
-+extern __initdata const u8 modsign_certificate_list_end[];
-+asm(".section .init.data,\"aw\"\n"
-+    "modsign_certificate_list:\n"
-+    ".incbin \"signing_key.x509\"\n"
-+    ".incbin \"extra_certificates\"\n"
-+    "modsign_certificate_list_end:"
-+    );
-+
-+/*
-+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice
-+ * if modsign.pub changes.
-+ */
-+static __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 load_module_signing_keys(void)
-+{
-+	key_ref_t key;
-+	const u8 *p, *end;
-+	size_t plen;
-+
-+	pr_notice("Loading module verification certificates\n");
-+
-+	end = modsign_certificate_list_end;
-+	p = modsign_certificate_list;
-+	while (p < end) {
-+		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-+		 * than 256 bytes in size.
-+		 */
-+		if (end - p < 4)
-+			goto dodgy_cert;
-+		if (p[0] != 0x30 &&
-+		    p[1] != 0x82)
-+			goto dodgy_cert;
-+		plen = (p[2] << 8) | p[3];
-+		plen += 4;
-+		if (plen > end - p)
-+			goto dodgy_cert;
-+
-+		key = key_create_or_update(make_key_ref(modsign_keyring, 1),
-+					   "asymmetric",
-+					   NULL,
-+					   p,
-+					   plen,
-+					   (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+					   KEY_USR_VIEW,
-+					   KEY_ALLOC_NOT_IN_QUOTA);
-+		if (IS_ERR(key))
-+			pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n",
-+			       PTR_ERR(key));
-+		else
-+			pr_notice("MODSIGN: Loaded cert '%s'\n",
-+				  key_ref_to_ptr(key)->description);
-+		p += plen;
-+	}
-+
-+	return 0;
-+
-+dodgy_cert:
-+	pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n");
-+	return 0;
-+}
-+late_initcall(load_module_signing_keys);
-diff --git a/kernel/module-internal.h b/kernel/module-internal.h
-index 14da0ea..648f481 100644
---- a/kernel/module-internal.h
-+++ b/kernel/module-internal.h
-@@ -9,6 +9,8 @@
-  * 2 of the Licence, or (at your option) any later version.
-  */
- 
-+extern struct key *modsign_keyring;
-+
- extern int mod_verify_sig(const void *mod, unsigned long modlen,
- 			  const void *sig, unsigned long siglen,
- 			  bool *_sig_ok);
--- 
-1.7.11.4
-
-
-From dcac300c703bc9a237deab7c7f0301f3803a3a9a Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:26 +0100
-Subject: [PATCH 23/26] MODSIGN: Implement module signature checking
-
-Check the signature on the module against the keys compiled into the kernel or
-available in a hardware key store.
-
-Currently, only RSA keys are supported - though that's easy enough to change,
-and the signature is expected to contain raw components (so not a PGP or
-PKCS#7 formatted blob).
-
-The signature blob is expected to consist of the following pieces in order:
-
- (1) The binary identifier for the key.  This is expected to match the
-     SubjectKeyIdentifier from an X.509 certificate.  Only X.509 type
-     identifiers are currently supported.
-
- (2) The signature data, consisting of a series of MPIs in which each is in
-     the format of a 2-byte BE word sizes followed by the content data.
-
- (3) A 12 byte information block of the form:
-
-	struct module_signature {
-		enum pkey_algo		algo : 8;
-		enum pkey_hash_algo	hash : 8;
-		enum pkey_id_type	id_type : 8;
-		u8			__pad;
-		__be32			id_length;
-		__be32			sig_length;
-	};
-
-     The three enums are defined in crypto/public_key.h.
-
-     'algo' contains the public-key algorithm identifier (0->DSA, 1->RSA).
-
-     'hash' contains the digest algorithm identifier (0->MD4, 1->MD5, 2->SHA1,
-      etc.).
-
-     'id_type' contains the public-key identifier type (0->PGP, 1->X.509).
-
-     '__pad' should be 0.
-
-     'id_length' should contain in the binary identifier length in BE form.
-
-     'sig_length' should contain in the signature data length in BE form.
-
-     The lengths are in BE order rather than CPU order to make dealing with
-     cross-compilation easier.
+From a6a74ede612b526dd0f958c2eee5adfa9b038b95 Mon Sep 17 00:00:00 2001
+From: Josh Boyer <jwboyer at redhat.com>
+Date: Mon, 15 Oct 2012 10:14:09 -0400
+Subject: [PATCH 1/2] Revert "MODSIGN: Sign modules during the build process"
 
-Signed-off-by: David Howells <dhowells at redhat.com>
+This reverts commit 80d65e58e93ffdabf58202653a0435bd3cf2d82e.
 ---
- init/Kconfig            |   8 ++
- kernel/module_signing.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 230 insertions(+), 1 deletion(-)
-
-diff --git a/init/Kconfig b/init/Kconfig
-index 00d4579..63fcbeb 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1588,6 +1588,14 @@ config MODULE_SRCVERSION_ALL
- config MODULE_SIG
- 	bool "Module signature verification"
- 	depends on MODULES
-+	select CONFIG_KEYS
-+	select CONFIG_CRYPTO
-+	select ASYMMETRIC_KEY_TYPE
-+	select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
-+	select PUBLIC_KEY_ALGO_RSA
-+	select ASN1
-+	select OID_REGISTRY
-+	select X509_CERTIFICATE_PARSER
- 	help
- 	  Check modules for valid signatures upon load: the signature
- 	  is simply appended to the module. For more information see
-diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-index 0af10a5..83eb505 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -10,14 +10,235 @@
-  */
- 
- #include <linux/kernel.h>
-+#include <linux/err.h>
-+#include <crypto/public_key.h>
-+#include <crypto/hash.h>
-+#include <keys/asymmetric-type.h>
- #include "module-internal.h"
+ scripts/Makefile.modpost |  77 +------------------------------
+ scripts/sign-file        | 115 -----------------------------------------------
+ 2 files changed, 1 insertion(+), 191 deletions(-)
+ delete mode 100644 scripts/sign-file
+
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index 0020891..a1cb022 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -14,8 +14,7 @@
+ # 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> (or <module.unsigned>) file
+-# 7) signs the modules to a <module.ko> file
++# 6) final link of the module to a <module.ko> file
+ 
+ # Step 3 is used to place certain information in the module's ELF
+ # section, including information such as:
+@@ -33,8 +32,6 @@
+ # 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.
+@@ -119,7 +116,6 @@ $(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) \
+@@ -129,78 +125,7 @@ $(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 = ./signing_key.priv
+-MODPUBKEY = ./signing_key.x509
+-
+-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
+ 
+-# We strip the module as best we can - note that using both strip and eu-strip
+-# results in a smaller module than using either alone.
+-EU_STRIP = $(shell which eu-strip || echo true)
+-
+-quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@
+-      cmd_sign_ko_stripped_ko_unsigned = \
+-		cp $< $@ && \
+-		strip -x -g $@ && \
+-		$(EU_STRIP) $@
+-
+-ifeq ($(SIGN_MODULES),1)
+-
+-quiet_cmd_genkeyid = GENKEYID $@
+-      cmd_genkeyid = \
+-		perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid
+-
+-%.signer %.keyid: %
+-	$(call if_changed,genkeyid)
+-
+-KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid
+-quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@
+-      cmd_sign_ko_ko_stripped = \
+-		sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@
+-else
+-KEYRING_DEP :=
+-quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
+-      cmd_sign_ko_ko_unsigned = \
+-		cp $< $@
+-endif
+-
+-$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE
+-	$(call if_changed,sign_ko_ko_stripped)
+-
+-$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE
+-	$(call if_changed,sign_ko_stripped_ko_unsigned)
+-
+-targets += $(modules)
+-endif
  
- /*
-+ * Module signature information block.
-+ *
-+ * The constituents of the signature section are, in order:
-+ *
-+ *	- Signer's name
-+ *	- Key identifier
-+ *	- Signature data
-+ *	- Information block
-+ */
-+struct module_signature {
-+	enum pkey_algo		algo : 8;	/* Public-key crypto algorithm */
-+	enum pkey_hash_algo	hash : 8;	/* Digest algorithm */
-+	enum pkey_id_type	id_type : 8;	/* Key identifier type */
-+	u8			signer_len;	/* Length of signer's name */
-+	u8			key_id_len;	/* Length of key identifier */
-+	u8			__pad[3];
-+	__be32			sig_len;	/* Length of signature data */
-+};
-+
-+/*
-+ * Digest the module contents.
-+ */
-+static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash,
-+						    const void *mod,
-+						    unsigned long modlen)
-+{
-+	struct public_key_signature *pks;
-+	struct crypto_shash *tfm;
-+	struct shash_desc *desc;
-+	size_t digest_size, desc_size;
-+	int ret;
-+
-+	pr_devel("==>%s()\n", __func__);
-+	
-+	/* Allocate the hashing algorithm we're going to need and find out how
-+	 * big the hash operational data will be.
-+	 */
-+	tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0);
-+	if (IS_ERR(tfm))
-+		return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
-+
-+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
-+	digest_size = crypto_shash_digestsize(tfm);
-+
-+	/* We allocate the hash operational data storage on the end of our
-+	 * context data and the digest output buffer on the end of that.
-+	 */
-+	ret = -ENOMEM;
-+	pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
-+	if (!pks)
-+		goto error_no_pks;
-+
-+	pks->pkey_hash_algo	= hash;
-+	pks->digest		= (u8 *)pks + sizeof(*pks) + desc_size;
-+	pks->digest_size	= digest_size;
-+
-+	desc = (void *)pks + sizeof(*pks);
-+	desc->tfm   = tfm;
-+	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-+
-+	ret = crypto_shash_init(desc);
-+	if (ret < 0)
-+		goto error;
-+
-+	ret = crypto_shash_finup(desc, mod, modlen, pks->digest);
-+	if (ret < 0)
-+		goto error;
-+
-+	crypto_free_shash(tfm);
-+	pr_devel("<==%s() = ok\n", __func__);
-+	return pks;
-+
-+error:
-+	kfree(pks);
-+error_no_pks:
-+	crypto_free_shash(tfm);
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ERR_PTR(ret);
-+}
-+
-+/*
-+ * Extract an MPI array from the signature data.  This represents the actual
-+ * signature.  Each raw MPI is prefaced by a BE 2-byte value indicating the
-+ * size of the MPI in bytes.
-+ *
-+ * RSA signatures only have one MPI, so currently we only read one.
-+ */
-+static int mod_extract_mpi_array(struct public_key_signature *pks,
-+				 const void *data, size_t len)
-+{
-+	size_t nbytes;
-+	MPI mpi;
-+
-+	if (len < 3)
-+		return -EBADMSG;
-+	nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1];
-+	data += 2;
-+	len -= 2;
-+	if (len != nbytes)
-+		return -EBADMSG;
-+
-+	mpi = mpi_read_raw_data(data, nbytes);
-+	if (!mpi)
-+		return -ENOMEM;
-+	pks->mpi[0] = mpi;
-+	pks->nr_mpi = 1;
-+	return 0;
-+}
-+
-+/*
-+ * Request an asymmetric key.
-+ */
-+static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
-+					  const u8 *key_id, size_t key_id_len)
-+{
-+	key_ref_t key;
-+	size_t i;
-+	char *id, *q;
-+
-+	pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len);
-+
-+	/* Construct an identifier. */
-+	id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL);
-+	if (!id)
-+		return ERR_PTR(-ENOKEY);
-+
-+	memcpy(id, signer, signer_len);
-+
-+	q = id + signer_len;
-+	*q++ = ':';
-+	*q++ = ' ';
-+	for (i = 0; i < key_id_len; i++) {
-+		*q++ = hex_asc[*key_id >> 4];
-+		*q++ = hex_asc[*key_id++ & 0x0f];
-+	}
-+
-+	*q = 0;
-+
-+	pr_debug("Look up: \"%s\"\n", id);
-+
-+	key = keyring_search(make_key_ref(modsign_keyring, 1),
-+			     &key_type_asymmetric, id);
-+	kfree(id);
-+
-+	if (IS_ERR(key)) {
-+		switch (PTR_ERR(key)) {
-+			/* Hide some search errors */
-+		case -EACCES:
-+		case -ENOTDIR:
-+		case -EAGAIN:
-+			return ERR_PTR(-ENOKEY);
-+		default:
-+			return ERR_CAST(key);
-+		}
-+	}
-+
-+	pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
-+	return key_ref_to_ptr(key);
-+}
-+
-+/*
-  * Verify the signature on a module.
-  */
- int mod_verify_sig(const void *mod, unsigned long modlen,
- 		   const void *sig, unsigned long siglen,
- 		   bool *_sig_ok)
- {
--	return -EKEYREJECTED;
-+	struct public_key_signature *pks;
-+	struct module_signature ms;
-+	struct key *key;
-+	size_t sig_len;
-+	int ret;
-+
-+	pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen);
-+
-+	if (siglen <= sizeof(ms))
-+		return -EBADMSG;
-+
-+	memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms));
-+	siglen -= sizeof(ms);
-+
-+	sig_len = be32_to_cpu(ms.sig_len);
-+	if (sig_len >= siglen ||
-+	    siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len)
-+		return -EBADMSG;
-+
-+	/* For the moment, only support RSA and X.509 identifiers */
-+	if (ms.algo != PKEY_ALGO_RSA ||
-+	    ms.id_type != PKEY_ID_X509)
-+		return -ENOPKG;
-+
-+	if (ms.hash >= PKEY_HASH__LAST ||
-+	    !pkey_hash_algo[ms.hash])
-+		return -ENOPKG;
-+
-+	key = request_asymmetric_key(sig, ms.signer_len,
-+				     sig + ms.signer_len, ms.key_id_len);
-+	if (IS_ERR(key))
-+		return PTR_ERR(key);
-+
-+	pks = mod_make_digest(ms.hash, mod, modlen);
-+	if (IS_ERR(pks)) {
-+		ret = PTR_ERR(pks);
-+		goto error_put_key;
-+	}
-+
-+	ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len,
-+				    sig_len);
-+	if (ret < 0)
-+		goto error_free_pks;
-+
-+	ret = verify_signature(key, pks);
-+	pr_devel("verify_signature() = %d\n", ret);
-+
-+	if (ret == 0)
-+		*_sig_ok = true;
-+
-+error_free_pks:
-+	mpi_free(pks->rsa.s);
-+	kfree(pks);
-+error_put_key:
-+	key_put(key);
-+	pr_devel("<==%s() = %d\n", __func__, ret);
-+	return ret;	
- }
--- 
-1.7.11.4
-
-
-From 89fbf1de73ed1ef29a3943d9f3bcf69a433191da Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 17:13:26 +0100
-Subject: [PATCH 24/26] MODSIGN: Provide a script for generating a key ID from
- an X.509 cert
-
-Provide a script to parse an X.509 certificate and certain pieces of
-information from it in order to generate a key identifier to be included within
-a module signature.
-
-The script takes the Subject Name and extracts (if present) the
-organizationName (O), the commonName (CN) and the emailAddress and fabricates
-the signer's name from them:
-
- (1) If both O and CN exist, then the name will be "O: CN", unless:
-
-     (a) CN is prefixed by O, in which case only CN is used.
-
-     (b) CN and O share at least the first 7 characters, in which case only CN
-     	 is used.
-
- (2) Otherwise, CN is used if present.
-
- (3) Otherwise, O is used if present.
-
- (4) Otherwise the emailAddress is used, if present.
-
- (5) Otherwise a blank name is used.
-
-The script emits a binary encoded identifier in the following form:
-
- - 2 BE bytes indicating the length of the signer's name.
-
- - 2 BE bytes indicating the length of the subject key identifier.
-
- - The characters of the signer's name.
-
- - The bytes of the subject key identifier.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- scripts/x509keyid | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 268 insertions(+)
- create mode 100755 scripts/x509keyid
-
-diff --git a/scripts/x509keyid b/scripts/x509keyid
-new file mode 100755
-index 0000000..c8e91a4
---- /dev/null
-+++ b/scripts/x509keyid
-@@ -0,0 +1,268 @@
-+#!/usr/bin/perl -w
-+#
-+# Generate an identifier from an X.509 certificate that can be placed in a
-+# module signature to indentify the key to use.
-+#
-+# Format:
-+#
-+#	./scripts/x509keyid <x509-cert> <signer's-name> <key-id>
-+#
-+# We read the DER-encoded X509 certificate and parse it to extract the Subject
-+# name and Subject Key Identifier.  The provide the data we need to build the
-+# certificate identifier.
-+#
-+# The signer's name part of the identifier is fabricated from the commonName,
-+# the organizationName or the emailAddress components of the X.509 subject
-+# name and written to the second named file.
-+#
-+# The subject key ID to select which of that signer's certificates we're
-+# intending to use to sign the module is written to the third named file.
-+#
-+use strict;
-+
-+my $raw_data;
-+
-+die "Need three filenames\n" if ($#ARGV != 2);
-+
-+my $src = $ARGV[0];
-+
-+open(FD, "<$src") || die $src;
-+binmode FD;
-+my @st = stat(FD);
-+die $src if (!@st);
-+read(FD, $raw_data, $st[7]) || die $src;
-+close(FD);
-+
-+my $UNIV = 0 << 6;
-+my $APPL = 1 << 6;
-+my $CONT = 2 << 6;
-+my $PRIV = 3 << 6;
-+
-+my $CONS = 0x20;
-+
-+my $BOOLEAN	= 0x01;
-+my $INTEGER	= 0x02;
-+my $BIT_STRING	= 0x03;
-+my $OCTET_STRING = 0x04;
-+my $NULL	= 0x05;
-+my $OBJ_ID	= 0x06;
-+my $UTF8String	= 0x0c;
-+my $SEQUENCE	= 0x10;
-+my $SET		= 0x11;
-+my $UTCTime	= 0x17;
-+my $GeneralizedTime = 0x18;
-+
-+my %OIDs = (
-+    pack("CCC", 85, 4, 3)	=> "commonName",
-+    pack("CCC", 85, 4, 6)	=> "countryName",
-+    pack("CCC", 85, 4, 10)	=> "organizationName",
-+    pack("CCC", 85, 4, 11)	=> "organizationUnitName",
-+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
-+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
-+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
-+    pack("CCC", 85, 29, 35)	=> "authorityKeyIdentifier",
-+    pack("CCC", 85, 29, 14)	=> "subjectKeyIdentifier",
-+    pack("CCC", 85, 29, 19)	=> "basicConstraints"
-+);
-+
-+###############################################################################
-+#
-+# Extract an ASN.1 element from a string and return information about it.
-+#
-+###############################################################################
-+sub asn1_extract($$@)
-+{
-+    my ($cursor, $expected_tag, $optional) = @_;
-+
-+    return [ -1 ]
-+	if ($cursor->[1] == 0 && $optional);
-+
-+    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
-+	if ($cursor->[1] < 2);
-+
-+    my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
-+
-+    if ($expected_tag != -1 && $tag != $expected_tag) {
-+	return [ -1 ]
-+	    if ($optional);
-+	die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
-+	" not ", $expected_tag, ")\n";
-+    }
-+
-+    $cursor->[0] += 2;
-+    $cursor->[1] -= 2;
-+
-+    die $src, ": ", $cursor->[0], ": ASN.1 long tag\n"
-+	if (($tag & 0x1f) == 0x1f);
-+    die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
-+	if ($len == 0x80);
-+
-+    if ($len > 0x80) {
-+	my $l = $len - 0x80;
-+	die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
-+	    if ($cursor->[1] < $l);
-+
-+	if ($l == 0x1) {
-+	    $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
-+	} elsif ($l = 0x2) {
-+	    $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
-+	} elsif ($l = 0x3) {
-+	    $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
-+	    $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
-+	} elsif ($l = 0x4) {
-+	    $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
-+	} else {
-+	    die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
-+	}
-+
-+	$cursor->[0] += $l;
-+	$cursor->[1] -= $l;
-+    }
-+
-+    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
-+	if ($cursor->[1] < $len);
-+
-+    my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
-+    $cursor->[0] += $len;
-+    $cursor->[1] -= $len;
-+
-+    return $ret;
-+}
-+
-+###############################################################################
-+#
-+# Retrieve the data referred to by a cursor
-+#
-+###############################################################################
-+sub asn1_retrieve($)
-+{
-+    my ($cursor) = @_;
-+    my ($offset, $len, $data) = @$cursor;
-+    return substr($$data, $offset, $len);
-+}
-+
-+###############################################################################
-+#
-+# Roughly parse the X.509 certificate
-+#
-+###############################################################################
-+my $cursor = [ 0, length($raw_data), \$raw_data ];
-+
-+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
-+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
-+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
-+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
-+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
-+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
-+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
-+
-+my $subject_key_id = ();
-+my $authority_key_id = ();
-+
-+#
-+# Parse the extension list
-+#
-+if ($extension_list->[0] != -1) {
-+    my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
-+
-+    while ($extensions->[1]->[1] > 0) {
-+	my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
-+	my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
-+	my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
-+	my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
-+
-+	my $raw_oid = asn1_retrieve($x_oid->[1]);
-+	next if (!exists($OIDs{$raw_oid}));
-+	my $x_type = $OIDs{$raw_oid};
-+
-+	my $raw_value = asn1_retrieve($x_val->[1]);
-+
-+	if ($x_type eq "subjectKeyIdentifier") {
-+	    my $vcursor = [ 0, length($raw_value), \$raw_value ];
-+
-+	    $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
-+	}
-+    }
-+}
-+
-+###############################################################################
-+#
-+# Determine what we're going to use as the signer's name.  In order of
-+# preference, take one of: commonName, organizationName or emailAddress.
-+#
-+###############################################################################
-+my $org = "";
-+my $cn = "";
-+my $email = "";
-+
-+while ($subject->[1]->[1] > 0) {
-+    my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
-+    my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
-+    my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
-+    my $n_val = asn1_extract($attr->[1], -1);
-+
-+    my $raw_oid = asn1_retrieve($n_oid->[1]);
-+    next if (!exists($OIDs{$raw_oid}));
-+    my $n_type = $OIDs{$raw_oid};
-+
-+    my $raw_value = asn1_retrieve($n_val->[1]);
-+
-+    if ($n_type eq "organizationName") {
-+	$org = $raw_value;
-+    } elsif ($n_type eq "commonName") {
-+	$cn = $raw_value;
-+    } elsif ($n_type eq "emailAddress") {
-+	$email = $raw_value;
-+    }
-+}
-+
-+my $id_name = $email;
-+
-+if ($org && $cn) {
-+    # Don't use the organizationName if the commonName repeats it
-+    if (length($org) <= length($cn) &&
-+	substr($cn, 0, length($org)) eq $org) {
-+	$id_name = $cn;
-+	goto got_id_name;
-+    }
-+
-+    # Or a signifcant chunk of it
-+    if (length($org) >= 7 &&
-+	length($cn) >= 7 &&
-+	substr($cn, 0, 7) eq substr($org, 0, 7)) {
-+	$id_name = $cn;
-+	goto got_id_name;
-+    }
-+
-+    $id_name = $org . ": " . $cn;
-+} elsif ($org) {
-+    $id_name = $org;
-+} elsif ($cn) {
-+    $id_name = $cn;
-+}
-+
-+got_id_name:
-+
-+###############################################################################
-+#
-+# Output the signer's name and the key identifier that we're going to include
-+# in module signatures.
-+#
-+###############################################################################
-+die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
-+    if (!$subject_key_id);
-+
-+my $id_key_id = asn1_retrieve($subject_key_id->[1]);
-+
-+open(OUTFD, ">$ARGV[1]") || die $ARGV[1];
-+print OUTFD $id_name;
-+close OUTFD || die $ARGV[1];
-+
-+open(OUTFD, ">$ARGV[2]") || die $ARGV[2];
-+print OUTFD $id_key_id;
-+close OUTFD || die $ARGV[2];
+ # Add FORCE to the prequisites of a target to force it to be always rebuilt.
+ # ---------------------------------------------------------------------------
+diff --git a/scripts/sign-file b/scripts/sign-file
+deleted file mode 100644
+index e58e34e..0000000
+--- a/scripts/sign-file
++++ /dev/null
+@@ -1,115 +0,0 @@
+-#!/bin/sh
+-#
+-# Sign a module file using the given key.
+-#
+-# Format: sign-file <key> <x509> <src-file> <dst-file>
+-#
+-
+-scripts=`dirname $0`
+-
+-CONFIG_MODULE_SIG_SHA512=y
+-if [ -r .config ]
+-then
+-    . ./.config
+-fi
+-
+-key="$1"
+-x509="$2"
+-src="$3"
+-dst="$4"
+-
+-if [ ! -r "$key" ]
+-then
+-    echo "Can't read private key" >&2
+-    exit 2
+-fi
+-
+-if [ ! -r "$x509" ]
+-then
+-    echo "Can't read X.509 certificate" >&2
+-    exit 2
+-fi
+-if [ ! -r "$x509.signer" ]
+-then
+-    echo "Can't read Signer name" >&2
+-    exit 2;
+-fi
+-if [ ! -r "$x509.keyid" ]
+-then
+-    echo "Can't read Key identifier" >&2
+-    exit 2;
+-fi
+-
+-#
+-# Signature parameters
+-#
+-algo=1		# Public-key crypto algorithm: RSA
+-hash=		# Digest algorithm
+-id_type=1	# Identifier type: X.509
+-
+-#
+-# Digest the data
+-#
+-dgst=
+-if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ]
+-then
+-    prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14"
+-    dgst=-sha1
+-    hash=2
+-elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ]
+-then
+-    prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C"
+-    dgst=-sha224
+-    hash=7
+-elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ]
+-then
+-    prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20"
+-    dgst=-sha256
+-    hash=4
+-elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ]
+-then
+-    prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30"
+-    dgst=-sha384
+-    hash=5
+-elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ]
+-then
+-    prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40"
+-    dgst=-sha512
+-    hash=6
+-else
+-    echo "$0: Can't determine hash algorithm" >&2
+-    exit 2
+-fi
+-
+-(
+-perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $?
+-openssl dgst $dgst -binary $src || exit $?
+-) >$src.dig || exit $?
+-
+-#
+-# Generate the binary signature, which will be just the integer that comprises
+-# the signature with no metadata attached.
+-#
+-openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $?
+-signerlen=`stat -c %s $x509.signer`
+-keyidlen=`stat -c %s $x509.keyid`
+-siglen=`stat -c %s $src.sig`
+-
+-#
+-# Build the signed binary
+-#
+-(
+-    cat $src || exit $?
+-    echo '~Module signature appended~' || exit $?
+-    cat $x509.signer $x509.keyid || exit $?
+-
+-    # Preface each signature integer with a 2-byte BE length
+-    perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $?
+-    cat $src.sig || exit $?
+-
+-    # Generate the information block
+-    perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $?
+-) >$dst~ || exit $?
+-
+-# Permit in-place signing
+-mv $dst~ $dst || exit $?
 -- 
-1.7.11.4
+1.7.12.1
 
 
-From 007c8fc3412f0a55cd3a32c5e42236703a17d1c1 Mon Sep 17 00:00:00 2001
+From b29453cb9b235041f789c81b1982179acb6d3d06 Mon Sep 17 00:00:00 2001
 From: Josh Boyer <jwboyer at redhat.com>
 Date: Mon, 24 Sep 2012 10:46:36 -0400
-Subject: [PATCH 25/26] MODSIGN: Add modules_sign make target
+Subject: [PATCH 2/2] MODSIGN: Add modules_sign make target
 
 If CONFIG_MODULE_SIG is set, and 'make modules_sign' is called then this
 patch will cause the modules to get a signature installed.  The make target
@@ -8838,10 +301,10 @@ Signed-off-by: Josh Boyer <jwboyer at redhat.com>
  create mode 100644 scripts/sign-file
 
 diff --git a/Makefile b/Makefile
-index 644048d..4479147 100644
+index 5be2ee8..618cfbbf 100644
 --- a/Makefile
 +++ b/Makefile
-@@ -965,6 +965,12 @@ _modinst_post: _modinst_
+@@ -968,6 +968,12 @@ _modinst_post: _modinst_
  	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
  	$(call cmd,depmod)
  
@@ -8934,7 +397,7 @@ index 0000000..17326bc
 +.PHONY: $(PHONY)
 diff --git a/scripts/sign-file b/scripts/sign-file
 new file mode 100644
-index 0000000..1a472bb
+index 0000000..e58e34e
 --- /dev/null
 +++ b/scripts/sign-file
 @@ -0,0 +1,115 @@
@@ -8950,7 +413,7 @@ index 0000000..1a472bb
 +CONFIG_MODULE_SIG_SHA512=y
 +if [ -r .config ]
 +then
-+    source ./.config
++    . ./.config
 +fi
 +
 +key="$1"
@@ -9054,265 +517,5 @@ index 0000000..1a472bb
 +# Permit in-place signing
 +mv $dst~ $dst || exit $?
 -- 
-1.7.11.4
-
-
-From 33c6737b352ec10a7e0d7b053fbb084c0b7a9d36 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells at redhat.com>
-Date: Mon, 24 Sep 2012 20:51:59 +0100
-Subject: [PATCH 26/26] MODSIGN: Extend the policy on signature check failure
-
-Extend the policy on handling various sorts of signature check failure such as
-not having the requisite key available or being in FIPS mode.
-
-If the key specified is not known (ENOKEY) permit the module to be loaded in
-non-enforcing mode, otherwise reject it.
-
-If in FIPS mode, any loading failure shall cause a panic.
-
-Also print a warning if we try and fail to find a module signing key:
-
-	Request for unknown module key 'Magrathea: Glacier signing key: 5dd0839552bd6af498253f8af1e65da3472941c6' err -11
-
-This contains the identity field and the key ID from the signature as well as
-the error code.  The error codes are the raw return from keyring_search() and
-may be translated to -ENOKEY.
-
-Signed-off-by: David Howells <dhowells at redhat.com>
----
- kernel/Makefile         | 2 +-
- kernel/module.c         | 9 ++++++++-
- kernel/module_signing.c | 3 +++
- 3 files changed, 12 insertions(+), 2 deletions(-)
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 63f8386..111a845 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -177,7 +177,7 @@ x509.genkey:
- 	@echo >>x509.genkey "x509_extensions = myexts"
- 	@echo >>x509.genkey
- 	@echo >>x509.genkey "[ req_distinguished_name ]"
--	@echo >>x509.genkey "O = Magarathea"
-+	@echo >>x509.genkey "O = Magrathea"
- 	@echo >>x509.genkey "CN = Glacier signing key"
- 	@echo >>x509.genkey "emailAddress = slartibartfast at magrathea.h2g2"
- 	@echo >>x509.genkey
-diff --git a/kernel/module.c b/kernel/module.c
-index ab69599..de16959 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 <linux/fips.h>
- #include "module-internal.h"
- 
- #define CREATE_TRACE_POINTS
-@@ -2470,7 +2471,13 @@ found_marker:
- 	sig = p + markerlen;
- 	/* Truncate module up to signature. */
- 	*len = p - mod;
--	return mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok);
-+	err = mod_verify_sig(mod, *len, sig, end - sig, &info->sig_ok);
-+	if (err < 0 && fips_enabled)
-+		panic("Module verification failed with error %d in FIPS mode\n",
-+		      err);
-+	if (err == -ENOKEY && !sig_enforce)
-+		err = 0;
-+	return err;
- }
- #else /* !CONFIG_MODULE_SIG */
- static int module_sig_check(struct load_info *info,
-diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-index 83eb505..2beea56 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -159,6 +159,9 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
- 
- 	key = keyring_search(make_key_ref(modsign_keyring, 1),
- 			     &key_type_asymmetric, id);
-+	if (IS_ERR(key))
-+		pr_warn("Request for unknown module key '%s' err %ld\n",
-+			id, PTR_ERR(key));
- 	kfree(id);
- 
- 	if (IS_ERR(key)) {
--- 
-1.7.11.4
-
-The current choice of lifetime for the autogenerated X.509 of 100 years,
-putting the validTo date in 2112, causes problems on 32-bit systems where a
-32-bit time_t wraps in 2106.  64-bit x86_64 systems seem to be unaffected.
-
-This can result in something like:
-
-	Loading module verification certificates
-	X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
-	MODSIGN: Problem loading in-kernel X.509 certificate (-127)
-
-Or:
-
-	X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid
-	MODSIGN: Problem loading in-kernel X.509 certificate (-129)
-
-Instead of turning the dates into time_t values and comparing, turn the system
-clock and the ASN.1 dates into tm structs and compare those piecemeal instead.
-
-Reported-by: Rusty Russell <rusty at rustcorp.com.au>
-Signed-off-by: David Howells <dhowells at redhat.com>
----
-
- crypto/asymmetric_keys/x509_cert_parser.c |   25 ++++++++---------
- crypto/asymmetric_keys/x509_parser.h      |    4 +--
- crypto/asymmetric_keys/x509_public_key.c  |   42 ++++++++++++++++++++++++++---
- 3 files changed, 51 insertions(+), 20 deletions(-)
-
-
-diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
-index 8fcac94..db07e8c 100644
---- a/crypto/asymmetric_keys/x509_cert_parser.c
-+++ b/crypto/asymmetric_keys/x509_cert_parser.c
-@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen,
- /*
-  * Record a certificate time.
-  */
--static int x509_note_time(time_t *_time,  size_t hdrlen,
-+static int x509_note_time(struct tm *tm,  size_t hdrlen,
- 			  unsigned char tag,
- 			  const unsigned char *value, size_t vlen)
- {
--	unsigned YY, MM, DD, hh, mm, ss;
- 	const unsigned char *p = value;
- 
- #define dec2bin(X) ((X) - '0')
-@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time,  size_t hdrlen,
- 		/* UTCTime: YYMMDDHHMMSSZ */
- 		if (vlen != 13)
- 			goto unsupported_time;
--		YY = DD2bin(p);
--		if (YY > 50)
--			YY += 1900;
-+		tm->tm_year = DD2bin(p);
-+		if (tm->tm_year >= 50)
-+			tm->tm_year += 1900;
- 		else
--			YY += 2000;
-+			tm->tm_year += 2000;
- 	} else if (tag == ASN1_GENTIM) {
- 		/* GenTime: YYYYMMDDHHMMSSZ */
- 		if (vlen != 15)
- 			goto unsupported_time;
--		YY = DD2bin(p) * 100 + DD2bin(p);
-+		tm->tm_year = DD2bin(p) * 100 + DD2bin(p);
- 	} else {
- 		goto unsupported_time;
- 	}
- 
--	MM = DD2bin(p);
--	DD = DD2bin(p);
--	hh = DD2bin(p);
--	mm = DD2bin(p);
--	ss = DD2bin(p);
-+	tm->tm_year -= 1900;
-+	tm->tm_mon  = DD2bin(p) - 1;
-+	tm->tm_mday = DD2bin(p);
-+	tm->tm_hour = DD2bin(p);
-+	tm->tm_min  = DD2bin(p);
-+	tm->tm_sec  = DD2bin(p);
- 
- 	if (*p != 'Z')
- 		goto unsupported_time;
- 
--	*_time = mktime(YY, MM, DD, hh, mm, ss);
- 	return 0;
- 
- unsupported_time:
-diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
-index 635053f..f86dc5f 100644
---- a/crypto/asymmetric_keys/x509_parser.h
-+++ b/crypto/asymmetric_keys/x509_parser.h
-@@ -18,8 +18,8 @@ struct x509_certificate {
- 	char		*subject;		/* Name of certificate subject */
- 	char		*fingerprint;		/* Key fingerprint as hex */
- 	char		*authority;		/* Authority key fingerprint as hex */
--	time_t		valid_from;
--	time_t		valid_to;
-+	struct tm	valid_from;
-+	struct tm	valid_to;
- 	enum pkey_algo	pkey_algo : 8;		/* Public key algorithm */
- 	enum pkey_algo	sig_pkey_algo : 8;	/* Signature public key algorithm */
- 	enum pkey_hash_algo sig_hash_algo : 8;	/* Signature hash algorithm */
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index 716917c..5ab736d 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -106,7 +106,7 @@ error_no_sig:
- static int x509_key_preparse(struct key_preparsed_payload *prep)
- {
- 	struct x509_certificate *cert;
--	time_t now;
-+	struct tm now;
- 	size_t srlen, sulen;
- 	char *desc = NULL;
- 	int ret;
-@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- 	pr_devel("Cert Issuer: %s\n", cert->issuer);
- 	pr_devel("Cert Subject: %s\n", cert->subject);
- 	pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]);
--	pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to);
-+	printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
-+		 cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
-+		 cert->valid_from.tm_mday, cert->valid_from.tm_hour,
-+		 cert->valid_from.tm_min,  cert->valid_from.tm_sec);
-+	printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n",
-+		 cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1,
-+		 cert->valid_to.tm_mday, cert->valid_to.tm_hour,
-+		 cert->valid_to.tm_min,  cert->valid_to.tm_sec);
- 	pr_devel("Cert Signature: %s + %s\n",
- 		 pkey_algo[cert->sig_pkey_algo],
- 		 pkey_hash_algo[cert->sig_hash_algo]);
-@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- 		goto error_free_cert;
- 	}
- 
--	now = CURRENT_TIME.tv_sec;
--	if (now < cert->valid_from) {
-+	time_to_tm(CURRENT_TIME.tv_sec, 0, &now);
-+	printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n",
-+		 now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
-+		 now.tm_hour, now.tm_min,  now.tm_sec);
-+	if (now.tm_year < cert->valid_from.tm_year ||
-+	    (now.tm_year == cert->valid_from.tm_year &&
-+	     (now.tm_mon < cert->valid_from.tm_mon ||
-+	      (now.tm_mon == cert->valid_from.tm_mon &&
-+	       (now.tm_mday < cert->valid_from.tm_mday ||
-+		(now.tm_mday == cert->valid_from.tm_mday &&
-+		 (now.tm_hour < cert->valid_from.tm_hour ||
-+		  (now.tm_hour == cert->valid_from.tm_hour &&
-+		   (now.tm_min < cert->valid_from.tm_min ||
-+		    (now.tm_min == cert->valid_from.tm_min &&
-+		     (now.tm_sec < cert->valid_from.tm_sec
-+		      ))))))))))) {
- 		pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
- 		ret = -EKEYREJECTED;
- 		goto error_free_cert;
- 	}
--	if (now >= cert->valid_to) {
-+	if (now.tm_year > cert->valid_to.tm_year ||
-+	    (now.tm_year == cert->valid_to.tm_year &&
-+	     (now.tm_mon > cert->valid_to.tm_mon ||
-+	      (now.tm_mon == cert->valid_to.tm_mon &&
-+	       (now.tm_mday > cert->valid_to.tm_mday ||
-+		(now.tm_mday == cert->valid_to.tm_mday &&
-+		 (now.tm_hour > cert->valid_to.tm_hour ||
-+		  (now.tm_hour == cert->valid_to.tm_hour &&
-+		   (now.tm_min > cert->valid_to.tm_min ||
-+		    (now.tm_min == cert->valid_to.tm_min &&
-+		     (now.tm_sec > cert->valid_to.tm_sec
-+		      ))))))))))) {
- 		pr_warn("Cert %s has expired\n", cert->fingerprint);
- 		ret = -EKEYEXPIRED;
- 		goto error_free_cert;
+1.7.12.1
 
diff --git a/secure-boot-20120924.patch b/secure-boot-20120924.patch
index 54825ef..06681ca 100644
--- a/secure-boot-20120924.patch
+++ b/secure-boot-20120924.patch
@@ -11,13 +11,13 @@ capability set if required.
 
 Signed-off-by: Matthew Garrett <mjg at redhat.com>
 ---
- include/linux/capability.h | 6 +++++-
+ include/uapi/linux/capability.h | 6 +++++-
  1 file changed, 5 insertions(+), 1 deletion(-)
 
 diff --git a/include/linux/capability.h b/include/linux/capability.h
 index d10b7ed..4345bc8 100644
---- a/include/linux/capability.h
-+++ b/include/linux/capability.h
+--- a/include/uapi/linux/capability.h
++++ b/include/uapi/linux/capability.h
 @@ -364,7 +364,11 @@ struct cpu_vfs_cap_data {
  
  #define CAP_BLOCK_SUSPEND    36


More information about the scm-commits mailing list