summaryrefslogtreecommitdiffstats
path: root/modsign-20120816.patch
diff options
context:
space:
mode:
Diffstat (limited to 'modsign-20120816.patch')
-rw-r--r--modsign-20120816.patch10434
1 files changed, 0 insertions, 10434 deletions
diff --git a/modsign-20120816.patch b/modsign-20120816.patch
deleted file mode 100644
index 3c679558d..000000000
--- a/modsign-20120816.patch
+++ /dev/null
@@ -1,10434 +0,0 @@
-From bcb9a5e7e8108872ec9fd7083209cbf3a47ef952 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:14 +0100
-Subject: [PATCH 01/32] 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@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 | 108 ++++++++++++++++++++++---------
- 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, 245 insertions(+), 101 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..732a53e 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,33 @@ 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)
-+ goto error_put_type;
-+ if (!description)
-+ description = prep.description;
-+ ret = -EINVAL;
-+ if (!description)
-+ goto error_free_prep;
-+ }
-
- ret = __key_link_begin(keyring, ktype, description, &prealloc);
- if (ret < 0)
-- goto error_2;
-+ 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 +871,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 +899,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 +920,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 +933,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;
-
-- 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 2f5f2d483565648dbe050fda8767edd5d65b1d98 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:17 +0100
-Subject: [PATCH 02/32] 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@redhat.com>
-Cc: David S. Miller <davem@davemloft.net>
-Cc: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
-Cc: Arnd Bergmann <arnd@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@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 15b76403afcc626b91e5fcee8b6a950a51f284ef Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:18 +0100
-Subject: [PATCH 03/32] KEYS: Create a key type that can be used for general
- cryptographic operations
-
-Create a key type that can be used for general cryptographic operations, such
-as encryption, decryption, signature generation and signature verification.
-
-The key type is "crypto" and can provide access to a variety of cryptographic
-algorithms.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/security/keys-crypto.txt | 181 ++++++++++++++++++++++
- include/keys/crypto-subtype.h | 57 +++++++
- include/keys/crypto-type.h | 25 +++
- security/keys/Kconfig | 2 +
- security/keys/Makefile | 1 +
- security/keys/crypto/Kconfig | 7 +
- security/keys/crypto/Makefile | 7 +
- security/keys/crypto/crypto_keys.h | 28 ++++
- security/keys/crypto/crypto_type.c | 272 +++++++++++++++++++++++++++++++++
- 9 files changed, 580 insertions(+)
- create mode 100644 Documentation/security/keys-crypto.txt
- create mode 100644 include/keys/crypto-subtype.h
- create mode 100644 include/keys/crypto-type.h
- create mode 100644 security/keys/crypto/Kconfig
- create mode 100644 security/keys/crypto/Makefile
- create mode 100644 security/keys/crypto/crypto_keys.h
- create mode 100644 security/keys/crypto/crypto_type.c
-
-diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
-new file mode 100644
-index 0000000..97dee80
---- /dev/null
-+++ b/Documentation/security/keys-crypto.txt
-@@ -0,0 +1,181 @@
-+ ======================
-+ CRYPTOGRAPHIC KEY TYPE
-+ ======================
-+
-+Contents:
-+
-+ - Overview.
-+ - Key identification.
-+ - Accessing crypto keys.
-+ - Implementing crypto parsers.
-+ - Implementing crypto subtypes.
-+
-+
-+========
-+OVERVIEW
-+========
-+
-+The "crypto" key type is designed to be a container for cryptographic keys,
-+without imposing any particular restrictions on the form of the cryptography or
-+the key.
-+
-+The crypto key is given a subtype that defines what sort of data is associated
-+with the key and provides operations to describe and destroy it. However, no
-+requirement is made that the key data actually be loaded into the key.
-+
-+The crypto key also has a number of data parsers registered with it. The data
-+parsers are responsible for extracing information the blobs of data passed to
-+the instantiator function. The first data parser that recognises the blob gets
-+to set the subtype of the key and define the operations that can be done on
-+that key.
-+
-+Completely in-kernel key retention and operation subtypes and parsers can be
-+defined, but it would also be possible to provide access to cryptographic
-+hardware (such as a TPM) that might be used to both retain the relevant key and
-+perform operations using that key. In such a case, the crypto key would then
-+merely be an interface to the TPM driver.
-+
-+
-+==================
-+KEY IDENTIFICATION
-+==================
-+
-+Because the identity of a key is not necessarily known and may not be easily
-+calculated when a crypto key is allocated, it may not be a simple matter to set
-+a key description to something that's useful for determining whether this is
-+the key you're looking for. Furthermore, it may be necessary to perform a
-+partial match upon the key identity.
-+
-+To help with this, when a key is loaded, the parser calculates the key
-+fingerprint and stores a copy in the key structure.
-+
-+The crypto key type's key matching function then performs more checks than just
-+the straightforward comparison of the description with the criterion string:
-+
-+ (1) If the criterion string is of the form "id:<hexdigits>" then the match
-+ function will examine a key's fingerprint to see if the hex digits given
-+ after the "id:" match the tail. For instance:
-+
-+ keyctl search @s crypto id:5acc2142
-+
-+ will match a key with fingerprint:
-+
-+ 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142
-+
-+ (2) If the criterion string is of the form "<subtype>:<hexdigits>" then the
-+ match will match the ID as in (1), but with the added restriction that
-+ only keys of the specified subtype (e.g. dsa or rsa) will be matched. For
-+ instance:
-+
-+ keyctl search @s crypto dsa:5acc2142
-+
-+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
-+displayed, along with the subtype:
-+
-+ 1a39e171 I----- 1 perm 3f010000 0 0 crypto modsign.0: DSA 5acc2142 []
-+
-+
-+=====================
-+ACCESSING CRYPTO KEYS
-+=====================
-+
-+To access crypto keys from within the kernel, the following inclusion is
-+required:
-+
-+ #include <keys/crypto-type.h>
-+
-+This gives access to the key type:
-+
-+ struct key_type key_type_crypto;
-+
-+
-+===========================
-+IMPLEMENTING CRYPTO PARSERS
-+===========================
-+
-+The crypto key type keeps a list of registered data parsers. An example of
-+such a parser is one that parses OpenPGP packet formatted data [RFC 4880].
-+
-+During key instantiation each parser in the list is tried until one doesn't
-+return -EBADMSG.
-+
-+The parser definition structure looks like the following:
-+
-+ struct crypto_key_parser {
-+ struct module *owner;
-+ const char *name;
-+
-+ int (*instantiate)(struct key *key,
-+ const void *data, size_t datalen);
-+ };
-+
-+The owner and name fields should be set to the owning module and the name of
-+the parser.
-+
-+There are a number of operations defined by the parser. They are all optional,
-+but it is expected that at least one will be defined.
-+
-+ (1) instantiate().
-+
-+ The arguments are the same as for the instantiate function in the key
-+ type. 'key' is the crypto key being instantiated; data and datalen are
-+ the instantiation data, presumably containing cryptographic key data, and
-+ the length of that data.
-+
-+ If the data format is not recognised, -EBADMSG should be returned. If it
-+ is recognised, but the key cannot for some reason be set up, some other
-+ negative error code should be returned.
-+
-+ If the key can be successfully set up, then key->payload should be set to
-+ point to the retained data, key->type_data.p[0] should be set to point to
-+ the subtype chosen and key->type_data.p[1] should be set to point to a
-+ copy of the key's identity string and 0 should be returned.
-+
-+ The key's identity string may be partially matched upon. For a public-key
-+ algorithm such as RSA and DSA this will likely be a printable hex version
-+ of the key's fingerprint.
-+
-+Functions are provided to register and unregister parsers:
-+
-+ int register_crypto_key_parser(struct crypto_key_parser *parser);
-+ void unregister_crypto_key_parser(struct crypto_key_parser *subtype);
-+
-+Parsers may not have the same name. The names are only used for displaying in
-+debugging messages.
-+
-+
-+============================
-+IMPLEMENTING CRYPTO SUBTYPES
-+============================
-+
-+The parser selects the appropriate subtype directly and sets it on the key; the
-+crypto key then retains a reference on the subtype module (which means the
-+parser can be removed thereafter).
-+
-+The subtype definition structure looks like the following:
-+
-+ struct crypto_key_subtype {
-+ struct module *owner;
-+ const char *name;
-+
-+ void (*describe)(const struct key *key, struct seq_file *m);
-+ void (*destroy)(void *payload);
-+ };
-+
-+The owner and name fields should be set to the owning module and the name of
-+the subtype.
-+
-+There are a number of operations defined by the subtype:
-+
-+ (1) describe().
-+
-+ Mandatory. This allows the subtype to display something in /proc/keys
-+ against the key. For instance the name of the public key algorithm type
-+ could be displayed. The key type will display the tail of the key
-+ identity string after this.
-+
-+ (2) destroy().
-+
-+ Mandatory. This should free the memory associated with the key. The
-+ crypto key will look after freeing the fingerprint and releasing the
-+ reference on the subtype module.
-diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
-new file mode 100644
-index 0000000..1f546e6
---- /dev/null
-+++ b/include/keys/crypto-subtype.h
-@@ -0,0 +1,57 @@
-+/* Cryptographic key subtype
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ *
-+ * See Documentation/security/keys-crypto.txt
-+ */
-+
-+#ifndef _KEYS_CRYPTO_SUBTYPE_H
-+#define _KEYS_CRYPTO_SUBTYPE_H
-+
-+#include <linux/seq_file.h>
-+#include <keys/crypto-type.h>
-+
-+extern struct key_type key_type_crypto;
-+
-+/*
-+ * Keys of this type declare a subtype that indicates the handlers and
-+ * capabilities.
-+ */
-+struct crypto_key_subtype {
-+ struct module *owner;
-+ const char *name;
-+ unsigned short name_len; /* length of name */
-+
-+ void (*describe)(const struct key *key, struct seq_file *m);
-+
-+ void (*destroy)(void *payload);
-+};
-+
-+/*
-+ * Data parser. Called during instantiation and signature verification
-+ * initiation.
-+ */
-+struct crypto_key_parser {
-+ struct list_head link;
-+ struct module *owner;
-+ const char *name;
-+
-+ /* Attempt to 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 (*preparse)(struct key_preparsed_payload *prep);
-+};
-+
-+extern int register_crypto_key_parser(struct crypto_key_parser *);
-+extern void unregister_crypto_key_parser(struct crypto_key_parser *);
-+
-+#endif /* _KEYS_CRYPTO_SUBTYPE_H */
-diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
-new file mode 100644
-index 0000000..47c00c7
---- /dev/null
-+++ b/include/keys/crypto-type.h
-@@ -0,0 +1,25 @@
-+/* Cryptographic key type interface
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ *
-+ * See Documentation/security/keys-crypto.txt
-+ */
-+
-+#ifndef _KEYS_CRYPTO_TYPE_H
-+#define _KEYS_CRYPTO_TYPE_H
-+
-+#include <linux/key-type.h>
-+
-+extern struct key_type key_type_crypto;
-+
-+/*
-+ * The payload is at the discretion of the subtype.
-+ */
-+
-+#endif /* _KEYS_CRYPTO_TYPE_H */
-diff --git a/security/keys/Kconfig b/security/keys/Kconfig
-index a90d6d3..992fe52 100644
---- a/security/keys/Kconfig
-+++ b/security/keys/Kconfig
-@@ -69,3 +69,5 @@ config KEYS_DEBUG_PROC_KEYS
- the resulting table.
-
- If you are unsure as to whether this is required, answer N.
-+
-+source security/keys/crypto/Kconfig
-diff --git a/security/keys/Makefile b/security/keys/Makefile
-index 504aaa0..67dae73 100644
---- a/security/keys/Makefile
-+++ b/security/keys/Makefile
-@@ -24,3 +24,4 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
- #
- obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
- obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
-+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto/
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-new file mode 100644
-index 0000000..3d15710
---- /dev/null
-+++ b/security/keys/crypto/Kconfig
-@@ -0,0 +1,7 @@
-+config CRYPTO_KEY_TYPE
-+ tristate "Cryptographic key type"
-+ depends on KEYS
-+ help
-+ This option provides support for a type of key that holds the keys
-+ required for cryptographic operations such as encryption, decryption,
-+ signature generation and signature verification.
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-new file mode 100644
-index 0000000..36db1d5
---- /dev/null
-+++ b/security/keys/crypto/Makefile
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for cryptographic keys
-+#
-+
-+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
-+
-+crypto_keys-y := crypto_type.o
-diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h
-new file mode 100644
-index 0000000..eb11788
---- /dev/null
-+++ b/security/keys/crypto/crypto_keys.h
-@@ -0,0 +1,28 @@
-+/* Internal crypto type stuff
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+static inline
-+struct crypto_key_subtype *crypto_key_subtype(const struct key *key)
-+{
-+ return key->type_data.p[0];
-+}
-+
-+static inline const char *crypto_key_id(const struct key *key)
-+{
-+ return key->type_data.p[1];
-+}
-+
-+
-+/*
-+ * crypto_type.c
-+ */
-+extern struct list_head crypto_key_parsers;
-+extern struct rw_semaphore crypto_key_parsers_sem;
-diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c
-new file mode 100644
-index 0000000..e8f83a6
---- /dev/null
-+++ b/security/keys/crypto/crypto_type.c
-@@ -0,0 +1,272 @@
-+/* Cryptographic key type
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ *
-+ * See Documentation/security/keys-crypto.txt
-+ */
-+#include <keys/crypto-subtype.h>
-+#include <linux/seq_file.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include "crypto_keys.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+LIST_HEAD(crypto_key_parsers);
-+DECLARE_RWSEM(crypto_key_parsers_sem);
-+
-+/*
-+ * Match crypto_keys on (part of) their name
-+ * We have some shorthand methods for matching keys. We allow:
-+ *
-+ * "<desc>" - request a key by description
-+ * "id:<id>" - request a key matching the ID
-+ * "<subtype>:<id>" - request a key of a subtype
-+ */
-+static int crypto_key_match(const struct key *key, const void *description)
-+{
-+ const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
-+ const char *spec = description;
-+ const char *id, *kid;
-+ ptrdiff_t speclen;
-+ size_t idlen, kidlen;
-+
-+ if (!subtype || !spec || !*spec)
-+ return 0;
-+
-+ /* See if the full key description matches as is */
-+ if (key->description && strcmp(key->description, description) == 0)
-+ return 1;
-+
-+ /* All tests from here on break the criterion description into a
-+ * specifier, a colon and then an identifier.
-+ */
-+ id = strchr(spec, ':');
-+ if (!id)
-+ return 0;
-+
-+ speclen = id - spec;
-+ id++;
-+
-+ /* Anything after here requires a partial match on the ID string */
-+ kid = crypto_key_id(key);
-+ if (!kid)
-+ return 0;
-+
-+ idlen = strlen(id);
-+ kidlen = strlen(kid);
-+ if (idlen > kidlen)
-+ return 0;
-+
-+ kid += kidlen - idlen;
-+ if (strcasecmp(id, kid) != 0)
-+ return 0;
-+
-+ if (speclen == 2 &&
-+ memcmp(spec, "id", 2) == 0)
-+ return 1;
-+
-+ if (speclen == subtype->name_len &&
-+ memcmp(spec, subtype->name, speclen) == 0)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/*
-+ * Describe the crypto key
-+ */
-+static void crypto_key_describe(const struct key *key, struct seq_file *m)
-+{
-+ const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
-+ const char *kid = crypto_key_id(key);
-+ size_t n;
-+
-+ seq_puts(m, key->description);
-+
-+ if (subtype) {
-+ seq_puts(m, ": ");
-+ subtype->describe(key, m);
-+
-+ if (kid) {
-+ seq_putc(m, ' ');
-+ n = strlen(kid);
-+ if (n <= 8)
-+ seq_puts(m, kid);
-+ else
-+ seq_puts(m, kid + n - 8);
-+ }
-+
-+ seq_puts(m, " [");
-+ /* put something here to indicate the key's capabilities */
-+ seq_putc(m, ']');
-+ }
-+}
-+
-+/*
-+ * Preparse a crypto 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 crypto_key_preparse(struct key_preparsed_payload *prep)
-+{
-+ struct crypto_key_parser *parser;
-+ int ret;
-+
-+ pr_devel("==>%s()\n", __func__);
-+
-+ if (prep->datalen == 0)
-+ return -EINVAL;
-+
-+ down_read(&crypto_key_parsers_sem);
-+
-+ ret = -EBADMSG;
-+ list_for_each_entry(parser, &crypto_key_parsers, link) {
-+ pr_debug("Trying parser '%s'\n", parser->name);
-+
-+ ret = parser->preparse(prep);
-+ if (ret != -EBADMSG) {
-+ pr_debug("Parser recognised the format (ret %d)\n",
-+ ret);
-+ break;
-+ }
-+ }
-+
-+ up_read(&crypto_key_parsers_sem);
-+ pr_devel("<==%s() = %d\n", __func__, ret);
-+ return ret;
-+}
-+
-+/*
-+ * Clean up the preparse data
-+ */
-+static void crypto_key_free_preparse(struct key_preparsed_payload *prep)
-+{
-+ struct crypto_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 crypto_key defined key
-+ */
-+static int crypto_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-+{
-+ 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;
-+}
-+
-+/*
-+ * dispose of the data dangling from the corpse of a crypto key
-+ */
-+static void crypto_key_destroy(struct key *key)
-+{
-+ struct crypto_key_subtype *subtype = crypto_key_subtype(key);
-+ if (subtype) {
-+ subtype->destroy(key->payload.data);
-+ module_put(subtype->owner);
-+ key->type_data.p[0] = NULL;
-+ }
-+ kfree(key->type_data.p[1]);
-+ key->type_data.p[1] = NULL;
-+}
-+
-+struct key_type key_type_crypto = {
-+ .name = "crypto",
-+ .preparse = crypto_key_preparse,
-+ .free_preparse = crypto_key_free_preparse,
-+ .instantiate = crypto_key_instantiate,
-+ .match = crypto_key_match,
-+ .destroy = crypto_key_destroy,
-+ .describe = crypto_key_describe,
-+};
-+EXPORT_SYMBOL_GPL(key_type_crypto);
-+
-+/**
-+ * register_crypto_key_parser - Register a crypto key blob parser
-+ * @parser: The parser to register
-+ */
-+int register_crypto_key_parser(struct crypto_key_parser *parser)
-+{
-+ struct crypto_key_parser *cursor;
-+ int ret;
-+
-+ down_write(&crypto_key_parsers_sem);
-+
-+ list_for_each_entry(cursor, &crypto_key_parsers, link) {
-+ if (strcmp(cursor->name, parser->name) == 0) {
-+ pr_err("Crypto key parser '%s' already registered\n",
-+ parser->name);
-+ ret = -EEXIST;
-+ goto out;
-+ }
-+ }
-+
-+ list_add_tail(&parser->link, &crypto_key_parsers);
-+
-+ pr_notice("Crypto key parser '%s' registered\n", parser->name);
-+ ret = 0;
-+
-+out:
-+ up_write(&crypto_key_parsers_sem);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(register_crypto_key_parser);
-+
-+/**
-+ * unregister_crypto_key_parser - Unregister a crypto key blob parser
-+ * @parser: The parser to unregister
-+ */
-+void unregister_crypto_key_parser(struct crypto_key_parser *parser)
-+{
-+ down_write(&crypto_key_parsers_sem);
-+ list_del(&parser->link);
-+ up_write(&crypto_key_parsers_sem);
-+
-+ pr_notice("Crypto key parser '%s' unregistered\n", parser->name);
-+}
-+EXPORT_SYMBOL_GPL(unregister_crypto_key_parser);
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init crypto_key_init(void)
-+{
-+ return register_key_type(&key_type_crypto);
-+}
-+
-+static void __exit crypto_key_cleanup(void)
-+{
-+ unregister_key_type(&key_type_crypto);
-+}
-+
-+module_init(crypto_key_init);
-+module_exit(crypto_key_cleanup);
---
-1.7.11.4
-
-
-From a4e8ef15db9c013c4d3141424120c5ba74376483 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:18 +0100
-Subject: [PATCH 04/32] KEYS: Add signature verification facility
-
-Add a facility whereby a key subtype may be asked to verify a signature against
-the data it is purported to have signed.
-
-This adds four routines:
-
- (1) struct crypto_key_verify_context *
- verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
-
- This sets up a verification context for the given signature using
- information in that signature to select a key from the specified keyring
- and to request a hash algorithm from the crypto layer.
-
- (2) int verify_sig_add_data(struct crypto_key_verify_context *ctx,
- const void *data, size_t datalen);
-
- Incrementally supply data to be signed. May be called multiple times.
-
- (3) int verify_sig_end(struct crypto_key_verify_context *ctx,
- const void *sig, size_t siglen);
-
- Complete the verification process and return the result. -EKEYREJECTED
- will indicate that the verification failed and 0 will indicate success.
- Other errors are also possible.
-
- (4) void verify_sig_cancel(struct crypto_key_verify_context *ctx);
-
- Cancel the verification process.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/security/keys-crypto.txt | 100 +++++++++++++++++++++
- include/keys/crypto-subtype.h | 36 +++++++-
- include/keys/crypto-type.h | 9 ++
- security/keys/crypto/Makefile | 2 +-
- security/keys/crypto/crypto_keys.h | 1 -
- security/keys/crypto/crypto_type.c | 2 +-
- security/keys/crypto/crypto_verify.c | 159 +++++++++++++++++++++++++++++++++
- 7 files changed, 304 insertions(+), 5 deletions(-)
- create mode 100644 security/keys/crypto/crypto_verify.c
-
-diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
-index 97dee80..0a886ec 100644
---- a/Documentation/security/keys-crypto.txt
-+++ b/Documentation/security/keys-crypto.txt
-@@ -7,6 +7,7 @@ Contents:
- - Overview.
- - Key identification.
- - Accessing crypto keys.
-+ - Signature verification.
- - Implementing crypto parsers.
- - Implementing crypto subtypes.
-
-@@ -89,6 +90,65 @@ This gives access to the key type:
- struct key_type key_type_crypto;
-
-
-+SIGNATURE VERIFICATION
-+----------------------
-+
-+The four operations that can perform cryptographic signature verification,
-+using one of a set of keys to provide the public key:
-+
-+ (1) Begin verification procedure.
-+
-+ struct crypto_key_verify_context *
-+ verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
-+
-+ This function sets up a verification context from the information in the
-+ signature and looks for a suitable key in the keyring. The signature blob
-+ must be presented again at the end of the procedure. The keys will be
-+ checked against parameters in the signature, and if the matching one is
-+ not found then -ENOKEY will be returned.
-+
-+ The hashing algorithm, if such a thing applies, will be determined from
-+ information in the signature and the appropriate crypto module will be
-+ used. -ENOPKG will be returned if the hash algorithm is unavailable.
-+
-+ The return value is an opaque pointer to be passed to the other functions,
-+ or a negative error code.
-+
-+ (2) Indicate data to be verified.
-+
-+ int verify_sig_add_data(struct crypto_key_verify_context *ctx,
-+ const void *data, size_t datalen);
-+
-+ This function is used to shovel data to the verification procedure so that
-+ it can load it into the hash, pass it to hardware or whatever is
-+ appropriate for the algorithm being employed.
-+
-+ The data is not canonicalised for the document type specified in the
-+ signature. The caller must do that.
-+
-+ It will return 0 if successful and a negative error code if not.
-+
-+ (3) Complete the verification process.
-+
-+ int verify_sig_end(struct crypto_key_verify_context *ctx,
-+ const void *sig, size_t siglen);
-+
-+ This function performs the actual signature verification step and cleans
-+ up the resources allocated at the beginning. The signature must be
-+ presented again as some of the data therein may need to be added to the
-+ internal hash.
-+
-+ It will return -EKEYREJECTED if the signature didn't match, 0 if
-+ successful and may return other errors as appropriate.
-+
-+ (4) Cancel the verification process.
-+
-+ void verify_sig_cancel(struct crypto_key_verify_context *ctx);
-+
-+ This function cleans up the resources allocated at the beginning. This is
-+ not necessary if verify_sig_end() was called.
-+
-+
- ===========================
- IMPLEMENTING CRYPTO PARSERS
- ===========================
-@@ -107,6 +167,8 @@ The parser definition structure looks like the following:
-
- int (*instantiate)(struct key *key,
- const void *data, size_t datalen);
-+ struct crypto_key_verify_context *(*verify_sig_begin)(
-+ struct key *keyring, const u8 *sig, size_t siglen);
- };
-
- The owner and name fields should be set to the owning module and the name of
-@@ -135,6 +197,44 @@ but it is expected that at least one will be defined.
- algorithm such as RSA and DSA this will likely be a printable hex version
- of the key's fingerprint.
-
-+ (2) verify_sig_begin().
-+
-+ This is similar in concept to the instantiate() function, except that it
-+ is given a signature blob to parse rather than a key data blob.
-+
-+ If the data format is not recognised, -EBADMSG should be returned. If it
-+ is recognised, but the signature verification process cannot for some
-+ reason be set up, some other negative error code should be returned.
-+ -ENOKEY should be used to indicate that no matching key is available and
-+ -ENOPKG should be returned if the hash algorithm or the verification
-+ algorithm are unavailable.
-+
-+ If successful, the parser should allocate a verification context and embed
-+ the following struct in it:
-+
-+ struct crypto_key_verify_context {
-+ struct key *key;
-+ int (*add_data)(struct crypto_key_verify_context *ctx,
-+ const void *data, size_t datalen);
-+ int (*end)(struct crypto_key_verify_context *ctx,
-+ const u8 *sig, size_t siglen);
-+ void (*cancel)(struct crypto_key_verify_context *ctx);
-+ };
-+
-+ and return a pointer to this to the caller, who will then pass it to the
-+ verification operation wrappers described in the "Signature Verification"
-+ section. The three operation pointers here correspond exactly to those
-+ wrappers and are all mandatory. container_of() should be used to retrieve
-+ the actual context.
-+
-+ Note that the crypto key type retains a reference on the parser module for
-+ the lifetime of this context, though the operation pointers need not point
-+ into this module.
-+
-+ The parser should also record a pointer to the key selected and take a
-+ reference on that key with key_get().
-+
-+
- Functions are provided to register and unregister parsers:
-
- int register_crypto_key_parser(struct crypto_key_parser *parser);
-diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
-index 1f546e6..61a5338 100644
---- a/include/keys/crypto-subtype.h
-+++ b/include/keys/crypto-subtype.h
-@@ -34,8 +34,7 @@ struct crypto_key_subtype {
- };
-
- /*
-- * Data parser. Called during instantiation and signature verification
-- * initiation.
-+ * Key data parser. Called during key instantiation.
- */
- struct crypto_key_parser {
- struct list_head link;
-@@ -54,4 +53,37 @@ struct crypto_key_parser {
- extern int register_crypto_key_parser(struct crypto_key_parser *);
- extern void unregister_crypto_key_parser(struct crypto_key_parser *);
-
-+/*
-+ * Context base for signature verification methods. Allocated by the subtype
-+ * and presumably embedded in something appropriate.
-+ */
-+struct crypto_sig_verify_context {
-+ struct key *key;
-+ struct crypto_sig_parser *parser;
-+ int (*add_data)(struct crypto_sig_verify_context *ctx,
-+ const void *data, size_t datalen);
-+ int (*end)(struct crypto_sig_verify_context *ctx,
-+ const u8 *sig, size_t siglen);
-+ void (*cancel)(struct crypto_sig_verify_context *ctx);
-+};
-+
-+/*
-+ * Signature data parser. Called during signature verification initiation.
-+ */
-+struct crypto_sig_parser {
-+ struct list_head link;
-+ struct module *owner;
-+ const char *name;
-+
-+ /* Attempt to recognise a signature blob and find a matching key.
-+ *
-+ * Return EBADMSG if not recognised.
-+ */
-+ struct crypto_sig_verify_context *(*verify_sig_begin)(
-+ struct key *keyring, const u8 *sig, size_t siglen);
-+};
-+
-+extern int register_crypto_sig_parser(struct crypto_sig_parser *);
-+extern void unregister_crypto_sig_parser(struct crypto_sig_parser *);
-+
- #endif /* _KEYS_CRYPTO_SUBTYPE_H */
-diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
-index 47c00c7..0fb362a 100644
---- a/include/keys/crypto-type.h
-+++ b/include/keys/crypto-type.h
-@@ -18,6 +18,15 @@
-
- extern struct key_type key_type_crypto;
-
-+struct crypto_sig_verify_context;
-+extern struct crypto_sig_verify_context *verify_sig_begin(
-+ struct key *key, const void *sig, size_t siglen);
-+extern int verify_sig_add_data(struct crypto_sig_verify_context *ctx,
-+ const void *data, size_t datalen);
-+extern int verify_sig_end(struct crypto_sig_verify_context *ctx,
-+ const void *sig, size_t siglen);
-+extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx);
-+
- /*
- * The payload is at the discretion of the subtype.
- */
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 36db1d5..67001bc 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -4,4 +4,4 @@
-
- obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
-
--crypto_keys-y := crypto_type.o
-+crypto_keys-y := crypto_type.o crypto_verify.o
-diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h
-index eb11788..ab9b381 100644
---- a/security/keys/crypto/crypto_keys.h
-+++ b/security/keys/crypto/crypto_keys.h
-@@ -24,5 +24,4 @@ static inline const char *crypto_key_id(const struct key *key)
- /*
- * crypto_type.c
- */
--extern struct list_head crypto_key_parsers;
- extern struct rw_semaphore crypto_key_parsers_sem;
-diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c
-index e8f83a6..821db37 100644
---- a/security/keys/crypto/crypto_type.c
-+++ b/security/keys/crypto/crypto_type.c
-@@ -18,7 +18,7 @@
-
- MODULE_LICENSE("GPL");
-
--LIST_HEAD(crypto_key_parsers);
-+static LIST_HEAD(crypto_key_parsers);
- DECLARE_RWSEM(crypto_key_parsers_sem);
-
- /*
-diff --git a/security/keys/crypto/crypto_verify.c b/security/keys/crypto/crypto_verify.c
-new file mode 100644
-index 0000000..d64f1c7
---- /dev/null
-+++ b/security/keys/crypto/crypto_verify.c
-@@ -0,0 +1,159 @@
-+/* Signature verification with a crypto key
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ *
-+ * See Documentation/security/keys-crypto.txt
-+ */
-+
-+#include <keys/crypto-subtype.h>
-+#include <linux/module.h>
-+#include <linux/err.h>
-+#include "crypto_keys.h"
-+
-+static LIST_HEAD(crypto_sig_parsers);
-+
-+/**
-+ * verify_sig_begin - Initiate the use of a crypto key to verify a signature
-+ * @keyring: The public keys to verify against
-+ * @sig: The signature data
-+ * @siglen: The signature length
-+ *
-+ * Returns a context or an error.
-+ */
-+struct crypto_sig_verify_context *verify_sig_begin(
-+ struct key *keyring, const void *sig, size_t siglen)
-+{
-+ struct crypto_sig_verify_context *ret;
-+ struct crypto_sig_parser *parser;
-+
-+ pr_devel("==>%s()\n", __func__);
-+
-+ if (siglen == 0 || !sig)
-+ return ERR_PTR(-EINVAL);
-+
-+ down_read(&crypto_key_parsers_sem);
-+
-+ ret = ERR_PTR(-EBADMSG);
-+ list_for_each_entry(parser, &crypto_sig_parsers, link) {
-+ if (parser->verify_sig_begin) {
-+ if (!try_module_get(parser->owner))
-+ continue;
-+
-+ pr_debug("Trying parser '%s'\n", parser->name);
-+
-+ ret = parser->verify_sig_begin(keyring, sig, siglen);
-+ if (IS_ERR(ret))
-+ module_put(parser->owner);
-+ else
-+ ret->parser = parser;
-+ if (ret != ERR_PTR(-EBADMSG)) {
-+ pr_debug("Parser recognised the format"
-+ " (ret %ld)\n",
-+ PTR_ERR(ret));
-+ break;
-+ }
-+ }
-+ }
-+
-+ up_read(&crypto_key_parsers_sem);
-+ pr_devel("<==%s() = %p\n", __func__, ret);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(verify_sig_begin);
-+
-+/**
-+ * verify_sig_add_data - Incrementally provide data to be verified
-+ * @ctx: The context from verify_sig_begin()
-+ * @data: Data
-+ * @datalen: The amount of @data
-+ *
-+ * This may be called multiple times.
-+ */
-+int verify_sig_add_data(struct crypto_sig_verify_context *ctx,
-+ const void *data, size_t datalen)
-+{
-+ return ctx->add_data(ctx, data, datalen);
-+}
-+EXPORT_SYMBOL_GPL(verify_sig_add_data);
-+
-+/**
-+ * verify_sig_end - Finalise signature verification and return result
-+ * @ctx: The context from verify_sig_begin()
-+ * @sig: The signature data
-+ * @siglen: The signature length
-+ */
-+int verify_sig_end(struct crypto_sig_verify_context *ctx,
-+ const void *sig, size_t siglen)
-+{
-+ struct crypto_sig_parser *parser = ctx->parser;
-+ int ret;
-+
-+ ret = ctx->end(ctx, sig, siglen);
-+ module_put(parser->owner);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(verify_sig_end);
-+
-+/**
-+ * verify_sig_end - Cancel signature verification
-+ * @ctx: The context from verify_sig_begin()
-+ */
-+void verify_sig_cancel(struct crypto_sig_verify_context *ctx)
-+{
-+ struct crypto_sig_parser *parser = ctx->parser;
-+
-+ ctx->cancel(ctx);
-+ module_put(parser->owner);
-+}
-+EXPORT_SYMBOL_GPL(verify_sig_cancel);
-+
-+/**
-+ * register_crypto_sig_parser - Register a crypto sig blob parser
-+ * @parser: The parser to register
-+ */
-+int register_crypto_sig_parser(struct crypto_sig_parser *parser)
-+{
-+ struct crypto_sig_parser *cursor;
-+ int ret;
-+
-+ down_write(&crypto_key_parsers_sem);
-+
-+ list_for_each_entry(cursor, &crypto_sig_parsers, link) {
-+ if (strcmp(cursor->name, parser->name) == 0) {
-+ pr_err("Crypto signature parser '%s' already registered\n",
-+ parser->name);
-+ ret = -EEXIST;
-+ goto out;
-+ }
-+ }
-+
-+ list_add_tail(&parser->link, &crypto_sig_parsers);
-+
-+ pr_notice("Crypto signature parser '%s' registered\n", parser->name);
-+ ret = 0;
-+
-+out:
-+ up_write(&crypto_key_parsers_sem);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(register_crypto_sig_parser);
-+
-+/**
-+ * unregister_crypto_sig_parser - Unregister a crypto sig blob parser
-+ * @parser: The parser to unregister
-+ */
-+void unregister_crypto_sig_parser(struct crypto_sig_parser *parser)
-+{
-+ down_write(&crypto_key_parsers_sem);
-+ list_del(&parser->link);
-+ up_write(&crypto_key_parsers_sem);
-+
-+ pr_notice("Crypto signature parser '%s' unregistered\n", parser->name);
-+}
-+EXPORT_SYMBOL_GPL(unregister_crypto_sig_parser);
---
-1.7.11.4
-
-
-From d8cb66a6f69869c8c2992f67915a7c238066f2fb Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:18 +0100
-Subject: [PATCH 05/32] KEYS: Asymmetric public-key algorithm crypto key
- subtype
-
-Add a subtype for supporting asymmetric public-key encryption algorithms such
-as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337).
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/Kconfig | 10 ++++
- security/keys/crypto/Makefile | 3 +-
- security/keys/crypto/public_key.c | 82 +++++++++++++++++++++++++
- security/keys/crypto/public_key.h | 123 ++++++++++++++++++++++++++++++++++++++
- 4 files changed, 217 insertions(+), 1 deletion(-)
- create mode 100644 security/keys/crypto/public_key.c
- create mode 100644 security/keys/crypto/public_key.h
-
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-index 3d15710..5f2b8ac 100644
---- a/security/keys/crypto/Kconfig
-+++ b/security/keys/crypto/Kconfig
-@@ -5,3 +5,13 @@ config CRYPTO_KEY_TYPE
- This option provides support for a type of key that holds the keys
- required for cryptographic operations such as encryption, decryption,
- signature generation and signature verification.
-+
-+config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
-+ tristate "Asymmetric public-key crypto algorithm subtype"
-+ depends on CRYPTO_KEY_TYPE
-+ select MPILIB
-+ help
-+ This option provides support for asymmetric public key type handling.
-+ If signature generation and/or verification are to be used,
-+ appropriate hash algorithms (such as SHA-1) must be available.
-+ ENOPKG will be reported if the requisite algorithm is unavailable.
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 67001bc..6384306 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -3,5 +3,6 @@
- #
-
- obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
--
- crypto_keys-y := crypto_type.o crypto_verify.o
-+
-+obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
-diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c
-new file mode 100644
-index 0000000..ebb31ec
---- /dev/null
-+++ b/security/keys/crypto/public_key.c
-@@ -0,0 +1,82 @@
-+/* Asymmetric public key crypto subtype
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "PKEY: "fmt
-+#include <linux/module.h>
-+#include <linux/export.h>
-+#include <linux/kernel.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 *crypto_key,
-+ struct seq_file *m)
-+{
-+ struct public_key *key = crypto_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);
-+
-+/*
-+ * Public key algorithm crypto key subtype
-+ */
-+struct crypto_key_subtype public_key_crypto_key_subtype = {
-+ .owner = THIS_MODULE,
-+ .name = "public_key",
-+ .describe = public_key_describe,
-+ .destroy = public_key_destroy,
-+};
-+EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype);
-diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h
-new file mode 100644
-index 0000000..228090d
---- /dev/null
-+++ b/security/keys/crypto/public_key.h
-@@ -0,0 +1,123 @@
-+/* Asymmetric public-key algorithm definitions
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_PUBLIC_KEY_H
-+#define _LINUX_PUBLIC_KEY_H
-+
-+#include <linux/mpi.h>
-+#include <crypto/hash.h>
-+#include <keys/crypto-subtype.h>
-+
-+struct public_key;
-+struct public_key_signature;
-+
-+enum pkey_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];
-+
-+/*
-+ * Public key type definition
-+ */
-+struct public_key_algorithm {
-+ const char *name;
-+ u8 n_pub_mpi; /* Number of MPIs in public key */
-+ u8 n_sec_mpi; /* Number of MPIs in secret key */
-+ u8 n_sig_mpi; /* Number of MPIs in a signature */
-+ int (*verify)(const struct public_key *key,
-+ const struct public_key_signature *sig);
-+};
-+
-+/*
-+ * Asymmetric public key data
-+ */
-+struct public_key {
-+ const struct public_key_algorithm *algo;
-+ u8 capabilities;
-+#define PKEY_CAN_ENCRYPT 0x01
-+#define PKEY_CAN_DECRYPT 0x02
-+#define PKEY_CAN_ENCDEC (PKEY_CAN_ENCRYPT | PKEY_CAN_DECRYPT)
-+#define PKEY_CAN_SIGN 0x04
-+#define PKEY_CAN_VERIFY 0x08
-+#define PKEY_CAN_SIGVER (PKEY_CAN_SIGN | PKEY_CAN_VERIFY)
-+ 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;
-+ };
-+
-+ u8 key_id[8]; /* ID of this key pair */
-+ u8 key_id_size; /* Number of bytes in key_id */
-+};
-+
-+/*
-+ * Asymmetric public key algorithm signature data
-+ */
-+struct public_key_signature {
-+ struct crypto_sig_verify_context base;
-+ u8 *digest;
-+ enum pkey_hash_algo pkey_hash_algo : 8;
-+ u8 signed_hash_msw[2];
-+ u8 digest_size; /* Number of bytes in digest */
-+ union {
-+ MPI mpi[2];
-+ struct {
-+ MPI s; /* m^d mod n */
-+ } rsa;
-+ struct {
-+ MPI r;
-+ MPI s;
-+ } dsa;
-+ };
-+ struct shash_desc hash; /* This must go last! */
-+};
-+
-+extern struct crypto_key_subtype public_key_crypto_key_subtype;
-+
-+#endif /* _LINUX_PUBLIC_KEY_H */
---
-1.7.11.4
-
-
-From 76b6843d2be046bd5ab8fbae8a1cc5b5d2d48a80 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:18 +0100
-Subject: [PATCH 06/32] 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@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 48c4be1c886e51edbbbebdb65421a7ca120a8d21 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:18 +0100
-Subject: [PATCH 07/32] KEYS: 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@redhat.com>
----
- security/keys/crypto/Kconfig | 7 +
- security/keys/crypto/Makefile | 1 +
- security/keys/crypto/crypto_rsa.c | 267 ++++++++++++++++++++++++++++++++++++++
- security/keys/crypto/public_key.h | 2 +
- 4 files changed, 277 insertions(+)
- create mode 100644 security/keys/crypto/crypto_rsa.c
-
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-index 5f2b8ac..4e3777e 100644
---- a/security/keys/crypto/Kconfig
-+++ b/security/keys/crypto/Kconfig
-@@ -15,3 +15,10 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
- If signature generation and/or verification are to be used,
- appropriate hash algorithms (such as SHA-1) must be available.
- ENOPKG will be reported if the requisite algorithm is unavailable.
-+
-+config CRYPTO_KEY_PKEY_ALGO_RSA
-+ tristate "RSA public-key algorithm"
-+ depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
-+ select MPILIB_EXTRA
-+ help
-+ This option enables support for the RSA algorithm (PKCS#1, RFC3447).
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 6384306..b6b1a5a 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
- crypto_keys-y := crypto_type.o crypto_verify.o
-
- obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
-+obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
-diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
-new file mode 100644
-index 0000000..6e95e60
---- /dev/null
-+++ b/security/keys/crypto/crypto_rsa.c
-@@ -0,0 +1,267 @@
-+/* RSA asymmetric public-key algorithm [RFC3447]
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "RSA: "fmt
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include "public_key.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+#define kenter(FMT, ...) \
-+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
-+#define kleave(FMT, ...) \
-+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
-+
-+/*
-+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
-+ */
-+static const u8 RSA_digest_info_MD5[] = {
-+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
-+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
-+ 0x05, 0x00, 0x04, 0x10
-+};
-+
-+static const u8 RSA_digest_info_SHA1[] = {
-+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-+ 0x2B, 0x0E, 0x03, 0x02, 0x1A,
-+ 0x05, 0x00, 0x04, 0x14
-+};
-+
-+static const u8 RSA_digest_info_RIPE_MD_160[] = {
-+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-+ 0x2B, 0x24, 0x03, 0x02, 0x01,
-+ 0x05, 0x00, 0x04, 0x14
-+};
-+
-+static const u8 RSA_digest_info_SHA224[] = {
-+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
-+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
-+ 0x05, 0x00, 0x04, 0x1C
-+};
-+
-+static const u8 RSA_digest_info_SHA256[] = {
-+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
-+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
-+ 0x05, 0x00, 0x04, 0x20
-+};
-+
-+static const u8 RSA_digest_info_SHA384[] = {
-+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
-+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
-+ 0x05, 0x00, 0x04, 0x30
-+};
-+
-+static const u8 RSA_digest_info_SHA512[] = {
-+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
-+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
-+ 0x05, 0x00, 0x04, 0x40
-+};
-+
-+static const struct {
-+ const u8 *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 = RSA_verify_signature,
-+};
-+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
-diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h
-index 228090d..947817b 100644
---- a/security/keys/crypto/public_key.h
-+++ b/security/keys/crypto/public_key.h
-@@ -61,6 +61,8 @@ struct public_key_algorithm {
- const struct public_key_signature *sig);
- };
-
-+extern const struct public_key_algorithm RSA_public_key_algorithm;
-+
- /*
- * Asymmetric public key data
- */
---
-1.7.11.4
-
-
-From 311305a6e970236bd30d8942552a26e6f93730ce Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:19 +0100
-Subject: [PATCH 08/32] KEYS: 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@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/crypto_rsa.c | 14 +++++++++++---
- 1 file changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
-index 6e95e60..796ed1d 100644
---- a/security/keys/crypto/crypto_rsa.c
-+++ b/security/keys/crypto/crypto_rsa.c
-@@ -222,15 +222,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 a9b954d2c225dc99ecc319ea760576f525f0a623 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 00:14:19 +0100
-Subject: [PATCH 09/32] PGPLIB: PGP definitions (RFC 4880)
-
-Provide some useful PGP definitions from RFC 4880. These describe details of
-public key crypto as used by crypto keys for things like signature
-verification.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/pgp.h | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 206 insertions(+)
- create mode 100644 include/linux/pgp.h
-
-diff --git a/include/linux/pgp.h b/include/linux/pgp.h
-new file mode 100644
-index 0000000..1359f64
---- /dev/null
-+++ b/include/linux/pgp.h
-@@ -0,0 +1,206 @@
-+/* PGP definitions (RFC 4880)
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_PGP_H
-+#define _LINUX_PGP_H
-+
-+#include <linux/types.h>
-+
-+struct pgp_key_ID {
-+ u8 id[8];
-+};
-+
-+struct pgp_time {
-+ u8 time[4];
-+};
-+
-+/*
-+ * PGP public-key algorithm identifiers [RFC4880: 9.1]
-+ */
-+enum pgp_pubkey_algo {
-+ PGP_PUBKEY_RSA_ENC_OR_SIG = 1,
-+ PGP_PUBKEY_RSA_ENC_ONLY = 2,
-+ PGP_PUBKEY_RSA_SIG_ONLY = 3,
-+ PGP_PUBKEY_ELGAMAL = 16,
-+ PGP_PUBKEY_DSA = 17,
-+ PGP_PUBKEY__LAST
-+};
-+
-+/*
-+ * PGP symmetric-key algorithm identifiers [RFC4880: 9.2]
-+ */
-+enum pgp_symkey_algo {
-+ PGP_SYMKEY_PLAINTEXT = 0,
-+ PGP_SYMKEY_IDEA = 1,
-+ PGP_SYMKEY_3DES = 2,
-+ PGP_SYMKEY_CAST5 = 3,
-+ PGP_SYMKEY_BLOWFISH = 4,
-+ PGP_SYMKEY_AES_128KEY = 7,
-+ PGP_SYMKEY_AES_192KEY = 8,
-+ PGP_SYMKEY_AES_256KEY = 9,
-+ PGP_SYMKEY_TWOFISH_256KEY = 10,
-+};
-+
-+/*
-+ * PGP compression algorithm identifiers [RFC4880: 9.3]
-+ */
-+enum pgp_compr_algo {
-+ PGP_COMPR_UNCOMPRESSED = 0,
-+ PGP_COMPR_ZIP = 1,
-+ PGP_COMPR_ZLIB = 2,
-+ PGP_COMPR_BZIP2 = 3,
-+};
-+
-+/*
-+ * PGP hash algorithm identifiers [RFC4880: 9.4]
-+ */
-+enum pgp_hash_algo {
-+ PGP_HASH_MD5 = 1,
-+ PGP_HASH_SHA1 = 2,
-+ PGP_HASH_RIPE_MD_160 = 3,
-+ PGP_HASH_SHA256 = 8,
-+ PGP_HASH_SHA384 = 9,
-+ PGP_HASH_SHA512 = 10,
-+ PGP_HASH_SHA224 = 11,
-+ PGP_HASH__LAST
-+};
-+
-+extern const char *const pgp_hash_algorithms[PGP_HASH__LAST];
-+
-+/*
-+ * PGP packet type tags [RFC4880: 4.3].
-+ */
-+enum pgp_packet_tag {
-+ PGP_PKT_RESERVED = 0,
-+ PGP_PKT_PUBKEY_ENC_SESSION_KEY = 1,
-+ PGP_PKT_SIGNATURE = 2,
-+ PGP_PKT_SYMKEY_ENC_SESSION_KEY = 3,
-+ PGP_PKT_ONEPASS_SIGNATURE = 4,
-+ PGP_PKT_SECRET_KEY = 5,
-+ PGP_PKT_PUBLIC_KEY = 6,
-+ PGP_PKT_SECRET_SUBKEY = 7,
-+ PGP_PKT_COMPRESSED_DATA = 8,
-+ PGP_PKT_SYM_ENC_DATA = 9,
-+ PGP_PKT_MARKER = 10,
-+ PGP_PKT_LITERAL_DATA = 11,
-+ PGP_PKT_TRUST = 12,
-+ PGP_PKT_USER_ID = 13,
-+ PGP_PKT_PUBLIC_SUBKEY = 14,
-+ PGP_PKT_USER_ATTRIBUTE = 17,
-+ PGP_PKT_SYM_ENC_AND_INTEG_DATA = 18,
-+ PGP_PKT_MODIFY_DETECT_CODE = 19,
-+ PGP_PKT_PRIVATE_0 = 60,
-+ PGP_PKT_PRIVATE_3 = 63,
-+ PGP_PKT__HIGHEST = 63
-+};
-+
-+/*
-+ * Signature (tag 2) packet [RFC4880: 5.2].
-+ */
-+enum pgp_signature_version {
-+ PGP_SIG_VERSION_3 = 3,
-+ PGP_SIG_VERSION_4 = 4,
-+};
-+
-+enum pgp_signature_type {
-+ PGP_SIG_BINARY_DOCUMENT_SIG = 0x00,
-+ PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG = 0x01,
-+ PGP_SIG_STANDALONE_SIG = 0x02,
-+ PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY = 0x10,
-+ PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY = 0x11,
-+ PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY = 0x12,
-+ PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY = 0x13,
-+ PGP_SIG_SUBKEY_BINDING_SIG = 0x18,
-+ PGP_SIG_PRIMARY_KEY_BINDING_SIG = 0x19,
-+ PGP_SIG_DIRECTLY_ON_KEY = 0x1F,
-+ PGP_SIG_KEY_REVOCATION_SIG = 0x20,
-+ PGP_SIG_SUBKEY_REVOCATION_SIG = 0x28,
-+ PGP_SIG_CERT_REVOCATION_SIG = 0x30,
-+ PGP_SIG_TIMESTAMP_SIG = 0x40,
-+ PGP_SIG_THIRD_PARTY_CONFIRM_SIG = 0x50,
-+};
-+
-+struct pgp_signature_v3_packet {
-+ enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_3 */
-+ u8 length_of_hashed; /* == 5 */
-+ struct {
-+ enum pgp_signature_type signature_type : 8;
-+ struct pgp_time creation_time;
-+ } hashed;
-+ struct pgp_key_ID issuer;
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ enum pgp_hash_algo hash_algo : 8;
-+} __packed;
-+
-+struct pgp_signature_v4_packet {
-+ enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_4 */
-+ enum pgp_signature_type signature_type : 8;
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ enum pgp_hash_algo hash_algo : 8;
-+} __packed;
-+
-+/*
-+ * V4 signature subpacket types [RFC4880: 5.2.3.1].
-+ */
-+enum pgp_sig_subpkt_type {
-+ PGP_SIG_CREATION_TIME = 2,
-+ PGP_SIG_EXPIRATION_TIME = 3,
-+ PGP_SIG_EXPORTABLE_CERT = 4,
-+ PGP_SIG_TRUST_SIG = 5,
-+ PGP_SIG_REGEXP = 6,
-+ PGP_SIG_REVOCABLE = 7,
-+ PGP_SIG_KEY_EXPIRATION_TIME = 9,
-+ PGP_SIG_PREF_SYM_ALGO = 11,
-+ PGP_SIG_REVOCATION_KEY = 12,
-+ PGP_SIG_ISSUER = 16,
-+ PGP_SIG_NOTATION_DATA = 20,
-+ PGP_SIG_PREF_HASH_ALGO = 21,
-+ PGP_SIG_PREF_COMPR_ALGO = 22,
-+ PGP_SIG_KEY_SERVER_PREFS = 23,
-+ PGP_SIG_PREF_KEY_SERVER = 24,
-+ PGP_SIG_PRIMARY_USER_ID = 25,
-+ PGP_SIG_POLICY_URI = 26,
-+ PGP_SIG_KEY_FLAGS = 27,
-+ PGP_SIG_SIGNERS_USER_ID = 28,
-+ PGP_SIG_REASON_FOR_REVOCATION = 29,
-+ PGP_SIG_FEATURES = 30,
-+ PGP_SIG_TARGET = 31,
-+ PGP_SIG_EMBEDDED_SIG = 32,
-+ PGP_SIG__LAST
-+};
-+
-+#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK 0x80
-+
-+/*
-+ * Key (tag 5, 6, 7 and 14) packet
-+ */
-+enum pgp_key_version {
-+ PGP_KEY_VERSION_2 = 2,
-+ PGP_KEY_VERSION_3 = 3,
-+ PGP_KEY_VERSION_4 = 4,
-+};
-+
-+struct pgp_key_v3_packet {
-+ enum pgp_key_version version : 8;
-+ struct pgp_time creation_time;
-+ u8 expiry[2]; /* 0 or time in days till expiry */
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ u8 key_material[0];
-+} __packed;
-+
-+struct pgp_key_v4_packet {
-+ enum pgp_key_version version : 8;
-+ struct pgp_time creation_time;
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ u8 key_material[0];
-+} __packed;
-+
-+#endif /* _LINUX_PGP_H */
---
-1.7.11.4
-
-
-From 1937e5a7e8ae1abdb7f1dc72f7b128e33c31d644 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:13 +0100
-Subject: [PATCH 10/32] PGPLIB: Basic packet parser
-
-Provide a simple parser that extracts the packets from a PGP packet blob and
-passes the desirous ones to the given processor function:
-
- struct pgp_parse_context {
- u64 types_of_interest;
- int (*process_packet)(struct pgp_parse_context *context,
- enum pgp_packet_tag type,
- u8 headerlen,
- const u8 *data,
- size_t datalen);
- };
-
- int pgp_parse_packets(const u8 *data, size_t datalen,
- struct pgp_parse_context *ctx);
-
-This is configured on with CONFIG_PGP_LIBRARY.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/pgplib.h | 47 +++++++
- security/keys/crypto/Kconfig | 6 +
- security/keys/crypto/Makefile | 1 +
- security/keys/crypto/pgp_library.c | 268 +++++++++++++++++++++++++++++++++++++
- 4 files changed, 322 insertions(+)
- create mode 100644 include/linux/pgplib.h
- create mode 100644 security/keys/crypto/pgp_library.c
-
-diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h
-new file mode 100644
-index 0000000..a045b3a
---- /dev/null
-+++ b/include/linux/pgplib.h
-@@ -0,0 +1,47 @@
-+/* PGP library definitions (RFC 4880)
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_PGPLIB_H
-+#define _LINUX_PGPLIB_H
-+
-+#if defined(CONFIG_PGP_LIBRARY) || defined(CONFIG_PGP_LIBRARY_MODULE)
-+
-+#include <linux/pgp.h>
-+
-+/*
-+ * PGP library packet parser
-+ */
-+struct pgp_parse_context {
-+ u64 types_of_interest;
-+ int (*process_packet)(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type,
-+ u8 headerlen,
-+ const u8 *data,
-+ size_t datalen);
-+};
-+
-+extern int pgp_parse_packets(const u8 *data, size_t datalen,
-+ struct pgp_parse_context *ctx);
-+
-+struct pgp_parse_pubkey {
-+ enum pgp_key_version version : 8;
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ time_t creation_time;
-+ time_t expires_at;
-+};
-+
-+extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
-+ struct pgp_parse_pubkey *pk);
-+
-+
-+#endif /* CONFIG_PGP_LIBRARY */
-+
-+#endif /* _LINUX_PGPLIB_H */
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-index 4e3777e..88ce0e2 100644
---- a/security/keys/crypto/Kconfig
-+++ b/security/keys/crypto/Kconfig
-@@ -22,3 +22,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA
- select MPILIB_EXTRA
- help
- This option enables support for the RSA algorithm (PKCS#1, RFC3447).
-+
-+config PGP_LIBRARY
-+ tristate "PGP parsing library"
-+ help
-+ This option enables a library that provides a number of simple
-+ utility functions for parsing PGP (RFC 4880) packet-based messages.
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index b6b1a5a..5fbe54e 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -7,3 +7,4 @@ crypto_keys-y := crypto_type.o crypto_verify.o
-
- obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
- obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
-+obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
-diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
-new file mode 100644
-index 0000000..39d2878
---- /dev/null
-+++ b/security/keys/crypto/pgp_library.c
-@@ -0,0 +1,268 @@
-+/* PGP packet parser (RFC 4880)
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+#define pr_fmt(fmt) "PGP: "fmt
-+#include <linux/pgplib.h>
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+MODULE_LICENSE("GPL");
-+
-+const char *const pgp_hash_algorithms[PGP_HASH__LAST] = {
-+ [PGP_HASH_MD5] = "md5",
-+ [PGP_HASH_SHA1] = "sha1",
-+ [PGP_HASH_RIPE_MD_160] = "rmd160",
-+ [PGP_HASH_SHA256] = "sha256",
-+ [PGP_HASH_SHA384] = "sha384",
-+ [PGP_HASH_SHA512] = "sha512",
-+ [PGP_HASH_SHA224] = "sha224",
-+};
-+EXPORT_SYMBOL_GPL(pgp_hash_algorithms);
-+
-+/**
-+ * pgp_parse_packet_header - Parse a PGP packet header
-+ * @_data: Start of the PGP packet (updated to PGP packet data)
-+ * @_datalen: Amount of data remaining in buffer (decreased)
-+ * @_type: Where the packet type will be returned
-+ * @_headerlen: Where the header length will be returned
-+ *
-+ * Parse a set of PGP packet header [RFC 4880: 4.2].
-+ *
-+ * Returns packet data size on success; non-zero on error. If successful,
-+ * *_data and *_datalen will have been updated and *_headerlen will be set to
-+ * hold the length of the packet header.
-+ */
-+static ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
-+ enum pgp_packet_tag *_type,
-+ u8 *_headerlen)
-+{
-+ enum pgp_packet_tag type;
-+ const u8 *data = *_data;
-+ size_t size, datalen = *_datalen;
-+
-+ pr_devel("-->pgp_parse_packet_header(,%zu,,)\n", datalen);
-+
-+ if (datalen < 2)
-+ goto short_packet;
-+
-+ pr_devel("pkthdr %02x, %02x\n", data[0], data[1]);
-+
-+ type = *data++;
-+ datalen--;
-+ if (!(type & 0x80)) {
-+ pr_debug("Packet type does not have MSB set\n");
-+ return -EBADMSG;
-+ }
-+ type &= ~0x80;
-+
-+ if (type & 0x40) {
-+ /* New packet length format */
-+ type &= ~0x40;
-+ pr_devel("new format: t=%u\n", type);
-+ switch (data[0]) {
-+ case 0x00 ... 0xbf:
-+ /* One-byte length */
-+ size = data[0];
-+ data++;
-+ datalen--;
-+ *_headerlen = 2;
-+ break;
-+ case 0xc0 ... 0xdf:
-+ /* Two-byte length */
-+ if (datalen < 2)
-+ goto short_packet;
-+ size = (data[0] - 192) * 256;
-+ size += data[1] + 192;
-+ data += 2;
-+ datalen -= 2;
-+ *_headerlen = 3;
-+ break;
-+ case 0xff:
-+ /* Five-byte length */
-+ if (datalen < 5)
-+ goto short_packet;
-+ size = data[1] << 24;
-+ size |= data[2] << 16;
-+ size |= data[3] << 8;
-+ size |= data[4];
-+ data += 5;
-+ datalen -= 5;
-+ *_headerlen = 6;
-+ break;
-+ default:
-+ pr_debug("Partial body length packet not supported\n");
-+ return -EBADMSG;
-+ }
-+ } else {
-+ /* Old packet length format */
-+ u8 length_type = type & 0x03;
-+ type >>= 2;
-+ pr_devel("old format: t=%u lt=%u\n", type, length_type);
-+
-+ switch (length_type) {
-+ case 0:
-+ /* One-byte length */
-+ size = data[0];
-+ data++;
-+ datalen--;
-+ *_headerlen = 2;
-+ break;
-+ case 1:
-+ /* Two-byte length */
-+ if (datalen < 2)
-+ goto short_packet;
-+ size = data[0] << 8;
-+ size |= data[1];
-+ data += 2;
-+ datalen -= 2;
-+ *_headerlen = 3;
-+ break;
-+ case 2:
-+ /* Four-byte length */
-+ if (datalen < 4)
-+ goto short_packet;
-+ size = data[0] << 24;
-+ size |= data[1] << 16;
-+ size |= data[2] << 8;
-+ size |= data[3];
-+ data += 4;
-+ datalen -= 4;
-+ *_headerlen = 5;
-+ break;
-+ default:
-+ pr_debug("Indefinite length packet not supported\n");
-+ return -EBADMSG;
-+ }
-+ }
-+
-+ pr_devel("datalen=%zu size=%zu", datalen, size);
-+ if (datalen < size)
-+ goto short_packet;
-+ if ((int)size < 0)
-+ goto too_big;
-+
-+ *_data = data;
-+ *_datalen = datalen;
-+ *_type = type;
-+ pr_devel("Found packet type=%u size=%zd\n", type, size);
-+ return size;
-+
-+short_packet:
-+ pr_debug("Attempt to parse short packet\n");
-+ return -EBADMSG;
-+too_big:
-+ pr_debug("Signature subpacket size >2G\n");
-+ return -EMSGSIZE;
-+}
-+
-+/**
-+ * pgp_parse_packets - Parse a set of PGP packets
-+ * @_data: Data to be parsed (updated)
-+ * @_datalen: Amount of data (updated)
-+ * @ctx: Parsing context
-+ *
-+ * Parse a set of PGP packets [RFC 4880: 4].
-+ */
-+int pgp_parse_packets(const u8 *data, size_t datalen,
-+ struct pgp_parse_context *ctx)
-+{
-+ enum pgp_packet_tag type;
-+ ssize_t pktlen;
-+ u8 headerlen;
-+ int ret;
-+
-+ while (datalen > 2) {
-+ pktlen = pgp_parse_packet_header(&data, &datalen, &type,
-+ &headerlen);
-+ if (pktlen < 0)
-+ return pktlen;
-+
-+ if ((ctx->types_of_interest >> type) & 1) {
-+ ret = ctx->process_packet(ctx, type, headerlen,
-+ data, pktlen);
-+ if (ret < 0)
-+ return ret;
-+ }
-+ data += pktlen;
-+ datalen -= pktlen;
-+ }
-+
-+ if (datalen != 0) {
-+ pr_debug("Excess octets in packet stream\n");
-+ return -EBADMSG;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(pgp_parse_packets);
-+
-+/**
-+ * pgp_parse_public_key - Parse the common part of a PGP pubkey packet
-+ * @_data: Content of packet (updated)
-+ * @_datalen: Length of packet remaining (updated)
-+ * @pk: Public key data
-+ *
-+ * Parse the common data struct for a PGP pubkey packet [RFC 4880: 5.5.2].
-+ */
-+int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
-+ struct pgp_parse_pubkey *pk)
-+{
-+ const u8 *data = *_data;
-+ size_t datalen = *_datalen;
-+ __be32 tmp;
-+
-+ if (datalen < 12) {
-+ pr_debug("Public key packet too short\n");
-+ return -EBADMSG;
-+ }
-+
-+ pk->version = *data++;
-+ switch (pk->version) {
-+ case PGP_KEY_VERSION_2:
-+ case PGP_KEY_VERSION_3:
-+ case PGP_KEY_VERSION_4:
-+ break;
-+ default:
-+ pr_debug("Public key packet with unhandled version %d\n",
-+ pk->version);
-+ return -EBADMSG;
-+ }
-+
-+ tmp = *data++ << 24;
-+ tmp |= *data++ << 16;
-+ tmp |= *data++ << 8;
-+ tmp |= *data++;
-+ pk->creation_time = tmp;
-+ if (pk->version == PGP_KEY_VERSION_4) {
-+ pk->expires_at = 0; /* Have to get it from the selfsignature */
-+ } else {
-+ unsigned short ndays;
-+ ndays = *data++ << 8;
-+ ndays |= *data++;
-+ if (ndays)
-+ pk->expires_at = pk->creation_time + ndays * 86400UL;
-+ else
-+ pk->expires_at = 0;
-+ datalen -= 2;
-+ }
-+
-+ pk->pubkey_algo = *data++;
-+ datalen -= 6;
-+
-+ pr_devel("%x,%x,%lx,%lx",
-+ pk->version, pk->pubkey_algo, pk->creation_time,
-+ pk->expires_at);
-+
-+ *_data = data;
-+ *_datalen = datalen;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(pgp_parse_public_key);
---
-1.7.11.4
-
-
-From 3379efc21d2ecc93de135e3265baabbe1f326d5a Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:17 +0100
-Subject: [PATCH 11/32] PGPLIB: Signature parser
-
-Provide some PGP signature parsing helpers:
-
- (1) A function to parse V4 signature subpackets and pass the desired ones to
- a processor function:
-
- int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
- struct pgp_parse_sig_context *ctx);
-
- (2) A function to parse out basic signature parameters from any PGP signature
- such that the algorithms and public key can be selected:
-
- int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
- struct pgp_sig_parameters *p);
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/pgplib.h | 25 ++++
- security/keys/crypto/pgp_library.c | 280 +++++++++++++++++++++++++++++++++++++
- 2 files changed, 305 insertions(+)
-
-diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h
-index a045b3a..34594a9 100644
---- a/include/linux/pgplib.h
-+++ b/include/linux/pgplib.h
-@@ -41,6 +41,31 @@ struct pgp_parse_pubkey {
- extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
- struct pgp_parse_pubkey *pk);
-
-+struct pgp_parse_sig_context {
-+ unsigned long types_of_interest[128 / BITS_PER_LONG];
-+ int (*process_packet)(struct pgp_parse_sig_context *context,
-+ enum pgp_sig_subpkt_type type,
-+ const u8 *data,
-+ size_t datalen);
-+};
-+
-+extern int pgp_parse_sig_packets(const u8 *data, size_t datalen,
-+ struct pgp_parse_sig_context *ctx);
-+
-+struct pgp_sig_parameters {
-+ enum pgp_signature_version version : 8;
-+ enum pgp_signature_type signature_type : 8;
-+ enum pgp_pubkey_algo pubkey_algo : 8;
-+ enum pgp_hash_algo hash_algo : 8;
-+ union {
-+ struct pgp_key_ID issuer;
-+ __be32 issuer32[2];
-+ };
-+};
-+
-+extern int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
-+ struct pgp_sig_parameters *p);
-+
-
- #endif /* CONFIG_PGP_LIBRARY */
-
-diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
-index 39d2878..50b7fa0 100644
---- a/security/keys/crypto/pgp_library.c
-+++ b/security/keys/crypto/pgp_library.c
-@@ -266,3 +266,283 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
- return 0;
- }
- EXPORT_SYMBOL_GPL(pgp_parse_public_key);
-+
-+/**
-+ * pgp_parse_sig_subpkt_header - Parse a PGP V4 signature subpacket header
-+ * @_data: Start of the subpacket (updated to subpacket data)
-+ * @_datalen: Amount of data remaining in buffer (decreased)
-+ * @_type: Where the subpacket type will be returned
-+ *
-+ * Parse a PGP V4 signature subpacket header [RFC 4880: 5.2.3.1].
-+ *
-+ * Returns packet data size on success; non-zero on error. If successful,
-+ * *_data and *_datalen will have been updated and *_headerlen will be set to
-+ * hold the length of the packet header.
-+ */
-+static ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
-+ enum pgp_sig_subpkt_type *_type)
-+{
-+ enum pgp_sig_subpkt_type type;
-+ const u8 *data = *_data;
-+ size_t size, datalen = *_datalen;
-+
-+ pr_devel("-->pgp_parse_sig_subpkt_header(,%zu,,)", datalen);
-+
-+ if (datalen < 2)
-+ goto short_subpacket;
-+
-+ pr_devel("subpkt hdr %02x, %02x\n", data[0], data[1]);
-+
-+ switch (data[0]) {
-+ case 0x00 ... 0xbf:
-+ /* One-byte length */
-+ size = data[0];
-+ data++;
-+ datalen--;
-+ break;
-+ case 0xc0 ... 0xfe:
-+ /* Two-byte length */
-+ if (datalen < 3)
-+ goto short_subpacket;
-+ size = (data[0] - 192) * 256;
-+ size += data[1] + 192;
-+ data += 2;
-+ datalen -= 2;
-+ break;
-+ case 0xff:
-+ if (datalen < 6)
-+ goto short_subpacket;
-+ size = data[1] << 24;
-+ size |= data[2] << 16;
-+ size |= data[3] << 8;
-+ size |= data[4];
-+ data += 5;
-+ datalen -= 5;
-+ break;
-+ }
-+
-+ /* The type octet is included in the size */
-+ pr_devel("datalen=%zu size=%zu", datalen, size);
-+ if (datalen < size)
-+ goto short_subpacket;
-+ if (size == 0)
-+ goto very_short_subpacket;
-+ if ((int)size < 0)
-+ goto too_big;
-+
-+ type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK;
-+ datalen--;
-+ size--;
-+
-+ *_data = data;
-+ *_datalen = datalen;
-+ *_type = type;
-+ pr_devel("Found subpkt type=%u size=%zd\n", type, size);
-+ return size;
-+
-+very_short_subpacket:
-+ pr_debug("Signature subpacket size can't be zero\n");
-+ return -EBADMSG;
-+short_subpacket:
-+ pr_debug("Attempt to parse short signature subpacket\n");
-+ return -EBADMSG;
-+too_big:
-+ pr_debug("Signature subpacket size >2G\n");
-+ return -EMSGSIZE;
-+}
-+
-+/**
-+ * pgp_parse_sig_subpkts - Parse a set of PGP V4 signatute subpackets
-+ * @_data: Data to be parsed (updated)
-+ * @_datalen: Amount of data (updated)
-+ * @ctx: Parsing context
-+ *
-+ * Parse a set of PGP signature subpackets [RFC 4880: 5.2.3].
-+ */
-+static int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
-+ struct pgp_parse_sig_context *ctx)
-+{
-+ enum pgp_sig_subpkt_type type;
-+ ssize_t pktlen;
-+ int ret;
-+
-+ pr_devel("-->pgp_parse_sig_subpkts(,%zu,,)", datalen);
-+
-+ while (datalen > 2) {
-+ pktlen = pgp_parse_sig_subpkt_header(&data, &datalen, &type);
-+ if (pktlen < 0)
-+ return pktlen;
-+ if (test_bit(type, ctx->types_of_interest)) {
-+ ret = ctx->process_packet(ctx, type, data, pktlen);
-+ if (ret < 0)
-+ return ret;
-+ }
-+ data += pktlen;
-+ datalen -= pktlen;
-+ }
-+
-+ if (datalen != 0) {
-+ pr_debug("Excess octets in signature subpacket stream\n");
-+ return -EBADMSG;
-+ }
-+
-+ return 0;
-+}
-+
-+struct pgp_parse_sig_params_ctx {
-+ struct pgp_parse_sig_context base;
-+ struct pgp_sig_parameters *params;
-+ bool got_the_issuer;
-+};
-+
-+/*
-+ * Process a V4 signature subpacket.
-+ */
-+static int pgp_process_sig_params_subpkt(struct pgp_parse_sig_context *context,
-+ enum pgp_sig_subpkt_type type,
-+ const u8 *data,
-+ size_t datalen)
-+{
-+ struct pgp_parse_sig_params_ctx *ctx =
-+ container_of(context, struct pgp_parse_sig_params_ctx, base);
-+
-+ if (ctx->got_the_issuer) {
-+ pr_debug("V4 signature packet has multiple issuers\n");
-+ return -EBADMSG;
-+ }
-+
-+ if (datalen != 8) {
-+ pr_debug("V4 signature issuer subpkt not 8 long (%zu)\n",
-+ datalen);
-+ return -EBADMSG;
-+ }
-+
-+ memcpy(&ctx->params->issuer, data, 8);
-+ ctx->got_the_issuer = true;
-+ return 0;
-+}
-+
-+/**
-+ * pgp_parse_sig_params - Parse basic parameters from a PGP signature packet
-+ * @_data: Content of packet (updated)
-+ * @_datalen: Length of packet remaining (updated)
-+ * @p: The basic parameters
-+ *
-+ * Parse the basic parameters from a PGP signature packet [RFC 4880: 5.2] that
-+ * are needed to start off a signature verification operation. The only ones
-+ * actually necessary are the signature type (which affects how the data is
-+ * transformed) and the hash algorithm.
-+ *
-+ * We also extract the public key algorithm and the issuer's key ID as we'll
-+ * need those to determine if we actually have the public key available. If
-+ * not, then we can't verify the signature anyway.
-+ *
-+ * Returns 0 if successful or a negative error code. *_data and *_datalen are
-+ * updated to point to the 16-bit subset of the hash value and the set of MPIs.
-+ */
-+int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
-+ struct pgp_sig_parameters *p)
-+{
-+ const u8 *data = *_data;
-+ size_t datalen = *_datalen;
-+ int ret;
-+
-+ pr_devel("-->pgp_parse_sig_params(,%zu,,)", datalen);
-+
-+ if (datalen < 1)
-+ return -EBADMSG;
-+ p->version = *data;
-+
-+ if (p->version == PGP_SIG_VERSION_3) {
-+ const struct pgp_signature_v3_packet *v3 = (const void *)data;
-+
-+ if (datalen < sizeof(*v3)) {
-+ pr_debug("Short V3 signature packet\n");
-+ return -EBADMSG;
-+ }
-+ datalen -= sizeof(*v3);
-+ data += sizeof(*v3);
-+
-+ /* V3 has everything we need in the header */
-+ p->signature_type = v3->hashed.signature_type;
-+ p->issuer = v3->issuer;
-+ p->pubkey_algo = v3->pubkey_algo;
-+ p->hash_algo = v3->hash_algo;
-+
-+ } else if (p->version == PGP_SIG_VERSION_4) {
-+ const struct pgp_signature_v4_packet *v4 = (const void *)data;
-+ struct pgp_parse_sig_params_ctx ctx = {
-+ .base.process_packet = pgp_process_sig_params_subpkt,
-+ .params = p,
-+ .got_the_issuer = false,
-+ };
-+ size_t subdatalen;
-+
-+ if (datalen < sizeof(*v4) + 2 + 2 + 2) {
-+ pr_debug("Short V4 signature packet\n");
-+ return -EBADMSG;
-+ }
-+ datalen -= sizeof(*v4);
-+ data += sizeof(*v4);
-+
-+ /* V4 has most things in the header... */
-+ p->signature_type = v4->signature_type;
-+ p->pubkey_algo = v4->pubkey_algo;
-+ p->hash_algo = v4->hash_algo;
-+
-+ /* ... but we have to get the key ID from the subpackets, of
-+ * which there are two sets. */
-+ __set_bit(PGP_SIG_ISSUER, ctx.base.types_of_interest);
-+
-+ subdatalen = *data++ << 8;
-+ subdatalen |= *data++;
-+ datalen -= 2;
-+ if (subdatalen) {
-+ /* Hashed subpackets */
-+ pr_devel("hashed data: %zu (after %zu)\n",
-+ subdatalen, sizeof(*v4));
-+ if (subdatalen > datalen + 2 + 2) {
-+ pr_debug("Short V4 signature packet [hdata]\n");
-+ return -EBADMSG;
-+ }
-+ ret = pgp_parse_sig_subpkts(data, subdatalen,
-+ &ctx.base);
-+ if (ret < 0)
-+ return ret;
-+ data += subdatalen;
-+ datalen -= subdatalen;
-+ }
-+
-+ subdatalen = *data++ << 8;
-+ subdatalen |= *data++;
-+ datalen -= 2;
-+ if (subdatalen) {
-+ /* Unhashed subpackets */
-+ pr_devel("unhashed data: %zu\n", subdatalen);
-+ if (subdatalen > datalen + 2) {
-+ pr_debug("Short V4 signature packet [udata]\n");
-+ return -EBADMSG;
-+ }
-+ ret = pgp_parse_sig_subpkts(data, subdatalen,
-+ &ctx.base);
-+ if (ret < 0)
-+ return ret;
-+ data += subdatalen;
-+ datalen -= subdatalen;
-+ }
-+
-+ if (!ctx.got_the_issuer) {
-+ pr_debug("V4 signature packet lacks issuer\n");
-+ return -EBADMSG;
-+ }
-+ } else {
-+ pr_debug("Signature packet with unhandled version %d\n",
-+ p->version);
-+ return -EBADMSG;
-+ }
-+
-+ *_data = data;
-+ *_datalen = datalen;
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(pgp_parse_sig_params);
---
-1.7.11.4
-
-
-From 39b6dd66338812a1e1806489d3fed50620011b14 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:17 +0100
-Subject: [PATCH 12/32] KEYS: PGP data parser
-
-Implement a PGP data parser for the crypto key type to use when instantiating a
-key.
-
-This parser attempts to parse the instantiation data as a PGP packet sequence
-(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm
-key or subkey from it.
-
-If it finds such a key, it will set up a public_key subtype payload with
-appropriate handler routines (DSA or RSA) and attach it to the key.
-
-Thanks to Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> for pointing out
-some errors.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/Kconfig | 12 ++
- security/keys/crypto/Makefile | 4 +
- security/keys/crypto/pgp_parser.h | 23 +++
- security/keys/crypto/pgp_public_key.c | 344 ++++++++++++++++++++++++++++++++++
- 4 files changed, 383 insertions(+)
- create mode 100644 security/keys/crypto/pgp_parser.h
- create mode 100644 security/keys/crypto/pgp_public_key.c
-
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-index 88ce0e2..1c2ae55 100644
---- a/security/keys/crypto/Kconfig
-+++ b/security/keys/crypto/Kconfig
-@@ -28,3 +28,15 @@ config PGP_LIBRARY
- help
- This option enables a library that provides a number of simple
- utility functions for parsing PGP (RFC 4880) packet-based messages.
-+
-+config CRYPTO_KEY_PGP_PARSER
-+ tristate "PGP key blob parser"
-+ depends on CRYPTO_KEY_TYPE
-+ select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
-+ select PGP_LIBRARY
-+ select MD5 # V3 fingerprint generation
-+ select SHA1 # V4 fingerprint generation
-+ help
-+ This option provides support for parsing PGP (RFC 4880) format blobs
-+ for key data and provides the ability to instantiate a crypto key
-+ from a public key packet found inside the blob.
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 5fbe54e..35733fc 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o
- obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
- obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
- obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
-+
-+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
-+pgp_key_parser-y := \
-+ pgp_public_key.o
-diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
-new file mode 100644
-index 0000000..1cda231
---- /dev/null
-+++ b/security/keys/crypto/pgp_parser.h
-@@ -0,0 +1,23 @@
-+/* PGP crypto data parser internal definitions
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/pgp.h>
-+
-+#define kenter(FMT, ...) \
-+ pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
-+#define kleave(FMT, ...) \
-+ pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
-+
-+/*
-+ * pgp_key_parser.c
-+ */
-+extern const
-+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
-diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c
-new file mode 100644
-index 0000000..c260e02
---- /dev/null
-+++ b/security/keys/crypto/pgp_public_key.c
-@@ -0,0 +1,344 @@
-+/* Instantiate a public key crypto key from PGP format data [RFC 4880]
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "PGP: "fmt
-+#include <keys/crypto-subtype.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/mpi.h>
-+#include <linux/pgplib.h>
-+#include <crypto/hash.h>
-+#include "public_key.h"
-+#include "pgp_parser.h"
-+
-+MODULE_LICENSE("GPL");
-+
-+const
-+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = {
-+#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \
-+ defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE)
-+ [PGP_PUBKEY_RSA_ENC_OR_SIG] = &RSA_public_key_algorithm,
-+ [PGP_PUBKEY_RSA_ENC_ONLY] = &RSA_public_key_algorithm,
-+ [PGP_PUBKEY_RSA_SIG_ONLY] = &RSA_public_key_algorithm,
-+#endif
-+ [PGP_PUBKEY_ELGAMAL] = NULL,
-+ [PGP_PUBKEY_DSA] = NULL,
-+};
-+
-+static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = {
-+ [PGP_PUBKEY_RSA_ENC_OR_SIG] = PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER,
-+ [PGP_PUBKEY_RSA_ENC_ONLY] = PKEY_CAN_ENCDEC,
-+ [PGP_PUBKEY_RSA_SIG_ONLY] = PKEY_CAN_SIGVER,
-+ [PGP_PUBKEY_ELGAMAL] = 0,
-+ [PGP_PUBKEY_DSA] = 0,
-+};
-+
-+static inline void digest_putc(struct shash_desc *digest, uint8_t ch)
-+{
-+ crypto_shash_update(digest, &ch, 1);
-+}
-+
-+struct pgp_key_data_parse_context {
-+ struct pgp_parse_context pgp;
-+ struct crypto_key_subtype *subtype;
-+ char *fingerprint;
-+ void *payload;
-+};
-+
-+/*
-+ * Calculate the public key ID (RFC4880 12.2)
-+ */
-+static int pgp_calc_pkey_keyid(struct shash_desc *digest,
-+ struct pgp_parse_pubkey *pgp,
-+ struct public_key *key)
-+{
-+ unsigned nb[ARRAY_SIZE(key->mpi)];
-+ unsigned nn[ARRAY_SIZE(key->mpi)];
-+ unsigned n;
-+ u8 *pp[ARRAY_SIZE(key->mpi)];
-+ u32 a32;
-+ int npkey = key->algo->n_pub_mpi;
-+ int i, ret = -ENOMEM;
-+
-+ kenter("");
-+
-+ for (i = 0; i < ARRAY_SIZE(pp); i++)
-+ pp[i] = NULL;
-+
-+ n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6;
-+ for (i = 0; i < npkey; i++) {
-+ nb[i] = mpi_get_nbits(key->mpi[i]);
-+ pp[i] = mpi_get_buffer(key->mpi[i], nn + i, NULL);
-+ if (!pp[i])
-+ goto error;
-+ n += 2 + nn[i];
-+ }
-+
-+ digest_putc(digest, 0x99); /* ctb */
-+ digest_putc(digest, n >> 8); /* 16-bit header length */
-+ digest_putc(digest, n);
-+ digest_putc(digest, pgp->version);
-+
-+ a32 = pgp->creation_time;
-+ digest_putc(digest, a32 >> 24);
-+ digest_putc(digest, a32 >> 16);
-+ digest_putc(digest, a32 >> 8);
-+ digest_putc(digest, a32 >> 0);
-+
-+ if (pgp->version < PGP_KEY_VERSION_4) {
-+ u16 a16;
-+
-+ if (pgp->expires_at)
-+ a16 = (pgp->expires_at - pgp->creation_time) / 86400UL;
-+ else
-+ a16 = 0;
-+ digest_putc(digest, a16 >> 8);
-+ digest_putc(digest, a16 >> 0);
-+ }
-+
-+ digest_putc(digest, pgp->pubkey_algo);
-+
-+ for (i = 0; i < npkey; i++) {
-+ digest_putc(digest, nb[i] >> 8);
-+ digest_putc(digest, nb[i]);
-+ crypto_shash_update(digest, pp[i], nn[i]);
-+ }
-+ ret = 0;
-+
-+error:
-+ for (i = 0; i < npkey; i++)
-+ kfree(pp[i]);
-+ kleave(" = %d", ret);
-+ return ret;
-+}
-+
-+/*
-+ * Calculate the public key ID fingerprint
-+ */
-+static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx,
-+ struct pgp_parse_pubkey *pgp,
-+ struct public_key *key)
-+{
-+ struct crypto_shash *tfm;
-+ struct shash_desc *digest;
-+ char *fingerprint;
-+ u8 *raw_fingerprint;
-+ int digest_size, offset;
-+ int ret, i;
-+
-+ ret = -ENOMEM;
-+ tfm = crypto_alloc_shash(pgp->version < PGP_KEY_VERSION_4 ?
-+ "md5" : "sha1", 0, 0);
-+ if (!tfm)
-+ goto cleanup;
-+
-+ digest = kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm),
-+ GFP_KERNEL);
-+ if (!digest)
-+ goto cleanup_tfm;
-+
-+ digest->tfm = tfm;
-+ digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-+ ret = crypto_shash_init(digest);
-+ if (ret < 0)
-+ goto cleanup_hash;
-+
-+ ret = pgp_calc_pkey_keyid(digest, pgp, key);
-+ if (ret < 0)
-+ goto cleanup_hash;
-+
-+ digest_size = crypto_shash_digestsize(tfm);
-+
-+ raw_fingerprint = kmalloc(digest_size, GFP_KERNEL);
-+ if (!raw_fingerprint)
-+ goto cleanup_hash;
-+
-+ ret = crypto_shash_final(digest, raw_fingerprint);
-+ if (ret < 0)
-+ goto cleanup_raw_fingerprint;
-+
-+ fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL);
-+ if (!fingerprint)
-+ goto cleanup_raw_fingerprint;
-+
-+ offset = digest_size - 8;
-+ pr_debug("offset %u/%u\n", offset, digest_size);
-+
-+ for (i = 0; i < digest_size; i++)
-+ sprintf(fingerprint + i * 2, "%02x", raw_fingerprint[i]);
-+ pr_debug("fingerprint %s\n", fingerprint);
-+
-+ memcpy(&key->key_id, raw_fingerprint + offset, 8);
-+ key->key_id_size = 8;
-+ key->id_type = PKEY_ID_PGP;
-+
-+ ctx->fingerprint = fingerprint;
-+ ret = 0;
-+cleanup_raw_fingerprint:
-+ kfree(raw_fingerprint);
-+cleanup_hash:
-+ kfree(digest);
-+cleanup_tfm:
-+ crypto_free_shash(tfm);
-+cleanup:
-+ kleave(" = %d", ret);
-+ return ret;
-+}
-+
-+/*
-+ * Extract a public key or public subkey from the PGP stream.
-+ */
-+static int pgp_process_public_key(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type,
-+ u8 headerlen,
-+ const u8 *data,
-+ size_t datalen)
-+{
-+ const struct public_key_algorithm *algo;
-+ struct pgp_key_data_parse_context *ctx =
-+ container_of(context, struct pgp_key_data_parse_context, pgp);
-+ struct pgp_parse_pubkey pgp;
-+ struct public_key *key;
-+ int i, ret;
-+
-+ kenter(",%u,%u,,%zu", type, headerlen, datalen);
-+
-+ if (ctx->subtype) {
-+ kleave(" = -ENOKEY [already]");
-+ return -EBADMSG;
-+ }
-+
-+ key = kzalloc(sizeof(struct public_key), GFP_KERNEL);
-+ if (!key)
-+ return -ENOMEM;
-+
-+ ret = pgp_parse_public_key(&data, &datalen, &pgp);
-+ if (ret < 0)
-+ goto cleanup;
-+
-+ if (pgp.pubkey_algo >= PGP_PUBKEY__LAST ||
-+ !pgp_public_key_algorithms[pgp.pubkey_algo]) {
-+ pr_debug("Unsupported public key algorithm %u\n",
-+ pgp.pubkey_algo);
-+ ret = -ENOPKG;
-+ goto cleanup;
-+ }
-+
-+ algo = key->algo = pgp_public_key_algorithms[pgp.pubkey_algo];
-+
-+ /* It's a public key, so that only gives us encrypt and verify
-+ * capabilities.
-+ */
-+ key->capabilities = pgp_public_key_capabilities[pgp.pubkey_algo] &
-+ (PKEY_CAN_ENCRYPT | PKEY_CAN_VERIFY);
-+
-+ for (i = 0; i < algo->n_pub_mpi; i++) {
-+ unsigned int remaining = datalen;
-+ if (remaining == 0) {
-+ pr_debug("short %zu mpi %d\n", datalen, i);
-+ goto cleanup_badmsg;
-+ }
-+ key->mpi[i] = mpi_read_from_buffer(data, &remaining);
-+ if (!key->mpi[i])
-+ goto cleanup_nomem;
-+ data += remaining;
-+ datalen -= remaining;
-+ }
-+
-+ if (datalen != 0) {
-+ pr_debug("excess %zu\n", datalen);
-+ goto cleanup_badmsg;
-+ }
-+
-+ ret = pgp_generate_fingerprint(ctx, &pgp, key);
-+ if (ret < 0)
-+ goto cleanup;
-+
-+ /* We're pinning the module by being linked against it */
-+ __module_get(public_key_crypto_key_subtype.owner);
-+ ctx->subtype = &public_key_crypto_key_subtype;
-+ ctx->payload = key;
-+ kleave(" = 0 [use]");
-+ return 0;
-+
-+cleanup_nomem:
-+ ret = -ENOMEM;
-+ goto cleanup;
-+cleanup_badmsg:
-+ ret = -EBADMSG;
-+cleanup:
-+ pr_devel("cleanup");
-+ if (key) {
-+ for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
-+ mpi_free(key->mpi[i]);
-+ kfree(key);
-+ }
-+ kleave(" = %d", ret);
-+ return ret;
-+}
-+
-+/*
-+ * Attempt to parse the instantiation data blob for a key as a PGP packet
-+ * message holding a key.
-+ */
-+static int pgp_key_preparse(struct key_preparsed_payload *prep)
-+{
-+ struct pgp_key_data_parse_context ctx;
-+ int ret;
-+
-+ kenter("");
-+
-+ ctx.pgp.types_of_interest =
-+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
-+ ctx.pgp.process_packet = pgp_process_public_key;
-+ ctx.subtype = NULL;
-+ ctx.fingerprint = NULL;
-+ ctx.payload = NULL;
-+
-+ ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp);
-+ if (ret < 0) {
-+ if (ctx.payload)
-+ ctx.subtype->destroy(ctx.payload);
-+ if (ctx.subtype)
-+ module_put(ctx.subtype->owner);
-+ kfree(ctx.fingerprint);
-+ return ret;
-+ }
-+
-+ prep->type_data[0] = ctx.subtype;
-+ prep->type_data[1] = ctx.fingerprint;
-+ prep->payload = ctx.payload;
-+ prep->quotalen = prep->datalen;
-+ return 0;
-+}
-+
-+static struct crypto_key_parser pgp_key_parser = {
-+ .owner = THIS_MODULE,
-+ .name = "pgp",
-+ .preparse = pgp_key_preparse,
-+};
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init pgp_key_init(void)
-+{
-+ return register_crypto_key_parser(&pgp_key_parser);
-+}
-+
-+static void __exit pgp_key_exit(void)
-+{
-+ unregister_crypto_key_parser(&pgp_key_parser);
-+}
-+
-+module_init(pgp_key_init);
-+module_exit(pgp_key_exit);
---
-1.7.11.4
-
-
-From 1095ff02a49868cf8f3706dd2c83474bcf2081f8 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:17 +0100
-Subject: [PATCH 13/32] KEYS: PGP-based public key signature verification
-
-Provide handlers for PGP-based public-key algorithm signature verification.
-This does most of the work involved in signature verification as most of it is
-public-key algorithm agnostic. The public-key verification algorithm itself
-is just the last little bit and is supplied the complete hash data to process.
-
-This requires glue logic putting on top to make use of it - something the next
-patch provides.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/Makefile | 3 +-
- security/keys/crypto/pgp_parser.h | 6 +
- security/keys/crypto/pgp_sig_verify.c | 325 ++++++++++++++++++++++++++++++++++
- 3 files changed, 333 insertions(+), 1 deletion(-)
- create mode 100644 security/keys/crypto/pgp_sig_verify.c
-
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 35733fc..0c8b8a1 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -11,4 +11,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
-
- obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
- pgp_key_parser-y := \
-- pgp_public_key.o
-+ pgp_public_key.o \
-+ pgp_sig_verify.o
-diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
-index 1cda231..6f5b3af 100644
---- a/security/keys/crypto/pgp_parser.h
-+++ b/security/keys/crypto/pgp_parser.h
-@@ -21,3 +21,9 @@
- */
- extern const
- struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
-+
-+/*
-+ * pgp_pubkey_sig.c
-+ */
-+extern struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin(
-+ struct key *crypto_key, const u8 *sigdata, size_t siglen);
-diff --git a/security/keys/crypto/pgp_sig_verify.c b/security/keys/crypto/pgp_sig_verify.c
-new file mode 100644
-index 0000000..f9bb949
---- /dev/null
-+++ b/security/keys/crypto/pgp_sig_verify.c
-@@ -0,0 +1,325 @@
-+/* PGP public key signature verification [RFC 4880]
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "PGPSIG: "fmt
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/pgplib.h>
-+#include <linux/err.h>
-+#include "public_key.h"
-+#include "pgp_parser.h"
-+
-+static const struct {
-+ enum pkey_hash_algo algo : 8;
-+} pgp_pubkey_hash[PGP_HASH__LAST] = {
-+ [PGP_HASH_MD5].algo = PKEY_HASH_MD5,
-+ [PGP_HASH_SHA1].algo = PKEY_HASH_SHA1,
-+ [PGP_HASH_RIPE_MD_160].algo = PKEY_HASH_RIPE_MD_160,
-+ [PGP_HASH_SHA256].algo = PKEY_HASH_SHA256,
-+ [PGP_HASH_SHA384].algo = PKEY_HASH_SHA384,
-+ [PGP_HASH_SHA512].algo = PKEY_HASH_SHA512,
-+ [PGP_HASH_SHA224].algo = PKEY_HASH_SHA224,
-+};
-+
-+static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx,
-+ const void *data, size_t datalen);
-+static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx,
-+ const u8 *sig, size_t siglen);
-+static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx);
-+
-+struct pgp_pkey_sig_parse_context {
-+ struct pgp_parse_context pgp;
-+ struct pgp_sig_parameters params;
-+};
-+
-+static int pgp_pkey_parse_signature(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type,
-+ u8 headerlen,
-+ const u8 *data,
-+ size_t datalen)
-+{
-+ struct pgp_pkey_sig_parse_context *ctx =
-+ container_of(context, struct pgp_pkey_sig_parse_context, pgp);
-+
-+ return pgp_parse_sig_params(&data, &datalen, &ctx->params);
-+}
-+
-+/*
-+ * Begin the process of verifying a DSA signature.
-+ *
-+ * This involves allocating the hash into which first the data and then the
-+ * metadata will be put, and parsing the signature to check that it matches the
-+ * key.
-+ */
-+struct crypto_sig_verify_context *pgp_pkey_verify_sig_begin(
-+ struct key *crypto_key, const u8 *sigdata, size_t siglen)
-+{
-+ struct pgp_pkey_sig_parse_context p;
-+ struct public_key_signature *sig;
-+ struct crypto_shash *tfm;
-+ const struct public_key *key = crypto_key->payload.data;
-+ size_t digest_size, desc_size;
-+ int ret;
-+
-+ kenter("{%d},,%zu", key_serial(crypto_key), siglen);
-+
-+ if (!key) {
-+ kleave(" = -ENOKEY [no public key]");
-+ return ERR_PTR(-ENOKEY);
-+ }
-+
-+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
-+ p.pgp.process_packet = pgp_pkey_parse_signature;
-+ ret = pgp_parse_packets(sigdata, siglen, &p.pgp);
-+ if (ret < 0)
-+ return ERR_PTR(ret);
-+
-+ if (p.params.pubkey_algo >= PGP_PUBKEY__LAST ||
-+ !pgp_public_key_algorithms[p.params.pubkey_algo]) {
-+ pr_debug("Unsupported public key algorithm %u\n",
-+ p.params.pubkey_algo);
-+ return ERR_PTR(-ENOPKG);
-+ }
-+
-+ if (pgp_public_key_algorithms[p.params.pubkey_algo] != key->algo) {
-+ kleave(" = -EKEYREJECTED [wrong pk algo]");
-+ return ERR_PTR(-EKEYREJECTED);
-+ }
-+
-+ if (!(key->capabilities & PKEY_CAN_VERIFY)) {
-+ kleave(" = -EKEYREJECTED [key can't verify]");
-+ return ERR_PTR(-EKEYREJECTED);
-+ }
-+
-+ if (p.params.hash_algo >= PGP_HASH__LAST ||
-+ !pgp_hash_algorithms[p.params.hash_algo]) {
-+ pr_debug("Unsupported hash algorithm %u\n",
-+ p.params.hash_algo);
-+ return ERR_PTR(-ENOPKG);
-+ }
-+
-+ pr_debug("Signature generated with %s hash\n",
-+ pgp_hash_algorithms[p.params.hash_algo]);
-+
-+ if (memcmp(&p.params.issuer, key->key_id, 8) != 0) {
-+ kleave(" = -ENOKEY [wrong key ID]");
-+ return ERR_PTR(-ENOKEY);
-+ }
-+
-+ if (p.params.signature_type != PGP_SIG_BINARY_DOCUMENT_SIG &&
-+ p.params.signature_type != PGP_SIG_STANDALONE_SIG) {
-+ /* We don't want to canonicalise */
-+ kleave(" = -EOPNOTSUPP [canon]");
-+ return ERR_PTR(-EOPNOTSUPP);
-+ }
-+
-+ /* Allocate the hashing algorithm we're going to need and find out how
-+ * big the hash operational data will be.
-+ */
-+ tfm = crypto_alloc_shash(pgp_hash_algorithms[p.params.hash_algo], 0, 0);
-+ if (IS_ERR(tfm))
-+ return PTR_ERR(tfm) == -ENOENT ?
-+ ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
-+
-+ desc_size = crypto_shash_descsize(tfm);
-+ digest_size = crypto_shash_digestsize(tfm);
-+
-+ /* We allocate the hash operational data storage on the end of our
-+ * context data.
-+ */
-+ sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL);
-+ if (!sig) {
-+ crypto_free_shash(tfm);
-+ return ERR_PTR(-ENOMEM);
-+ }
-+
-+ sig->base.key = crypto_key;
-+ sig->base.add_data = pgp_pkey_verify_sig_add_data;
-+ sig->base.end = pgp_pkey_verify_sig_end;
-+ sig->base.cancel = pgp_pkey_verify_sig_cancel;
-+ sig->pkey_hash_algo = pgp_pubkey_hash[p.params.hash_algo].algo;
-+ sig->digest = (u8 *)sig + sizeof(*sig) + desc_size;
-+ sig->digest_size = digest_size;
-+ sig->hash.tfm = tfm;
-+ sig->hash.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-+
-+ ret = crypto_shash_init(&sig->hash);
-+ if (ret < 0) {
-+ crypto_free_shash(sig->hash.tfm);
-+ kfree(sig);
-+ return ERR_PTR(ret);
-+ }
-+
-+ key_get(sig->base.key);
-+ kleave(" = %p", sig);
-+ return &sig->base;
-+}
-+
-+/*
-+ * Load data into the hash
-+ */
-+static int pgp_pkey_verify_sig_add_data(struct crypto_sig_verify_context *ctx,
-+ const void *data, size_t datalen)
-+{
-+ struct public_key_signature *sig =
-+ container_of(ctx, struct public_key_signature, base);
-+
-+ return crypto_shash_update(&sig->hash, data, datalen);
-+}
-+
-+struct pgp_pkey_sig_digest_context {
-+ struct pgp_parse_context pgp;
-+ const struct public_key *key;
-+ struct public_key_signature *sig;
-+};
-+
-+/*
-+ * Extract required metadata from the signature packet and add what we need to
-+ * to the hash.
-+ */
-+static int pgp_pkey_digest_signature(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type,
-+ u8 headerlen,
-+ const u8 *data,
-+ size_t datalen)
-+{
-+ struct pgp_pkey_sig_digest_context *ctx =
-+ container_of(context, struct pgp_pkey_sig_digest_context, pgp);
-+ enum pgp_signature_version version;
-+ int i;
-+
-+ kenter(",%u,%u,,%zu", type, headerlen, datalen);
-+
-+ version = *data;
-+ if (version == PGP_SIG_VERSION_3) {
-+ /* We just include an excerpt of the metadata from a V3
-+ * signature.
-+ */
-+ crypto_shash_update(&ctx->sig->hash, data + 1, 5);
-+ data += sizeof(struct pgp_signature_v3_packet);
-+ datalen -= sizeof(struct pgp_signature_v3_packet);
-+ } else if (version == PGP_SIG_VERSION_4) {
-+ /* We add the whole metadata header and some of the hashed data
-+ * for a V4 signature, plus a trailer.
-+ */
-+ size_t hashedsz, unhashedsz;
-+ u8 trailer[6];
-+
-+ hashedsz = 4 + 2 + (data[4] << 8) + data[5];
-+ crypto_shash_update(&ctx->sig->hash, data, hashedsz);
-+
-+ trailer[0] = version;
-+ trailer[1] = 0xffU;
-+ trailer[2] = hashedsz >> 24;
-+ trailer[3] = hashedsz >> 16;
-+ trailer[4] = hashedsz >> 8;
-+ trailer[5] = hashedsz;
-+
-+ crypto_shash_update(&ctx->sig->hash, trailer, 6);
-+ data += hashedsz;
-+ datalen -= hashedsz;
-+
-+ unhashedsz = 2 + (data[0] << 8) + data[1];
-+ data += unhashedsz;
-+ datalen -= unhashedsz;
-+ }
-+
-+ if (datalen <= 2) {
-+ kleave(" = -EBADMSG");
-+ return -EBADMSG;
-+ }
-+
-+ /* There's a quick check on the hash available. */
-+ ctx->sig->signed_hash_msw[0] = *data++;
-+ ctx->sig->signed_hash_msw[1] = *data++;
-+ datalen -= 2;
-+
-+ /* And then the cryptographic data, which we'll need for the
-+ * algorithm.
-+ */
-+ for (i = 0; i < ctx->key->algo->n_sig_mpi; i++) {
-+ unsigned int remaining = datalen;
-+ if (remaining == 0) {
-+ pr_debug("short %zu mpi %d\n", datalen, i);
-+ return -EBADMSG;
-+ }
-+ ctx->sig->mpi[i] = mpi_read_from_buffer(data, &remaining);
-+ if (!ctx->sig->mpi[i])
-+ return -ENOMEM;
-+ data += remaining;
-+ datalen -= remaining;
-+ }
-+
-+ if (datalen != 0) {
-+ kleave(" = -EBADMSG [trailer %zu]", datalen);
-+ return -EBADMSG;
-+ }
-+
-+ kleave(" = 0");
-+ return 0;
-+}
-+
-+/*
-+ * The data is now all loaded into the hash; load the metadata, finalise the
-+ * hash and perform the verification step.
-+ */
-+static int pgp_pkey_verify_sig_end(struct crypto_sig_verify_context *ctx,
-+ const u8 *sigdata, size_t siglen)
-+{
-+ struct public_key_signature *sig =
-+ container_of(ctx, struct public_key_signature, base);
-+ const struct public_key *key = sig->base.key->payload.data;
-+ struct pgp_pkey_sig_digest_context p;
-+ int ret;
-+
-+ kenter("");
-+
-+ /* Firstly we add metadata, starting with some of the data from the
-+ * signature packet */
-+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
-+ p.pgp.process_packet = pgp_pkey_digest_signature;
-+ p.key = key;
-+ p.sig = sig;
-+ ret = pgp_parse_packets(sigdata, siglen, &p.pgp);
-+ if (ret < 0)
-+ goto error_free_ctx;
-+
-+ crypto_shash_final(&sig->hash, sig->digest);
-+
-+ ret = key->algo->verify(key, sig);
-+
-+error_free_ctx:
-+ pgp_pkey_verify_sig_cancel(ctx);
-+ kleave(" = %d", ret);
-+ return ret;
-+}
-+
-+/*
-+ * Cancel an in-progress data loading
-+ */
-+static void pgp_pkey_verify_sig_cancel(struct crypto_sig_verify_context *ctx)
-+{
-+ struct public_key_signature *sig =
-+ container_of(ctx, struct public_key_signature, base);
-+ int i;
-+
-+ kenter("");
-+
-+ /* !!! Do we need to tell the crypto layer to cancel too? */
-+ crypto_free_shash(sig->hash.tfm);
-+ key_put(sig->base.key);
-+ for (i = 0; i < ARRAY_SIZE(sig->mpi); i++)
-+ mpi_free(sig->mpi[i]);
-+ kfree(sig);
-+
-+ kleave("");
-+}
---
-1.7.11.4
-
-
-From 69d9f31b888090b5705b7148760143a6b706a116 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:17 +0100
-Subject: [PATCH 14/32] KEYS: PGP format signature parser
-
-Implement a signature parser that will attempt to parse a signature blob as a
-PGP packet format message. If it can, it will find an appropriate crypto key
-and set the public-key algorithm according to the data in the signature.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/Makefile | 1 +
- security/keys/crypto/pgp_sig_parser.c | 136 ++++++++++++++++++++++++++++++++++
- 2 files changed, 137 insertions(+)
- create mode 100644 security/keys/crypto/pgp_sig_parser.c
-
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index 0c8b8a1..a9a34c6 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -12,4 +12,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
- obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
- pgp_key_parser-y := \
- pgp_public_key.o \
-+ pgp_sig_parser.o \
- pgp_sig_verify.o
-diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c
-new file mode 100644
-index 0000000..683eb53
---- /dev/null
-+++ b/security/keys/crypto/pgp_sig_parser.c
-@@ -0,0 +1,136 @@
-+/* Handling for PGP public key signature data [RFC 4880]
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#define pr_fmt(fmt) "PGPSIG: "fmt
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/pgplib.h>
-+#include <linux/err.h>
-+#include "public_key.h"
-+#include "pgp_parser.h"
-+
-+struct PGP_sig_parse_context {
-+ struct pgp_parse_context pgp;
-+ struct pgp_sig_parameters params;
-+ bool found_sig;
-+};
-+
-+/*
-+ * Look inside signature sections for a key ID
-+ */
-+static int pgp_process_signature(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type,
-+ u8 headerlen,
-+ const u8 *data,
-+ size_t datalen)
-+{
-+ struct PGP_sig_parse_context *ctx =
-+ container_of(context, struct PGP_sig_parse_context, pgp);
-+
-+ ctx->found_sig = true;
-+ return pgp_parse_sig_params(&data, &datalen, &ctx->params);
-+}
-+
-+/*
-+ * Attempt to find a key to use for PGP signature verification, starting off by
-+ * looking in the supplied keyring.
-+ *
-+ * The function may also look for other key sources such as a TPM. If an
-+ * alternative key is found it can be added to the keyring for future
-+ * reference.
-+ */
-+static struct key *find_key_for_pgp_sig(struct key *keyring,
-+ const u8 *sig, size_t siglen)
-+{
-+ struct PGP_sig_parse_context p;
-+ key_ref_t key;
-+ char criterion[3 + 8 * 2 + 1];
-+ int ret;
-+
-+ if (!keyring)
-+ return ERR_PTR(-ENOKEY);
-+
-+ /* Need to find the key ID */
-+ p.pgp.types_of_interest = (1 << PGP_PKT_SIGNATURE);
-+ p.pgp.process_packet = pgp_process_signature;
-+ p.found_sig = false;
-+ ret = pgp_parse_packets(sig, siglen, &p.pgp);
-+ if (ret < 0)
-+ return ERR_PTR(ret);
-+
-+ if (!p.found_sig)
-+ return ERR_PTR(-ENOMSG);
-+
-+ sprintf(criterion, "id:%08x%08x",
-+ be32_to_cpu(p.params.issuer32[0]),
-+ be32_to_cpu(p.params.issuer32[1]));
-+
-+ pr_debug("Look up: %s\n", criterion);
-+
-+ key = keyring_search(make_key_ref(keyring, 1),
-+ &key_type_crypto, criterion);
-+ if (IS_ERR(key)) {
-+ switch (PTR_ERR(key)) {
-+ /* Hide some search errors */
-+ case -EACCES:
-+ case -ENOTDIR:
-+ case -EAGAIN:
-+ return ERR_PTR(-ENOKEY);
-+ default:
-+ return ERR_CAST(key);
-+ }
-+ }
-+
-+ pr_debug("Found key %x\n", key_serial(key_ref_to_ptr(key)));
-+ return key_ref_to_ptr(key);
-+}
-+
-+/*
-+ * Attempt to parse a signature as a PGP packet format blob and find a
-+ * matching key.
-+ */
-+static struct crypto_sig_verify_context *pgp_verify_sig_begin(
-+ struct key *keyring, const u8 *sig, size_t siglen)
-+{
-+ struct crypto_sig_verify_context *ctx;
-+ struct key *key;
-+
-+ key = find_key_for_pgp_sig(keyring, sig, siglen);
-+ if (IS_ERR(key))
-+ return ERR_CAST(key);
-+
-+ /* We only handle in-kernel public key signatures for the moment */
-+ ctx = pgp_pkey_verify_sig_begin(key, sig, siglen);
-+ key_put(key);
-+ return ctx;
-+}
-+
-+static struct crypto_sig_parser pgp_sig_parser = {
-+ .owner = THIS_MODULE,
-+ .name = "pgp",
-+ .verify_sig_begin = pgp_verify_sig_begin,
-+};
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init pgp_sig_init(void)
-+{
-+ return register_crypto_sig_parser(&pgp_sig_parser);
-+}
-+
-+static void __exit pgp_sig_exit(void)
-+{
-+ unregister_crypto_sig_parser(&pgp_sig_parser);
-+}
-+
-+module_init(pgp_sig_init);
-+module_exit(pgp_sig_exit);
---
-1.7.11.4
-
-
-From fe109b5adbb22b3503cb1f72f5585543218ba990 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:17 +0100
-Subject: [PATCH 15/32] KEYS: Provide PGP key description autogeneration
-
-Provide a facility to autogenerate the name of PGP keys from the contents of
-the payload. If add_key() is given a blank description, a description is
-constructed from the last user ID packet in the payload data plus the last 8
-hex digits of the key ID. For instance:
-
- keyctl padd crypto "" @s </tmp/key.pub
-
-might create a key with a constructed description that can be seen in
-/proc/keys:
-
-2f674b96 I--Q--- 1 perm 39390000 0 0 crypto Sample kernel key 31f0ae93: PGP.RSA 31f0ae93 []
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/crypto/pgp_public_key.c | 64 +++++++++++++++++++++++++++++------
- 1 file changed, 53 insertions(+), 11 deletions(-)
-
-diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c
-index c260e02..2347ecd 100644
---- a/security/keys/crypto/pgp_public_key.c
-+++ b/security/keys/crypto/pgp_public_key.c
-@@ -52,6 +52,9 @@ struct pgp_key_data_parse_context {
- struct crypto_key_subtype *subtype;
- char *fingerprint;
- void *payload;
-+ const char *user_id;
-+ size_t user_id_len;
-+ size_t fingerprint_len;
- };
-
- /*
-@@ -166,6 +169,7 @@ static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx,
- if (ret < 0)
- goto cleanup_raw_fingerprint;
-
-+ ctx->fingerprint_len = digest_size * 2;
- fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL);
- if (!fingerprint)
- goto cleanup_raw_fingerprint;
-@@ -212,6 +216,13 @@ static int pgp_process_public_key(struct pgp_parse_context *context,
-
- kenter(",%u,%u,,%zu", type, headerlen, datalen);
-
-+ if (type == PGP_PKT_USER_ID) {
-+ ctx->user_id = data;
-+ ctx->user_id_len = datalen;
-+ kleave(" = 0 [user ID]");
-+ return 0;
-+ }
-+
- if (ctx->subtype) {
- kleave(" = -ENOKEY [already]");
- return -EBADMSG;
-@@ -297,21 +308,44 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep)
-
- kenter("");
-
-+ memset(&ctx, 0, sizeof(ctx));
- ctx.pgp.types_of_interest =
-- (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
-+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY) |
-+ (1 << PGP_PKT_USER_ID);
- ctx.pgp.process_packet = pgp_process_public_key;
-- ctx.subtype = NULL;
-- ctx.fingerprint = NULL;
-- ctx.payload = NULL;
-
- ret = pgp_parse_packets(prep->data, prep->datalen, &ctx.pgp);
-- if (ret < 0) {
-- if (ctx.payload)
-- ctx.subtype->destroy(ctx.payload);
-- if (ctx.subtype)
-- module_put(ctx.subtype->owner);
-- kfree(ctx.fingerprint);
-- return ret;
-+ if (ret < 0)
-+ goto error;
-+
-+ if (ctx.user_id && ctx.user_id_len > 0) {
-+ /* Propose a description for the key (user ID without the comment) */
-+ size_t ulen = ctx.user_id_len, flen = ctx.fingerprint_len;
-+ const char *p;
-+
-+ p = memchr(ctx.user_id, '(', ulen);
-+ if (p) {
-+ /* Remove the comment */
-+ do {
-+ p--;
-+ } while (*p == ' ' && p > ctx.user_id);
-+ if (*p != ' ')
-+ p++;
-+ ulen = p - ctx.user_id;
-+ }
-+
-+ if (ulen > 255 - 9)
-+ ulen = 255 - 9;
-+ prep->description = kmalloc(ulen + 1 + 8 + 1, GFP_KERNEL);
-+ ret = -ENOMEM;
-+ if (!prep->description)
-+ goto error;
-+ memcpy(prep->description, ctx.user_id, ulen);
-+ prep->description[ulen] = ' ';
-+ memcpy(prep->description + ulen + 1,
-+ ctx.fingerprint + flen - 8, 8);
-+ prep->description[ulen + 9] = 0;
-+ pr_debug("desc '%s'\n", prep->description);
- }
-
- prep->type_data[0] = ctx.subtype;
-@@ -319,6 +353,14 @@ static int pgp_key_preparse(struct key_preparsed_payload *prep)
- prep->payload = ctx.payload;
- prep->quotalen = prep->datalen;
- return 0;
-+
-+error:
-+ if (ctx.payload)
-+ ctx.subtype->destroy(ctx.payload);
-+ if (ctx.subtype)
-+ module_put(ctx.subtype->owner);
-+ kfree(ctx.fingerprint);
-+ return ret;
- }
-
- static struct crypto_key_parser pgp_key_parser = {
---
-1.7.11.4
-
-
-From 77b00423d002eb013293177310644c8284b6ea2f Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:18 +0100
-Subject: [PATCH 16/32] KEYS: Provide a function to load keys from a PGP
- keyring blob
-
-Provide a function to load keys from a PGP keyring blob for use in initialising
-the module signing key keyring:
-
- int load_PGP_keys(const u8 *pgpdata, size_t pgpdatalen,
- struct key *keyring, const char *descprefix);
-
-The keys are labelled with descprefix plus a number to uniquify them. The keys
-will actually be identified by the ID calculated from the PGP data rather than
-by the description, so this shouldn't be a problem.
-
-The keys are attached to the keyring supplied.
-
-Looking as root in /proc/keys after the module signing keyring has been loaded:
-
-24460d1c I----- 1 perm 3f010000 0 0 crypto modsign.0: dsa 5acc2142 []
-3ca85723 I----- 1 perm 1f010000 0 0 keyring .module_sign: 1/4
-
-Thanks to Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> for some pointing
-out some errors.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/security/keys-crypto.txt | 20 ++++++
- include/keys/crypto-type.h | 3 +
- security/keys/crypto/Kconfig | 9 +++
- security/keys/crypto/Makefile | 1 +
- security/keys/crypto/pgp_preload.c | 115 +++++++++++++++++++++++++++++++++
- 5 files changed, 148 insertions(+)
- create mode 100644 security/keys/crypto/pgp_preload.c
-
-diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
-index 0a886ec..be5067e 100644
---- a/Documentation/security/keys-crypto.txt
-+++ b/Documentation/security/keys-crypto.txt
-@@ -10,6 +10,7 @@ Contents:
- - Signature verification.
- - Implementing crypto parsers.
- - Implementing crypto subtypes.
-+ - Initial PGP key preloading.
-
-
- ========
-@@ -279,3 +280,22 @@ There are a number of operations defined by the subtype:
- Mandatory. This should free the memory associated with the key. The
- crypto key will look after freeing the fingerprint and releasing the
- reference on the subtype module.
-+
-+
-+=======================
-+INITIAL PGP KEY LOADING
-+=======================
-+
-+A function is provided to perform an initial load of a set of public keys bound
-+into a PGP packet format blob:
-+
-+ int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
-+ struct key *keyring);
-+
-+This takes the blob of data defined by pgpdata and pgpdatalen, extracts keys
-+from them and adds them to the specified keyring. The keys are labelled with a
-+description generated from the fingerprint and last user ID of each key. The
-+description is required to prevent all but the last key being discarded when
-+the keys are linked into the keyring.
-+
-+This function is only available during initial kernel set up.
-diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
-index 0fb362a..ed9b203 100644
---- a/include/keys/crypto-type.h
-+++ b/include/keys/crypto-type.h
-@@ -31,4 +31,7 @@ extern void verify_sig_cancel(struct crypto_sig_verify_context *ctx);
- * The payload is at the discretion of the subtype.
- */
-
-+extern __init int preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
-+ struct key *keyring);
-+
- #endif /* _KEYS_CRYPTO_TYPE_H */
-diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
-index 1c2ae55..8af0155 100644
---- a/security/keys/crypto/Kconfig
-+++ b/security/keys/crypto/Kconfig
-@@ -40,3 +40,12 @@ config CRYPTO_KEY_PGP_PARSER
- This option provides support for parsing PGP (RFC 4880) format blobs
- for key data and provides the ability to instantiate a crypto key
- from a public key packet found inside the blob.
-+
-+config PGP_PRELOAD
-+ bool "PGP public key preloading facility"
-+ select PGP_LIBRARY
-+ select CRYPTO_KEY_PGP_PARSER
-+ help
-+ This option provides a facility for the kernel to preload PGP-wrapped
-+ bundles of keys during boot. It is used by module signing to load
-+ the module signing keys for example.
-diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
-index a9a34c6..c873674 100644
---- a/security/keys/crypto/Makefile
-+++ b/security/keys/crypto/Makefile
-@@ -8,6 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o
- obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
- obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
- obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
-+obj-$(CONFIG_PGP_PRELOAD) += pgp_preload.o
-
- obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
- pgp_key_parser-y := \
-diff --git a/security/keys/crypto/pgp_preload.c b/security/keys/crypto/pgp_preload.c
-new file mode 100644
-index 0000000..ca4cfe6
---- /dev/null
-+++ b/security/keys/crypto/pgp_preload.c
-@@ -0,0 +1,115 @@
-+/* Cryptographic key request handling
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ *
-+ * See Documentation/security/keys-crypto.txt
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/key.h>
-+#include <linux/pgplib.h>
-+#include <linux/err.h>
-+#include <keys/crypto-type.h>
-+#include "crypto_keys.h"
-+
-+struct preload_pgp_keys_context {
-+ struct pgp_parse_context pgp;
-+ key_ref_t keyring;
-+ const u8 *key_start;
-+ const u8 *key_end;
-+ bool found_key;
-+};
-+
-+/*
-+ * Create a key.
-+ */
-+static int __init create_pgp_key(struct preload_pgp_keys_context *ctx)
-+{
-+ key_ref_t key;
-+
-+ key = key_create_or_update(ctx->keyring, "crypto", NULL,
-+ ctx->key_start,
-+ ctx->key_end - ctx->key_start,
-+ KEY_POS_ALL | KEY_USR_VIEW,
-+ KEY_ALLOC_NOT_IN_QUOTA);
-+ if (IS_ERR(key))
-+ return PTR_ERR(key);
-+
-+ pr_notice("Loaded %s key: %s\n",
-+ key_ref_to_ptr(key)->description,
-+ crypto_key_id(key_ref_to_ptr(key)));
-+
-+ key_ref_put(key);
-+ return 0;
-+}
-+
-+/*
-+ * Extract a public key or subkey from the PGP stream.
-+ */
-+static int __init found_pgp_key(struct pgp_parse_context *context,
-+ enum pgp_packet_tag type, u8 headerlen,
-+ const u8 *data, size_t datalen)
-+{
-+ struct preload_pgp_keys_context *ctx =
-+ container_of(context, struct preload_pgp_keys_context, pgp);
-+ int ret;
-+
-+ if (ctx->found_key) {
-+ ctx->key_end = data - headerlen;
-+ ret = create_pgp_key(ctx);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
-+ ctx->key_start = data - headerlen;
-+ ctx->found_key = true;
-+ return 0;
-+}
-+
-+/**
-+ * preload_pgp_keys - Load keys from a PGP keyring blob
-+ * @pgpdata: The PGP keyring blob containing the keys.
-+ * @pgpdatalen: The size of the @pgpdata blob.
-+ * @keyring: The keyring to add the new keys to.
-+ *
-+ * Preload a pack of keys from a PGP keyring blob.
-+ *
-+ * The keys have their descriptions generated from the user ID and fingerprint
-+ * in the PGP stream. Since keys can be matched on their key IDs independently
-+ * of the key description, the description is mostly irrelevant apart from the
-+ * fact that keys of the same description displace one another from a keyring.
-+ *
-+ * The caller should override the current creds if they want the keys to be
-+ * owned by someone other than the current process's owner. Keys will not be
-+ * accounted towards the owner's quota.
-+ *
-+ * This function may only be called whilst the kernel is booting.
-+ */
-+int __init preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
-+ struct key *keyring)
-+{
-+ struct preload_pgp_keys_context ctx;
-+ int ret;
-+
-+ ctx.pgp.types_of_interest =
-+ (1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
-+ ctx.pgp.process_packet = found_pgp_key;
-+ ctx.keyring = make_key_ref(keyring, 1);
-+ ctx.found_key = false;
-+
-+ ret = pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ctx.found_key) {
-+ ctx.key_end = pgpdata + pgpdatalen;
-+ return create_pgp_key(&ctx);
-+ }
-+ return 0;
-+}
---
-1.7.11.4
-
-
-From d569964b0037289f291f5ac48df54a6b90b3435a Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:33:48 +0100
-Subject: [PATCH 17/32] Make most arch asm/module.h files use
- asm-generic/module.h
-
-Use the mapping of Elf_[SPE]hdr, Elf_Addr, Elf_Sym, Elf_Dyn, Elf_Rel/Rela,
-ELF_R_TYPE() and ELF_R_SYM() to either the 32-bit version or the 64-bit version
-into asm-generic/module.h for all arches bar MIPS.
-
-Also, use the generic definition mod_arch_specific where possible.
-
-To this end, I've defined three new config bools:
-
- (*) HAVE_MOD_ARCH_SPECIFIC
-
- Arches define this if they don't want to use the empty generic
- mod_arch_specific struct.
-
- (*) MODULES_USE_ELF_RELA
-
- Arches define this if their modules can contain RELA records. This causes
- the Elf_Rela mapping to be emitted and allows apply_relocate_add() to be
- defined by the arch rather than have the core emit an error message.
-
- (*) MODULES_USE_ELF_REL
-
- Arches define this if their modules can contain REL records. This causes
- the Elf_Rel mapping to be emitted and allows apply_relocate() to be
- defined by the arch rather than have the core emit an error message.
-
-Note that it is possible to allow both REL and RELA records: m68k and mips are
-two arches that do this.
-
-With this, some arch asm/module.h files can be deleted entirely and replaced
-with a generic-y marker in the arch Kbuild file.
-
-Additionally, I have removed the bits from m32r and score that handle the
-unsupported type of relocation record as that's now handled centrally.
-
-Thanks to Jonas Gorski <jonas.gorski@gmail.com> for some MIPS fixes.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Acked-by: Sam Ravnborg <sam@ravnborg.org>
----
- arch/Kconfig | 19 ++++++++++++++++++
- arch/alpha/Kconfig | 2 ++
- arch/alpha/include/asm/module.h | 10 ++--------
- arch/arm/Kconfig | 2 ++
- arch/arm/include/asm/module.h | 8 ++------
- arch/avr32/Kconfig | 2 ++
- arch/avr32/include/asm/module.h | 6 ++----
- arch/blackfin/Kconfig | 2 ++
- arch/blackfin/include/asm/module.h | 4 +---
- arch/c6x/Kconfig | 1 +
- arch/c6x/include/asm/module.h | 12 +-----------
- arch/cris/Kconfig | 1 +
- arch/cris/include/asm/Kbuild | 2 ++
- arch/cris/include/asm/module.h | 9 ---------
- arch/frv/include/asm/module.h | 8 +-------
- arch/h8300/Kconfig | 1 +
- arch/h8300/include/asm/Kbuild | 2 ++
- arch/h8300/include/asm/module.h | 11 -----------
- arch/hexagon/Kconfig | 1 +
- arch/ia64/Kconfig | 2 ++
- arch/ia64/include/asm/module.h | 6 ++----
- arch/m32r/Kconfig | 1 +
- arch/m32r/include/asm/Kbuild | 2 ++
- arch/m32r/include/asm/module.h | 10 ----------
- arch/m32r/kernel/module.c | 15 --------------
- arch/m68k/Kconfig | 3 +++
- arch/m68k/include/asm/module.h | 6 ++----
- arch/microblaze/Kconfig | 1 +
- arch/mips/Kconfig | 3 +++
- arch/mips/include/asm/module.h | 10 ++++++++--
- arch/mips/kernel/module.c | 2 ++
- arch/mn10300/Kconfig | 1 +
- arch/mn10300/include/asm/module.h | 7 +------
- arch/openrisc/Kconfig | 1 +
- arch/parisc/Kconfig | 2 ++
- arch/parisc/include/asm/module.h | 16 +++------------
- arch/powerpc/Kconfig | 2 ++
- arch/powerpc/include/asm/module.h | 7 +------
- arch/s390/Kconfig | 2 ++
- arch/s390/include/asm/module.h | 18 +++--------------
- arch/score/Kconfig | 2 ++
- arch/score/include/asm/module.h | 6 +-----
- arch/score/kernel/module.c | 10 ----------
- arch/sh/Kconfig | 2 ++
- arch/sh/include/asm/module.h | 14 +++----------
- arch/sparc/Kconfig | 1 +
- arch/sparc/include/asm/Kbuild | 1 +
- arch/sparc/include/asm/module.h | 24 -----------------------
- arch/tile/Kconfig | 1 +
- arch/unicore32/Kconfig | 1 +
- arch/x86/Kconfig | 2 ++
- arch/x86/um/Kconfig | 2 ++
- arch/xtensa/Kconfig | 1 +
- arch/xtensa/include/asm/module.h | 9 +--------
- include/asm-generic/module.h | 40 +++++++++++++++++++++++++++++++-------
- include/linux/moduleloader.h | 36 ++++++++++++++++++++++++++++++----
- kernel/module.c | 20 -------------------
- 57 files changed, 169 insertions(+), 223 deletions(-)
- delete mode 100644 arch/cris/include/asm/module.h
- delete mode 100644 arch/h8300/include/asm/module.h
- delete mode 100644 arch/m32r/include/asm/module.h
- delete mode 100644 arch/sparc/include/asm/module.h
-
-diff --git a/arch/Kconfig b/arch/Kconfig
-index 72f2fa1..3450115 100644
---- a/arch/Kconfig
-+++ b/arch/Kconfig
-@@ -281,4 +281,23 @@ config SECCOMP_FILTER
-
- See Documentation/prctl/seccomp_filter.txt for details.
-
-+config HAVE_MOD_ARCH_SPECIFIC
-+ bool
-+ help
-+ The arch uses struct mod_arch_specific to store data. Many arches
-+ just need a simple module loader without arch specific data - those
-+ should not enable this.
-+
-+config MODULES_USE_ELF_RELA
-+ bool
-+ help
-+ Modules only use ELF RELA relocations. Modules with ELF REL
-+ relocations will give an error.
-+
-+config MODULES_USE_ELF_REL
-+ bool
-+ help
-+ Modules only use ELF REL relocations. Modules with ELF RELA
-+ relocations will give an error.
-+
- source "kernel/gcov/Kconfig"
-diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
-index 9944ded..7e3710c 100644
---- a/arch/alpha/Kconfig
-+++ b/arch/alpha/Kconfig
-@@ -20,6 +20,8 @@ config ALPHA
- select GENERIC_CMOS_UPDATE
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
- help
- The Alpha is a 64-bit general-purpose processor designed and
- marketed by the Digital Equipment Corporation of blessed memory,
-diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h
-index 7b63743..9cd13b5 100644
---- a/arch/alpha/include/asm/module.h
-+++ b/arch/alpha/include/asm/module.h
-@@ -1,19 +1,13 @@
- #ifndef _ALPHA_MODULE_H
- #define _ALPHA_MODULE_H
-
-+#include <asm-generic/module.h>
-+
- struct mod_arch_specific
- {
- unsigned int gotsecindex;
- };
-
--#define Elf_Sym Elf64_Sym
--#define Elf_Shdr Elf64_Shdr
--#define Elf_Ehdr Elf64_Ehdr
--#define Elf_Phdr Elf64_Phdr
--#define Elf_Dyn Elf64_Dyn
--#define Elf_Rel Elf64_Rel
--#define Elf_Rela Elf64_Rela
--
- #define ARCH_SHF_SMALL SHF_ALPHA_GPREL
-
- #ifdef MODULE
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index e91c7cd..c75c217 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -50,6 +50,8 @@ config ARM
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
- select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
-+ select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
-+ select MODULES_USE_ELF_REL
- help
- The ARM series is a line of low-power-consumption RISC chip designs
- licensed by ARM Ltd and targeted at embedded applications and
-diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
-index 6c6809f..0d3a28d 100644
---- a/arch/arm/include/asm/module.h
-+++ b/arch/arm/include/asm/module.h
-@@ -1,9 +1,7 @@
- #ifndef _ASM_ARM_MODULE_H
- #define _ASM_ARM_MODULE_H
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#include <asm-generic/module.h>
-
- struct unwind_table;
-
-@@ -16,13 +14,11 @@ enum {
- ARM_SEC_DEVEXIT,
- ARM_SEC_MAX,
- };
--#endif
-
- struct mod_arch_specific {
--#ifdef CONFIG_ARM_UNWIND
- struct unwind_table *unwind[ARM_SEC_MAX];
--#endif
- };
-+#endif
-
- /*
- * Add the ARM architecture version to the version magic string
-diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
-index 5ade51c..06e73bf 100644
---- a/arch/avr32/Kconfig
-+++ b/arch/avr32/Kconfig
-@@ -15,6 +15,8 @@ config AVR32
- select ARCH_WANT_IPC_PARSE_VERSION
- select ARCH_HAVE_NMI_SAFE_CMPXCHG
- select GENERIC_CLOCKEVENTS
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
- help
- AVR32 is a high-performance 32-bit RISC microprocessor core,
- designed for cost-sensitive embedded applications, with particular
-diff --git a/arch/avr32/include/asm/module.h b/arch/avr32/include/asm/module.h
-index 4514445..3f083d3 100644
---- a/arch/avr32/include/asm/module.h
-+++ b/arch/avr32/include/asm/module.h
-@@ -1,6 +1,8 @@
- #ifndef __ASM_AVR32_MODULE_H
- #define __ASM_AVR32_MODULE_H
-
-+#include <asm-generic/module.h>
-+
- struct mod_arch_syminfo {
- unsigned long got_offset;
- int got_initialized;
-@@ -17,10 +19,6 @@ struct mod_arch_specific {
- struct mod_arch_syminfo *syminfo;
- };
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--
- #define MODULE_PROC_FAMILY "AVR32v1"
-
- #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
-diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
-index f348619..a48d8be 100644
---- a/arch/blackfin/Kconfig
-+++ b/arch/blackfin/Kconfig
-@@ -41,6 +41,8 @@ config BLACKFIN
- select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
- select GENERIC_SMP_IDLE_THREAD
- select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
-
- config GENERIC_CSUM
- def_bool y
-diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h
-index ed5689b..231a149 100644
---- a/arch/blackfin/include/asm/module.h
-+++ b/arch/blackfin/include/asm/module.h
-@@ -7,9 +7,7 @@
- #ifndef _ASM_BFIN_MODULE_H
- #define _ASM_BFIN_MODULE_H
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#include <asm-generic/module.h>
-
- struct mod_arch_specific {
- Elf_Shdr *text_l1;
-diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
-index 052f81a..8f3a304 100644
---- a/arch/c6x/Kconfig
-+++ b/arch/c6x/Kconfig
-@@ -16,6 +16,7 @@ config C6X
- select OF
- select OF_EARLY_FLATTREE
- select GENERIC_CLOCKEVENTS
-+ select MODULES_USE_ELF_RELA
-
- config MMU
- def_bool n
-diff --git a/arch/c6x/include/asm/module.h b/arch/c6x/include/asm/module.h
-index a453f97..5c7269c 100644
---- a/arch/c6x/include/asm/module.h
-+++ b/arch/c6x/include/asm/module.h
-@@ -13,17 +13,7 @@
- #ifndef _ASM_C6X_MODULE_H
- #define _ASM_C6X_MODULE_H
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--#define Elf_Addr Elf32_Addr
--#define Elf_Word Elf32_Word
--
--/*
-- * This file contains the C6x architecture specific module code.
-- */
--struct mod_arch_specific {
--};
-+#include <asm-generic/module.h>
-
- struct loaded_sections {
- unsigned int new_vaddr;
-diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
-index e922154..7bb8cf9 100644
---- a/arch/cris/Kconfig
-+++ b/arch/cris/Kconfig
-@@ -47,6 +47,7 @@ config CRIS
- select GENERIC_IOMAP
- select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
- select GENERIC_CMOS_UPDATE
-+ select MODULES_USE_ELF_RELA
-
- config HZ
- int
-diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
-index 04d02a5..28b690d 100644
---- a/arch/cris/include/asm/Kbuild
-+++ b/arch/cris/include/asm/Kbuild
-@@ -7,3 +7,5 @@ header-y += ethernet.h
- header-y += etraxgpio.h
- header-y += rs485.h
- header-y += sync_serial.h
-+
-+generic-y += module.h
-diff --git a/arch/cris/include/asm/module.h b/arch/cris/include/asm/module.h
-deleted file mode 100644
-index 7ee7231..0000000
---- a/arch/cris/include/asm/module.h
-+++ /dev/null
-@@ -1,9 +0,0 @@
--#ifndef _ASM_CRIS_MODULE_H
--#define _ASM_CRIS_MODULE_H
--/* cris is simple */
--struct mod_arch_specific { };
--
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--#endif /* _ASM_CRIS_MODULE_H */
-diff --git a/arch/frv/include/asm/module.h b/arch/frv/include/asm/module.h
-index 3d5c636..a8848f0 100644
---- a/arch/frv/include/asm/module.h
-+++ b/arch/frv/include/asm/module.h
-@@ -11,13 +11,7 @@
- #ifndef _ASM_MODULE_H
- #define _ASM_MODULE_H
-
--struct mod_arch_specific
--{
--};
--
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#include <asm-generic/module.h>
-
- /*
- * Include the architecture version.
-diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
-index 5e8a0d9..c149d3b29 100644
---- a/arch/h8300/Kconfig
-+++ b/arch/h8300/Kconfig
-@@ -6,6 +6,7 @@ config H8300
- select ARCH_WANT_IPC_PARSE_VERSION
- select GENERIC_IRQ_SHOW
- select GENERIC_CPU_DEVICES
-+ select MODULES_USE_ELF_RELA
-
- config SYMBOL_PREFIX
- string
-diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
-index c68e168..871382d 100644
---- a/arch/h8300/include/asm/Kbuild
-+++ b/arch/h8300/include/asm/Kbuild
-@@ -1 +1,3 @@
- include include/asm-generic/Kbuild.asm
-+
-+generic-y += module.h
-diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h
-deleted file mode 100644
-index 8e46724..0000000
---- a/arch/h8300/include/asm/module.h
-+++ /dev/null
-@@ -1,11 +0,0 @@
--#ifndef _ASM_H8300_MODULE_H
--#define _ASM_H8300_MODULE_H
--/*
-- * This file contains the H8/300 architecture specific module code.
-- */
--struct mod_arch_specific { };
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--
--#endif /* _ASM_H8/300_MODULE_H */
-diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
-index b2fdfb7..0744f7d 100644
---- a/arch/hexagon/Kconfig
-+++ b/arch/hexagon/Kconfig
-@@ -30,6 +30,7 @@ config HEXAGON
- select KTIME_SCALAR
- select GENERIC_CLOCKEVENTS
- select GENERIC_CLOCKEVENTS_BROADCAST
-+ select MODULES_USE_ELF_RELA
- ---help---
- Qualcomm Hexagon is a processor architecture designed for high
- performance and low power across a wide variety of applications.
-diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index 310cf57..6881464 100644
---- a/arch/ia64/Kconfig
-+++ b/arch/ia64/Kconfig
-@@ -39,6 +39,8 @@ config IA64
- select ARCH_THREAD_INFO_ALLOCATOR
- select ARCH_CLOCKSOURCE_DATA
- select GENERIC_TIME_VSYSCALL
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
- default y
- help
- The Itanium Processor Family is Intel's 64-bit successor to
-diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h
-index 908eaef..dfba22a 100644
---- a/arch/ia64/include/asm/module.h
-+++ b/arch/ia64/include/asm/module.h
-@@ -1,6 +1,8 @@
- #ifndef _ASM_IA64_MODULE_H
- #define _ASM_IA64_MODULE_H
-
-+#include <asm-generic/module.h>
-+
- /*
- * IA-64-specific support for kernel module loader.
- *
-@@ -29,10 +31,6 @@ struct mod_arch_specific {
- unsigned int next_got_entry; /* index of next available got entry */
- };
-
--#define Elf_Shdr Elf64_Shdr
--#define Elf_Sym Elf64_Sym
--#define Elf_Ehdr Elf64_Ehdr
--
- #define MODULE_PROC_FAMILY "ia64"
- #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \
- "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
-diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
-index 49498bb..fc61533 100644
---- a/arch/m32r/Kconfig
-+++ b/arch/m32r/Kconfig
-@@ -13,6 +13,7 @@ config M32R
- select GENERIC_IRQ_SHOW
- select GENERIC_ATOMIC64
- select ARCH_USES_GETTIMEOFFSET
-+ select MODULES_USE_ELF_RELA
-
- config SBUS
- bool
-diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
-index c68e168..871382d 100644
---- a/arch/m32r/include/asm/Kbuild
-+++ b/arch/m32r/include/asm/Kbuild
-@@ -1 +1,3 @@
- include include/asm-generic/Kbuild.asm
-+
-+generic-y += module.h
-diff --git a/arch/m32r/include/asm/module.h b/arch/m32r/include/asm/module.h
-deleted file mode 100644
-index eb73ee0..0000000
---- a/arch/m32r/include/asm/module.h
-+++ /dev/null
-@@ -1,10 +0,0 @@
--#ifndef _ASM_M32R_MODULE_H
--#define _ASM_M32R_MODULE_H
--
--struct mod_arch_specific { };
--
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--
--#endif /* _ASM_M32R_MODULE_H */
-diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
-index 3071fe8..38233b6 100644
---- a/arch/m32r/kernel/module.c
-+++ b/arch/m32r/kernel/module.c
-@@ -201,18 +201,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
- }
- return 0;
- }
--
--int apply_relocate(Elf32_Shdr *sechdrs,
-- const char *strtab,
-- unsigned int symindex,
-- unsigned int relsec,
-- struct module *me)
--{
--#if 0
-- printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
-- me->name);
-- return -ENOEXEC;
--#endif
-- return 0;
--
--}
-diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
-index 4a46990..714a850 100644
---- a/arch/m68k/Kconfig
-+++ b/arch/m68k/Kconfig
-@@ -12,6 +12,9 @@ config M68K
- select FPU if MMU
- select ARCH_WANT_IPC_PARSE_VERSION
- select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_REL
-+ select MODULES_USE_ELF_RELA
-
- config RWSEM_GENERIC_SPINLOCK
- bool
-diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
-index edffe66..8b58fce 100644
---- a/arch/m68k/include/asm/module.h
-+++ b/arch/m68k/include/asm/module.h
-@@ -1,6 +1,8 @@
- #ifndef _ASM_M68K_MODULE_H
- #define _ASM_M68K_MODULE_H
-
-+#include <asm-generic/module.h>
-+
- enum m68k_fixup_type {
- m68k_fixup_memoffset,
- m68k_fixup_vnode_shift,
-@@ -36,8 +38,4 @@ struct module;
- extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
- struct m68k_fixup_info *end);
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--
- #endif /* _ASM_M68K_MODULE_H */
-diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
-index ab9afca..b4f409f 100644
---- a/arch/microblaze/Kconfig
-+++ b/arch/microblaze/Kconfig
-@@ -24,6 +24,7 @@ config MICROBLAZE
- select GENERIC_CPU_DEVICES
- select GENERIC_ATOMIC64
- select GENERIC_CLOCKEVENTS
-+ select MODULES_USE_ELF_RELA
-
- config SWAP
- def_bool n
-diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
-index 331d574..5ff52db 100644
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -36,6 +36,9 @@ config MIPS
- select BUILDTIME_EXTABLE_SORT
- select GENERIC_CLOCKEVENTS
- select GENERIC_CMOS_UPDATE
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_REL
-+ select MODULES_USE_ELF_RELA if 64BIT
-
- menu "Machine selection"
-
-diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
-index 7531ecd..c93b62b 100644
---- a/arch/mips/include/asm/module.h
-+++ b/arch/mips/include/asm/module.h
-@@ -34,11 +34,14 @@ typedef struct {
- } Elf64_Mips_Rela;
-
- #ifdef CONFIG_32BIT
--
- #define Elf_Shdr Elf32_Shdr
- #define Elf_Sym Elf32_Sym
- #define Elf_Ehdr Elf32_Ehdr
- #define Elf_Addr Elf32_Addr
-+#define Elf_Rel Elf32_Rel
-+#define Elf_Rela Elf32_Rela
-+#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
-+#define ELF_R_SYM(X) ELF32_R_SYM(X)
-
- #define Elf_Mips_Rel Elf32_Rel
- #define Elf_Mips_Rela Elf32_Rela
-@@ -49,11 +52,14 @@ typedef struct {
- #endif
-
- #ifdef CONFIG_64BIT
--
- #define Elf_Shdr Elf64_Shdr
- #define Elf_Sym Elf64_Sym
- #define Elf_Ehdr Elf64_Ehdr
- #define Elf_Addr Elf64_Addr
-+#define Elf_Rel Elf64_Rel
-+#define Elf_Rela Elf64_Rela
-+#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
-+#define ELF_R_SYM(X) ELF64_R_SYM(X)
-
- #define Elf_Mips_Rel Elf64_Mips_Rel
- #define Elf_Mips_Rela Elf64_Mips_Rela
-diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
-index 4f8c3cb..9f102cf 100644
---- a/arch/mips/kernel/module.c
-+++ b/arch/mips/kernel/module.c
-@@ -324,6 +324,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
- return 0;
- }
-
-+#ifdef CONFIG_MODULES_USE_ELF_RELA
- int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec,
- struct module *me)
-@@ -363,6 +364,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-
- return 0;
- }
-+#endif
-
- /* Given an address, look for it in the module exception tables. */
- const struct exception_table_entry *search_module_dbetables(unsigned long addr)
-diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
-index 5cfb086..aa03f2e 100644
---- a/arch/mn10300/Kconfig
-+++ b/arch/mn10300/Kconfig
-@@ -8,6 +8,7 @@ config MN10300
- select HAVE_ARCH_KGDB
- select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
- select GENERIC_CLOCKEVENTS
-+ select MODULES_USE_ELF_RELA
-
- config AM33_2
- def_bool n
-diff --git a/arch/mn10300/include/asm/module.h b/arch/mn10300/include/asm/module.h
-index 5d7057d..6571103 100644
---- a/arch/mn10300/include/asm/module.h
-+++ b/arch/mn10300/include/asm/module.h
-@@ -12,12 +12,7 @@
- #ifndef _ASM_MODULE_H
- #define _ASM_MODULE_H
-
--struct mod_arch_specific {
--};
--
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#include <asm-generic/module.h>
-
- /*
- * Include the MN10300 architecture version.
-diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
-index 49765b5..05f2ba4 100644
---- a/arch/openrisc/Kconfig
-+++ b/arch/openrisc/Kconfig
-@@ -21,6 +21,7 @@ config OPENRISC
- select GENERIC_CLOCKEVENTS
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select MODULES_USE_ELF_RELA
-
- config MMU
- def_bool y
-diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
-index 3ff21b5..166d991 100644
---- a/arch/parisc/Kconfig
-+++ b/arch/parisc/Kconfig
-@@ -19,6 +19,8 @@ config PARISC
- select ARCH_HAVE_NMI_SAFE_CMPXCHG
- select GENERIC_SMP_IDLE_THREAD
- select GENERIC_STRNCPY_FROM_USER
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
-
- help
- The PA-RISC microprocessor is designed by Hewlett-Packard and used
-diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h
-index 1f41234..bab37e9 100644
---- a/arch/parisc/include/asm/module.h
-+++ b/arch/parisc/include/asm/module.h
-@@ -1,21 +1,11 @@
- #ifndef _ASM_PARISC_MODULE_H
- #define _ASM_PARISC_MODULE_H
-+
-+#include <asm-generic/module.h>
-+
- /*
- * This file contains the parisc architecture specific module code.
- */
--#ifdef CONFIG_64BIT
--#define Elf_Shdr Elf64_Shdr
--#define Elf_Sym Elf64_Sym
--#define Elf_Ehdr Elf64_Ehdr
--#define Elf_Addr Elf64_Addr
--#define Elf_Rela Elf64_Rela
--#else
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--#define Elf_Addr Elf32_Addr
--#define Elf_Rela Elf32_Rela
--#endif
-
- struct unwind_table;
-
-diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 352f416..74f8478 100644
---- a/arch/powerpc/Kconfig
-+++ b/arch/powerpc/Kconfig
-@@ -139,6 +139,8 @@ config PPC
- select GENERIC_CLOCKEVENTS
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
-
- config EARLY_PRINTK
- bool
-diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
-index 0192a4e..c1df590 100644
---- a/arch/powerpc/include/asm/module.h
-+++ b/arch/powerpc/include/asm/module.h
-@@ -11,6 +11,7 @@
-
- #include <linux/list.h>
- #include <asm/bug.h>
-+#include <asm-generic/module.h>
-
-
- #ifndef __powerpc64__
-@@ -60,16 +61,10 @@ struct mod_arch_specific {
- */
-
- #ifdef __powerpc64__
--# define Elf_Shdr Elf64_Shdr
--# define Elf_Sym Elf64_Sym
--# define Elf_Ehdr Elf64_Ehdr
- # ifdef MODULE
- asm(".section .stubs,\"ax\",@nobits; .align 3; .previous");
- # endif
- #else
--# define Elf_Shdr Elf32_Shdr
--# define Elf_Sym Elf32_Sym
--# define Elf_Ehdr Elf32_Ehdr
- # ifdef MODULE
- asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
- asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
-diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 107610e..c76a052 100644
---- a/arch/s390/Kconfig
-+++ b/arch/s390/Kconfig
-@@ -125,6 +125,8 @@ config S390
- select GENERIC_CLOCKEVENTS
- select KTIME_SCALAR if 32BIT
- select HAVE_ARCH_SECCOMP_FILTER
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_RELA
-
- config SCHED_OMIT_FRAME_POINTER
- def_bool y
-diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h
-index f0b6b26..df1f861 100644
---- a/arch/s390/include/asm/module.h
-+++ b/arch/s390/include/asm/module.h
-@@ -1,5 +1,8 @@
- #ifndef _ASM_S390_MODULE_H
- #define _ASM_S390_MODULE_H
-+
-+#include <asm-generic/module.h>
-+
- /*
- * This file contains the s390 architecture specific module code.
- */
-@@ -28,19 +31,4 @@ struct mod_arch_specific
- struct mod_arch_syminfo *syminfo;
- };
-
--#ifdef CONFIG_64BIT
--#define ElfW(x) Elf64_ ## x
--#define ELFW(x) ELF64_ ## x
--#else
--#define ElfW(x) Elf32_ ## x
--#define ELFW(x) ELF32_ ## x
--#endif
--
--#define Elf_Addr ElfW(Addr)
--#define Elf_Rela ElfW(Rela)
--#define Elf_Shdr ElfW(Shdr)
--#define Elf_Sym ElfW(Sym)
--#define Elf_Ehdr ElfW(Ehdr)
--#define ELF_R_SYM ELFW(R_SYM)
--#define ELF_R_TYPE ELFW(R_TYPE)
- #endif /* _ASM_S390_MODULE_H */
-diff --git a/arch/score/Kconfig b/arch/score/Kconfig
-index ba0f412..e2c8db4 100644
---- a/arch/score/Kconfig
-+++ b/arch/score/Kconfig
-@@ -10,6 +10,8 @@ config SCORE
- select ARCH_DISCARD_MEMBLOCK
- select GENERIC_CPU_DEVICES
- select GENERIC_CLOCKEVENTS
-+ select HAVE_MOD_ARCH_SPECIFIC
-+ select MODULES_USE_ELF_REL
-
- choice
- prompt "System type"
-diff --git a/arch/score/include/asm/module.h b/arch/score/include/asm/module.h
-index f0b5dc0..abf395b 100644
---- a/arch/score/include/asm/module.h
-+++ b/arch/score/include/asm/module.h
-@@ -3,6 +3,7 @@
-
- #include <linux/list.h>
- #include <asm/uaccess.h>
-+#include <asm-generic/module.h>
-
- struct mod_arch_specific {
- /* Data Bus Error exception tables */
-@@ -13,11 +14,6 @@ struct mod_arch_specific {
-
- typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
--#define Elf_Addr Elf32_Addr
--
- /* Given an address, look for it in the exception tables. */
- #ifdef CONFIG_MODULES
- const struct exception_table_entry *search_module_dbetables(unsigned long addr);
-diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c
-index 469e3b6..1378d99 100644
---- a/arch/score/kernel/module.c
-+++ b/arch/score/kernel/module.c
-@@ -125,16 +125,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
- return 0;
- }
-
--int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-- unsigned int symindex, unsigned int relsec,
-- struct module *me)
--{
-- /* Non-standard return value... most other arch's return -ENOEXEC
-- * for an unsupported relocation variant
-- */
-- return 0;
--}
--
- /* Given an address, look for it in the module exception tables. */
- const struct exception_table_entry *search_module_dbetables(unsigned long addr)
- {
-diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
-index 36f5141..656329a 100644
---- a/arch/sh/Kconfig
-+++ b/arch/sh/Kconfig
-@@ -35,6 +35,8 @@ config SUPERH
- select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
-+ select MODULES_USE_ELF_RELA
- help
- The SuperH is a RISC processor targeted for use in embedded systems
- and consumer electronics; it was also used in the Sega Dreamcast
-diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h
-index b7927de..81300d8b 100644
---- a/arch/sh/include/asm/module.h
-+++ b/arch/sh/include/asm/module.h
-@@ -1,21 +1,13 @@
- #ifndef _ASM_SH_MODULE_H
- #define _ASM_SH_MODULE_H
-
--struct mod_arch_specific {
-+#include <asm-generic/module.h>
-+
- #ifdef CONFIG_DWARF_UNWINDER
-+struct mod_arch_specific {
- struct list_head fde_list;
- struct list_head cie_list;
--#endif
- };
--
--#ifdef CONFIG_64BIT
--#define Elf_Shdr Elf64_Shdr
--#define Elf_Sym Elf64_Sym
--#define Elf_Ehdr Elf64_Ehdr
--#else
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
- #endif
-
- #ifdef CONFIG_CPU_LITTLE_ENDIAN
-diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
-index 67f1f6f..a244e70 100644
---- a/arch/sparc/Kconfig
-+++ b/arch/sparc/Kconfig
-@@ -37,6 +37,7 @@ config SPARC
- select GENERIC_CLOCKEVENTS
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select MODULES_USE_ELF_RELA
-
- config SPARC32
- def_bool !64BIT
-diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
-index 67f83e0..fbe1cb5 100644
---- a/arch/sparc/include/asm/Kbuild
-+++ b/arch/sparc/include/asm/Kbuild
-@@ -21,4 +21,5 @@ generic-y += div64.h
- generic-y += local64.h
- generic-y += irq_regs.h
- generic-y += local.h
-+generic-y += module.h
- generic-y += word-at-a-time.h
-diff --git a/arch/sparc/include/asm/module.h b/arch/sparc/include/asm/module.h
-deleted file mode 100644
-index ff8e02d..0000000
---- a/arch/sparc/include/asm/module.h
-+++ /dev/null
-@@ -1,24 +0,0 @@
--#ifndef __SPARC_MODULE_H
--#define __SPARC_MODULE_H
--struct mod_arch_specific { };
--
--/*
-- * Use some preprocessor magic to define the correct symbol
-- * for sparc32 and sparc64.
-- * Elf_Addr becomes Elf32_Addr for sparc32 and Elf64_Addr for sparc64
-- */
--#define ___ELF(a, b, c) a##b##c
--#define __ELF(a, b, c) ___ELF(a, b, c)
--#define _Elf(t) __ELF(Elf, CONFIG_BITS, t)
--#define _ELF(t) __ELF(ELF, CONFIG_BITS, t)
--
--#define Elf_Shdr _Elf(_Shdr)
--#define Elf_Sym _Elf(_Sym)
--#define Elf_Ehdr _Elf(_Ehdr)
--#define Elf_Rela _Elf(_Rela)
--#define Elf_Addr _Elf(_Addr)
--
--#define ELF_R_SYM _ELF(_R_SYM)
--#define ELF_R_TYPE _ELF(_R_TYPE)
--
--#endif /* __SPARC_MODULE_H */
-diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
-index 932e443..1603f30 100644
---- a/arch/tile/Kconfig
-+++ b/arch/tile/Kconfig
-@@ -17,6 +17,7 @@ config TILE
- select SYS_HYPERVISOR
- select ARCH_HAVE_NMI_SAFE_CMPXCHG
- select GENERIC_CLOCKEVENTS
-+ select MODULES_USE_ELF_RELA
-
- # FIXME: investigate whether we need/want these options.
- # select HAVE_IOREMAP_PROT
-diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
-index b0a4743..5ef0814 100644
---- a/arch/unicore32/Kconfig
-+++ b/arch/unicore32/Kconfig
-@@ -14,6 +14,7 @@ config UNICORE32
- select GENERIC_IRQ_SHOW
- select ARCH_WANT_FRAME_POINTERS
- select GENERIC_IOMAP
-+ select MODULES_USE_ELF_REL
- help
- UniCore-32 is 32-bit Instruction Set Architecture,
- including a series of low-power-consumption RISC chip
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 8ec3a1a..01726cb 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -97,6 +97,8 @@ config X86
- select KTIME_SCALAR if X86_32
- select GENERIC_STRNCPY_FROM_USER
- select GENERIC_STRNLEN_USER
-+ select MODULES_USE_ELF_REL if X86_32
-+ select MODULES_USE_ELF_RELA if X86_64
-
- config INSTRUCTION_DECODER
- def_bool (KPROBES || PERF_EVENTS || UPROBES)
-diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
-index 9926e11..a4b0c10 100644
---- a/arch/x86/um/Kconfig
-+++ b/arch/x86/um/Kconfig
-@@ -21,9 +21,11 @@ config 64BIT
- config X86_32
- def_bool !64BIT
- select HAVE_AOUT
-+ select MODULES_USE_ELF_REL
-
- config X86_64
- def_bool 64BIT
-+ select MODULES_USE_ELF_RELA
-
- config RWSEM_XCHGADD_ALGORITHM
- def_bool X86_XADD && 64BIT
-diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
-index 8ed64cf..4816e44 100644
---- a/arch/xtensa/Kconfig
-+++ b/arch/xtensa/Kconfig
-@@ -11,6 +11,7 @@ config XTENSA
- select HAVE_GENERIC_HARDIRQS
- select GENERIC_IRQ_SHOW
- select GENERIC_CPU_DEVICES
-+ select MODULES_USE_ELF_RELA
- help
- Xtensa processors are 32-bit RISC machines designed by Tensilica
- primarily for embedded systems. These processors are both
-diff --git a/arch/xtensa/include/asm/module.h b/arch/xtensa/include/asm/module.h
-index d9b34be..488b40c 100644
---- a/arch/xtensa/include/asm/module.h
-+++ b/arch/xtensa/include/asm/module.h
-@@ -13,15 +13,8 @@
- #ifndef _XTENSA_MODULE_H
- #define _XTENSA_MODULE_H
-
--struct mod_arch_specific
--{
-- /* No special elements, yet. */
--};
--
- #define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " "
-
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#include <asm-generic/module.h>
-
- #endif /* _XTENSA_MODULE_H */
-diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h
-index ed5b44d..14dc41d 100644
---- a/include/asm-generic/module.h
-+++ b/include/asm-generic/module.h
-@@ -5,18 +5,44 @@
- * Many architectures just need a simple module
- * loader without arch specific data.
- */
-+#ifndef CONFIG_HAVE_MOD_ARCH_SPECIFIC
- struct mod_arch_specific
- {
- };
-+#endif
-
- #ifdef CONFIG_64BIT
--#define Elf_Shdr Elf64_Shdr
--#define Elf_Sym Elf64_Sym
--#define Elf_Ehdr Elf64_Ehdr
--#else
--#define Elf_Shdr Elf32_Shdr
--#define Elf_Sym Elf32_Sym
--#define Elf_Ehdr Elf32_Ehdr
-+#define Elf_Shdr Elf64_Shdr
-+#define Elf_Phdr Elf64_Phdr
-+#define Elf_Sym Elf64_Sym
-+#define Elf_Dyn Elf64_Dyn
-+#define Elf_Ehdr Elf64_Ehdr
-+#define Elf_Addr Elf64_Addr
-+#ifdef CONFIG_MODULES_USE_ELF_REL
-+#define Elf_Rel Elf64_Rel
-+#endif
-+#ifdef CONFIG_MODULES_USE_ELF_RELA
-+#define Elf_Rela Elf64_Rela
-+#endif
-+#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
-+#define ELF_R_SYM(X) ELF64_R_SYM(X)
-+
-+#else /* CONFIG_64BIT */
-+
-+#define Elf_Shdr Elf32_Shdr
-+#define Elf_Phdr Elf32_Phdr
-+#define Elf_Sym Elf32_Sym
-+#define Elf_Dyn Elf32_Dyn
-+#define Elf_Ehdr Elf32_Ehdr
-+#define Elf_Addr Elf32_Addr
-+#ifdef CONFIG_MODULES_USE_ELF_REL
-+#define Elf_Rel Elf32_Rel
-+#endif
-+#ifdef CONFIG_MODULES_USE_ELF_RELA
-+#define Elf_Rela Elf32_Rela
-+#endif
-+#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
-+#define ELF_R_SYM(X) ELF32_R_SYM(X)
- #endif
-
- #endif /* __ASM_GENERIC_MODULE_H */
-diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
-index b2be02e..560ca53 100644
---- a/include/linux/moduleloader.h
-+++ b/include/linux/moduleloader.h
-@@ -28,21 +28,49 @@ void *module_alloc(unsigned long size);
- /* Free memory returned from module_alloc. */
- void module_free(struct module *mod, void *module_region);
-
--/* Apply the given relocation to the (simplified) ELF. Return -error
-- or 0. */
-+/*
-+ * Apply the given relocation to the (simplified) ELF. Return -error
-+ * or 0.
-+ */
-+#ifdef CONFIG_MODULES_USE_ELF_REL
- int apply_relocate(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *mod);
-+#else
-+static inline int apply_relocate(Elf_Shdr *sechdrs,
-+ const char *strtab,
-+ unsigned int symindex,
-+ unsigned int relsec,
-+ struct module *me)
-+{
-+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
-+ return -ENOEXEC;
-+}
-+#endif
-
--/* Apply the given add relocation to the (simplified) ELF. Return
-- -error or 0 */
-+/*
-+ * Apply the given add relocation to the (simplified) ELF. Return
-+ * -error or 0
-+ */
-+#ifdef CONFIG_MODULES_USE_ELF_RELA
- int apply_relocate_add(Elf_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *mod);
-+#else
-+static inline int apply_relocate_add(Elf_Shdr *sechdrs,
-+ const char *strtab,
-+ unsigned int symindex,
-+ unsigned int relsec,
-+ struct module *me)
-+{
-+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
-+ return -ENOEXEC;
-+}
-+#endif
-
- /* Any final processing of module before access. Return -error or 0. */
- int module_finalize(const Elf_Ehdr *hdr,
-diff --git a/kernel/module.c b/kernel/module.c
-index 4edbd9c..087aeed 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -1949,26 +1949,6 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
- return ret;
- }
-
--int __weak apply_relocate(Elf_Shdr *sechdrs,
-- const char *strtab,
-- unsigned int symindex,
-- unsigned int relsec,
-- struct module *me)
--{
-- pr_err("module %s: REL relocation unsupported\n", me->name);
-- return -ENOEXEC;
--}
--
--int __weak apply_relocate_add(Elf_Shdr *sechdrs,
-- const char *strtab,
-- unsigned int symindex,
-- unsigned int relsec,
-- struct module *me)
--{
-- pr_err("module %s: RELA relocation unsupported\n", me->name);
-- return -ENOEXEC;
--}
--
- static int apply_relocations(struct module *mod, const struct load_info *info)
- {
- unsigned int i;
---
-1.7.11.4
-
-
-From c6cfa3260f1e2961e69a2e3240695954aed24976 Mon Sep 17 00:00:00 2001
-From: Ralf Baechle <ralf@linux-mips.org>
-Date: Thu, 16 Aug 2012 01:38:43 +0100
-Subject: [PATCH 18/32] MIPS: Fix module.c build for 32 bit
-
-Fixes build failure introduced by "Make most arch asm/module.h files use
-asm-generic/module.h" by moving all the RELA processing code to a
-separate file to be used only for RELA processing on 64-bit kernels.
-
- CC arch/mips/kernel/module.o
-arch/mips/kernel/module.c:250:14: error: 'reloc_handlers_rela' defined but not
-used [-Werror=unused-variable]
-cc1: all warnings being treated as errors
-
-make[6]: *** [arch/mips/kernel/module.o] Error 1
-
-Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- arch/mips/kernel/Makefile | 1 +
- arch/mips/kernel/module-rela.c | 144 +++++++++++++++++++++++++++++++++++++++++
- arch/mips/kernel/module.c | 124 +----------------------------------
- arch/mips/kernel/module.h | 12 ++++
- 4 files changed, 159 insertions(+), 122 deletions(-)
- create mode 100644 arch/mips/kernel/module-rela.c
- create mode 100644 arch/mips/kernel/module.h
-
-diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c
-new file mode 100644
-index 0000000..4e784a8
---- /dev/null
-+++ b/arch/mips/kernel/module-rela.c
-@@ -0,0 +1,144 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program 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
-+ *
-+ * Copyright (C) 2001 Rusty Russell.
-+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
-+ * Copyright (C) 2005 Thiemo Seufer
-+ */
-+
-+#include <linux/elf.h>
-+#include <linux/err.h>
-+#include <linux/errno.h>
-+#include <linux/moduleloader.h>
-+#include "module.h"
-+
-+static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
-+{
-+ *location = v;
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
-+{
-+ if (v % 4) {
-+ pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
-+ me->name);
-+ return -ENOEXEC;
-+ }
-+
-+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-+ printk(KERN_ERR
-+ "module %s: relocation overflow\n",
-+ me->name);
-+ return -ENOEXEC;
-+ }
-+
-+ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
-+{
-+ *location = (*location & 0xffff0000) |
-+ ((((long long) v + 0x8000LL) >> 16) & 0xffff);
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
-+{
-+ *location = (*location & 0xffff0000) | (v & 0xffff);
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
-+{
-+ *(Elf_Addr *)location = v;
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_higher_rela(struct module *me, u32 *location,
-+ Elf_Addr v)
-+{
-+ *location = (*location & 0xffff0000) |
-+ ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
-+
-+ return 0;
-+}
-+
-+static int apply_r_mips_highest_rela(struct module *me, u32 *location,
-+ Elf_Addr v)
-+{
-+ *location = (*location & 0xffff0000) |
-+ ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
-+
-+ return 0;
-+}
-+
-+static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
-+ Elf_Addr v) = {
-+ [R_MIPS_NONE] = apply_r_mips_none,
-+ [R_MIPS_32] = apply_r_mips_32_rela,
-+ [R_MIPS_26] = apply_r_mips_26_rela,
-+ [R_MIPS_HI16] = apply_r_mips_hi16_rela,
-+ [R_MIPS_LO16] = apply_r_mips_lo16_rela,
-+ [R_MIPS_64] = apply_r_mips_64_rela,
-+ [R_MIPS_HIGHER] = apply_r_mips_higher_rela,
-+ [R_MIPS_HIGHEST] = apply_r_mips_highest_rela
-+};
-+
-+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-+ unsigned int symindex, unsigned int relsec,
-+ struct module *me)
-+{
-+ Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
-+ Elf_Sym *sym;
-+ u32 *location;
-+ unsigned int i;
-+ Elf_Addr v;
-+ int res;
-+
-+ pr_debug("Applying relocate section %u to %u\n", relsec,
-+ sechdrs[relsec].sh_info);
-+
-+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-+ /* This is where to make the change */
-+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-+ + rel[i].r_offset;
-+ /* This is the symbol it is referring to */
-+ sym = (Elf_Sym *)sechdrs[symindex].sh_addr
-+ + ELF_MIPS_R_SYM(rel[i]);
-+ if (IS_ERR_VALUE(sym->st_value)) {
-+ /* Ignore unresolved weak symbol */
-+ if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
-+ continue;
-+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
-+ me->name, strtab + sym->st_name);
-+ return -ENOENT;
-+ }
-+
-+ v = sym->st_value + rel[i].r_addend;
-+
-+ res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
-+ if (res)
-+ return res;
-+ }
-+
-+ return 0;
-+}
-diff --git a/arch/mips/kernel/module.h b/arch/mips/kernel/module.h
-new file mode 100644
-index 0000000..675d091
---- /dev/null
-+++ b/arch/mips/kernel/module.h
-@@ -0,0 +1,12 @@
-+/* Internal definitions for MIPS module code
-+ *
-+ * 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.
-+ */
-+
-+/*
-+ * module.c
-+ */
-+extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v);
-diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
-index fdaf65e..cd1e6c2 100644
---- a/arch/mips/kernel/Makefile
-+++ b/arch/mips/kernel/Makefile
-@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
-
- obj-$(CONFIG_STACKTRACE) += stacktrace.o
- obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
-+obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o
-
- obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
-
-diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
-index 9f102cf..e7dc80b 100644
---- a/arch/mips/kernel/module.c
-+++ b/arch/mips/kernel/module.c
-@@ -30,6 +30,7 @@
- #include <linux/kernel.h>
- #include <linux/spinlock.h>
- #include <linux/jump_label.h>
-+#include "module.h"
-
- #include <asm/pgtable.h> /* MODULE_START */
-
-@@ -51,7 +52,7 @@ void *module_alloc(unsigned long size)
- }
- #endif
-
--static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
-+int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
- {
- return 0;
- }
-@@ -63,13 +64,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v)
- return 0;
- }
-
--static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
--{
-- *location = v;
--
-- return 0;
--}
--
- static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
- {
- if (v % 4) {
-@@ -91,26 +85,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
- return 0;
- }
-
--static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
--{
-- if (v % 4) {
-- pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
-- me->name);
-- return -ENOEXEC;
-- }
--
-- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-- printk(KERN_ERR
-- "module %s: relocation overflow\n",
-- me->name);
-- return -ENOEXEC;
-- }
--
-- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
--
-- return 0;
--}
--
- static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
- {
- struct mips_hi16 *n;
-@@ -132,14 +106,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
- return 0;
- }
-
--static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
--{
-- *location = (*location & 0xffff0000) |
-- ((((long long) v + 0x8000LL) >> 16) & 0xffff);
--
-- return 0;
--}
--
- static void free_relocation_chain(struct mips_hi16 *l)
- {
- struct mips_hi16 *next;
-@@ -217,38 +183,6 @@ out_danger:
- return -ENOEXEC;
- }
-
--static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
--{
-- *location = (*location & 0xffff0000) | (v & 0xffff);
--
-- return 0;
--}
--
--static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
--{
-- *(Elf_Addr *)location = v;
--
-- return 0;
--}
--
--static int apply_r_mips_higher_rela(struct module *me, u32 *location,
-- Elf_Addr v)
--{
-- *location = (*location & 0xffff0000) |
-- ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
--
-- return 0;
--}
--
--static int apply_r_mips_highest_rela(struct module *me, u32 *location,
-- Elf_Addr v)
--{
-- *location = (*location & 0xffff0000) |
-- ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
--
-- return 0;
--}
--
- static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
- Elf_Addr v) = {
- [R_MIPS_NONE] = apply_r_mips_none,
-@@ -258,18 +192,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
- [R_MIPS_LO16] = apply_r_mips_lo16_rel
- };
-
--static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
-- Elf_Addr v) = {
-- [R_MIPS_NONE] = apply_r_mips_none,
-- [R_MIPS_32] = apply_r_mips_32_rela,
-- [R_MIPS_26] = apply_r_mips_26_rela,
-- [R_MIPS_HI16] = apply_r_mips_hi16_rela,
-- [R_MIPS_LO16] = apply_r_mips_lo16_rela,
-- [R_MIPS_64] = apply_r_mips_64_rela,
-- [R_MIPS_HIGHER] = apply_r_mips_higher_rela,
-- [R_MIPS_HIGHEST] = apply_r_mips_highest_rela
--};
--
- int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
- unsigned int symindex, unsigned int relsec,
- struct module *me)
-@@ -324,48 +246,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
- return 0;
- }
-
--#ifdef CONFIG_MODULES_USE_ELF_RELA
--int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-- unsigned int symindex, unsigned int relsec,
-- struct module *me)
--{
-- Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
-- Elf_Sym *sym;
-- u32 *location;
-- unsigned int i;
-- Elf_Addr v;
-- int res;
--
-- pr_debug("Applying relocate section %u to %u\n", relsec,
-- sechdrs[relsec].sh_info);
--
-- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-- /* This is where to make the change */
-- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-- + rel[i].r_offset;
-- /* This is the symbol it is referring to */
-- sym = (Elf_Sym *)sechdrs[symindex].sh_addr
-- + ELF_MIPS_R_SYM(rel[i]);
-- if (IS_ERR_VALUE(sym->st_value)) {
-- /* Ignore unresolved weak symbol */
-- if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
-- continue;
-- printk(KERN_WARNING "%s: Unknown symbol %s\n",
-- me->name, strtab + sym->st_name);
-- return -ENOENT;
-- }
--
-- v = sym->st_value + rel[i].r_addend;
--
-- res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
-- if (res)
-- return res;
-- }
--
-- return 0;
--}
--#endif
--
- /* Given an address, look for it in the module exception tables. */
- const struct exception_table_entry *search_module_dbetables(unsigned long addr)
- {
---
-1.7.11.4
-
-
-From 661f0147e9414fb2237f56d88d1f92d8a42345c9 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 19/32] Provide macros for forming the name of an ELF note and
- its section
-
-Provide macros for stringifying the name of an ELF note and its section
-appropriately so that the macro can be used in both C and assembly.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/elfnote.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h
-index 278e3ef..949d494 100644
---- a/include/linux/elfnote.h
-+++ b/include/linux/elfnote.h
-@@ -58,6 +58,7 @@
- ELFNOTE_END
-
- #else /* !__ASSEMBLER__ */
-+#include <linux/stringify.h>
- #include <linux/elf.h>
- /*
- * Use an anonymous structure which matches the shape of
-@@ -93,6 +94,9 @@
-
- #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
- #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
-+
-+#define ELFNOTE_NAME(name) __stringify(name)
-+#define ELFNOTE_SECTION(name) ".note."ELFNOTE_NAME(name)
- #endif /* __ASSEMBLER__ */
-
- #endif /* _LINUX_ELFNOTE_H */
---
-1.7.11.4
-
-
-From 544f02e192a8a38153d7dedc61bc107545666c0d Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 20/32] MODSIGN: Provide gitignore and make clean rules for
- extra files
-
-Provide gitignore and make clean rules for extra files to hide and clean up the
-extra files produced by module signing stuff once it is added. Also add a
-clean up rule for the module content extractor program used to extract the data
-to be signed.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- .gitignore | 12 ++++++++++++
- Makefile | 1 +
- scripts/mod/.gitignore | 1 +
- 3 files changed, 14 insertions(+)
-
-diff --git a/.gitignore b/.gitignore
-index 57af07c..7948eeb 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -14,6 +14,9 @@
- *.o.*
- *.a
- *.s
-+*.ko.unsigned
-+*.ko.digest
-+*.ko.digest.sig
- *.ko
- *.so
- *.so.dbg
-@@ -84,3 +87,12 @@ GTAGS
- *.orig
- *~
- \#*#
-+
-+#
-+# GPG leavings from module signing
-+#
-+genkey
-+modsign.pub
-+modsign.sec
-+random_seed
-+trustdb.gpg
-diff --git a/Makefile b/Makefile
-index ddf5be9..70a6b5b 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.*' \
-diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore
-index e9b7abe..223dfd6 100644
---- a/scripts/mod/.gitignore
-+++ b/scripts/mod/.gitignore
-@@ -1,4 +1,5 @@
- elfconfig.h
- mk_elfconfig
- modpost
-+mod-extract
-
---
-1.7.11.4
-
-
-From 6e21809168e7b45a830ec354ec9fc1582fcffe4f Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 21/32] MODSIGN: Provide Documentation and Kconfig options
-
-Provide documentation and kernel configuration options for module signing.
-
-The documentation can be found in:
-
- Documentation/module-signing.txt
-
-The following configuration options are added:
-
- (1) CONFIG_MODULE_SIG
-
- Enable module signing. This will both cause the build process to sign
- modules and the kernel to check modules when they're loaded.
-
- (2) CONFIG_MODULE_SIG_SHA1
- CONFIG_MODULE_SIG_SHA224
- CONFIG_MODULE_SIG_SHA256
- CONFIG_MODULE_SIG_SHA384
- CONFIG_MODULE_SIG_SHA512
-
- Select the cryptographic hash used to digest the data prior to signing.
- Additionally, the crypto module selected will be built into the kernel as
- it won't be possible to load it as a module without incurring a circular
- dependency when the kernel tries to check its signature.
-
- (3) CONFIG_MODULE_SIG_FORCE
-
- Require that any module loaded must be signed with a key compiled into
- the kernel. All other modules are rejected with EKEYREJECTED.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/module-signing.txt | 194 +++++++++++++++++++++++++++++++++++++++
- include/linux/modsign.h | 27 ++++++
- init/Kconfig | 54 +++++++++++
- 3 files changed, 275 insertions(+)
- create mode 100644 Documentation/module-signing.txt
- create mode 100644 include/linux/modsign.h
-
-diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
-new file mode 100644
-index 0000000..d75d473
---- /dev/null
-+++ b/Documentation/module-signing.txt
-@@ -0,0 +1,194 @@
-+ ==============================
-+ KERNEL MODULE SIGNING FACILITY
-+ ==============================
-+
-+The module signing facility applies cryptographic signature checking to modules
-+on module load, checking the signature against a ring of public keys compiled
-+into the kernel. GPG is used to do the cryptographic work and determines the
-+format of the signature and key data. The facility uses GPG's MPI library to
-+handle the huge numbers involved.
-+
-+This facility is enabled through CONFIG_MODULE_SIG. Turning on signature
-+checking will also force the module's ELF metadata to be verified before the
-+signature is checked.
-+
-+The signature checker in the kernel is capable of handling multiple keys of
-+either DSA or RSA type, and can support any of MD5, RIPE-MD-160, SHA-1,
-+SHA-224, SHA-256, SHA-384 and SHA-512 hashes - PROVIDED(!) the requisite
-+algorithms are compiled into the kernel.
-+
-+(!) NOTE: Modules may only be verified initially with algorithms compiled into
-+the kernel. Further algorithm modules may be loaded and used - but these must
-+first pass a verification step using already loaded/compiled-in algorithms.
-+
-+
-+=====================
-+SUPPLYING PUBLIC KEYS
-+=====================
-+
-+A set of public keys must be supplied at kernel image build time. This is done
-+by taking a GPG public key file and placing it in the base of the kernel
-+directory in a file called modsign.pub.
-+
-+For example, a throwaway key could be generated automatically by something like
-+the following:
-+
-+ cat >genkey <<EOF
-+ %pubring modsign.pub
-+ %secring modsign.sec
-+ Key-Type: RSA
-+ Key-Length: 4096
-+ Name-Real: A. N. Other
-+ Name-Comment: Kernel Module GPG key
-+ %commit
-+ EOF
-+ gpg --homedir . --batch --gen-key genkey
-+
-+The above generates fresh keys using /dev/random. If there's insufficient data
-+in /dev/random, more can be provided using the rngd program if there's a
-+hardware random number generator available.
-+
-+Note that no GPG password is used in the above scriptlet.
-+
-+The modsign.pub file is compiled into the kernel directly by the assembler by
-+means of an ".incbin" directive in kernel/modsign-pubkey.c.
-+
-+Once the kernel is running, the keys are visible to root as kernel crypto keys
-+in /proc/keys in a keyring called .module_sign:
-+
-+335ab517 I----- 1 perm 1f030000 0 0 keyring .module_sign: 2/4
-+38d7d169 I----- 1 perm 3f010000 0 0 crypto modsign.0: rsa 57532ca5 []
-+195fa736 I----- 1 perm 3f010000 0 0 crypto modsign.1: dsa 5acc2142 []
-+
-+This keyring can be listed with the keyctl program. See:
-+
-+ Documentation/security/keys-crypto.txt
-+
-+for more information of crypto keys.
-+
-+
-+============================
-+SELECTING THE HASH ALGORITHM
-+============================
-+
-+The hash algorithm to be used is selected by a multiple choice configuration
-+item that enables one of the following variables:
-+
-+ CONFIG_SIG_SHA1
-+ CONFIG_SIG_SHA224
-+ CONFIG_SIG_SHA256
-+ CONFIG_SIG_SHA384
-+ CONFIG_SIG_SHA512
-+
-+These cause an appropriate "--digest-algo=" parameter to be passed to gpg when
-+signing a module and force the appropriate hash algorithm to be compiled
-+directly into the kernel rather than being built as a module.
-+
-+
-+==============
-+MODULE SIGNING
-+==============
-+
-+Modules will then be signed automatically. The kernel make command line can
-+include the following options:
-+
-+ (*) MODSECKEY=<secret-key-ring-path>
-+
-+ This indicates the whereabouts of the GPG keyring that is the source of
-+ the secret key to be used. The default is "./modsign.sec".
-+
-+ (*) MODPUBKEY=<public-key-ring-path>
-+
-+ This indicates the whereabouts of the GPG keyring that is the source of
-+ the public key to be used. The default is "./modsign.pub".
-+
-+ (*) MODKEYNAME=<key-name>
-+
-+ The name of the key pair to be used from the aforementioned keyrings.
-+ This defaults to being unset, thus leaving the choice of default key to
-+ gpg.
-+
-+ (*) KEYFLAGS="gpg-options"
-+
-+ Override the complete gpg command line, including the preceding three
-+ options. The default options supplied to gpg are:
-+
-+ --no-default-keyring
-+ --secret-keyring $(MODSECKEY)
-+ --keyring $(MODPUBKEY)
-+ --no-default-keyring
-+ --homedir .
-+ --no-options
-+ --no-auto-check-trustdb
-+ --no-permission-warning
-+ --digest-algo=<hash-algorithm>
-+
-+ with:
-+
-+ --default-key $(MODKEYNAME)
-+
-+ being added if requested.
-+
-+The resulting module.ko file will be the signed module.
-+
-+
-+========================
-+STRIPPING SIGNED MODULES
-+========================
-+
-+Signed modules may be safely stripped with any of the following:
-+
-+ strip -x
-+ strip -g
-+ eu-strip
-+
-+as the signature only covers those parts of the module the kernel actually uses
-+and any ELF metadata required to deal with them. Any necessary ELF metadata
-+that is affected by stripping is canonicalised by the sig generator and the sig
-+checker to hide strip effects.
-+
-+This permits the debuginfo to be detached from the module and placed in another
-+spot so that gdb can find it when referring to that module without the need for
-+multiple signed versions of the module. Such is done by rpmbuild when
-+producing RPMs.
-+
-+It also permits the module to be stripped as far as possible for when modules
-+are being reduced prior to being included in an initial ramdisk composition.
-+
-+Note that "strip" and "strip -s" may not be used on a module, signed or
-+otherwise, as they remove the symbol table and render the relocation tables
-+unusable.
-+
-+
-+======================
-+LOADING SIGNED MODULES
-+======================
-+
-+Modules are loaded with insmod, exactly as for unsigned modules. The signature
-+is inserted into the module object file during the build process as an ELF note
-+called "module.sig" in an ELF section called ".note.module.sig". The signature
-+checker will detect it and apply signature checking.
-+
-+
-+=========================================
-+NON-VALID SIGNATURES AND UNSIGNED MODULES
-+=========================================
-+
-+If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on
-+the kernel command line, the kernel will _only_ load validly signed modules
-+for which it has a public key. Otherwise, it will also load modules that are
-+unsigned. Any module for which the kernel has a key, but which proves to have
-+a signature mismatch will not be permitted to load (returning EKEYREJECTED).
-+
-+This table indicates the behaviours of the various situations:
-+
-+ MODULE STATE PERMISSIVE MODE ENFORCING MODE
-+ ======================================= =============== ===============
-+ Unsigned Ok EKEYREJECTED
-+ Signed, no public key ENOKEY ENOKEY
-+ Validly signed, public key Ok Ok
-+ Invalidly signed, public key EKEYREJECTED EKEYREJECTED
-+ Validly signed, expired key EKEYEXPIRED EKEYEXPIRED
-+ Signed, hash algorithm unavailable ENOPKG ENOPKG
-+ Corrupt signature EBADMSG EBADMSG
-+ Corrupt ELF ELIBBAD ELIBBAD
-diff --git a/include/linux/modsign.h b/include/linux/modsign.h
-new file mode 100644
-index 0000000..c5ac87a
---- /dev/null
-+++ b/include/linux/modsign.h
-@@ -0,0 +1,27 @@
-+/* Module signing definitions
-+ *
-+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_MODSIGN_H
-+#define _LINUX_MODSIGN_H
-+
-+#ifdef CONFIG_MODULE_SIG
-+
-+#include <linux/elfnote.h>
-+
-+/*
-+ * The parameters of the ELF note used to carry the signature
-+ */
-+#define MODSIGN_NOTE_NAME module.sig
-+#define MODSIGN_NOTE_TYPE 100
-+
-+#endif
-+
-+#endif /* _LINUX_MODSIGN_H */
-diff --git a/init/Kconfig b/init/Kconfig
-index af6c7f8..e23ed83 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1585,6 +1585,60 @@ config MODULE_SRCVERSION_ALL
- the version). With this option, such a "srcversion" field
- will be created for all modules. If unsure, say N.
-
-+config MODULE_SIG
-+ bool "Module signature verification"
-+ depends on MODULES
-+ select KEYS
-+ select CRYPTO_KEY_TYPE
-+ select CRYPTO_KEY_PKEY_ALGO_DSA
-+ select CRYPTO_KEY_PKEY_ALGO_RSA
-+ select PGP_PARSER
-+ select PGP_PRELOAD
-+ help
-+ Check modules for valid signatures upon load. For more information
-+ see:
-+
-+ Documentation/module-signing.txt
-+
-+choice
-+ prompt "Which hash algorithm should modules be signed with?"
-+ depends on MODULE_SIG
-+ help
-+ This determines which sort of hashing algorithm will be used during
-+ signature generation. This algorithm _must_ be built into the kernel
-+ directly so that signature verification can take place. It is not
-+ possible to load a signed module containing the algorithm to check
-+ the signature on that module.
-+
-+config MODULE_SIG_SHA1
-+ bool "Sign modules with SHA-1"
-+ select CRYPTO_SHA1
-+
-+config MODULE_SIG_SHA224
-+ bool "Sign modules with SHA-224"
-+ select CRYPTO_SHA224
-+
-+config MODULE_SIG_SHA256
-+ bool "Sign modules with SHA-256"
-+ select CRYPTO_SHA256
-+
-+config MODULE_SIG_SHA384
-+ bool "Sign modules with SHA-384"
-+ select CRYPTO_SHA384
-+
-+config MODULE_SIG_SHA512
-+ bool "Sign modules with SHA-512"
-+ select CRYPTO_SHA512
-+
-+endchoice
-+
-+config MODULE_SIG_FORCE
-+ bool "Required modules to be validly signed (EXPERIMENTAL)"
-+ depends on MODULE_SIG
-+ help
-+ Reject unsigned modules or signed modules for which we don't have a
-+ key.
-+
- endif # MODULES
-
- config INIT_ALL_POSSIBLE
---
-1.7.11.4
-
-
-From 7733934d34b7f03574b4578edfad4a60d6fe3d56 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 22/32] MODSIGN: Sign modules during the build process
-
-If CONFIG_MODULE_SIG is set, then this patch will cause the module to get a
-signature installed. The following steps will occur:
-
- (1) The module will be linked to foo.ko.unsigned instead of foo.ko
-
- (2) The module's signable content will be extracted to foo.ko.digest by the
- mod-extract program.
-
- (3) The signature will be generated on foo.ko.digest by gpg and placed in
- foo.ko.digest.sig
-
- (4) The signature will be encapsulated into an ELF note and placed into a file
- called foo.ko.note.o using the output from modsign-note.sh piped into the
- assembler.
-
- (5) The unsigned module from (1) and the signature ELF note from (4) will be
- linked together to produce foo.ko
-
-Step (3) requires private and public keys to be available. By default these
-are expected to be found in PGP keyring files called modsign.sec (the secret
-key) and modsign.pub (the public key) in the build root.
-
-If the secret key is not found then signing will be skipped and the unsigned
-module from (1) will just be copied to foo.ko.
-
-If signing occurs, lines like the following will be seen:
-
- LD [M] fs/foo/foo.ko.unsigned
- SIGN [M] fs/foo/foo.ko
-
-will appear in the build log. If it is skipped, the following will be seen:
-
- LD [M] fs/foo/foo.ko.unsigned
- NO SIGN [M] fs/foo/foo.ko
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- scripts/Makefile.modpost | 87 ++++-
- scripts/mod/Makefile | 2 +-
- scripts/mod/mod-extract.c | 913 ++++++++++++++++++++++++++++++++++++++++++++
- scripts/mod/modsign-note.sh | 16 +
- 4 files changed, 1016 insertions(+), 2 deletions(-)
- create mode 100644 scripts/mod/mod-extract.c
- create mode 100644 scripts/mod/modsign-note.sh
-
-diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
-index 08dce14..17465d8 100644
---- a/scripts/Makefile.modpost
-+++ b/scripts/Makefile.modpost
-@@ -14,7 +14,8 @@
- # 3) create one <module>.mod.c file pr. module
- # 4) create one Module.symvers file with CRC for all exported symbols
- # 5) compile all <module>.mod.c files
--# 6) final link of the module to a <module.ko> file
-+# 6) final link of the module to a <module.ko> (or <module.unsigned>) file
-+# 7) signs the modules to a <module.ko> file
-
- # Step 3 is used to place certain information in the module's ELF
- # section, including information such as:
-@@ -32,6 +33,8 @@
- # Step 4 is solely used to allow module versioning in external modules,
- # where the CRC of each module is retrieved from the Module.symvers file.
-
-+# Step 7 is dependent on CONFIG_MODULE_SIG being enabled.
-+
- # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
- # symbols in the final module linking stage
- # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
-@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
- targets += $(modules:.ko=.mod.o)
-
- # Step 6), final link of the modules
-+ifneq ($(CONFIG_MODULE_SIG),y)
- quiet_cmd_ld_ko_o = LD [M] $@
- cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \
- $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-@@ -125,7 +129,88 @@ $(modules): %.ko :%.o %.mod.o FORCE
- $(call if_changed,ld_ko_o)
-
- targets += $(modules)
-+else
-+quiet_cmd_ld_ko_unsigned_o = LD [M] $@
-+ cmd_ld_ko_unsigned_o = \
-+ $(LD) -r $(LDFLAGS) \
-+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-+ -o $@ $(filter-out FORCE,$^) \
-+ $(if $(AFTER_LINK),; $(AFTER_LINK))
-+
-+$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
-+ $(call if_changed,ld_ko_unsigned_o)
-+
-+targets += $(modules:.ko=.ko.unsigned)
-+
-+# Step 7), sign the modules
-+MODSECKEY = ./modsign.sec
-+MODPUBKEY = ./modsign.pub
-+KEYFLAGS = --no-default-keyring --secret-keyring $(MODSECKEY) --keyring $(MODPUBKEY) --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning
-+
-+ifdef CONFIG_MODULE_SIG_SHA1
-+KEYFLAGS += --digest-algo=SHA1
-+else
-+ifdef CONFIG_MODULE_SIG_SHA224
-+KEYFLAGS += --digest-algo=SHA224
-+else
-+ifdef CONFIG_MODULE_SIG_SHA256
-+KEYFLAGS += --digest-algo=SHA256
-+else
-+ifdef CONFIG_MODULE_SIG_SHA384
-+KEYFLAGS += --digest-algo=SHA384
-+else
-+ifdef CONFIG_MODULE_SIG_SHA512
-+KEYFLAGS += --digest-algo=SHA512
-+else
-+endif
-+endif
-+endif
-+endif
-+endif
-+
-+ifdef MODKEYNAME
-+KEYFLAGS += --default-key $(MODKEYNAME)
-+endif
-
-+ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
-+ifeq ($(KBUILD_SRC),)
-+ # no O= is being used
-+ SCRIPTS_DIR := scripts
-+else
-+ SCRIPTS_DIR := $(KBUILD_SRC)/scripts
-+endif
-+SIGN_MODULES := 1
-+else
-+SIGN_MODULES := 0
-+endif
-+
-+# only sign if it's an in-tree module
-+ifneq ($(KBUILD_EXTMOD),)
-+SIGN_MODULES := 0
-+endif
-+
-+ifeq ($(SIGN_MODULES),1)
-+KEYRING_DEP := modsign.sec modsign.pub
-+quiet_cmd_sign_ko_ko_unsigned = SIGN [M] $@
-+ cmd_sign_ko_ko_unsigned = \
-+ scripts/mod/mod-extract $< $@.digest && \
-+ rm -f $@.digest.sig && \
-+ gpg --batch --no-greeting $(KEYFLAGS) -b $@.digest && \
-+ sh $(SCRIPTS_DIR)/mod/modsign-note.sh $@.digest.sig | \
-+ $(CC) -x assembler-with-cpp $(c_flags) $(CFLAGS_MODULE) -c -o $@.note.o - && \
-+ $(LD) -r $(LDFLAGS) -o $@ $< $@.note.o
-+else
-+KEYRING_DEP :=
-+quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
-+ cmd_sign_ko_ko_unsigned = \
-+ cp $< $@
-+endif
-+
-+$(modules): %.ko :%.ko.unsigned $(KEYRING_DEP) FORCE
-+ $(call if_changed,sign_ko_ko_unsigned)
-+
-+targets += $(modules)
-+endif
-
- # Add FORCE to the prequisites of a target to force it to be always rebuilt.
- # ---------------------------------------------------------------------------
-diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
-index ff954f8..4654e3b 100644
---- a/scripts/mod/Makefile
-+++ b/scripts/mod/Makefile
-@@ -1,4 +1,4 @@
--hostprogs-y := modpost mk_elfconfig
-+hostprogs-y := modpost mk_elfconfig mod-extract
- always := $(hostprogs-y) empty.o
-
- modpost-objs := modpost.o file2alias.o sumversion.o
-diff --git a/scripts/mod/mod-extract.c b/scripts/mod/mod-extract.c
-new file mode 100644
-index 0000000..0c0e3e3
---- /dev/null
-+++ b/scripts/mod/mod-extract.c
-@@ -0,0 +1,913 @@
-+/* mod-extract.c: module extractor for signing
-+ *
-+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <stdarg.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <fcntl.h>
-+#include <sys/mman.h>
-+#include <sys/stat.h>
-+#include <elf.h>
-+#include <asm/byteorder.h>
-+
-+static void extract_elf64(void *buffer, size_t size, Elf64_Ehdr *hdr);
-+static void extract_elf32(void *buffer, size_t size, Elf32_Ehdr *hdr);
-+
-+struct byteorder {
-+ uint16_t (*get16)(const uint16_t *);
-+ uint32_t (*get32)(const uint32_t *);
-+ uint64_t (*get64)(const uint64_t *);
-+ void (*set16)(uint16_t *, uint16_t);
-+ void (*set32)(uint32_t *, uint32_t);
-+ void (*set64)(uint64_t *, uint64_t);
-+};
-+
-+static uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); }
-+static uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); }
-+static uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); }
-+static uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); }
-+static uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); }
-+static uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); }
-+
-+static void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); }
-+static void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); }
-+static void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); }
-+static void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); }
-+static void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); }
-+static void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); }
-+
-+static const struct byteorder byteorder_le = {
-+ get16_le, get32_le, get64_le,
-+ set16_le, set32_le, set64_le
-+};
-+static const struct byteorder byteorder_be = {
-+ get16_be, get32_be, get64_be,
-+ set16_be, set32_be, set64_be
-+};
-+static const struct byteorder *order;
-+
-+static inline uint16_t get16(const uint16_t *p) { return order->get16(p); }
-+static inline uint32_t get32(const uint32_t *p) { return order->get32(p); }
-+static inline uint64_t get64(const uint64_t *p) { return order->get64(p); }
-+static inline void set16(uint16_t *p, uint16_t n) { order->set16(p, n); }
-+static inline void set32(uint32_t *p, uint32_t n) { order->set32(p, n); }
-+static inline void set64(uint64_t *p, uint64_t n) { order->set64(p, n); }
-+
-+static FILE *outfd;
-+static uint8_t csum, xcsum;
-+
-+static void write_out(const void *data, size_t size)
-+{
-+ const uint8_t *p = data;
-+ size_t loop;
-+
-+ for (loop = 0; loop < size; loop++) {
-+ csum += p[loop];
-+ xcsum += p[loop];
-+ }
-+
-+ if (fwrite(data, 1, size, outfd) != size) {
-+ perror("write");
-+ exit(1);
-+ }
-+}
-+
-+#define write_out_val(VAL) write_out(&(VAL), sizeof(VAL))
-+
-+static int is_verbose;
-+
-+static __attribute__((format(printf, 1, 2)))
-+void verbose(const char *fmt, ...)
-+{
-+ va_list va;
-+
-+ if (is_verbose) {
-+ va_start(va, fmt);
-+ vprintf(fmt, va);
-+ va_end(va);
-+ }
-+}
-+
-+static __attribute__((noreturn))
-+void usage(void)
-+{
-+ fprintf(stderr, "Usage: mod-extract [-v] <modulefile> <extractfile>\n");
-+ exit(2);
-+}
-+
-+/*
-+ *
-+ */
-+int main(int argc, char **argv)
-+{
-+ struct stat st;
-+ Elf32_Ehdr *hdr32;
-+ Elf64_Ehdr *hdr64;
-+ size_t len;
-+ void *buffer;
-+ int fd, be, b64;
-+
-+ while (argc > 1 && strcmp("-v", argv[1]) == 0) {
-+ argv++;
-+ argc--;
-+ is_verbose++;
-+ }
-+
-+ if (argc != 3)
-+ usage();
-+
-+ /* map the module into memory */
-+ fd = open(argv[1], O_RDONLY);
-+ if (fd < 0) {
-+ perror("open input");
-+ exit(1);
-+ }
-+
-+ if (fstat(fd, &st) < 0) {
-+ perror("fstat");
-+ exit(1);
-+ }
-+
-+ len = st.st_size;
-+
-+ buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
-+ if (buffer == MAP_FAILED) {
-+ perror("mmap");
-+ exit(1);
-+ }
-+
-+ if (close(fd) < 0) {
-+ perror("close input");
-+ exit(1);
-+ }
-+
-+ /* check it's an ELF object */
-+ hdr32 = buffer;
-+ hdr64 = buffer;
-+
-+ if (hdr32->e_ident[EI_MAG0] != ELFMAG0 ||
-+ hdr32->e_ident[EI_MAG1] != ELFMAG1 ||
-+ hdr32->e_ident[EI_MAG2] != ELFMAG2 ||
-+ hdr32->e_ident[EI_MAG3] != ELFMAG3
-+ ) {
-+ fprintf(stderr, "Module does not appear to be ELF\n");
-+ exit(3);
-+ }
-+
-+ /* determine endianness and word size */
-+ b64 = (hdr32->e_ident[EI_CLASS] == ELFCLASS64);
-+ be = (hdr32->e_ident[EI_DATA] == ELFDATA2MSB);
-+ order = be ? &byteorder_be : &byteorder_le;
-+
-+ verbose("Module is %s-bit %s-endian\n",
-+ b64 ? "64" : "32",
-+ be ? "big" : "little");
-+
-+ /* open the output file */
-+ outfd = fopen(argv[2], "w");
-+ if (!outfd) {
-+ perror("open output");
-+ exit(1);
-+ }
-+
-+ /* perform the extraction */
-+ if (b64)
-+ extract_elf64(buffer, len, hdr64);
-+ else
-+ extract_elf32(buffer, len, hdr32);
-+
-+ /* done */
-+ if (fclose(outfd) == EOF) {
-+ perror("close output");
-+ exit(1);
-+ }
-+
-+ return 0;
-+}
-+
-+/*
-+ * extract a RELA table
-+ * - need to canonicalise the entries in case section addition/removal has
-+ * rearranged the symbol table and the section table
-+ */
-+static void extract_elf64_rela(const void *buffer, int secix, int targetix,
-+ const Elf64_Rela *relatab, size_t nrels,
-+ const Elf64_Sym *symbols, size_t nsyms,
-+ const Elf64_Shdr *sections, size_t nsects, int *canonmap,
-+ const char *strings, size_t nstrings,
-+ const char *sh_name)
-+{
-+ struct {
-+ uint64_t r_offset;
-+ uint64_t r_addend;
-+ uint64_t st_value;
-+ uint64_t st_size;
-+ uint32_t r_type;
-+ uint16_t st_shndx;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+
-+ } __attribute__((packed)) relocation;
-+
-+ const Elf64_Sym *symbol;
-+ size_t loop;
-+
-+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
-+ for (loop = 0; loop < nrels; loop++) {
-+ Elf64_Section st_shndx;
-+ Elf64_Xword r_info;
-+
-+ /* decode the relocation */
-+ r_info = get64(&relatab[loop].r_info);
-+ relocation.r_offset = relatab[loop].r_offset;
-+ relocation.r_addend = relatab[loop].r_addend;
-+ set32(&relocation.r_type, ELF64_R_TYPE(r_info));
-+
-+ if (ELF64_R_SYM(r_info) >= nsyms) {
-+ fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
-+ (size_t)ELF64_R_SYM(r_info), loop);
-+ exit(1);
-+ }
-+
-+ /* decode the symbol referenced by the relocation */
-+ symbol = &symbols[ELF64_R_SYM(r_info)];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = symbol->st_shndx;
-+ st_shndx = get16(&symbol->st_shndx);
-+
-+ /* canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < nsects)
-+ set16(&relocation.st_shndx, canonmap[st_shndx]);
-+
-+ write_out_val(relocation);
-+
-+ /* undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + get32(&symbol->st_name);
-+ write_out(name, strlen(name) + 1);
-+ }
-+ }
-+
-+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
-+}
-+
-+/*
-+ * extract a REL table
-+ * - need to canonicalise the entries in case section addition/removal has
-+ * rearranged the symbol table and the section table
-+ */
-+static void extract_elf64_rel(const void *buffer, int secix, int targetix,
-+ const Elf64_Rel *relatab, size_t nrels,
-+ const Elf64_Sym *symbols, size_t nsyms,
-+ const Elf64_Shdr *sections, size_t nsects, int *canonmap,
-+ const char *strings, size_t nstrings,
-+ const char *sh_name)
-+{
-+ struct {
-+ uint64_t r_offset;
-+ uint64_t st_value;
-+ uint64_t st_size;
-+ uint32_t r_type;
-+ uint16_t st_shndx;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+
-+ } __attribute__((packed)) relocation;
-+
-+ const Elf64_Sym *symbol;
-+ size_t loop;
-+
-+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
-+ for (loop = 0; loop < nrels; loop++) {
-+ Elf64_Section st_shndx;
-+ Elf64_Xword r_info;
-+
-+ /* decode the relocation */
-+ r_info = get64(&relatab[loop].r_info);
-+ relocation.r_offset = relatab[loop].r_offset;
-+ set32(&relocation.r_type, ELF64_R_TYPE(r_info));
-+
-+ if (ELF64_R_SYM(r_info) >= nsyms) {
-+ fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
-+ (size_t)ELF64_R_SYM(r_info), loop);
-+ exit(1);
-+ }
-+
-+ /* decode the symbol referenced by the relocation */
-+ symbol = &symbols[ELF64_R_SYM(r_info)];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = symbol->st_shndx;
-+ st_shndx = get16(&symbol->st_shndx);
-+
-+ /* canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < nsects)
-+ set16(&relocation.st_shndx, canonmap[st_shndx]);
-+
-+ write_out_val(relocation);
-+
-+ /* undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + get32(&symbol->st_name);
-+ write_out(name, strlen(name) + 1);
-+ }
-+ }
-+
-+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
-+}
-+
-+/*
-+ * extract the data from a 64-bit module
-+ */
-+static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
-+{
-+ const Elf64_Sym *symbols;
-+ Elf64_Shdr *sections;
-+ const char *secstrings, *strings;
-+ size_t nsyms, nstrings;
-+ int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
-+
-+ sections = buffer + get64(&hdr->e_shoff);
-+ secstrings = buffer + get64(&sections[get16(&hdr->e_shstrndx)].sh_offset);
-+ shnum = get16(&hdr->e_shnum);
-+
-+ /* find the symbol table and the string table and produce a list of
-+ * index numbers of sections that contribute to the kernel's module
-+ * image
-+ */
-+ canonlist = calloc(sizeof(int), shnum * 2);
-+ if (!canonlist) {
-+ perror("calloc");
-+ exit(1);
-+ }
-+ canonmap = canonlist + shnum;
-+ canon = 0;
-+
-+ symbols = NULL;
-+ strings = NULL;
-+ nstrings = 0;
-+ nsyms = 0;
-+
-+ for (loop = 1; loop < shnum; loop++) {
-+ const char *sh_name = secstrings + get32(&sections[loop].sh_name);
-+ Elf64_Word sh_type = get32(&sections[loop].sh_type);
-+ Elf64_Xword sh_size = get64(&sections[loop].sh_size);
-+ Elf64_Xword sh_flags = get64(&sections[loop].sh_flags);
-+ Elf64_Word sh_info = get32(&sections[loop].sh_info);
-+ Elf64_Off sh_offset = get64(&sections[loop].sh_offset);
-+ void *data = buffer + sh_offset;
-+
-+ /* quick sanity check */
-+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
-+ fprintf(stderr, "Section goes beyond EOF\n");
-+ exit(3);
-+ }
-+
-+ /* we only need to canonicalise allocatable sections */
-+ if (sh_flags & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+ else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
-+ get64(&sections[sh_info].sh_flags) & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+
-+ /* keep track of certain special sections */
-+ switch (sh_type) {
-+ case SHT_SYMTAB:
-+ if (strcmp(sh_name, ".symtab") == 0) {
-+ symbols = data;
-+ nsyms = sh_size / sizeof(Elf64_Sym);
-+ }
-+ break;
-+
-+ case SHT_STRTAB:
-+ if (strcmp(sh_name, ".strtab") == 0) {
-+ strings = data;
-+ nstrings = sh_size;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ }
-+
-+ if (!symbols) {
-+ fprintf(stderr, "Couldn't locate symbol table\n");
-+ exit(3);
-+ }
-+
-+ if (!strings) {
-+ fprintf(stderr, "Couldn't locate strings table\n");
-+ exit(3);
-+ }
-+
-+ /* canonicalise the index numbers of the contributing section */
-+ do {
-+ changed = 0;
-+
-+ for (loop = 0; loop < canon - 1; loop++) {
-+ const char *x = secstrings + get32(&sections[canonlist[loop + 0]].sh_name);
-+ const char *y = secstrings + get32(&sections[canonlist[loop + 1]].sh_name);
-+ if (strcmp(x, y) > 0) {
-+ tmp = canonlist[loop + 0];
-+ canonlist[loop + 0] = canonlist[loop + 1];
-+ canonlist[loop + 1] = tmp;
-+ changed = 1;
-+ }
-+ }
-+
-+ } while (changed);
-+
-+ for (loop = 0; loop < canon; loop++)
-+ canonmap[canonlist[loop]] = loop + 1;
-+
-+ if (is_verbose > 1) {
-+ printf("\nSection canonicalisation map:\n");
-+ for (loop = 1; loop < shnum; loop++) {
-+ const char *x = secstrings + get32(&sections[loop].sh_name);
-+ printf("%4d %s\n", canonmap[loop], x);
-+ }
-+
-+ printf("\nAllocated section list in canonical order:\n");
-+ for (loop = 0; loop < canon; loop++) {
-+ const char *x = secstrings + get32(&sections[canonlist[loop]].sh_name);
-+ printf("%4d %s\n", canonlist[loop], x);
-+ }
-+ }
-+
-+ /* iterate through the section table looking for sections we want to
-+ * contribute to the signature */
-+ verbose("\n");
-+ verbose("CAN FILE POS CS SECT NAME\n");
-+ verbose("=== ======== == ==== ==============================\n");
-+
-+ for (loop = 0; loop < canon; loop++) {
-+ int sect = canonlist[loop];
-+ const char *sh_name = secstrings + get32(&sections[sect].sh_name);
-+ Elf64_Word sh_type = get32(&sections[sect].sh_type);
-+ Elf64_Xword sh_size = get64(&sections[sect].sh_size);
-+ Elf64_Xword sh_flags = get64(&sections[sect].sh_flags);
-+ Elf64_Word sh_info = get32(&sections[sect].sh_info);
-+ Elf64_Off sh_offset = get64(&sections[sect].sh_offset);
-+ void *data = buffer + sh_offset;
-+
-+ csum = 0;
-+
-+ /* include canonicalised relocation sections */
-+ if (sh_type == SHT_REL || sh_type == SHT_RELA) {
-+ Elf32_Word canon_sh_info;
-+
-+ if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
-+ fprintf(stderr,
-+ "Invalid ELF - REL/RELA sh_info does"
-+ " not refer to a valid section\n");
-+ exit(3);
-+ }
-+
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ set32(&canon_sh_info, canonmap[sh_info]);
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+ write_out_val(canon_sh_info);
-+
-+ if (sh_type == SHT_RELA)
-+ extract_elf64_rela(buffer, sect, sh_info,
-+ data, sh_size / sizeof(Elf64_Rela),
-+ symbols, nsyms,
-+ sections, shnum, canonmap,
-+ strings, nstrings,
-+ sh_name);
-+ else
-+ extract_elf64_rel(buffer, sect, sh_info,
-+ data, sh_size / sizeof(Elf64_Rel),
-+ symbols, nsyms,
-+ sections, shnum, canonmap,
-+ strings, nstrings,
-+ sh_name);
-+ continue;
-+ }
-+
-+ /* include the headers of BSS sections */
-+ if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+
-+ verbose("%02x %4d %s\n", csum, sect, sh_name);
-+ }
-+
-+ /* include allocatable loadable sections */
-+ if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
-+ goto include_section;
-+
-+ /* not this section */
-+ continue;
-+
-+ include_section:
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+
-+ /* write out the section data */
-+ write_out(data, sh_size);
-+
-+ verbose("%02x %4d %s\n", csum, sect, sh_name);
-+ }
-+
-+ verbose("%08lx (%lu bytes csum 0x%02x)\n",
-+ ftell(outfd), ftell(outfd), xcsum);
-+}
-+
-+/*
-+ * extract a RELA table
-+ * - need to canonicalise the entries in case section addition/removal has
-+ * rearranged the symbol table and the section table
-+ */
-+static void extract_elf32_rela(const void *buffer, int secix, int targetix,
-+ const Elf32_Rela *relatab, size_t nrels,
-+ const Elf32_Sym *symbols, size_t nsyms,
-+ const Elf32_Shdr *sections, size_t nsects,
-+ int *canonmap,
-+ const char *strings, size_t nstrings,
-+ const char *sh_name)
-+{
-+ struct {
-+ uint32_t r_offset;
-+ uint32_t r_addend;
-+ uint32_t st_value;
-+ uint32_t st_size;
-+ uint16_t st_shndx;
-+ uint8_t r_type;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+
-+ } __attribute__((packed)) relocation;
-+
-+ const Elf32_Sym *symbol;
-+ size_t loop;
-+
-+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
-+ for (loop = 0; loop < nrels; loop++) {
-+ Elf32_Section st_shndx;
-+ Elf32_Word r_info;
-+
-+ /* decode the relocation */
-+ r_info = get32(&relatab[loop].r_info);
-+ relocation.r_offset = relatab[loop].r_offset;
-+ relocation.r_addend = relatab[loop].r_addend;
-+ relocation.r_type = ELF32_R_TYPE(r_info);
-+
-+ if (ELF32_R_SYM(r_info) >= nsyms) {
-+ fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
-+ ELF32_R_SYM(r_info), loop);
-+ exit(1);
-+ }
-+
-+ /* decode the symbol referenced by the relocation */
-+ symbol = &symbols[ELF32_R_SYM(r_info)];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = symbol->st_shndx;
-+ st_shndx = get16(&symbol->st_shndx);
-+
-+ /* canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < nsects)
-+ set16(&relocation.st_shndx, canonmap[st_shndx]);
-+
-+ write_out_val(relocation);
-+
-+ /* undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + get32(&symbol->st_name);
-+ write_out(name, strlen(name) + 1);
-+ }
-+ }
-+
-+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
-+}
-+
-+/*
-+ * extract a REL table
-+ * - need to canonicalise the entries in case section addition/removal has
-+ * rearranged the symbol table and the section table
-+ */
-+static void extract_elf32_rel(const void *buffer, int secix, int targetix,
-+ const Elf32_Rel *relatab, size_t nrels,
-+ const Elf32_Sym *symbols, size_t nsyms,
-+ const Elf32_Shdr *sections, size_t nsects,
-+ int *canonmap,
-+ const char *strings, size_t nstrings,
-+ const char *sh_name)
-+{
-+ struct {
-+ uint32_t r_offset;
-+ uint32_t st_value;
-+ uint32_t st_size;
-+ uint16_t st_shndx;
-+ uint8_t r_type;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+
-+ } __attribute__((packed)) relocation;
-+
-+ const Elf32_Sym *symbol;
-+ size_t loop;
-+
-+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
-+ for (loop = 0; loop < nrels; loop++) {
-+ Elf32_Section st_shndx;
-+ Elf32_Word r_info;
-+
-+ /* decode the relocation */
-+ r_info = get32(&relatab[loop].r_info);
-+ relocation.r_offset = relatab[loop].r_offset;
-+ relocation.r_type = ELF32_R_TYPE(r_info);
-+
-+ if (ELF32_R_SYM(r_info) >= nsyms) {
-+ fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
-+ ELF32_R_SYM(r_info), loop);
-+ exit(1);
-+ }
-+
-+ /* decode the symbol referenced by the relocation */
-+ symbol = &symbols[ELF32_R_SYM(r_info)];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = symbol->st_shndx;
-+ st_shndx = get16(&symbol->st_shndx);
-+
-+ /* canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < nsects)
-+ set16(&relocation.st_shndx, canonmap[st_shndx]);
-+
-+ write_out_val(relocation);
-+
-+ /* undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + get32(&symbol->st_name);
-+ write_out(name, strlen(name) + 1);
-+ }
-+ }
-+
-+ verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
-+}
-+
-+/*
-+ * extract the data from a 32-bit module
-+ */
-+static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
-+{
-+ const Elf32_Sym *symbols;
-+ Elf32_Shdr *sections;
-+ const char *secstrings, *strings;
-+ size_t nsyms, nstrings;
-+ int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
-+
-+ sections = buffer + get32(&hdr->e_shoff);
-+ secstrings = buffer + get32(&sections[get16(&hdr->e_shstrndx)].sh_offset);
-+ shnum = get16(&hdr->e_shnum);
-+
-+ /* find the symbol table and the string table and produce a list of
-+ * index numbers of sections that contribute to the kernel's module
-+ * image
-+ */
-+ canonlist = calloc(sizeof(int), shnum * 2);
-+ if (!canonlist) {
-+ perror("calloc");
-+ exit(1);
-+ }
-+ canonmap = canonlist + shnum;
-+ canon = 0;
-+
-+ symbols = NULL;
-+ strings = NULL;
-+ nstrings = 0;
-+ nsyms = 0;
-+
-+ for (loop = 1; loop < shnum; loop++) {
-+ const char *sh_name = secstrings + get32(&sections[loop].sh_name);
-+ Elf32_Word sh_type = get32(&sections[loop].sh_type);
-+ Elf32_Xword sh_size = get32(&sections[loop].sh_size);
-+ Elf32_Xword sh_flags = get32(&sections[loop].sh_flags);
-+ Elf64_Word sh_info = get32(&sections[loop].sh_info);
-+ Elf32_Off sh_offset = get32(&sections[loop].sh_offset);
-+ void *data = buffer + sh_offset;
-+
-+ /* quick sanity check */
-+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
-+ fprintf(stderr, "Section goes beyond EOF\n");
-+ exit(3);
-+ }
-+
-+ /* we only need to canonicalise allocatable sections */
-+ if (sh_flags & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+ else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
-+ get32(&sections[sh_info].sh_flags) & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+
-+ /* keep track of certain special sections */
-+ switch (sh_type) {
-+ case SHT_SYMTAB:
-+ if (strcmp(sh_name, ".symtab") == 0) {
-+ symbols = data;
-+ nsyms = sh_size / sizeof(Elf32_Sym);
-+ }
-+ break;
-+
-+ case SHT_STRTAB:
-+ if (strcmp(sh_name, ".strtab") == 0) {
-+ strings = data;
-+ nstrings = sh_size;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ }
-+
-+ if (!symbols) {
-+ fprintf(stderr, "Couldn't locate symbol table\n");
-+ exit(3);
-+ }
-+
-+ if (!strings) {
-+ fprintf(stderr, "Couldn't locate strings table\n");
-+ exit(3);
-+ }
-+
-+ /* canonicalise the index numbers of the contributing section */
-+ do {
-+ changed = 0;
-+
-+ for (loop = 0; loop < canon - 1; loop++) {
-+ const char *x = secstrings + get32(&sections[canonlist[loop + 0]].sh_name);
-+ const char *y = secstrings + get32(&sections[canonlist[loop + 1]].sh_name);
-+ if (strcmp(x, y) > 0) {
-+ tmp = canonlist[loop + 0];
-+ canonlist[loop + 0] = canonlist[loop + 1];
-+ canonlist[loop + 1] = tmp;
-+ changed = 1;
-+ }
-+ }
-+
-+ } while (changed);
-+
-+ for (loop = 0; loop < canon; loop++)
-+ canonmap[canonlist[loop]] = loop + 1;
-+
-+ if (is_verbose > 1) {
-+ printf("\nSection canonicalisation map:\n");
-+ for (loop = 1; loop < shnum; loop++) {
-+ const char *x = secstrings + get32(&sections[loop].sh_name);
-+ printf("%4d %s\n", canonmap[loop], x);
-+ }
-+
-+ printf("\nAllocated section list in canonical order:\n");
-+ for (loop = 0; loop < canon; loop++) {
-+ const char *x = secstrings + get32(&sections[canonlist[loop]].sh_name);
-+ printf("%4d %s\n", canonlist[loop], x);
-+ }
-+ }
-+
-+ /* iterate through the section table looking for sections we want to
-+ * contribute to the signature */
-+ verbose("\n");
-+ verbose("CAN FILE POS CS SECT NAME\n");
-+ verbose("=== ======== == ==== ==============================\n");
-+
-+ for (loop = 0; loop < canon; loop++) {
-+ int sect = canonlist[loop];
-+ const char *sh_name = secstrings + get32(&sections[sect].sh_name);
-+ Elf32_Word sh_type = get32(&sections[sect].sh_type);
-+ Elf32_Xword sh_size = get32(&sections[sect].sh_size);
-+ Elf32_Xword sh_flags = get32(&sections[sect].sh_flags);
-+ Elf32_Word sh_info = get32(&sections[sect].sh_info);
-+ Elf32_Off sh_offset = get32(&sections[sect].sh_offset);
-+ void *data = buffer + sh_offset;
-+
-+ csum = 0;
-+
-+ /* quick sanity check */
-+ if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
-+ fprintf(stderr, "section goes beyond EOF\n");
-+ exit(3);
-+ }
-+
-+ /* include canonicalised relocation sections */
-+ if (sh_type == SHT_REL || sh_type == SHT_RELA) {
-+ Elf32_Word canon_sh_info;
-+
-+ if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
-+ fprintf(stderr,
-+ "Invalid ELF - REL/RELA sh_info does"
-+ " not refer to a valid section\n");
-+ exit(3);
-+ }
-+
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ set32(&canon_sh_info, canonmap[sh_info]);
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+ write_out_val(canon_sh_info);
-+
-+ if (sh_type == SHT_RELA)
-+ extract_elf32_rela(buffer, sect, sh_info,
-+ data, sh_size / sizeof(Elf32_Rela),
-+ symbols, nsyms,
-+ sections, shnum, canonmap,
-+ strings, nstrings,
-+ sh_name);
-+ else
-+ extract_elf32_rel(buffer, sect, sh_info,
-+ data, sh_size / sizeof(Elf32_Rel),
-+ symbols, nsyms,
-+ sections, shnum, canonmap,
-+ strings, nstrings,
-+ sh_name);
-+ continue;
-+ }
-+
-+ /* include the headers of BSS sections */
-+ if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+
-+ verbose("%02x %4d %s\n", csum, sect, sh_name);
-+ }
-+
-+ /* include allocatable loadable sections */
-+ if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
-+ goto include_section;
-+
-+ /* not this section */
-+ continue;
-+
-+ include_section:
-+ verbose("%3u %08lx ", loop, ftell(outfd));
-+
-+ /* write out selected portions of the section header */
-+ write_out(sh_name, strlen(sh_name));
-+ write_out_val(sections[sect].sh_type);
-+ write_out_val(sections[sect].sh_flags);
-+ write_out_val(sections[sect].sh_size);
-+ write_out_val(sections[sect].sh_addralign);
-+
-+ /* write out the section data */
-+ write_out(data, sh_size);
-+
-+ verbose("%02x %4d %s\n", csum, sect, sh_name);
-+ }
-+
-+ verbose("%08lx (%lu bytes csum 0x%02x)\n",
-+ ftell(outfd), ftell(outfd), xcsum);
-+}
-diff --git a/scripts/mod/modsign-note.sh b/scripts/mod/modsign-note.sh
-new file mode 100644
-index 0000000..bca67c0
---- /dev/null
-+++ b/scripts/mod/modsign-note.sh
-@@ -0,0 +1,16 @@
-+#!/bin/sh
-+#
-+# Generate a module signature note source file
-+#
-+# mod-sign.sh <sig-file> ><note-src-file>
-+#
-+
-+SIG=$1
-+
-+cat <<EOF
-+#include <linux/modsign.h>
-+
-+ELFNOTE(MODSIGN_NOTE_NAME, MODSIGN_NOTE_TYPE, .incbin "$SIG")
-+EOF
-+
-+exit 0
---
-1.7.11.4
-
-
-From ee3ca99bcf972f0d072d91f9256c39a197153b8e Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 23/32] MODSIGN: Module signature verification stub
-
-Create a stub for the module signature verifier and link it into module.c so
-that it gets called. A field is added to struct module to record whether or
-not a valid module signature was detected.
-
-The stub also implements the policy for handling unsigned modules and the
-printing of error messages to indicate various problems with the module.
-
-If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on
-the kernel command line, the kernel will _only_ load validly signed modules
-for which it has a public key. Otherwise, it will also load modules that are
-unsigned. Any module for which the kernel has a key, but which proves to have
-a signature mismatch will not be permitted to load.
-
-This table indicates the behaviours in the various situations:
-
- MODULE STATE PERMISSIVE MODE ENFORCING MODE
- ======================================= =============== ===============
- Unsigned Ok EKEYREJECTED
- Signed, no public key ENOKEY ENOKEY
- Validly signed, public key Ok Ok
- Invalidly signed, public key EKEYREJECTED EKEYREJECTED
- Validly signed, expired key EKEYEXPIRED EKEYEXPIRED
- Signed, hash algorithm unavailable ENOPKG ENOPKG
- Corrupt signature EBADMSG EBADMSG
- Corrupt ELF ELIBBAD ELIBBAD
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/module.h | 3 ++
- kernel/Makefile | 1 +
- kernel/module-verify-defs.h | 77 +++++++++++++++++++++++++++++++
- kernel/module-verify.c | 110 ++++++++++++++++++++++++++++++++++++++++++++
- kernel/module-verify.h | 20 ++++++++
- kernel/module.c | 26 +++++++++--
- 6 files changed, 232 insertions(+), 5 deletions(-)
- create mode 100644 kernel/module-verify-defs.h
- create mode 100644 kernel/module-verify.c
- create mode 100644 kernel/module-verify.h
-
-diff --git a/include/linux/module.h b/include/linux/module.h
-index fbcafe2..7391833 100644
---- a/include/linux/module.h
-+++ b/include/linux/module.h
-@@ -227,6 +227,9 @@ struct module
- /* Unique handle for this module */
- char name[MODULE_NAME_LEN];
-
-+ /* Is this module GPG signed */
-+ bool gpgsig_ok;
-+
- /* Sysfs stuff. */
- struct module_kobject mkobj;
- struct module_attribute *modinfo_attrs;
-diff --git a/kernel/Makefile b/kernel/Makefile
-index c0cc67a..cec222a 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-verify.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
-diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h
-new file mode 100644
-index 0000000..141ddab
---- /dev/null
-+++ b/kernel/module-verify-defs.h
-@@ -0,0 +1,77 @@
-+/* Module verification internal definitions
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifdef CONFIG_MODULE_SIG
-+
-+/*
-+ * Internal state
-+ */
-+struct module_verify_data {
-+ struct crypto_key_verify_context *mod_sig; /* Module signing context */
-+ union {
-+ const void *buffer; /* module buffer */
-+ const Elf_Ehdr *hdr; /* ELF header */
-+ };
-+ const Elf_Shdr *sections; /* ELF section table */
-+ const char *secstrings; /* ELF section string table */
-+ const void *sig; /* Signature note content */
-+ size_t size; /* module object size */
-+ size_t nsects; /* number of sections */
-+ size_t sig_size; /* Size of signature */
-+ size_t signed_size; /* count of bytes contributed to digest */
-+ unsigned *canonlist; /* list of canonicalised sections */
-+ unsigned *canonmap; /* section canonicalisation map */
-+ unsigned ncanon; /* number of canonicalised sections */
-+ unsigned sig_index; /* module signature section index */
-+ uint8_t xcsum; /* checksum of bytes contributed to digest */
-+ uint8_t csum; /* checksum of bytes representing a section */
-+};
-+
-+/*
-+ * Whether or not we support various types of ELF relocation record
-+ */
-+#if defined(MODULE_HAS_ELF_REL_ONLY)
-+#define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
-+#define is_elf_rela(sh_type) (0)
-+#elif defined(MODULE_HAS_ELF_RELA_ONLY)
-+#define is_elf_rel(sh_type) (0)
-+#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
-+#else
-+#define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
-+#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
-+#endif
-+
-+/*
-+ * Debugging. Define DEBUG to enable.
-+ */
-+#define _debug(FMT, ...) \
-+ do { \
-+ if (unlikely(modsign_debug)) \
-+ pr_debug(FMT, ##__VA_ARGS__); \
-+ } while (0)
-+
-+#ifdef DEBUG
-+#define count_and_csum(C, __p, __n) \
-+ do { \
-+ int __loop; \
-+ for (__loop = 0; __loop < __n; __loop++) { \
-+ (C)->csum += __p[__loop]; \
-+ (C)->xcsum += __p[__loop]; \
-+ } \
-+ (C)->signed_size += __n; \
-+ } while (0)
-+#else
-+#define count_and_csum(C, __p, __n) \
-+ do { \
-+ } while (0)
-+#endif
-+
-+#endif /* CONFIG_MODULE_SIG */
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-new file mode 100644
-index 0000000..4bf857e
---- /dev/null
-+++ b/kernel/module-verify.c
-@@ -0,0 +1,110 @@
-+/* Module signature verification
-+ *
-+ * The code in this file examines a signed kernel module and attempts to
-+ * determine if the PGP signature inside the module matches a digest of the
-+ * allocatable sections and the canonicalised relocation tables for those
-+ * allocatable sections.
-+ *
-+ * The module signature is included in an ELF note within the ELF structure of
-+ * the module blob. This, combined with the minimal canonicalisation performed
-+ * here, permits the module to pass through "strip -x", "strip -g" and
-+ * "eu-strip" without becoming corrupt. "strip" and "strip -s" will render a
-+ * module unusable by removing the symbol table.
-+ *
-+ * Copyright (C) 2004, 2011, 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ * - Derived from GregKH's RSA module signer
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#undef DEBUG
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/err.h>
-+#include <linux/elf.h>
-+#include <linux/elfnote.h>
-+#include <linux/sched.h>
-+#include <linux/cred.h>
-+#include <linux/modsign.h>
-+#include <linux/moduleparam.h>
-+#include <keys/crypto-type.h>
-+#include "module-verify.h"
-+#include "module-verify-defs.h"
-+
-+#ifdef DEBUG
-+static int modsign_debug;
-+core_param(modsign_debug, modsign_debug, int, 0644);
-+#else
-+#define modsign_debug false
-+#endif
-+
-+#ifdef CONFIG_MODULE_SIG_FORCE
-+#define modsign_signedonly true
-+#else
-+static bool modsign_signedonly;
-+#endif
-+
-+static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
-+static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
-+
-+/*
-+ * Verify a module's integrity
-+ */
-+int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
-+{
-+ struct module_verify_data mvdata;
-+ int ret;
-+
-+ memset(&mvdata, 0, sizeof(mvdata));
-+ mvdata.buffer = hdr;
-+ mvdata.size = size;
-+
-+ if (mvdata.sig_index <= 0) {
-+ /* Deal with an unsigned module */
-+ if (modsign_signedonly) {
-+ pr_err("An attempt to load unsigned module was rejected\n");
-+ return -EKEYREJECTED;
-+ } else {
-+ return 0;
-+ }
-+ goto out;
-+ }
-+
-+ ret = 0;
-+
-+out:
-+ switch (ret) {
-+ case 0: /* Good signature */
-+ *_gpgsig_ok = true;
-+ break;
-+ case -ELIBBAD:
-+ pr_err("Module format error encountered\n");
-+ break;
-+ case -EBADMSG:
-+ pr_err("Module signature error encountered\n");
-+ break;
-+ case -EKEYREJECTED: /* Signature mismatch or number format error */
-+ pr_err("Module signature verification failed\n");
-+ break;
-+ case -ENOKEY: /* Signed, but we don't have the public key */
-+ pr_err("Module signed with unknown public key\n");
-+ break;
-+ default: /* Other error (probably ENOMEM) */
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int __init sign_setup(char *str)
-+{
-+#ifndef CONFIG_MODULE_SIG_FORCE
-+ modsign_signedonly = true;
-+#endif
-+ return 0;
-+}
-+__setup("enforcemodulesig", sign_setup);
-diff --git a/kernel/module-verify.h b/kernel/module-verify.h
-new file mode 100644
-index 0000000..c640634
---- /dev/null
-+++ b/kernel/module-verify.h
-@@ -0,0 +1,20 @@
-+/* Module verification definitions
-+ *
-+ * Copyright (C) 2004, 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifdef CONFIG_MODULE_SIG
-+extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok);
-+#else
-+static inline int module_verify(const Elf_Ehdr *hdr, size_t size,
-+ bool *_gpgsig_ok)
-+{
-+ return 0;
-+}
-+#endif
-diff --git a/kernel/module.c b/kernel/module.c
-index 087aeed..a59a9da 100644
---- a/kernel/module.c
-+++ b/kernel/module.c
-@@ -58,6 +58,7 @@
- #include <linux/jump_label.h>
- #include <linux/pfn.h>
- #include <linux/bsearch.h>
-+#include "module-verify.h"
-
- #define CREATE_TRACE_POINTS
- #include <trace/events/module.h>
-@@ -2382,7 +2383,8 @@ static inline void kmemleak_load_module(const struct module *mod,
- /* Sets info->hdr and info->len. */
- static int copy_and_check(struct load_info *info,
- const void __user *umod, unsigned long len,
-- const char __user *uargs)
-+ const char __user *uargs,
-+ bool *_gpgsig_ok)
- {
- int err;
- Elf_Ehdr *hdr;
-@@ -2415,6 +2417,12 @@ static int copy_and_check(struct load_info *info,
- goto free_hdr;
- }
-
-+ /* Verify the module's contents */
-+ *_gpgsig_ok = false;
-+ err = module_verify(hdr, len, _gpgsig_ok);
-+ if (err < 0)
-+ goto free_hdr;
-+
- info->hdr = hdr;
- info->len = len;
- return 0;
-@@ -2757,7 +2765,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
- return 0;
- }
-
--static struct module *layout_and_allocate(struct load_info *info)
-+static struct module *layout_and_allocate(struct load_info *info,
-+ bool gpgsig_ok)
- {
- /* Module within temporary copy. */
- struct module *mod;
-@@ -2767,6 +2776,7 @@ static struct module *layout_and_allocate(struct load_info *info)
- mod = setup_load_info(info);
- if (IS_ERR(mod))
- return mod;
-+ mod->gpgsig_ok = gpgsig_ok;
-
- err = check_modinfo(mod, info);
- if (err)
-@@ -2850,17 +2860,18 @@ static struct module *load_module(void __user *umod,
- struct load_info info = { NULL, };
- struct module *mod;
- long err;
-+ bool gpgsig_ok;
-
- pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n",
- umod, len, uargs);
-
- /* Copy in the blobs from userspace, check they are vaguely sane. */
-- err = copy_and_check(&info, umod, len, uargs);
-+ err = copy_and_check(&info, umod, len, uargs, &gpgsig_ok);
- if (err)
- return ERR_PTR(err);
-
- /* Figure out module layout, and allocate all the memory. */
-- mod = layout_and_allocate(&info);
-+ mod = layout_and_allocate(&info, gpgsig_ok);
- if (IS_ERR(mod)) {
- err = PTR_ERR(mod);
- goto free_copy;
-@@ -3497,8 +3508,13 @@ void print_modules(void)
- printk(KERN_DEFAULT "Modules linked in:");
- /* Most callers should already have preempt disabled, but make sure */
- preempt_disable();
-- list_for_each_entry_rcu(mod, &modules, list)
-+ list_for_each_entry_rcu(mod, &modules, list) {
- printk(" %s%s", mod->name, module_flags(mod, buf));
-+#ifdef CONFIG_MODULE_SIG
-+ if (!mod->gpgsig_ok)
-+ printk("(U)");
-+#endif
-+ }
- preempt_enable();
- if (last_unloaded_module[0])
- printk(" [last unloaded: %s]", last_unloaded_module);
---
-1.7.11.4
-
-
-From 0f8f372047d8220e1d918797972746bb9fe345d9 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 24/32] MODSIGN: Automatically generate module signing keys if
- missing
-
-Automatically generate keys for module signing if they're absent so that
-allyesconfig doesn't break. The builder should consider generating their own
-keyrings, however, so that the keys are appropriately named and any extra keys
-required get imported.
-
-Also change the names of the keyring files to modsign.pub and modsign.sec so
-that they are then a more obvious what they're about and add a dependency for
-the signing rules on the keyring files so that the signatures get regenerated
-if the keyrings change.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/Makefile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 49 insertions(+)
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index cec222a..28cd248 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)
-+
-+###############################################################################
-+#
-+# If module signing is requested, say by allyesconfig, but a key has not been
-+# supplied, then one will need to be generated to make sure the build does not
-+# fail and that the kernel may be used afterwards.
-+#
-+###############################################################################
-+ifeq ($(CONFIG_MODULE_SIG),y)
-+modsign.pub modsign.sec: genkey
-+ @echo "###"
-+ @echo "### Now generating a PGP key pair to be used for signing modules."
-+ @echo "###"
-+ @echo "### If this takes a long time, you might wish to run rngd in the"
-+ @echo "### background to keep the supply of entropy topped up. It"
-+ @echo "### needs to be run as root and should use a hardware random"
-+ @echo "### number generator if one is available, eg:"
-+ @echo "###"
-+ @echo "### rngd -r /dev/hwrandom"
-+ @echo "###"
-+ gpg --homedir . --batch --gen-key genkey
-+ @echo "###"
-+ @echo "### Key pair generated."
-+ @echo "###"
-+ rm -f pubring.gpg secring.gpg trustdb.gpg
-+
-+genkey:
-+ @echo "###" >&2
-+ @echo "### Now generating a sample key generation script." >&2
-+ @echo "###" >&2
-+ @echo "### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2
-+ @echo "### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2
-+ @echo "###" >&2
-+ @echo "### If you have a hardware random number generator feeding" >&2
-+ @echo "### into /dev/random, you should drop the %no-protection" >&2
-+ @echo "### and %transient-key lines from the script." >&2
-+ @echo "###" >&2
-+ echo "%pubring modsign.pub" >genkey
-+ echo "%secring modsign.sec" >>genkey
-+ echo "%no-protection: yes" >> genkey
-+ echo "%transient-key: yes" >>genkey
-+ echo "Key-Type: RSA" >>genkey
-+ echo "Key-Length: 4096" >>genkey
-+ echo "Name-Real: Sample kernel key" >>genkey
-+ echo "Name-Comment: Sample kernel module signing key" >>genkey
-+ echo "%commit" >>genkey
-+
-+endif
-+CLEAN_FILES += modsign.pub modsign.sec genkey random_seed
---
-1.7.11.4
-
-
-From be5544dce081ccb49fd452a6273c5024208b2f06 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 25/32] MODSIGN: Provide module signing public keys to the
- kernel
-
-Include a PGP keyring containing the public keys required to perform module
-verification in the kernel image during build and create a special keyring
-during boot which is then populated with keys of crypto type holding the public
-keys found in the PGP keyring.
-
-These can be seen by root:
-
-[root@andromeda ~]# cat /proc/keys
-07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd []
-15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4
-...
-
-It is probably worth permitting root to invalidate these keys, resulting in
-their removal and preventing further modules from being loaded with that key.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/Makefile | 25 ++++++++-------
- kernel/modsign-pubkey.c | 75 +++++++++++++++++++++++++++++++++++++++++++++
- kernel/module-verify-defs.h | 4 +++
- kernel/module-verify.c | 2 --
- 4 files changed, 93 insertions(+), 13 deletions(-)
- create mode 100644 kernel/modsign-pubkey.c
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 28cd248..1d20704 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -55,7 +55,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
- obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
- obj-$(CONFIG_UID16) += uid16.o
- obj-$(CONFIG_MODULES) += module.o
--obj-$(CONFIG_MODULE_SIG) += module-verify.o
-+obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o
-+kernel/modsign-pubkey.o: modsign.pub
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
-@@ -159,16 +160,18 @@ modsign.pub modsign.sec: genkey
- rm -f pubring.gpg secring.gpg trustdb.gpg
-
- genkey:
-- @echo "###" >&2
-- @echo "### Now generating a sample key generation script." >&2
-- @echo "###" >&2
-- @echo "### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2
-- @echo "### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2
-- @echo "###" >&2
-- @echo "### If you have a hardware random number generator feeding" >&2
-- @echo "### into /dev/random, you should drop the %no-protection" >&2
-- @echo "### and %transient-key lines from the script." >&2
-- @echo "###" >&2
-+ @echo "kernel/Makefile:163: ###" >&2
-+ @echo "kernel/Makefile:163: ### CONFIG_MODULE_SIG is enabled so a public key is needed." >&2
-+ @echo "kernel/Makefile:163: ###" >&2
-+ @echo "kernel/Makefile:163: ### Now generating a sample key generation script." >&2
-+ @echo "kernel/Makefile:163: ###" >&2
-+ @echo "kernel/Makefile:163: ### IT IS STRONGLY RECOMMENDED THAT YOU SUPPLY YOUR OWN" >&2
-+ @echo "kernel/Makefile:163: ### SCRIPT WITH APPROPRIATE NAME FIELDS FILLED IN." >&2
-+ @echo "kernel/Makefile:163: ###" >&2
-+ @echo "kernel/Makefile:163: ### If you have a hardware random number generator feeding" >&2
-+ @echo "kernel/Makefile:163: ### into /dev/random, you should drop the %no-protection" >&2
-+ @echo "kernel/Makefile:163: ### and %transient-key lines from the script." >&2
-+ @echo "kernel/Makefile:163: ###" >&2
- echo "%pubring modsign.pub" >genkey
- echo "%secring modsign.sec" >>genkey
- echo "%no-protection: yes" >> genkey
-diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c
-new file mode 100644
-index 0000000..5fdb082
---- /dev/null
-+++ b/kernel/modsign-pubkey.c
-@@ -0,0 +1,75 @@
-+/* Public keys for module signature verification
-+ *
-+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/cred.h>
-+#include <linux/err.h>
-+#include <keys/crypto-type.h>
-+#include "module-verify-defs.h"
-+
-+struct key *modsign_keyring;
-+
-+extern __initdata const u8 modsign_public_keys[];
-+extern __initdata const u8 modsign_public_keys_end[];
-+asm(".section .init.data,\"aw\"\n"
-+ "modsign_public_keys:\n"
-+ ".incbin \"modsign.pub\"\n"
-+ "modsign_public_keys_end:"
-+ );
-+
-+/*
-+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice
-+ * if modsign.pub changes.
-+ */
-+static __initdata const char annoy_ccache[] = __TIME__ "foo";
-+
-+/*
-+ * Load the compiled-in keys
-+ */
-+static __init int module_verify_init(void)
-+{
-+ pr_notice("Initialise module verification\n");
-+
-+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign",
-+ 0, 0, current_cred(),
-+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW | KEY_USR_READ,
-+ KEY_ALLOC_NOT_IN_QUOTA);
-+ if (IS_ERR(modsign_keyring))
-+ panic("Can't allocate module signing keyring\n");
-+
-+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0)
-+ panic("Can't instantiate module signing keyring\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Must be initialised before we try and load the keys into the keyring.
-+ */
-+device_initcall(module_verify_init);
-+
-+/*
-+ * Load the compiled-in keys
-+ */
-+static __init int modsign_pubkey_init(void)
-+{
-+ pr_notice("Load module verification keys\n");
-+
-+ if (preload_pgp_keys(modsign_public_keys,
-+ modsign_public_keys_end - modsign_public_keys,
-+ modsign_keyring) < 0)
-+ panic("Can't load module signing keys\n");
-+
-+ return 0;
-+}
-+late_initcall(modsign_pubkey_init);
-diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h
-index 141ddab..2fe31e1 100644
---- a/kernel/module-verify-defs.h
-+++ b/kernel/module-verify-defs.h
-@@ -11,6 +11,10 @@
-
- #ifdef CONFIG_MODULE_SIG
-
-+#include <linux/module.h>
-+
-+extern struct key *modsign_keyring;
-+
- /*
- * Internal state
- */
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index 4bf857e..05473e6 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -28,8 +28,6 @@
- #include <linux/err.h>
- #include <linux/elf.h>
- #include <linux/elfnote.h>
--#include <linux/sched.h>
--#include <linux/cred.h>
- #include <linux/modsign.h>
- #include <linux/moduleparam.h>
- #include <keys/crypto-type.h>
---
-1.7.11.4
-
-
-From 34c918aacc002f8a7226a26a0d8af614c6f4430e Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:45 +0100
-Subject: [PATCH 26/32] MODSIGN: Check the ELF container
-
-Check the ELF container of the kernel module to prevent the kernel from
-crashing or getting corrupted whilst trying to use it and locate the module
-signature note if present.
-
-We try to check as little as possible. We check the metadata that the
-signature checker actually has to use, and leave anything that it doesn't
-actually need to the signature to catch.
-
-The stuff we need to check is:
-
- (1) The locations and offsets in the ELF header of important parts like the
- section table.
-
- (2) The section table. Note that we only check sh_info for section types that
- we're actually interested in (string, symbol and relocation tables). We
- also check that alignments are what we expect for those tables.
-
- (3) That non-empty string tables have the required NUL at the end so that we
- can be sure that all strings therein are NUL-terminated. We don't bother
- checking for the required NUL at the beginning as it shouldn't cause a
- problem to us.
-
- (4) The name offset and section index in each symbol. We could defer this to
- when we deal with the relocation tables so that we only check symbols that
- are used by relocations - but we would then end up checking some symbols
- multiple times.
-
- (5) The module signature note section and the first note in it if present.
-
- (6) That relocations applied to an allocatable section only refer to
- symbols in allocatable sections and absolute symbols (done in the module
- signing code rather than here).
-
-Note that these checks survive "strip -x", "strip -g" and "eu-strip" being
-applied to a module and detect if the module was given to "strip" or "strip -s"
-and report an error.
-
-We can skip some direct checks that turn out unnecessary or redundant:
-
- (1) That sh_link has a greater than 0 value for symbol tables and relocation
- tables. These require the index of a string table and a symbol table
- respectively - and since we have already checked section 0 is of SHT_NULL
- type, checking the symbol type renders the sh_link > 0 check redundant.
-
- (2) That a non-empty string table begins with a NUL. Since we check the
- string table ends with a NUL, any string in there will be NUL-terminated
- and shouldn't cause us to transgress beyond the bounds of the string table
- when using strlen().
-
- (3) That strings in a string table actually make sense. We don't care, so
- long as it is NUL terminated. Any string that refers to an undefined
- symbol is added to the crypto digest and will be checked that way.
- Strings that we directly look for (such as ".modinfo") will be validated
- by that.
-
- (4) That sections don't overlap. We don't actually care if sections overlap
- in the file, provided we don't see bad metadata. If the sections holding
- the allocatable content overlap, then the signature check is likely to
- fail.
-
- (5) That symbol values and relocation offsets and addends make sense. We just
- add this data to the digest if it pertains to an allocatable section.
-
- (6) That allocatable note sections, other than the signature note, make sense.
- The contents of these get added to the digest in their entirety, so we
- don't need to check them manually.
-
-If bad ELF is detected, ELIBBAD is indicated.
-
-Note! The "noinline" attribute on the module_verify_elf() function results in
-somewhat smaller code. Similarly, having separate loops to check basic section
-parameters and to check type-specific features of sections results in smaller
-code, presumably because some local variables can be discarded.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 230 insertions(+)
-
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index 05473e6..2161d11 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -51,6 +51,228 @@ static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
- static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
-
- /*
-+ * Verify the minimum amount of ELF structure of a module needed to check the
-+ * module's signature without bad ELF crashing the kernel.
-+ */
-+static noinline int module_verify_elf(struct module_verify_data *mvdata)
-+{
-+ const struct elf_note *note;
-+ const Elf_Ehdr *hdr = mvdata->hdr;
-+ const Elf_Shdr *section, *secstop;
-+ const Elf_Sym *symbols, *symbol, *symstop;
-+ const char *strtab;
-+ size_t size, secstrsize, strsize, notesize, notemetasize;
-+ unsigned line;
-+
-+ size = mvdata->size;
-+
-+#define elfcheck(X) \
-+do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while (0)
-+
-+#define seccheck(X) \
-+do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while (0)
-+
-+#define symcheck(X) \
-+do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0)
-+
-+ /* Validate the ELF header */
-+ elfcheck(size > sizeof(Elf_Ehdr));
-+ elfcheck(hdr->e_ehsize < size);
-+
-+ elfcheck(hdr->e_shnum < SHN_LORESERVE);
-+ elfcheck(hdr->e_shstrndx < hdr->e_shnum);
-+ elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
-+ elfcheck(hdr->e_shoff < size);
-+ elfcheck(hdr->e_shoff >= hdr->e_ehsize);
-+ elfcheck(hdr->e_shoff % sizeof(long) == 0);
-+ elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff);
-+
-+ /* Validate the section table contents */
-+ mvdata->nsects = hdr->e_shnum;
-+ mvdata->sections = mvdata->buffer + hdr->e_shoff;
-+ secstop = mvdata->sections + mvdata->nsects;
-+
-+ /* Section 0 is special, usually indicating an undefined symbol */
-+ section = &mvdata->sections[SHN_UNDEF];
-+ seccheck(section->sh_type == SHT_NULL);
-+
-+ /* We also want access to the section name table */
-+ section = &mvdata->sections[hdr->e_shstrndx];
-+ seccheck(section->sh_type == SHT_STRTAB);
-+ secstrsize = mvdata->sections[hdr->e_shstrndx].sh_size;
-+
-+ for (section = mvdata->sections + 1; section < secstop; section++) {
-+ seccheck(section->sh_name < secstrsize);
-+ seccheck(section->sh_link < hdr->e_shnum);
-+
-+ /* Section file offsets must reside within the file, though
-+ * they don't have to actually consume file space (.bss for
-+ * example).
-+ */
-+ seccheck(section->sh_offset >= hdr->e_ehsize);
-+ if (section->sh_addralign > 1)
-+ seccheck((section->sh_offset &
-+ (section->sh_addralign - 1)) == 0);
-+ seccheck(section->sh_offset <= size);
-+ if (section->sh_type != SHT_NOBITS)
-+ seccheck(section->sh_size <= size - section->sh_offset);
-+
-+ /* Some types of section should contain arrays of fixed-length
-+ * records of a predetermined size and mustn't contain partial
-+ * records. Also, records we're going to access directly must
-+ * have appropriate alignment that we don't get a misalignment
-+ * exception.
-+ */
-+ if (section->sh_entsize > 1)
-+ seccheck(section->sh_size % section->sh_entsize == 0);
-+
-+ switch (section->sh_type) {
-+ case SHT_SYMTAB:
-+ seccheck(section->sh_entsize == sizeof(Elf_Sym));
-+ seccheck(section->sh_addralign % sizeof(long) == 0);
-+ break;
-+ case SHT_REL:
-+#ifdef Elf_Rel
-+ seccheck(section->sh_entsize == sizeof(Elf_Rel));
-+ seccheck(section->sh_addralign % sizeof(long) == 0);
-+ break;
-+#else
-+ seccheck(false);
-+ break;
-+#endif
-+ case SHT_RELA:
-+#ifdef Elf_Rela
-+ seccheck(section->sh_entsize == sizeof(Elf_Rela));
-+ seccheck(section->sh_addralign % sizeof(long) == 0);
-+ break;
-+#else
-+ seccheck(false);
-+ break;
-+#endif
-+ case SHT_NOTE:
-+ seccheck(section->sh_addralign % 4 == 0);
-+ break;
-+ case SHT_STRTAB:
-+ /* We require all string tables to be non-empty. If
-+ * not empty, a string table must end in a NUL (it
-+ * should also begin with a NUL, but it's not a problem
-+ * for us if it doesn't).
-+ */
-+ seccheck(section->sh_size >= 2);
-+ strtab = mvdata->buffer + section->sh_offset;
-+ seccheck(strtab[section->sh_size - 1] == '\0');
-+ break;
-+ }
-+ }
-+
-+ /* Check features specific to the type of each section.
-+ *
-+ * Note that having a separate loop here allows the compiler to discard
-+ * some local variables used in the above loop thus making the code
-+ * smaller.
-+ */
-+ for (section = mvdata->sections + 1; section < secstop; section++) {
-+ switch (section->sh_type) {
-+ case SHT_SYMTAB:
-+ /* Symbol tables nominate a string table. */
-+ seccheck(mvdata->sections[section->sh_link].sh_type ==
-+ SHT_STRTAB);
-+
-+ /* Validate the symbols in the table. The first symbol
-+ * (STN_UNDEF) is special.
-+ */
-+ symbol = symbols = mvdata->buffer + section->sh_offset;
-+ symstop = mvdata->buffer +
-+ (section->sh_offset + section->sh_size);
-+
-+ symcheck(ELF_ST_TYPE(symbols[0].st_info) == STT_NOTYPE);
-+ symcheck(symbol[0].st_shndx == SHN_UNDEF);
-+
-+ strsize = mvdata->sections[section->sh_link].sh_size;
-+ for (symbol++; symbol < symstop; symbol++) {
-+ symcheck(symbol->st_name < strsize);
-+ symcheck(symbol->st_shndx < hdr->e_shnum ||
-+ symbol->st_shndx >= SHN_LORESERVE);
-+ }
-+ break;
-+
-+#ifdef Elf_Rel
-+ case SHT_REL:
-+#endif
-+#ifdef Elf_Rela
-+ case SHT_RELA:
-+#endif
-+ /* Relocation tables nominate a symbol table and a
-+ * target section to which the relocations will be
-+ * applied.
-+ */
-+ seccheck(mvdata->sections[section->sh_link].sh_type ==
-+ SHT_SYMTAB);
-+ seccheck(section->sh_info > 0);
-+ seccheck(section->sh_info < hdr->e_shnum);
-+ break;
-+ }
-+ }
-+
-+ /* We can now use section name string table section as we checked its
-+ * bounds in the loop above.
-+ *
-+ * Each name is NUL-terminated, and the table as a whole should have a
-+ * NUL at either end as there to be at least one named section for the
-+ * module information.
-+ */
-+ section = &mvdata->sections[hdr->e_shstrndx];
-+ mvdata->secstrings = mvdata->buffer + section->sh_offset;
-+
-+ for (section = mvdata->sections + 1; section < secstop; section++) {
-+ const char *name = mvdata->secstrings + section->sh_name;
-+
-+ switch (section->sh_type) {
-+ case SHT_NOTE:
-+ if (strcmp(name, modsign_note_section) != 0)
-+ continue;
-+
-+ /* We've found a note purporting to contain a signature
-+ * so we should check the structure of that.
-+ */
-+ notemetasize = sizeof(struct elf_note) +
-+ roundup(sizeof(modsign_note_name), 4);
-+
-+ seccheck(mvdata->sig_index == 0);
-+ seccheck(section->sh_size > notemetasize);
-+ note = mvdata->buffer + section->sh_offset;
-+ seccheck(note->n_type == MODSIGN_NOTE_TYPE);
-+ seccheck(note->n_namesz == sizeof(modsign_note_name));
-+
-+ notesize = section->sh_size - notemetasize;
-+ seccheck(note->n_descsz <= notesize);
-+
-+ seccheck(memcmp(note + 1, modsign_note_name,
-+ note->n_namesz) == 0);
-+
-+ mvdata->sig_size = note->n_descsz;
-+ mvdata->sig = (void *)note + notemetasize;
-+ mvdata->sig_index = section - mvdata->sections;
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+
-+elfcheck_error:
-+ _debug("Verify ELF error (check %u)\n", line);
-+ return -ELIBBAD;
-+seccheck_error:
-+ _debug("Verify ELF error [sec %ld] (check %u)\n",
-+ (long)(section - mvdata->sections), line);
-+ return -ELIBBAD;
-+symcheck_error:
-+ _debug("Verify ELF error [sym %ld] (check %u)\n",
-+ (long)(symbol - symbols), line);
-+ return -ELIBBAD;
-+}
-+
-+/*
- * Verify a module's integrity
- */
- int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
-@@ -62,6 +284,14 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
- mvdata.buffer = hdr;
- mvdata.size = size;
-
-+ /* Minimally check the ELF to make sure building the signature digest
-+ * won't crash the kernel.
-+ */
-+ ret = module_verify_elf(&mvdata);
-+ if (ret < 0)
-+ goto out;
-+
-+ /* The ELF checker found the sig for us if it exists */
- if (mvdata.sig_index <= 0) {
- /* Deal with an unsigned module */
- if (modsign_signedonly) {
---
-1.7.11.4
-
-
-From 2de4559e24c416e6813c10edbe3cc433ecd0dd50 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 27/32] MODSIGN: Produce a filtered and canonicalised section
- list
-
-Build a list of the sections in which we're interested and canonicalise the
-section indices to avoid the problems of the section table being altered by ld
-when the signature is linked into the binary and by strip.
-
-The only sections in which we're actually interested are those that are marked
-allocatable (which will be kept in memory) and relocation tables that are
-applicable to those sections.
-
-Canonicalisation is done by sorting the filtered list in order of section name.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 80 insertions(+)
-
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index 2161d11..646b104 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -273,6 +273,80 @@ symcheck_error:
- }
-
- /*
-+ * Canonicalise the section table index numbers.
-+ *
-+ * We build a list of the sections we want to add to the digest and sort it by
-+ * name. We're only interested in adding two types of section:
-+ *
-+ * (1) Allocatable sections. These should have no references to other
-+ * sections.
-+ *
-+ * (2) Relocation tables for allocatable sections. The section table entry
-+ * has a reference to the target section to which the relocations will be
-+ * applied. The relocation entries have references to symbols in
-+ * non-allocatable sections. Symbols can be replaced by their contents,
-+ * but do include a further reference to a section - which must be
-+ * canonicalised.
-+ *
-+ * We also build a map of raw section index to canonical section index.
-+ */
-+static int module_verify_canonicalise(struct module_verify_data *mvdata)
-+{
-+ const Elf_Shdr *sechdrs = mvdata->sections;
-+ unsigned *canonlist, canon, loop, tmp;
-+ bool changed;
-+
-+ canonlist = kmalloc(sizeof(unsigned) * mvdata->nsects * 2, GFP_KERNEL);
-+ if (!canonlist)
-+ return -ENOMEM;
-+
-+ mvdata->canonlist = canonlist;
-+ mvdata->canonmap = canonlist + mvdata->nsects;
-+ canon = 0;
-+
-+ for (loop = 1; loop < mvdata->nsects; loop++) {
-+ const Elf_Shdr *section = mvdata->sections + loop;
-+
-+ if (loop == mvdata->sig_index)
-+ continue;
-+
-+ /* We only want allocatable sections and relocation tables */
-+ if (section->sh_flags & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+ else if ((is_elf_rel(section->sh_type) ||
-+ is_elf_rela(section->sh_type)) &&
-+ mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC)
-+ canonlist[canon++] = loop;
-+ }
-+
-+ /* Sort the canonicalisation list */
-+ do {
-+ changed = false;
-+
-+ for (loop = 0; loop < canon - 1; loop++) {
-+ const char *x, *y;
-+
-+ x = mvdata->secstrings + sechdrs[canonlist[loop + 0]].sh_name;
-+ y = mvdata->secstrings + sechdrs[canonlist[loop + 1]].sh_name;
-+
-+ if (strcmp(x, y) > 0) {
-+ tmp = canonlist[loop + 0];
-+ canonlist[loop + 0] = canonlist[loop + 1];
-+ canonlist[loop + 1] = tmp;
-+ changed = true;
-+ }
-+ }
-+ } while (changed);
-+
-+ /* What we really want is a raw-to-canon lookup table */
-+ memset(mvdata->canonmap, 0xff, mvdata->nsects * sizeof(unsigned));
-+ for (loop = 0; loop < canon; loop++)
-+ mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
-+ mvdata->ncanon = canon;
-+ return 0;
-+}
-+
-+/*
- * Verify a module's integrity
- */
- int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
-@@ -303,7 +377,13 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
- goto out;
- }
-
-+ /* Produce a canonicalisation map for the sections */
-+ ret = module_verify_canonicalise(&mvdata);
-+ if (ret < 0)
-+ goto out;
-+
- ret = 0;
-+ kfree(mvdata.canonlist);
-
- out:
- switch (ret) {
---
-1.7.11.4
-
-
-From 3c8e71a46663f1fc3ee49fe3f6fa5c3bb85b704c Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 28/32] MODSIGN: Create digest of module content and check
- signature
-
-Apply signature checking to modules on module load, checking the signature
-against the ring of public keys compiled into the kernel (if enabled by
-CONFIG_MODULE_SIG). Turning on signature checking will also force the module's
-ELF metadata to be verified first.
-
-There are several reasons why these patches are useful, amongst which are:
-
- (1) to prevent accidentally corrupted modules from causing damage;
-
- (2) to prevent maliciously modified modules from causing damage;
-
- (3) to allow a sysadmin (or more likely an IT department) to enforce a policy
- that only known and approved modules shall be loaded onto machines which
- they're expected to support;
-
- (4) to allow other support providers to do likewise, or at least to _detect_
- the fact that unsupported modules are loaded;
-
- (5) to allow the detection of modules replaced by a second-order distro or a
- preloaded Linux purveyor.
-
-These patches have two main appeals: (a) preventing malicious modules from
-being loaded, and (b) reducing support workload by pointing out modules on a
-crashing box that aren't what they're expected to be.
-
-Note that this is not a complete solution by any means: the core kernel is not
-protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least
-controls) one relatively simple attack vector. To protect the kernel image
-would be the responsibility of the boot loader or the system BIOS.
-
-This facility is optional: the builder of a kernel is by no means under any
-requirement to actually enable it, let alone force the set of loadable modules
-to be restricted to just those that the builder provides (there are degrees of
-restriction available).
-
-Note! The "noinline" attribute on module_verify_signature() results in
-somewhat smaller code.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify-defs.h | 13 +-
- kernel/module-verify.c | 332 +++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 338 insertions(+), 7 deletions(-)
-
-diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h
-index 2fe31e1..cb477a2 100644
---- a/kernel/module-verify-defs.h
-+++ b/kernel/module-verify-defs.h
-@@ -19,7 +19,7 @@ extern struct key *modsign_keyring;
- * Internal state
- */
- struct module_verify_data {
-- struct crypto_key_verify_context *mod_sig; /* Module signing context */
-+ struct crypto_sig_verify_context *mod_sig; /* Module signing context */
- union {
- const void *buffer; /* module buffer */
- const Elf_Ehdr *hdr; /* ELF header */
-@@ -42,15 +42,16 @@ struct module_verify_data {
- /*
- * Whether or not we support various types of ELF relocation record
- */
--#if defined(MODULE_HAS_ELF_REL_ONLY)
-+#ifdef Elf_Rel
- #define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
--#define is_elf_rela(sh_type) (0)
--#elif defined(MODULE_HAS_ELF_RELA_ONLY)
-+#else
- #define is_elf_rel(sh_type) (0)
-+#endif
-+
-+#ifdef Elf_Rela
- #define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
- #else
--#define is_elf_rel(sh_type) ((sh_type) == SHT_REL)
--#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA)
-+#define is_elf_rela(sh_type) (0)
- #endif
-
- /*
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index 646b104..bee7e04 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -50,6 +50,22 @@ static bool modsign_signedonly;
- static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME);
- static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME);
-
-+#define crypto_digest_update_data(C, PTR, N) \
-+do { \
-+ uint8_t *__p = (uint8_t *)(PTR); \
-+ size_t __n = (N); \
-+ count_and_csum((C), __p, __n); \
-+ verify_sig_add_data((C)->mod_sig, __p, __n); \
-+} while (0)
-+
-+#define crypto_digest_update_val(C, VAL) \
-+do { \
-+ uint8_t *__p = (uint8_t *)&(VAL); \
-+ size_t __n = sizeof(VAL); \
-+ count_and_csum((C), __p, __n); \
-+ verify_sig_add_data((C)->mod_sig, __p, __n); \
-+} while (0)
-+
- /*
- * Verify the minimum amount of ELF structure of a module needed to check the
- * module's signature without bad ELF crashing the kernel.
-@@ -346,6 +362,320 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata)
- return 0;
- }
-
-+#ifdef Elf_Rel
-+/*
-+ * Extract an ELF REL table
-+ *
-+ * We need to canonicalise the entries in case section/symbol addition/removal
-+ * has rearranged the symbol table and the section table.
-+ */
-+static int extract_elf_rel(struct module_verify_data *mvdata,
-+ unsigned secix,
-+ const Elf_Rel *reltab, size_t nrels,
-+ const char *sh_name)
-+{
-+ struct {
-+#ifdef CONFIG_64BIT
-+ uint64_t r_offset;
-+ uint64_t st_value;
-+ uint64_t st_size;
-+ uint32_t r_type;
-+ uint16_t st_shndx;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+#else
-+ uint32_t r_offset;
-+ uint32_t st_value;
-+ uint32_t st_size;
-+ uint16_t st_shndx;
-+ uint8_t r_type;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+#endif
-+ } __packed relocation;
-+
-+ const Elf_Shdr *relsec, *symsec, *strsec;
-+ const Elf_Rel *reloc;
-+ const Elf_Sym *symbols, *symbol;
-+ const char *strings;
-+ unsigned long r_sym;
-+ size_t nsyms, loop;
-+
-+ relsec = &mvdata->sections[secix];
-+ symsec = &mvdata->sections[relsec->sh_link];
-+ strsec = &mvdata->sections[symsec->sh_link];
-+ nsyms = symsec->sh_size / sizeof(Elf_Sym);
-+ symbols = mvdata->buffer + symsec->sh_offset;
-+ strings = mvdata->buffer + strsec->sh_offset;
-+
-+ /* Contribute the relevant bits from a join of
-+ * { REL, SYMBOL, SECTION }
-+ */
-+ for (loop = 0; loop < nrels; loop++) {
-+ unsigned st_shndx;
-+
-+ reloc = &reltab[loop];
-+
-+ /* Decode the relocation */
-+ relocation.r_offset = reloc->r_offset;
-+ relocation.r_type = ELF_R_TYPE(reloc->r_info);
-+
-+ /* Decode the symbol referenced by the relocation */
-+ r_sym = ELF_R_SYM(reloc->r_info);
-+ if (r_sym >= nsyms)
-+ return -ELIBBAD;
-+ symbol = &symbols[r_sym];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = symbol->st_shndx;
-+ st_shndx = symbol->st_shndx;
-+
-+ /* Canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) {
-+ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC))
-+ return -ELIBBAD;
-+ relocation.st_shndx = mvdata->canonmap[st_shndx];
-+ }
-+
-+ crypto_digest_update_val(mvdata, relocation);
-+
-+ /* Undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + symbol->st_name;
-+ crypto_digest_update_data(mvdata,
-+ name, strlen(name) + 1);
-+ }
-+ }
-+
-+ _debug("%08zx %02x digested the %s section, nrels %zu\n",
-+ mvdata->signed_size, mvdata->csum, sh_name, nrels);
-+
-+ return 0;
-+}
-+#endif
-+
-+#ifdef Elf_Rela
-+/*
-+ * Extract an ELF RELA table
-+ *
-+ * We need to canonicalise the entries in case section/symbol addition/removal
-+ * has rearranged the symbol table and the section table.
-+ */
-+static int extract_elf_rela(struct module_verify_data *mvdata,
-+ unsigned secix,
-+ const Elf_Rela *relatab, size_t nrels,
-+ const char *sh_name)
-+{
-+ struct {
-+#ifdef CONFIG_64BIT
-+ uint64_t r_offset;
-+ uint64_t r_addend;
-+ uint64_t st_value;
-+ uint64_t st_size;
-+ uint32_t r_type;
-+ uint16_t st_shndx;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+#else
-+ uint32_t r_offset;
-+ uint32_t r_addend;
-+ uint32_t st_value;
-+ uint32_t st_size;
-+ uint16_t st_shndx;
-+ uint8_t r_type;
-+ uint8_t st_info;
-+ uint8_t st_other;
-+#endif
-+ } __packed relocation;
-+
-+ const Elf_Shdr *relsec, *symsec, *strsec;
-+ const Elf_Rela *reloc;
-+ const Elf_Sym *symbols, *symbol;
-+ unsigned long r_sym;
-+ const char *strings;
-+ size_t nsyms, loop;
-+
-+ relsec = &mvdata->sections[secix];
-+ symsec = &mvdata->sections[relsec->sh_link];
-+ strsec = &mvdata->sections[symsec->sh_link];
-+ nsyms = symsec->sh_size / sizeof(Elf_Sym);
-+ symbols = mvdata->buffer + symsec->sh_offset;
-+ strings = mvdata->buffer + strsec->sh_offset;
-+
-+ /* Contribute the relevant bits from a join of
-+ * { RELA, SYMBOL, SECTION }
-+ */
-+ for (loop = 0; loop < nrels; loop++) {
-+ unsigned st_shndx;
-+
-+ reloc = &relatab[loop];
-+
-+ /* Decode the relocation */
-+ relocation.r_offset = reloc->r_offset;
-+ relocation.r_addend = reloc->r_addend;
-+ relocation.r_type = ELF_R_TYPE(reloc->r_info);
-+
-+ /* Decode the symbol referenced by the relocation */
-+ r_sym = ELF_R_SYM(reloc->r_info);
-+ if (r_sym >= nsyms)
-+ return -ELIBBAD;
-+ symbol = &symbols[r_sym];
-+ relocation.st_info = symbol->st_info;
-+ relocation.st_other = symbol->st_other;
-+ relocation.st_value = symbol->st_value;
-+ relocation.st_size = symbol->st_size;
-+ relocation.st_shndx = 0;
-+ st_shndx = symbol->st_shndx;
-+
-+ /* Canonicalise the section used by the symbol */
-+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) {
-+ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC))
-+ return -ELIBBAD;
-+ relocation.st_shndx = mvdata->canonmap[st_shndx];
-+ }
-+
-+ crypto_digest_update_val(mvdata, relocation);
-+
-+ /* Undefined symbols must be named if referenced */
-+ if (st_shndx == SHN_UNDEF) {
-+ const char *name = strings + symbol->st_name;
-+ crypto_digest_update_data(mvdata,
-+ name, strlen(name) + 1);
-+ }
-+ }
-+
-+ _debug("%08zx %02x digested the %s section, nrels %zu\n",
-+ mvdata->signed_size, mvdata->csum, sh_name, nrels);
-+
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Verify a module's signature
-+ */
-+static noinline int module_verify_signature(struct module_verify_data *mvdata)
-+{
-+ struct crypto_sig_verify_context *mod_sig;
-+ const Elf_Shdr *sechdrs = mvdata->sections;
-+ const char *secstrings = mvdata->secstrings;
-+ const u8 *sig = mvdata->sig;
-+ size_t sig_size = mvdata->sig_size;
-+ int loop, ret;
-+
-+ _debug("sig in section %u (size %zu)\n",
-+ mvdata->sig_index, mvdata->sig_size);
-+ _debug("%02x%02x%02x%02x%02x%02x%02x%02x\n",
-+ sig[0], sig[1], sig[2], sig[3],
-+ sig[4], sig[5], sig[6], sig[7]);
-+
-+ /* Find the crypto key for the module signature
-+ * - !!! if this tries to load the required hash algorithm module,
-+ * we will deadlock!!!
-+ */
-+ mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size);
-+ if (IS_ERR(mod_sig)) {
-+ pr_err("Couldn't initiate module signature verification: %ld\n",
-+ PTR_ERR(mod_sig));
-+ return PTR_ERR(mod_sig);
-+ }
-+
-+ mvdata->mod_sig = mod_sig;
-+#ifdef DEBUG
-+ mvdata->xcsum = 0;
-+#endif
-+
-+ /* Load data from each relevant section into the digest. Note that
-+ * canonlist[] is a filtered list and only contains the sections we
-+ * actually want.
-+ */
-+ for (loop = 0; loop < mvdata->ncanon; loop++) {
-+ int sect = mvdata->canonlist[loop];
-+ unsigned long sh_type = sechdrs[sect].sh_type;
-+ unsigned long sh_info = sechdrs[sect].sh_info;
-+ unsigned long sh_size = sechdrs[sect].sh_size;
-+ const char *sh_name = secstrings + sechdrs[sect].sh_name;
-+ const void *data = mvdata->buffer + sechdrs[sect].sh_offset;
-+
-+#ifdef DEBUG
-+ mvdata->csum = 0;
-+#endif
-+
-+ /* Digest the headers of any section we include. */
-+ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
-+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type);
-+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags);
-+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size);
-+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign);
-+
-+ /* Relocation record sections refer to the section to be
-+ * relocated, but this needs to be canonicalised to survive
-+ * stripping.
-+ */
-+ if (is_elf_rel(sh_type) || is_elf_rela(sh_type))
-+ crypto_digest_update_val(mvdata,
-+ mvdata->canonmap[sh_info]);
-+
-+ /* Since relocation records give details of how we have to
-+ * alter the allocatable sections, we need to digest these too.
-+ *
-+ * These, however, refer to metadata (symbols and sections)
-+ * that may have been altered by the process of adding the
-+ * signature section or the process of being stripped.
-+ *
-+ * To deal with this, we substitute the referenced metadata for
-+ * the references to that metadata. So, for instance, the
-+ * symbol ref from the relocation record is replaced with the
-+ * contents of the symbol to which it refers, and the symbol's
-+ * section ref is replaced with a canonicalised section number.
-+ */
-+#ifdef Elf_Rel
-+ if (is_elf_rel(sh_type)) {
-+ ret = extract_elf_rel(mvdata, sect,
-+ data,
-+ sh_size / sizeof(Elf_Rel),
-+ sh_name);
-+ if (ret < 0)
-+ goto format_error;
-+ continue;
-+ }
-+#endif
-+
-+#ifdef Elf_Rela
-+ if (is_elf_rela(sh_type)) {
-+ ret = extract_elf_rela(mvdata, sect,
-+ data,
-+ sh_size / sizeof(Elf_Rela),
-+ sh_name);
-+ if (ret < 0)
-+ goto format_error;
-+ continue;
-+ }
-+#endif
-+
-+ /* Include allocatable loadable sections */
-+ if (sh_type != SHT_NOBITS)
-+ crypto_digest_update_data(mvdata, data, sh_size);
-+
-+ _debug("%08zx %02x digested the %s section, size %ld\n",
-+ mvdata->signed_size, mvdata->csum, sh_name, sh_size);
-+ }
-+
-+ _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
-+ mvdata->signed_size, mvdata->xcsum);
-+
-+ /* Do the actual signature verification */
-+ ret = verify_sig_end(mvdata->mod_sig, sig, sig_size);
-+ _debug("verify-sig : %d\n", ret);
-+ return ret;
-+
-+format_error:
-+ verify_sig_cancel(mvdata->mod_sig);
-+ return -ELIBBAD;
-+}
-+
- /*
- * Verify a module's integrity
- */
-@@ -382,7 +712,7 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
- if (ret < 0)
- goto out;
-
-- ret = 0;
-+ ret = module_verify_signature(&mvdata);
- kfree(mvdata.canonlist);
-
- out:
---
-1.7.11.4
-
-
-From 53142a9c74e2922885d03555d26213fc38553b90 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 29/32] MODSIGN: Suppress some redundant ELF checks
-
-Suppress some redundant ELF checks in module_verify_elf() that are also done
-by copy_and_check() in the core module loader code prior to calling
-module_verify().
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index bee7e04..f3a694f 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -97,11 +97,11 @@ do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0)
-
- elfcheck(hdr->e_shnum < SHN_LORESERVE);
- elfcheck(hdr->e_shstrndx < hdr->e_shnum);
-- elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr));
-- elfcheck(hdr->e_shoff < size);
-+ /* elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); */
-+ /* elfcheck(hdr->e_shoff < size); */
- elfcheck(hdr->e_shoff >= hdr->e_ehsize);
- elfcheck(hdr->e_shoff % sizeof(long) == 0);
-- elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff);
-+ /* elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); */
-
- /* Validate the section table contents */
- mvdata->nsects = hdr->e_shnum;
---
-1.7.11.4
-
-
-From 14d36171021b1c16f6c664bd4ab31e1d989ab282 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 30/32] MODSIGN: Panic the kernel if FIPS is enabled upon
- module signing failure
-
-If module signing fails when the kernel is running with FIPS enabled then the
-kernel should panic lest the crypto layer be compromised. Possibly a panic
-shouldn't happen on cases like ENOMEM.
-
-Reported-by: Stephan Mueller <stephan.mueller@atsec.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index f3a694f..896c0ff 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -30,6 +30,7 @@
- #include <linux/elfnote.h>
- #include <linux/modsign.h>
- #include <linux/moduleparam.h>
-+#include <linux/fips.h>
- #include <keys/crypto-type.h>
- #include "module-verify.h"
- #include "module-verify-defs.h"
-@@ -716,6 +717,10 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok)
- kfree(mvdata.canonlist);
-
- out:
-+ if (ret < 0 && fips_enabled)
-+ panic("Module verification failed with error %d in FIPS mode\n",
-+ ret);
-+
- switch (ret) {
- case 0: /* Good signature */
- *_gpgsig_ok = true;
---
-1.7.11.4
-
-
-From 1e8e625508f013acfb8ade3b5c30dcc7ff710ce9 Mon Sep 17 00:00:00 2001
-From: Josh Boyer <jwboyer@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 31/32] MODSIGN: Allow modules to be signed with an unknown
- key unless enforcing
-
-Currently we fail the loading of modules that are signed with a public key
-that is not in the modsign keyring even if we are not in enforcing mode.
-This is somewhat at odds with the fact that we allow a completely unsigned
-module to load in such a case.
-
-We should allow modules signed with an unknown key to load in cases
-where we are not enforcing and not in FIPS mode.
-
-Signed-off-by: Josh Boyer <jwboyer@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/module-verify.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/kernel/module-verify.c b/kernel/module-verify.c
-index 896c0ff..041506f 100644
---- a/kernel/module-verify.c
-+++ b/kernel/module-verify.c
-@@ -736,6 +736,13 @@ out:
- break;
- case -ENOKEY: /* Signed, but we don't have the public key */
- pr_err("Module signed with unknown public key\n");
-+ if (!modsign_signedonly) {
-+ /* Allow a module to be signed with an unknown public
-+ * key unless we're enforcing.
-+ */
-+ pr_info("Allowing\n");
-+ ret = 0;
-+ }
- break;
- default: /* Other error (probably ENOMEM) */
- break;
---
-1.7.11.4
-
-
-From 7ac7095ee6624789c6a971d16f5ca823ebbde3c7 Mon Sep 17 00:00:00 2001
-From: Peter Jones <pjones@redhat.com>
-Date: Thu, 16 Aug 2012 01:38:46 +0100
-Subject: [PATCH 32/32] MODSIGN: Fix documentation of signed-nokey behavior
- when not enforcing.
-
-jwboyer's previous commit changes the behavior of module signing when
-there's a valid signature but we don't know the public key and are in
-permissive mode. This updates the documentation to match.
-
-Signed-off-by: Peter Jones <pjones@redhat.com>
-Acked-by: Josh Boyer <jwboyer@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/module-signing.txt | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
-index d75d473..8c4bef9 100644
---- a/Documentation/module-signing.txt
-+++ b/Documentation/module-signing.txt
-@@ -185,7 +185,7 @@ This table indicates the behaviours of the various situations:
- MODULE STATE PERMISSIVE MODE ENFORCING MODE
- ======================================= =============== ===============
- Unsigned Ok EKEYREJECTED
-- Signed, no public key ENOKEY ENOKEY
-+ Signed, no public key Ok ENOKEY
- Validly signed, public key Ok Ok
- Invalidly signed, public key EKEYREJECTED EKEYREJECTED
- Validly signed, expired key EKEYEXPIRED EKEYEXPIRED
---
-1.7.11.4
-