summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/842.c1
-rw-r--r--crypto/Kconfig34
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/aes_generic.c2
-rw-r--r--crypto/af_alg.c11
-rw-r--r--crypto/ahash.c12
-rw-r--r--crypto/algapi.c4
-rw-r--r--crypto/algif_hash.c10
-rw-r--r--crypto/algif_skcipher.c31
-rw-r--r--crypto/ansi_cprng.c2
-rw-r--r--crypto/anubis.c1
-rw-r--r--crypto/api.c4
-rw-r--r--crypto/arc4.c1
-rw-r--r--crypto/asymmetric_keys/asymmetric_keys.h5
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c265
-rw-r--r--crypto/asymmetric_keys/pkcs7_key_type.c2
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c99
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.h6
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c90
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c102
-rw-r--r--crypto/asymmetric_keys/signature.c1
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c57
-rw-r--r--crypto/asymmetric_keys/x509_parser.h8
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c115
-rw-r--r--crypto/async_tx/async_xor.c3
-rw-r--r--crypto/authenc.c1
-rw-r--r--crypto/authencesn.c1
-rw-r--r--crypto/blowfish_generic.c2
-rw-r--r--crypto/camellia_generic.c2
-rw-r--r--crypto/cast5_generic.c2
-rw-r--r--crypto/cast6_generic.c2
-rw-r--r--crypto/cbc.c1
-rw-r--r--crypto/ccm.c5
-rw-r--r--crypto/chainiv.c1
-rw-r--r--crypto/cmac.c1
-rw-r--r--crypto/crc32.c1
-rw-r--r--crypto/crc32c_generic.c2
-rw-r--r--crypto/crct10dif_generic.c2
-rw-r--r--crypto/cryptd.c1
-rw-r--r--crypto/crypto_null.c6
-rw-r--r--crypto/crypto_user.c6
-rw-r--r--crypto/ctr.c3
-rw-r--r--crypto/cts.c4
-rw-r--r--crypto/deflate.c2
-rw-r--r--crypto/des_generic.c2
-rw-r--r--crypto/drbg.c257
-rw-r--r--crypto/ecb.c1
-rw-r--r--crypto/eseqiv.c1
-rw-r--r--crypto/fcrypt.c1
-rw-r--r--crypto/gcm.c7
-rw-r--r--crypto/ghash-generic.c2
-rw-r--r--crypto/hmac.c26
-rw-r--r--crypto/khazad.c1
-rw-r--r--crypto/krng.c2
-rw-r--r--crypto/lrw.c1
-rw-r--r--crypto/lz4.c3
-rw-r--r--crypto/lz4hc.c3
-rw-r--r--crypto/lzo.c1
-rw-r--r--crypto/mcryptd.c706
-rw-r--r--crypto/md4.c2
-rw-r--r--crypto/md5.c1
-rw-r--r--crypto/michael_mic.c1
-rw-r--r--crypto/pcbc.c1
-rw-r--r--crypto/pcrypt.c1
-rw-r--r--crypto/rmd128.c1
-rw-r--r--crypto/rmd160.c1
-rw-r--r--crypto/rmd256.c1
-rw-r--r--crypto/rmd320.c1
-rw-r--r--crypto/salsa20_generic.c2
-rw-r--r--crypto/seed.c1
-rw-r--r--crypto/seqiv.c1
-rw-r--r--crypto/serpent_generic.c4
-rw-r--r--crypto/sha1_generic.c4
-rw-r--r--crypto/sha256_generic.c12
-rw-r--r--crypto/sha512_generic.c9
-rw-r--r--crypto/tcrypt.c32
-rw-r--r--crypto/tea.c4
-rw-r--r--crypto/testmgr.c983
-rw-r--r--crypto/testmgr.h66
-rw-r--r--crypto/tgr192.c8
-rw-r--r--crypto/twofish_generic.c2
-rw-r--r--crypto/vmac.c3
-rw-r--r--crypto/wp512.c12
-rw-r--r--crypto/xcbc.c1
-rw-r--r--crypto/xts.c1
-rw-r--r--crypto/zlib.c1
86 files changed, 2095 insertions, 987 deletions
diff --git a/crypto/842.c b/crypto/842.c
index 65c7a89cfa09..b48f4f108c47 100644
--- a/crypto/842.c
+++ b/crypto/842.c
@@ -180,3 +180,4 @@ module_exit(nx842_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("842 Compression Algorithm");
+MODULE_ALIAS_CRYPTO("842");
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 00b5906f57b7..87bbc9c1e681 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -158,6 +158,20 @@ config CRYPTO_CRYPTD
converts an arbitrary synchronous software crypto algorithm
into an asynchronous algorithm that executes in a kernel thread.
+config CRYPTO_MCRYPTD
+ tristate "Software async multi-buffer crypto daemon"
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_HASH
+ select CRYPTO_MANAGER
+ select CRYPTO_WORKQUEUE
+ help
+ This is a generic software asynchronous crypto daemon that
+ provides the kernel thread to assist multi-buffer crypto
+ algorithms for submitting jobs and flushing jobs in multi-buffer
+ crypto algorithms. Multi-buffer crypto algorithms are executed
+ in the context of this kernel thread and drivers can post
+ their crypto request asynchronously to be processed by this daemon.
+
config CRYPTO_AUTHENC
tristate "Authenc support"
select CRYPTO_AEAD
@@ -543,7 +557,7 @@ config CRYPTO_SHA1_ARM
config CRYPTO_SHA1_ARM_NEON
tristate "SHA1 digest algorithm (ARM NEON)"
- depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+ depends on ARM && KERNEL_MODE_NEON
select CRYPTO_SHA1_ARM
select CRYPTO_SHA1
select CRYPTO_HASH
@@ -559,6 +573,22 @@ config CRYPTO_SHA1_PPC
This is the powerpc hardware accelerated implementation of the
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+config CRYPTO_SHA1_MB
+ tristate "SHA1 digest algorithm (x86_64 Multi-Buffer, Experimental)"
+ depends on X86 && 64BIT
+ select CRYPTO_SHA1
+ select CRYPTO_HASH
+ select CRYPTO_MCRYPTD
+ help
+ SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+ using multi-buffer technique. This algorithm computes on
+ multiple data lanes concurrently with SIMD instructions for
+ better throughput. It should not be enabled by default but
+ used when there is significant amount of work to keep the keep
+ the data lanes filled to get performance benefit. If the data
+ lanes remain unfilled, a flush operation will be initiated to
+ process the crypto jobs, adding a slight latency.
+
config CRYPTO_SHA256
tristate "SHA224 and SHA256 digest algorithm"
select CRYPTO_HASH
@@ -603,7 +633,7 @@ config CRYPTO_SHA512_SPARC64
config CRYPTO_SHA512_ARM_NEON
tristate "SHA384 and SHA512 digest algorithm (ARM NEON)"
- depends on ARM && KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+ depends on ARM && KERNEL_MODE_NEON
select CRYPTO_SHA512
select CRYPTO_HASH
help
diff --git a/crypto/Makefile b/crypto/Makefile
index cfa57b3f5a4d..1445b9100c05 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_CRYPTO_GCM) += gcm.o
obj-$(CONFIG_CRYPTO_CCM) += ccm.o
obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
+obj-$(CONFIG_CRYPTO_MCRYPTD) += mcryptd.o
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
index fd0d6b454975..9b3c54c1cbe8 100644
--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -1474,4 +1474,4 @@ module_exit(aes_fini);
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("aes");
+MODULE_ALIAS_CRYPTO("aes");
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 6a3ad8011585..4665b79c729a 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -399,7 +399,7 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
{
struct cmsghdr *cmsg;
- for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ for_each_cmsghdr(cmsg, msg) {
if (!CMSG_OK(msg, cmsg))
return -EINVAL;
if (cmsg->cmsg_level != SOL_ALG)
@@ -421,6 +421,12 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
con->op = *(u32 *)CMSG_DATA(cmsg);
break;
+ case ALG_SET_AEAD_ASSOCLEN:
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+ con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg);
+ break;
+
default:
return -EINVAL;
}
@@ -449,6 +455,9 @@ void af_alg_complete(struct crypto_async_request *req, int err)
{
struct af_alg_completion *completion = req->data;
+ if (err == -EINPROGRESS)
+ return;
+
completion->err = err;
complete(&completion->completion);
}
diff --git a/crypto/ahash.c b/crypto/ahash.c
index f2a5d8f656ff..f6a36a52d738 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -131,8 +131,10 @@ int crypto_hash_walk_first(struct ahash_request *req,
{
walk->total = req->nbytes;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
walk->sg = req->src;
@@ -147,8 +149,10 @@ int crypto_ahash_walk_first(struct ahash_request *req,
{
walk->total = req->nbytes;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
walk->sg = req->src;
@@ -167,8 +171,10 @@ int crypto_hash_walk_first_compat(struct hash_desc *hdesc,
{
walk->total = len;
- if (!walk->total)
+ if (!walk->total) {
+ walk->entrylen = 0;
return 0;
+ }
walk->alignmask = crypto_hash_alignmask(hdesc->tfm);
walk->sg = sg;
diff --git a/crypto/algapi.c b/crypto/algapi.c
index e8d3a7dca8c4..71a8143e23b1 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -509,8 +509,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name)
struct crypto_template *crypto_lookup_template(const char *name)
{
- return try_then_request_module(__crypto_lookup_template(name), "%s",
- name);
+ return try_then_request_module(__crypto_lookup_template(name),
+ "crypto-%s", name);
}
EXPORT_SYMBOL_GPL(crypto_lookup_template);
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 850246206b12..01f56eb7816e 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -42,7 +42,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
struct alg_sock *ask = alg_sk(sk);
struct hash_ctx *ctx = ask->private;
unsigned long iovlen;
- struct iovec *iov;
+ const struct iovec *iov;
long copied = 0;
int err;
@@ -58,7 +58,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
ctx->more = 0;
- for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
+ for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
iovlen--, iov++) {
unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base;
@@ -174,7 +174,7 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
goto unlock;
}
- err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
+ err = memcpy_to_msg(msg, ctx->result, len);
unlock:
release_sock(sk);
@@ -258,8 +258,8 @@ static void hash_sock_destruct(struct sock *sk)
struct alg_sock *ask = alg_sk(sk);
struct hash_ctx *ctx = ask->private;
- sock_kfree_s(sk, ctx->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
+ sock_kzfree_s(sk, ctx->result,
+ crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index a19c027b29bd..c12207c8dde9 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -49,7 +49,7 @@ struct skcipher_ctx {
struct ablkcipher_request req;
};
-#define MAX_SGL_ENTS ((PAGE_SIZE - sizeof(struct skcipher_sg_list)) / \
+#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
sizeof(struct scatterlist) - 1)
static inline int skcipher_sndbuf(struct sock *sk)
@@ -251,6 +251,7 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
struct af_alg_control con = {};
long copied = 0;
bool enc = 0;
+ bool init = 0;
int err;
int i;
@@ -259,6 +260,7 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
if (err)
return err;
+ init = 1;
switch (con.op) {
case ALG_OP_ENCRYPT:
enc = 1;
@@ -280,7 +282,7 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
if (!ctx->more && ctx->used)
goto unlock;
- if (!ctx->used) {
+ if (init) {
ctx->enc = enc;
if (con.iv)
memcpy(ctx->iv, con.iv->iv, ivsize);
@@ -298,9 +300,9 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
len = min_t(unsigned long, len,
PAGE_SIZE - sg->offset - sg->length);
- err = memcpy_fromiovec(page_address(sg_page(sg)) +
- sg->offset + sg->length,
- msg->msg_iov, len);
+ err = memcpy_from_msg(page_address(sg_page(sg)) +
+ sg->offset + sg->length,
+ msg, len);
if (err)
goto unlock;
@@ -337,8 +339,8 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
if (!sg_page(sg + i))
goto unlock;
- err = memcpy_fromiovec(page_address(sg_page(sg + i)),
- msg->msg_iov, plen);
+ err = memcpy_from_msg(page_address(sg_page(sg + i)),
+ msg, plen);
if (err) {
__free_page(sg_page(sg + i));
sg_assign_page(sg + i, NULL);
@@ -359,8 +361,6 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock,
err = 0;
ctx->more = msg->msg_flags & MSG_MORE;
- if (!ctx->more && !list_empty(&ctx->tsgl))
- sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
unlock:
skcipher_data_wakeup(sk);
@@ -408,8 +408,6 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
done:
ctx->more = flags & MSG_MORE;
- if (!ctx->more && !list_empty(&ctx->tsgl))
- sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
unlock:
skcipher_data_wakeup(sk);
@@ -429,13 +427,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
unsigned long iovlen;
- struct iovec *iov;
+ const struct iovec *iov;
int err = -EAGAIN;
int used;
long copied = 0;
lock_sock(sk);
- for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
+ for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
iovlen--, iov++) {
unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base;
@@ -448,14 +446,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
while (!sg->length)
sg++;
- used = ctx->used;
- if (!used) {
+ if (!ctx->used) {
err = skcipher_wait_for_data(sk, flags);
if (err)
goto unlock;
}
- used = min_t(unsigned long, used, seglen);
+ used = min_t(unsigned long, ctx->used, seglen);
used = af_alg_make_sg(&ctx->rsgl, from, used, 1);
err = used;
@@ -566,7 +563,7 @@ static void skcipher_sock_destruct(struct sock *sk)
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
skcipher_free_sgl(sk);
- sock_kfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
+ sock_kzfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 666f1962a160..b4485a108389 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -476,4 +476,4 @@ module_param(dbg, int, 0);
MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
module_init(prng_mod_init);
module_exit(prng_mod_fini);
-MODULE_ALIAS("stdrng");
+MODULE_ALIAS_CRYPTO("stdrng");
diff --git a/crypto/anubis.c b/crypto/anubis.c
index 008c8a4fb67c..4bb187c2a902 100644
--- a/crypto/anubis.c
+++ b/crypto/anubis.c
@@ -704,3 +704,4 @@ module_exit(anubis_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Anubis Cryptographic Algorithm");
+MODULE_ALIAS_CRYPTO("anubis");
diff --git a/crypto/api.c b/crypto/api.c
index a2b39c5f3649..2a81e98a0021 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -216,11 +216,11 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
alg = crypto_alg_lookup(name, type, mask);
if (!alg) {
- request_module("%s", name);
+ request_module("crypto-%s", name);
if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
CRYPTO_ALG_NEED_FALLBACK))
- request_module("%s-all", name);
+ request_module("crypto-%s-all", name);
alg = crypto_alg_lookup(name, type, mask);
}
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 5a772c3657d5..f1a81925558f 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -166,3 +166,4 @@ module_exit(arc4_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
+MODULE_ALIAS_CRYPTO("arc4");
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h
index a63c551c6557..f97330886d58 100644
--- a/crypto/asymmetric_keys/asymmetric_keys.h
+++ b/crypto/asymmetric_keys/asymmetric_keys.h
@@ -9,9 +9,10 @@
* 2 of the Licence, or (at your option) any later version.
*/
-int asymmetric_keyid_match(const char *kid, const char *id);
+extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
-static inline const char *asymmetric_key_id(const struct key *key)
+static inline
+const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
{
return key->type_data.p[1];
}
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index eb8cd46961a5..bcbbbd794e1d 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -15,6 +15,7 @@
#include <linux/seq_file.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/ctype.h>
#include "asymmetric_keys.h"
MODULE_LICENSE("GPL");
@@ -22,85 +23,209 @@ MODULE_LICENSE("GPL");
static LIST_HEAD(asymmetric_key_parsers);
static DECLARE_RWSEM(asymmetric_key_parsers_sem);
-/*
- * Match asymmetric key id with partial match
- * @id: key id to match in a form "id:<id>"
+/**
+ * asymmetric_key_generate_id: Construct an asymmetric key ID
+ * @val_1: First binary blob
+ * @len_1: Length of first binary blob
+ * @val_2: Second binary blob
+ * @len_2: Length of second binary blob
+ *
+ * Construct an asymmetric key ID from a pair of binary blobs.
*/
-int asymmetric_keyid_match(const char *kid, const char *id)
+struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
+ size_t len_1,
+ const void *val_2,
+ size_t len_2)
{
- size_t idlen, kidlen;
+ struct asymmetric_key_id *kid;
+
+ kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
+ GFP_KERNEL);
+ if (!kid)
+ return ERR_PTR(-ENOMEM);
+ kid->len = len_1 + len_2;
+ memcpy(kid->data, val_1, len_1);
+ memcpy(kid->data + len_1, val_2, len_2);
+ return kid;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_generate_id);
- if (!kid || !id)
- return 0;
+/**
+ * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same.
+ * @kid_1, @kid_2: The key IDs to compare
+ */
+bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2)
+{
+ if (!kid1 || !kid2)
+ return false;
+ if (kid1->len != kid2->len)
+ return false;
+ return memcmp(kid1->data, kid2->data, kid1->len) == 0;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
- /* make it possible to use id as in the request: "id:<id>" */
- if (strncmp(id, "id:", 3) == 0)
- id += 3;
+/**
+ * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
+ * partially match
+ * @kid_1, @kid_2: The key IDs to compare
+ */
+bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2)
+{
+ if (!kid1 || !kid2)
+ return false;
+ if (kid1->len < kid2->len)
+ return false;
+ return memcmp(kid1->data + (kid1->len - kid2->len),
+ kid2->data, kid2->len) == 0;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
- /* Anything after here requires a partial match on the ID string */
- idlen = strlen(id);
- kidlen = strlen(kid);
- if (idlen > kidlen)
- return 0;
+/**
+ * asymmetric_match_key_ids - Search asymmetric key IDs
+ * @kids: The list of key IDs to check
+ * @match_id: The key ID we're looking for
+ * @match: The match function to use
+ */
+static bool asymmetric_match_key_ids(
+ const struct asymmetric_key_ids *kids,
+ const struct asymmetric_key_id *match_id,
+ bool (*match)(const struct asymmetric_key_id *kid1,
+ const struct asymmetric_key_id *kid2))
+{
+ int i;
+
+ if (!kids || !match_id)
+ return false;
+ for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+ if (match(kids->id[i], match_id))
+ return true;
+ return false;
+}
- kid += kidlen - idlen;
- if (strcasecmp(id, kid) != 0)
- return 0;
+/**
+ * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
+ * @id: The ID as a hex string.
+ */
+struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
+{
+ struct asymmetric_key_id *match_id;
+ size_t hexlen;
+ int ret;
- return 1;
+ if (!*id)
+ return ERR_PTR(-EINVAL);
+ hexlen = strlen(id);
+ if (hexlen & 1)
+ return ERR_PTR(-EINVAL);
+
+ match_id = kmalloc(sizeof(struct asymmetric_key_id) + hexlen / 2,
+ GFP_KERNEL);
+ if (!match_id)
+ return ERR_PTR(-ENOMEM);
+ match_id->len = hexlen / 2;
+ ret = hex2bin(match_id->data, id, hexlen / 2);
+ if (ret < 0) {
+ kfree(match_id);
+ return ERR_PTR(-EINVAL);
+ }
+ return match_id;
}
-EXPORT_SYMBOL_GPL(asymmetric_keyid_match);
/*
- * Match asymmetric keys on (part of) their name
- * We have some shorthand methods for matching keys. We allow:
- *
- * "<desc>" - request a key by description
- * "id:<id>" - request a key matching the ID
- * "<subtype>:<id>" - request a key of a subtype
+ * Match asymmetric keys by an exact match on an ID.
*/
-static int asymmetric_key_match(const struct key *key, const void *description)
+static bool asymmetric_key_cmp(const struct key *key,
+ const struct key_match_data *match_data)
{
- const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
- const char *spec = description;
- const char *id;
- ptrdiff_t speclen;
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *match_id = match_data->preparsed;
- if (!subtype || !spec || !*spec)
- return 0;
+ return asymmetric_match_key_ids(kids, match_id,
+ asymmetric_key_id_same);
+}
- /* See if the full key description matches as is */
- if (key->description && strcmp(key->description, description) == 0)
- return 1;
+/*
+ * Match asymmetric keys by a partial match on an IDs.
+ */
+static bool asymmetric_key_cmp_partial(const struct key *key,
+ const struct key_match_data *match_data)
+{
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *match_id = match_data->preparsed;
- /* 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;
+ return asymmetric_match_key_ids(kids, match_id,
+ asymmetric_key_id_partial);
+}
+
+/*
+ * Preparse the match criterion. If we don't set lookup_type and cmp,
+ * the default will be an exact match on the key description.
+ *
+ * There are some specifiers for matching key IDs rather than by the key
+ * description:
+ *
+ * "id:<id>" - find a key by partial match on any available ID
+ * "ex:<id>" - find a key by exact match on any available ID
+ *
+ * These have to be searched by iteration rather than by direct lookup because
+ * the key is hashed according to its description.
+ */
+static int asymmetric_key_match_preparse(struct key_match_data *match_data)
+{
+ struct asymmetric_key_id *match_id;
+ const char *spec = match_data->raw_data;
+ const char *id;
+ bool (*cmp)(const struct key *, const struct key_match_data *) =
+ asymmetric_key_cmp;
- speclen = id - spec;
- id++;
+ if (!spec || !*spec)
+ return -EINVAL;
+ if (spec[0] == 'i' &&
+ spec[1] == 'd' &&
+ spec[2] == ':') {
+ id = spec + 3;
+ cmp = asymmetric_key_cmp_partial;
+ } else if (spec[0] == 'e' &&
+ spec[1] == 'x' &&
+ spec[2] == ':') {
+ id = spec + 3;
+ } else {
+ goto default_match;
+ }
- if (speclen == 2 && memcmp(spec, "id", 2) == 0)
- return asymmetric_keyid_match(asymmetric_key_id(key), id);
+ match_id = asymmetric_key_hex_to_key_id(id);
+ if (IS_ERR(match_id))
+ return PTR_ERR(match_id);
- if (speclen == subtype->name_len &&
- memcmp(spec, subtype->name, speclen) == 0)
- return 1;
+ match_data->preparsed = match_id;
+ match_data->cmp = cmp;
+ match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
+ return 0;
+default_match:
return 0;
}
/*
+ * Free the preparsed the match criterion.
+ */
+static void asymmetric_key_match_free(struct key_match_data *match_data)
+{
+ kfree(match_data->preparsed);
+}
+
+/*
* Describe the asymmetric key
*/
static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
{
const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
- const char *kid = asymmetric_key_id(key);
- size_t n;
+ const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+ const struct asymmetric_key_id *kid;
+ const unsigned char *p;
+ int n;
seq_puts(m, key->description);
@@ -108,13 +233,16 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
seq_puts(m, ": ");
subtype->describe(key, m);
- if (kid) {
+ if (kids && kids->id[1]) {
+ kid = kids->id[1];
seq_putc(m, ' ');
- n = strlen(kid);
- if (n <= 8)
- seq_puts(m, kid);
- else
- seq_puts(m, kid + n - 8);
+ n = kid->len;
+ p = kid->data;
+ if (n > 4) {
+ p += n - 4;
+ n = 4;
+ }
+ seq_printf(m, "%*phN", n, p);
}
seq_puts(m, " [");
@@ -165,6 +293,8 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
{
struct asymmetric_key_subtype *subtype = prep->type_data[0];
+ struct asymmetric_key_ids *kids = prep->type_data[1];
+ int i;
pr_devel("==>%s()\n", __func__);
@@ -172,7 +302,11 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
subtype->destroy(prep->payload[0]);
module_put(subtype->owner);
}
- kfree(prep->type_data[1]);
+ if (kids) {
+ for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+ kfree(kids->id[i]);
+ kfree(kids);
+ }
kfree(prep->description);
}
@@ -182,13 +316,20 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
static void asymmetric_key_destroy(struct key *key)
{
struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
+ struct asymmetric_key_ids *kids = key->type_data.p[1];
+
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;
+
+ if (kids) {
+ kfree(kids->id[0]);
+ kfree(kids->id[1]);
+ kfree(kids);
+ key->type_data.p[1] = NULL;
+ }
}
struct key_type key_type_asymmetric = {
@@ -196,10 +337,10 @@ struct key_type key_type_asymmetric = {
.preparse = asymmetric_key_preparse,
.free_preparse = asymmetric_key_free_preparse,
.instantiate = generic_key_instantiate,
- .match = asymmetric_key_match,
+ .match_preparse = asymmetric_key_match_preparse,
+ .match_free = asymmetric_key_match_free,
.destroy = asymmetric_key_destroy,
.describe = asymmetric_key_describe,
- .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
};
EXPORT_SYMBOL_GPL(key_type_asymmetric);
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
index 3de5fb011de0..751f8fd7335d 100644
--- a/crypto/asymmetric_keys/pkcs7_key_type.c
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -72,11 +72,9 @@ error:
*/
static struct key_type key_type_pkcs7 = {
.name = "pkcs7_test",
- .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
.preparse = pkcs7_preparse,
.free_preparse = user_free_preparse,
.instantiate = generic_key_instantiate,
- .match = user_match,
.revoke = user_revoke,
.destroy = user_destroy,
.describe = user_describe,
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 42e56aa7d277..3bd5a1e4c493 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -29,8 +29,25 @@ struct pkcs7_parse_context {
enum OID last_oid; /* Last OID encountered */
unsigned x509_index;
unsigned sinfo_index;
+ const void *raw_serial;
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer;
};
+/*
+ * Free a signed information block.
+ */
+static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
+{
+ if (sinfo) {
+ mpi_free(sinfo->sig.mpi[0]);
+ kfree(sinfo->sig.digest);
+ kfree(sinfo->signing_cert_id);
+ kfree(sinfo);
+ }
+}
+
/**
* pkcs7_free_message - Free a PKCS#7 message
* @pkcs7: The PKCS#7 message to free
@@ -54,9 +71,7 @@ void pkcs7_free_message(struct pkcs7_message *pkcs7)
while (pkcs7->signed_infos) {
sinfo = pkcs7->signed_infos;
pkcs7->signed_infos = sinfo->next;
- mpi_free(sinfo->sig.mpi[0]);
- kfree(sinfo->sig.digest);
- kfree(sinfo);
+ pkcs7_free_signed_info(sinfo);
}
kfree(pkcs7);
}
@@ -71,51 +86,46 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message);
struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
{
struct pkcs7_parse_context *ctx;
- struct pkcs7_message *msg;
- long ret;
+ struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
+ int ret;
- ret = -ENOMEM;
- msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
- if (!msg)
- goto error_no_sig;
ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
if (!ctx)
- goto error_no_ctx;
+ goto out_no_ctx;
+ ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
+ if (!ctx->msg)
+ goto out_no_msg;
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
if (!ctx->sinfo)
- goto error_no_sinfo;
+ goto out_no_sinfo;
- ctx->msg = msg;
ctx->data = (unsigned long)data;
ctx->ppcerts = &ctx->certs;
ctx->ppsinfo = &ctx->msg->signed_infos;
/* Attempt to decode the signature */
ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
- if (ret < 0)
- goto error_decode;
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out;
+ }
+ msg = ctx->msg;
+ ctx->msg = NULL;
+
+out:
while (ctx->certs) {
struct x509_certificate *cert = ctx->certs;
ctx->certs = cert->next;
x509_free_certificate(cert);
}
- mpi_free(ctx->sinfo->sig.mpi[0]);
- kfree(ctx->sinfo->sig.digest);
- kfree(ctx->sinfo);
+ pkcs7_free_signed_info(ctx->sinfo);
+out_no_sinfo:
+ pkcs7_free_message(ctx->msg);
+out_no_msg:
kfree(ctx);
+out_no_ctx:
return msg;
-
-error_decode:
- mpi_free(ctx->sinfo->sig.mpi[0]);
- kfree(ctx->sinfo->sig.digest);
- kfree(ctx->sinfo);
-error_no_sinfo:
- kfree(ctx);
-error_no_ctx:
- pkcs7_free_message(msg);
-error_no_sig:
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(pkcs7_parse_message);
@@ -246,10 +256,10 @@ int pkcs7_extract_cert(void *context, size_t hdrlen,
if (IS_ERR(x509))
return PTR_ERR(x509);
- pr_debug("Got cert for %s\n", x509->subject);
- pr_debug("- fingerprint %s\n", x509->fingerprint);
-
x509->index = ++ctx->x509_index;
+ pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
+ pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
+
*ctx->ppcerts = x509;
ctx->ppcerts = &x509->next;
return 0;
@@ -338,8 +348,8 @@ int pkcs7_sig_note_serial(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
- ctx->sinfo->raw_serial = value;
- ctx->sinfo->raw_serial_size = vlen;
+ ctx->raw_serial = value;
+ ctx->raw_serial_size = vlen;
return 0;
}
@@ -351,8 +361,8 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
- ctx->sinfo->raw_issuer = value;
- ctx->sinfo->raw_issuer_size = vlen;
+ ctx->raw_issuer = value;
+ ctx->raw_issuer_size = vlen;
return 0;
}
@@ -385,10 +395,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
-
- ctx->sinfo->index = ++ctx->sinfo_index;
- *ctx->ppsinfo = ctx->sinfo;
- ctx->ppsinfo = &ctx->sinfo->next;
+ struct pkcs7_signed_info *sinfo = ctx->sinfo;
+ struct asymmetric_key_id *kid;
+
+ /* Generate cert issuer + serial number key ID */
+ kid = asymmetric_key_generate_id(ctx->raw_serial,
+ ctx->raw_serial_size,
+ ctx->raw_issuer,
+ ctx->raw_issuer_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+
+ sinfo->signing_cert_id = kid;
+ sinfo->index = ++ctx->sinfo_index;
+ *ctx->ppsinfo = sinfo;
+ ctx->ppsinfo = &sinfo->next;
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
if (!ctx->sinfo)
return -ENOMEM;
diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h
index d25f4d15370f..efc7dc9b8f9c 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.h
+++ b/crypto/asymmetric_keys/pkcs7_parser.h
@@ -23,6 +23,7 @@ struct pkcs7_signed_info {
struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
unsigned index;
bool trusted;
+ bool unsupported_crypto; /* T if not usable due to missing crypto */
/* Message digest - the digest of the Content Data (or NULL) */
const void *msgdigest;
@@ -33,10 +34,7 @@ struct pkcs7_signed_info {
const void *authattrs;
/* Issuing cert serial number and issuer's name */
- const void *raw_serial;
- unsigned raw_serial_size;
- unsigned raw_issuer_size;
- const void *raw_issuer;
+ struct asymmetric_key_id *signing_cert_id;
/* Message signature.
*
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index e666eb011a85..1d29376072da 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -23,9 +23,9 @@
/**
* Check the trust on one PKCS#7 SignedInfo block.
*/
-int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
- struct pkcs7_signed_info *sinfo,
- struct key *trust_keyring)
+static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
+ struct pkcs7_signed_info *sinfo,
+ struct key *trust_keyring)
{
struct public_key_signature *sig = &sinfo->sig;
struct x509_certificate *x509, *last = NULL, *p;
@@ -35,6 +35,11 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
kenter(",%u,", sinfo->index);
+ if (sinfo->unsupported_crypto) {
+ kleave(" = -ENOPKG [cached]");
+ return -ENOPKG;
+ }
+
for (x509 = sinfo->signer; x509; x509 = x509->signer) {
if (x509->seen) {
if (x509->verified) {
@@ -49,15 +54,18 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* Look to see if this certificate is present in the trusted
* keys.
*/
- key = x509_request_asymmetric_key(trust_keyring, x509->subject,
- x509->fingerprint);
- if (!IS_ERR(key))
+ key = x509_request_asymmetric_key(trust_keyring, x509->id,
+ false);
+ if (!IS_ERR(key)) {
/* One of the X.509 certificates in the PKCS#7 message
* is apparently the same as one we already trust.
* Verify that the trusted variant can also validate
* the signature on the descendant.
*/
+ pr_devel("sinfo %u: Cert %u as key %x\n",
+ sinfo->index, x509->index, key_serial(key));
goto matched;
+ }
if (key == ERR_PTR(-ENOMEM))
return -ENOMEM;
@@ -77,16 +85,36 @@ int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* No match - see if the root certificate has a signer amongst the
* trusted keys.
*/
- if (!last || !last->issuer || !last->authority) {
- kleave(" = -ENOKEY [no backref]");
- return -ENOKEY;
+ if (last && last->authority) {
+ key = x509_request_asymmetric_key(trust_keyring, last->authority,
+ false);
+ if (!IS_ERR(key)) {
+ x509 = last;
+ pr_devel("sinfo %u: Root cert %u signer is key %x\n",
+ sinfo->index, x509->index, key_serial(key));
+ goto matched;
+ }
+ if (PTR_ERR(key) != -ENOKEY)
+ return PTR_ERR(key);
+ }
+
+ /* As a last resort, see if we have a trusted public key that matches
+ * the signed info directly.
+ */
+ key = x509_request_asymmetric_key(trust_keyring,
+ sinfo->signing_cert_id,
+ false);
+ if (!IS_ERR(key)) {
+ pr_devel("sinfo %u: Direct signer is key %x\n",
+ sinfo->index, key_serial(key));
+ x509 = NULL;
+ goto matched;
}
+ if (PTR_ERR(key) != -ENOKEY)
+ return PTR_ERR(key);
- key = x509_request_asymmetric_key(trust_keyring, last->issuer,
- last->authority);
- if (IS_ERR(key))
- return PTR_ERR(key) == -ENOMEM ? -ENOMEM : -ENOKEY;
- x509 = last;
+ kleave(" = -ENOKEY [no backref]");
+ return -ENOKEY;
matched:
ret = verify_signature(key, sig);
@@ -100,10 +128,12 @@ matched:
}
verified:
- x509->verified = true;
- for (p = sinfo->signer; p != x509; p = p->signer) {
- p->verified = true;
- p->trusted = trusted;
+ if (x509) {
+ x509->verified = true;
+ for (p = sinfo->signer; p != x509; p = p->signer) {
+ p->verified = true;
+ p->trusted = trusted;
+ }
}
sinfo->trusted = trusted;
kleave(" = 0");
@@ -141,24 +171,28 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
{
struct pkcs7_signed_info *sinfo;
struct x509_certificate *p;
- int cached_ret = 0, ret;
+ int cached_ret = -ENOKEY;
+ int ret;
for (p = pkcs7->certs; p; p = p->next)
p->seen = false;
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
ret = pkcs7_validate_trust_one(pkcs7, sinfo, trust_keyring);
- if (ret < 0) {
- if (ret == -ENOPKG) {
+ switch (ret) {
+ case -ENOKEY:
+ continue;
+ case -ENOPKG:
+ if (cached_ret == -ENOKEY)
cached_ret = -ENOPKG;
- } else if (ret == -ENOKEY) {
- if (cached_ret == 0)
- cached_ret = -ENOKEY;
- } else {
- return ret;
- }
+ continue;
+ case 0:
+ *_trusted |= sinfo->trusted;
+ cached_ret = 0;
+ continue;
+ default:
+ return ret;
}
- *_trusted |= sinfo->trusted;
}
return cached_ret;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index c62cf8006e1f..cd455450b069 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -131,8 +131,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
struct x509_certificate *x509;
unsigned certix = 1;
- kenter("%u,%u,%u",
- sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size);
+ kenter("%u", sinfo->index);
for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
/* I'm _assuming_ that the generator of the PKCS#7 message will
@@ -140,21 +139,11 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
* PKCS#7 message - but I can't be 100% sure of that. It's
* possible this will need element-by-element comparison.
*/
- if (x509->raw_serial_size != sinfo->raw_serial_size ||
- memcmp(x509->raw_serial, sinfo->raw_serial,
- sinfo->raw_serial_size) != 0)
+ if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id))
continue;
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
sinfo->index, certix);
- if (x509->raw_issuer_size != sinfo->raw_issuer_size ||
- memcmp(x509->raw_issuer, sinfo->raw_issuer,
- sinfo->raw_issuer_size) != 0) {
- pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n",
- sinfo->index);
- continue;
- }
-
if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
sinfo->index);
@@ -164,9 +153,14 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
sinfo->signer = x509;
return 0;
}
- pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n",
- sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial);
- return -ENOKEY;
+
+ /* The relevant X.509 cert isn't found here, but it might be found in
+ * the trust keyring.
+ */
+ pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
+ sinfo->index,
+ sinfo->signing_cert_id->len, sinfo->signing_cert_id->data);
+ return 0;
}
/*
@@ -184,15 +178,18 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
p->seen = false;
for (;;) {
- pr_debug("verify %s: %s\n", x509->subject, x509->fingerprint);
+ pr_debug("verify %s: %*phN\n",
+ x509->subject,
+ x509->raw_serial_size, x509->raw_serial);
x509->seen = true;
ret = x509_get_sig_params(x509);
if (ret < 0)
- return ret;
+ goto maybe_missing_crypto_in_x509;
pr_debug("- issuer %s\n", x509->issuer);
if (x509->authority)
- pr_debug("- authkeyid %s\n", x509->authority);
+ pr_debug("- authkeyid %*phN\n",
+ x509->authority->len, x509->authority->data);
if (!x509->authority ||
strcmp(x509->subject, x509->issuer) == 0) {
@@ -209,7 +206,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
ret = x509_check_signature(x509->pub, x509);
if (ret < 0)
- return ret;
+ goto maybe_missing_crypto_in_x509;
x509->signer = x509;
pr_debug("- self-signed\n");
return 0;
@@ -218,13 +215,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
/* Look through the X.509 certificates in the PKCS#7 message's
* list to see if the next one is there.
*/
- pr_debug("- want %s\n", x509->authority);
+ pr_debug("- want %*phN\n",
+ x509->authority->len, x509->authority->data);
for (p = pkcs7->certs; p; p = p->next) {
- pr_debug("- cmp [%u] %s\n", p->index, p->fingerprint);
- if (p->raw_subject_size == x509->raw_issuer_size &&
- strcmp(p->fingerprint, x509->authority) == 0 &&
- memcmp(p->raw_subject, x509->raw_issuer,
- x509->raw_issuer_size) == 0)
+ if (!p->skid)
+ continue;
+ pr_debug("- cmp [%u] %*phN\n",
+ p->index, p->skid->len, p->skid->data);
+ if (asymmetric_key_id_same(p->skid, x509->authority))
goto found_issuer;
}
@@ -233,7 +231,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
return 0;
found_issuer:
- pr_debug("- issuer %s\n", p->subject);
+ pr_debug("- subject %s\n", p->subject);
if (p->seen) {
pr_warn("Sig %u: X.509 chain contains loop\n",
sinfo->index);
@@ -250,6 +248,17 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
x509 = p;
might_sleep();
}
+
+maybe_missing_crypto_in_x509:
+ /* Just prune the certificate chain at this point if we lack some
+ * crypto module to go further. Note, however, we don't want to set
+ * sinfo->missing_crypto as the signed info block may still be
+ * validatable against an X.509 cert lower in the chain that we have a
+ * trusted copy of.
+ */
+ if (ret == -ENOPKG)
+ return 0;
+ return ret;
}
/*
@@ -269,11 +278,14 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
if (ret < 0)
return ret;
- /* Find the key for the signature */
+ /* Find the key for the signature if there is one */
ret = pkcs7_find_key(pkcs7, sinfo);
if (ret < 0)
return ret;
+ if (!sinfo->signer)
+ return 0;
+
pr_devel("Using X.509[%u] for sig %u\n",
sinfo->signer->index, sinfo->index);
@@ -291,11 +303,33 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
/**
* pkcs7_verify - Verify a PKCS#7 message
* @pkcs7: The PKCS#7 message to be verified
+ *
+ * Verify a PKCS#7 message is internally consistent - that is, the data digest
+ * matches the digest in the AuthAttrs and any signature in the message or one
+ * of the X.509 certificates it carries that matches another X.509 cert in the
+ * message can be verified.
+ *
+ * This does not look to match the contents of the PKCS#7 message against any
+ * external public keys.
+ *
+ * Returns, in order of descending priority:
+ *
+ * (*) -EKEYREJECTED if a signature failed to match for which we found an
+ * appropriate X.509 certificate, or:
+ *
+ * (*) -EBADMSG if some part of the message was invalid, or:
+ *
+ * (*) -ENOPKG if none of the signature chains are verifiable because suitable
+ * crypto modules couldn't be found, or:
+ *
+ * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified
+ * (note that a signature chain may be of zero length), or:
*/
int pkcs7_verify(struct pkcs7_message *pkcs7)
{
struct pkcs7_signed_info *sinfo;
struct x509_certificate *x509;
+ int enopkg = -ENOPKG;
int ret, n;
kenter("");
@@ -304,18 +338,24 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
ret = x509_get_sig_params(x509);
if (ret < 0)
return ret;
- pr_debug("X.509[%u] %s\n", n, x509->authority);
+ pr_debug("X.509[%u] %*phN\n",
+ n, x509->authority->len, x509->authority->data);
}
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
ret = pkcs7_verify_one(pkcs7, sinfo);
if (ret < 0) {
+ if (ret == -ENOPKG) {
+ sinfo->unsupported_crypto = true;
+ continue;
+ }
kleave(" = %d", ret);
return ret;
}
+ enopkg = 0;
}
- kleave(" = 0");
- return 0;
+ kleave(" = %d", enopkg);
+ return enopkg;
}
EXPORT_SYMBOL_GPL(pkcs7_verify);
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
index 50b3f880b4ff..7525fd183574 100644
--- a/crypto/asymmetric_keys/signature.c
+++ b/crypto/asymmetric_keys/signature.c
@@ -11,6 +11,7 @@
* 2 of the Licence, or (at your option) any later version.
*/
+#define pr_fmt(fmt) "SIG: "fmt
#include <keys/asymmetric-subtype.h>
#include <linux/module.h>
#include <linux/err.h>
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index ac72348c186a..a668d90302d3 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -46,7 +46,8 @@ void x509_free_certificate(struct x509_certificate *cert)
public_key_destroy(cert->pub);
kfree(cert->issuer);
kfree(cert->subject);
- kfree(cert->fingerprint);
+ kfree(cert->id);
+ kfree(cert->skid);
kfree(cert->authority);
kfree(cert->sig.digest);
mpi_free(cert->sig.rsa.s);
@@ -62,6 +63,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
{
struct x509_certificate *cert;
struct x509_parse_context *ctx;
+ struct asymmetric_key_id *kid;
long ret;
ret = -ENOMEM;
@@ -89,6 +91,17 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
if (ret < 0)
goto error_decode;
+ /* Generate cert issuer + serial number key ID */
+ kid = asymmetric_key_generate_id(cert->raw_serial,
+ cert->raw_serial_size,
+ cert->raw_issuer,
+ cert->raw_issuer_size);
+ if (IS_ERR(kid)) {
+ ret = PTR_ERR(kid);
+ goto error_decode;
+ }
+ cert->id = kid;
+
kfree(ctx);
return cert;
@@ -407,36 +420,36 @@ int x509_process_extension(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
const unsigned char *v = value;
- char *f;
int i;
pr_debug("Extension: %u\n", ctx->last_oid);
if (ctx->last_oid == OID_subjectKeyIdentifier) {
/* Get hold of the key fingerprint */
- if (vlen < 3)
+ if (ctx->cert->skid || vlen < 3)
return -EBADMSG;
if (v[0] != ASN1_OTS || v[1] != vlen - 2)
return -EBADMSG;
v += 2;
vlen -= 2;
- f = kmalloc(vlen * 2 + 1, GFP_KERNEL);
- if (!f)
- return -ENOMEM;
- for (i = 0; i < vlen; i++)
- sprintf(f + i * 2, "%02x", v[i]);
- pr_debug("fingerprint %s\n", f);
- ctx->cert->fingerprint = f;
+ ctx->cert->raw_skid_size = vlen;
+ ctx->cert->raw_skid = v;
+ kid = asymmetric_key_generate_id(ctx->cert->raw_subject,
+ ctx->cert->raw_subject_size,
+ v, vlen);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ ctx->cert->skid = kid;
+ pr_debug("subjkeyid %*phN\n", kid->len, kid->data);
return 0;
}
if (ctx->last_oid == OID_authorityKeyIdentifier) {
- size_t key_len;
-
/* Get hold of the CA key fingerprint */
- if (vlen < 5)
+ if (ctx->cert->authority || vlen < 5)
return -EBADMSG;
/* Authority Key Identifier must be a Constructed SEQUENCE */
@@ -454,7 +467,7 @@ int x509_process_extension(void *context, size_t hdrlen,
v[3] > vlen - 4)
return -EBADMSG;
- key_len = v[3];
+ vlen = v[3];
v += 4;
} else {
/* Long Form length */
@@ -476,17 +489,17 @@ int x509_process_extension(void *context, size_t hdrlen,
v[sub + 1] > vlen - 4 - sub)
return -EBADMSG;
- key_len = v[sub + 1];
+ vlen = v[sub + 1];
v += (sub + 2);
}
- f = kmalloc(key_len * 2 + 1, GFP_KERNEL);
- if (!f)
- return -ENOMEM;
- for (i = 0; i < key_len; i++)
- sprintf(f + i * 2, "%02x", v[i]);
- pr_debug("authority %s\n", f);
- ctx->cert->authority = f;
+ kid = asymmetric_key_generate_id(ctx->cert->raw_issuer,
+ ctx->cert->raw_issuer_size,
+ v, vlen);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->authority = kid;
return 0;
}
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 1b76f207c1f3..3dfe6b5d6f0b 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -19,8 +19,9 @@ struct x509_certificate {
struct public_key_signature sig; /* Signature parameters */
char *issuer; /* Name of certificate issuer */
char *subject; /* Name of certificate subject */
- char *fingerprint; /* Key fingerprint as hex */
- char *authority; /* Authority key fingerprint as hex */
+ struct asymmetric_key_id *id; /* Serial number + issuer */
+ struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */
+ struct asymmetric_key_id *authority; /* Authority key identifier (optional) */
struct tm valid_from;
struct tm valid_to;
const void *tbs; /* Signed data */
@@ -33,10 +34,13 @@ struct x509_certificate {
const void *raw_issuer; /* Raw issuer name in ASN.1 */
const void *raw_subject; /* Raw subject name in ASN.1 */
unsigned raw_subject_size;
+ unsigned raw_skid_size;
+ const void *raw_skid; /* Raw subjectKeyId in ASN.1 */
unsigned index;
bool seen; /* Infinite recursion prevention */
bool verified;
bool trusted;
+ bool unsupported_crypto; /* T if can't be verified due to missing crypto */
};
/*
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index f3d62307e6ee..a6c42031628e 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -25,7 +25,7 @@
#include "x509_parser.h"
static bool use_builtin_keys;
-static char *ca_keyid;
+static struct asymmetric_key_id *ca_keyid;
#ifndef MODULE
static int __init ca_keys_setup(char *str)
@@ -33,10 +33,16 @@ static int __init ca_keys_setup(char *str)
if (!str) /* default system keyring */
return 1;
- if (strncmp(str, "id:", 3) == 0)
- ca_keyid = str; /* owner key 'id:xxxxxx' */
- else if (strcmp(str, "builtin") == 0)
+ if (strncmp(str, "id:", 3) == 0) {
+ struct asymmetric_key_id *p;
+ p = asymmetric_key_hex_to_key_id(str + 3);
+ if (p == ERR_PTR(-EINVAL))
+ pr_err("Unparsable hex string in ca_keys\n");
+ else if (!IS_ERR(p))
+ ca_keyid = p; /* owner key 'id:xxxxxx' */
+ } else if (strcmp(str, "builtin") == 0) {
use_builtin_keys = true;
+ }
return 1;
}
@@ -46,31 +52,35 @@ __setup("ca_keys=", ca_keys_setup);
/**
* x509_request_asymmetric_key - Request a key by X.509 certificate params.
* @keyring: The keys to search.
- * @subject: The name of the subject to whom the key belongs.
- * @key_id: The subject key ID as a hex string.
+ * @kid: The key ID.
+ * @partial: Use partial match if true, exact if false.
*
* Find a key in the given keyring by subject name and key ID. These might,
* for instance, be the issuer name and the authority key ID of an X.509
* certificate that needs to be verified.
*/
struct key *x509_request_asymmetric_key(struct key *keyring,
- const char *subject,
- const char *key_id)
+ const struct asymmetric_key_id *kid,
+ bool partial)
{
key_ref_t key;
- size_t subject_len = strlen(subject), key_id_len = strlen(key_id);
- char *id;
+ char *id, *p;
- /* Construct an identifier "<subjname>:<keyid>". */
- id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL);
+ /* Construct an identifier "id:<keyid>". */
+ p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL);
if (!id)
return ERR_PTR(-ENOMEM);
- memcpy(id, subject, subject_len);
- id[subject_len + 0] = ':';
- id[subject_len + 1] = ' ';
- memcpy(id + subject_len + 2, key_id, key_id_len);
- id[subject_len + 2 + key_id_len] = 0;
+ if (partial) {
+ *p++ = 'i';
+ *p++ = 'd';
+ } else {
+ *p++ = 'e';
+ *p++ = 'x';
+ }
+ *p++ = ':';
+ p = bin2hex(p, kid->data, kid->len);
+ *p = 0;
pr_debug("Look up: \"%s\"\n", id);
@@ -112,6 +122,8 @@ int x509_get_sig_params(struct x509_certificate *cert)
pr_devel("==>%s()\n", __func__);
+ if (cert->unsupported_crypto)
+ return -ENOPKG;
if (cert->sig.rsa.s)
return 0;
@@ -124,8 +136,13 @@ int x509_get_sig_params(struct x509_certificate *cert)
* big the hash operational data will be.
*/
tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
- if (IS_ERR(tfm))
- return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
+ if (IS_ERR(tfm)) {
+ if (PTR_ERR(tfm) == -ENOENT) {
+ cert->unsupported_crypto = true;
+ return -ENOPKG;
+ }
+ return PTR_ERR(tfm);
+ }
desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
digest_size = crypto_shash_digestsize(tfm);
@@ -172,6 +189,8 @@ int x509_check_signature(const struct public_key *pub,
return ret;
ret = public_key_verify_signature(pub, &cert->sig);
+ if (ret == -ENOPKG)
+ cert->unsupported_crypto = true;
pr_debug("Cert Verification: %d\n", ret);
return ret;
}
@@ -195,11 +214,11 @@ static int x509_validate_trust(struct x509_certificate *cert,
if (!trust_keyring)
return -EOPNOTSUPP;
- if (ca_keyid && !asymmetric_keyid_match(cert->authority, ca_keyid))
+ if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid))
return -EPERM;
- key = x509_request_asymmetric_key(trust_keyring,
- cert->issuer, cert->authority);
+ key = x509_request_asymmetric_key(trust_keyring, cert->authority,
+ false);
if (!IS_ERR(key)) {
if (!use_builtin_keys
|| test_bit(KEY_FLAG_BUILTIN, &key->flags))
@@ -214,9 +233,11 @@ static int x509_validate_trust(struct x509_certificate *cert,
*/
static int x509_key_preparse(struct key_preparsed_payload *prep)
{
+ struct asymmetric_key_ids *kids;
struct x509_certificate *cert;
+ const char *q;
size_t srlen, sulen;
- char *desc = NULL;
+ char *desc = NULL, *p;
int ret;
cert = x509_cert_parse(prep->data, prep->datalen);
@@ -249,19 +270,12 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
pkey_algo_name[cert->sig.pkey_algo],
hash_algo_name[cert->sig.pkey_hash_algo]);
- if (!cert->fingerprint) {
- pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
- cert->subject);
- ret = -EKEYREJECTED;
- goto error_free_cert;
- }
-
cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
cert->pub->id_type = PKEY_ID_X509;
/* Check the signature on the key if it appears to be self-signed */
if (!cert->authority ||
- strcmp(cert->fingerprint, cert->authority) == 0) {
+ asymmetric_key_id_same(cert->skid, cert->authority)) {
ret = x509_check_signature(cert->pub, cert); /* self-signed */
if (ret < 0)
goto error_free_cert;
@@ -273,31 +287,52 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
/* Propose a description */
sulen = strlen(cert->subject);
- srlen = strlen(cert->fingerprint);
+ if (cert->raw_skid) {
+ srlen = cert->raw_skid_size;
+ q = cert->raw_skid;
+ } else {
+ srlen = cert->raw_serial_size;
+ q = cert->raw_serial;
+ }
+ if (srlen > 1 && *q == 0) {
+ srlen--;
+ q++;
+ }
+
ret = -ENOMEM;
- desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL);
+ desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
if (!desc)
goto error_free_cert;
- memcpy(desc, cert->subject, sulen);
- desc[sulen] = ':';
- desc[sulen + 1] = ' ';
- memcpy(desc + sulen + 2, cert->fingerprint, srlen);
- desc[sulen + 2 + srlen] = 0;
+ p = memcpy(desc, cert->subject, sulen);
+ p += sulen;
+ *p++ = ':';
+ *p++ = ' ';
+ p = bin2hex(p, q, srlen);
+ *p = 0;
+
+ kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL);
+ if (!kids)
+ goto error_free_desc;
+ kids->id[0] = cert->id;
+ kids->id[1] = cert->skid;
/* We're pinning the module by being linked against it */
__module_get(public_key_subtype.owner);
prep->type_data[0] = &public_key_subtype;
- prep->type_data[1] = cert->fingerprint;
+ prep->type_data[1] = kids;
prep->payload[0] = cert->pub;
prep->description = desc;
prep->quotalen = 100;
/* We've finished with the certificate */
cert->pub = NULL;
- cert->fingerprint = NULL;
+ cert->id = NULL;
+ cert->skid = NULL;
desc = NULL;
ret = 0;
+error_free_desc:
+ kfree(desc);
error_free_cert:
x509_free_certificate(cert);
return ret;
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 3c562f5a60bb..e1bce26cd4f9 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -78,8 +78,6 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
tx = dma->device_prep_dma_xor(chan, dma_dest, src_list,
xor_src_cnt, unmap->len,
dma_flags);
- src_list[0] = tmp;
-
if (unlikely(!tx))
async_tx_quiesce(&submit->depend_tx);
@@ -92,6 +90,7 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
xor_src_cnt, unmap->len,
dma_flags);
}
+ src_list[0] = tmp;
dma_set_unmap(tx, unmap);
async_tx_submit(chan, tx, submit);
diff --git a/crypto/authenc.c b/crypto/authenc.c
index e1223559d5df..78fb16cab13f 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -721,3 +721,4 @@ module_exit(crypto_authenc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");
+MODULE_ALIAS_CRYPTO("authenc");
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 4be0dd4373a9..024bff2344fc 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -814,3 +814,4 @@ module_exit(crypto_authenc_esn_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
+MODULE_ALIAS_CRYPTO("authencesn");
diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c
index 8baf5447d35b..7bd71f02d0dd 100644
--- a/crypto/blowfish_generic.c
+++ b/crypto/blowfish_generic.c
@@ -138,4 +138,4 @@ module_exit(blowfish_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
-MODULE_ALIAS("blowfish");
+MODULE_ALIAS_CRYPTO("blowfish");
diff --git a/crypto/camellia_generic.c b/crypto/camellia_generic.c
index 26bcd7a2d6b4..1b74c5a3e891 100644
--- a/crypto/camellia_generic.c
+++ b/crypto/camellia_generic.c
@@ -1098,4 +1098,4 @@ module_exit(camellia_fini);
MODULE_DESCRIPTION("Camellia Cipher Algorithm");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("camellia");
+MODULE_ALIAS_CRYPTO("camellia");
diff --git a/crypto/cast5_generic.c b/crypto/cast5_generic.c
index 5558f630a0eb..84c86db67ec7 100644
--- a/crypto/cast5_generic.c
+++ b/crypto/cast5_generic.c
@@ -549,4 +549,4 @@ module_exit(cast5_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cast5 Cipher Algorithm");
-MODULE_ALIAS("cast5");
+MODULE_ALIAS_CRYPTO("cast5");
diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c
index de732528a430..f408f0bd8de2 100644
--- a/crypto/cast6_generic.c
+++ b/crypto/cast6_generic.c
@@ -291,4 +291,4 @@ module_exit(cast6_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
-MODULE_ALIAS("cast6");
+MODULE_ALIAS_CRYPTO("cast6");
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 61ac42e1e32b..780ee27b2d43 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -289,3 +289,4 @@ module_exit(crypto_cbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CBC block cipher algorithm");
+MODULE_ALIAS_CRYPTO("cbc");
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 1df84217f7c9..003bbbd21a2b 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -879,5 +879,6 @@ module_exit(crypto_ccm_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Counter with CBC MAC");
-MODULE_ALIAS("ccm_base");
-MODULE_ALIAS("rfc4309");
+MODULE_ALIAS_CRYPTO("ccm_base");
+MODULE_ALIAS_CRYPTO("rfc4309");
+MODULE_ALIAS_CRYPTO("ccm");
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index 9c294c8f9a07..63c17d5992f7 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -359,3 +359,4 @@ module_exit(chainiv_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Chain IV Generator");
+MODULE_ALIAS_CRYPTO("chainiv");
diff --git a/crypto/cmac.c b/crypto/cmac.c
index 50880cf17fad..7a8bfbd548f6 100644
--- a/crypto/cmac.c
+++ b/crypto/cmac.c
@@ -313,3 +313,4 @@ module_exit(crypto_cmac_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CMAC keyed hash algorithm");
+MODULE_ALIAS_CRYPTO("cmac");
diff --git a/crypto/crc32.c b/crypto/crc32.c
index 9d1c41569898..187ded28cb0b 100644
--- a/crypto/crc32.c
+++ b/crypto/crc32.c
@@ -156,3 +156,4 @@ module_exit(crc32_mod_fini);
MODULE_AUTHOR("Alexander Boyko <alexander_boyko@xyratex.com>");
MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_CRYPTO("crc32");
diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c
index d9c7beba8e50..2a062025749d 100644
--- a/crypto/crc32c_generic.c
+++ b/crypto/crc32c_generic.c
@@ -170,5 +170,5 @@ module_exit(crc32c_mod_fini);
MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("crc32c");
+MODULE_ALIAS_CRYPTO("crc32c");
MODULE_SOFTDEP("pre: crc32c");
diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c
index 877e7114ec5c..08bb4f504520 100644
--- a/crypto/crct10dif_generic.c
+++ b/crypto/crct10dif_generic.c
@@ -124,4 +124,4 @@ module_exit(crct10dif_mod_fini);
MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
MODULE_DESCRIPTION("T10 DIF CRC calculation.");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("crct10dif");
+MODULE_ALIAS_CRYPTO("crct10dif");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index e592c90abebb..650afac10fd7 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -955,3 +955,4 @@ module_exit(cryptd_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Software async crypto daemon");
+MODULE_ALIAS_CRYPTO("cryptd");
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 1dc54bb95a87..a20319132e33 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -145,9 +145,9 @@ static struct crypto_alg null_algs[3] = { {
.coa_decompress = null_compress } }
} };
-MODULE_ALIAS("compress_null");
-MODULE_ALIAS("digest_null");
-MODULE_ALIAS("cipher_null");
+MODULE_ALIAS_CRYPTO("compress_null");
+MODULE_ALIAS_CRYPTO("digest_null");
+MODULE_ALIAS_CRYPTO("cipher_null");
static int __init crypto_null_mod_init(void)
{
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index e2a34feec7a4..c5148a35ae0a 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -201,10 +201,7 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
return -EINVAL;
- if (!p->cru_driver_name[0])
- return -EINVAL;
-
- alg = crypto_alg_match(p, 1);
+ alg = crypto_alg_match(p, 0);
if (!alg)
return -ENOENT;
@@ -537,3 +534,4 @@ module_exit(crypto_user_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
MODULE_DESCRIPTION("Crypto userspace configuration API");
+MODULE_ALIAS("net-pf-16-proto-21");
diff --git a/crypto/ctr.c b/crypto/ctr.c
index f2b94f27bb2c..2386f7313952 100644
--- a/crypto/ctr.c
+++ b/crypto/ctr.c
@@ -466,4 +466,5 @@ module_exit(crypto_ctr_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CTR Counter block mode");
-MODULE_ALIAS("rfc3686");
+MODULE_ALIAS_CRYPTO("rfc3686");
+MODULE_ALIAS_CRYPTO("ctr");
diff --git a/crypto/cts.c b/crypto/cts.c
index 042223f8e733..bd9405820e8a 100644
--- a/crypto/cts.c
+++ b/crypto/cts.c
@@ -202,7 +202,8 @@ static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
/* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
/* 6. Decrypt En to create Pn-1 */
- memset(iv, 0, sizeof(iv));
+ memzero_explicit(iv, sizeof(iv));
+
sg_set_buf(&sgsrc[0], s + bsize, bsize);
sg_set_buf(&sgdst[0], d, bsize);
err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
@@ -350,3 +351,4 @@ module_exit(crypto_cts_module_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC");
+MODULE_ALIAS_CRYPTO("cts");
diff --git a/crypto/deflate.c b/crypto/deflate.c
index b57d70eb156b..95d8d37c5021 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -222,4 +222,4 @@ module_exit(deflate_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
-
+MODULE_ALIAS_CRYPTO("deflate");
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index 298d464ab7d2..42912948776b 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -983,7 +983,7 @@ static struct crypto_alg des_algs[2] = { {
.cia_decrypt = des3_ede_decrypt } }
} };
-MODULE_ALIAS("des3_ede");
+MODULE_ALIAS_CRYPTO("des3_ede");
static int __init des_generic_mod_init(void)
{
diff --git a/crypto/drbg.c b/crypto/drbg.c
index a53ee099e281..d748a1d0ca24 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -98,6 +98,7 @@
*/
#include <crypto/drbg.h>
+#include <linux/string.h>
/***************************************************************
* Backend cipher definitions available to DRBG
@@ -117,27 +118,18 @@ static const struct drbg_core drbg_cores[] = {
{
.flags = DRBG_CTR | DRBG_STRENGTH128,
.statelen = 32, /* 256 bits as defined in 10.2.1 */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 16,
.cra_name = "ctr_aes128",
.backend_cra_name = "ecb(aes)",
}, {
.flags = DRBG_CTR | DRBG_STRENGTH192,
.statelen = 40, /* 320 bits as defined in 10.2.1 */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 16,
.cra_name = "ctr_aes192",
.backend_cra_name = "ecb(aes)",
}, {
.flags = DRBG_CTR | DRBG_STRENGTH256,
.statelen = 48, /* 384 bits as defined in 10.2.1 */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 16,
.cra_name = "ctr_aes256",
.backend_cra_name = "ecb(aes)",
@@ -147,36 +139,24 @@ static const struct drbg_core drbg_cores[] = {
{
.flags = DRBG_HASH | DRBG_STRENGTH128,
.statelen = 55, /* 440 bits */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 20,
.cra_name = "sha1",
.backend_cra_name = "sha1",
}, {
.flags = DRBG_HASH | DRBG_STRENGTH256,
.statelen = 111, /* 888 bits */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 48,
.cra_name = "sha384",
.backend_cra_name = "sha384",
}, {
.flags = DRBG_HASH | DRBG_STRENGTH256,
.statelen = 111, /* 888 bits */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 64,
.cra_name = "sha512",
.backend_cra_name = "sha512",
}, {
.flags = DRBG_HASH | DRBG_STRENGTH256,
.statelen = 55, /* 440 bits */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 32,
.cra_name = "sha256",
.backend_cra_name = "sha256",
@@ -186,36 +166,24 @@ static const struct drbg_core drbg_cores[] = {
{
.flags = DRBG_HMAC | DRBG_STRENGTH128,
.statelen = 20, /* block length of cipher */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 20,
.cra_name = "hmac_sha1",
.backend_cra_name = "hmac(sha1)",
}, {
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 48, /* block length of cipher */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 48,
.cra_name = "hmac_sha384",
.backend_cra_name = "hmac(sha384)",
}, {
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 64, /* block length of cipher */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 64,
.cra_name = "hmac_sha512",
.backend_cra_name = "hmac(sha512)",
}, {
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 32, /* block length of cipher */
- .max_addtllen = 35,
- .max_bits = 19,
- .max_req = 48,
.blocklen_bytes = 32,
.cra_name = "hmac_sha256",
.backend_cra_name = "hmac(sha256)",
@@ -302,52 +270,19 @@ static bool drbg_fips_continuous_test(struct drbg_state *drbg,
* Convert an integer into a byte representation of this integer.
* The byte representation is big-endian
*
- * @buf buffer holding the converted integer
* @val value to be converted
- * @buflen length of buffer
+ * @buf buffer holding the converted integer -- caller must ensure that
+ * buffer size is at least 32 bit
*/
#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
-static inline void drbg_int2byte(unsigned char *buf, uint64_t val,
- size_t buflen)
+static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
{
- unsigned char *byte;
- uint64_t i;
+ struct s {
+ __be32 conv;
+ };
+ struct s *conversion = (struct s *) buf;
- byte = buf + (buflen - 1);
- for (i = 0; i < buflen; i++)
- *(byte--) = val >> (i * 8) & 0xff;
-}
-
-/*
- * Increment buffer
- *
- * @dst buffer to increment
- * @add value to add
- */
-static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
- const unsigned char *add, size_t addlen)
-{
- /* implied: dstlen > addlen */
- unsigned char *dstptr;
- const unsigned char *addptr;
- unsigned int remainder = 0;
- size_t len = addlen;
-
- dstptr = dst + (dstlen-1);
- addptr = add + (addlen-1);
- while (len) {
- remainder += *dstptr + *addptr;
- *dstptr = remainder & 0xff;
- remainder >>= 8;
- len--; dstptr--; addptr--;
- }
- len = dstlen - addlen;
- while (len && remainder > 0) {
- remainder = *dstptr + 1;
- *dstptr = remainder & 0xff;
- remainder >>= 8;
- len--; dstptr--;
- }
+ conversion->conv = cpu_to_be32(val);
}
#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
@@ -357,6 +292,13 @@ static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
#ifdef CONFIG_CRYPTO_DRBG_CTR
#define CRYPTO_DRBG_CTR_STRING "CTR "
+MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes256");
+MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes256");
+MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes192");
+MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes192");
+MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128");
+MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128");
+
static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
unsigned char *outval, const struct drbg_string *in);
static int drbg_init_sym_kernel(struct drbg_state *drbg);
@@ -483,10 +425,10 @@ static int drbg_ctr_df(struct drbg_state *drbg,
/* 10.4.2 step 2 -- calculate the entire length of all input data */
list_for_each_entry(seed, seedlist, list)
inputlen += seed->len;
- drbg_int2byte(&L_N[0], inputlen, 4);
+ drbg_cpu_to_be32(inputlen, &L_N[0]);
/* 10.4.2 step 3 */
- drbg_int2byte(&L_N[4], bytes_to_return, 4);
+ drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
@@ -517,7 +459,7 @@ static int drbg_ctr_df(struct drbg_state *drbg,
* holds zeros after allocation -- even the increment of i
* is irrelevant as the increment remains within length of i
*/
- drbg_int2byte(iv, i, 4);
+ drbg_cpu_to_be32(i, iv);
/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
if (ret)
@@ -556,9 +498,9 @@ static int drbg_ctr_df(struct drbg_state *drbg,
ret = 0;
out:
- memset(iv, 0, drbg_blocklen(drbg));
- memset(temp, 0, drbg_statelen(drbg));
- memset(pad, 0, drbg_blocklen(drbg));
+ memzero_explicit(iv, drbg_blocklen(drbg));
+ memzero_explicit(temp, drbg_statelen(drbg));
+ memzero_explicit(pad, drbg_blocklen(drbg));
return ret;
}
@@ -588,7 +530,6 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
unsigned int len = 0;
struct drbg_string cipherin;
- unsigned char prefix = DRBG_PREFIX1;
memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
if (3 > reseed)
@@ -608,7 +549,7 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
*/
while (len < (drbg_statelen(drbg))) {
/* 10.2.1.2 step 2.1 */
- drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ crypto_inc(drbg->V, drbg_blocklen(drbg));
/*
* 10.2.1.2 step 2.2 */
ret = drbg_kcapi_sym(drbg, drbg->C, temp + len, &cipherin);
@@ -633,9 +574,9 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
ret = 0;
out:
- memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
+ memzero_explicit(temp, drbg_statelen(drbg) + drbg_blocklen(drbg));
if (2 != reseed)
- memset(df_data, 0, drbg_statelen(drbg));
+ memzero_explicit(df_data, drbg_statelen(drbg));
return ret;
}
@@ -651,7 +592,6 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
int len = 0;
int ret = 0;
struct drbg_string data;
- unsigned char prefix = DRBG_PREFIX1;
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
@@ -663,7 +603,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
}
/* 10.2.1.5.2 step 4.1 */
- drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ crypto_inc(drbg->V, drbg_blocklen(drbg));
drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg));
while (len < buflen) {
int outlen = 0;
@@ -677,7 +617,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
drbg_blocklen(drbg) : (buflen - len);
if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) {
/* 10.2.1.5.2 step 6 */
- drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ crypto_inc(drbg->V, drbg_blocklen(drbg));
continue;
}
/* 10.2.1.5.2 step 4.3 */
@@ -685,7 +625,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
len += outlen;
/* 10.2.1.5.2 step 6 */
if (len < buflen)
- drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
+ crypto_inc(drbg->V, drbg_blocklen(drbg));
}
/* 10.2.1.5.2 step 6 */
@@ -694,7 +634,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
len = ret;
out:
- memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg));
return len;
}
@@ -719,6 +659,15 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg);
#ifdef CONFIG_CRYPTO_DRBG_HMAC
#define CRYPTO_DRBG_HMAC_STRING "HMAC "
+MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
+MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
+MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384");
+MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha384");
+MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha256");
+MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha256");
+MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha1");
+MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha1");
+
/* update function of HMAC DRBG as defined in 10.1.2.2 */
static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
int reseed)
@@ -729,11 +678,9 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
LIST_HEAD(seedlist);
LIST_HEAD(vdatalist);
- if (!reseed) {
- /* 10.1.2.3 step 2 */
- memset(drbg->C, 0, drbg_statelen(drbg));
+ if (!reseed)
+ /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
memset(drbg->V, 1, drbg_statelen(drbg));
- }
drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
list_add_tail(&seed1.list, &seedlist);
@@ -832,6 +779,47 @@ static struct drbg_state_ops drbg_hmac_ops = {
#ifdef CONFIG_CRYPTO_DRBG_HASH
#define CRYPTO_DRBG_HASH_STRING "HASH "
+MODULE_ALIAS_CRYPTO("drbg_pr_sha512");
+MODULE_ALIAS_CRYPTO("drbg_nopr_sha512");
+MODULE_ALIAS_CRYPTO("drbg_pr_sha384");
+MODULE_ALIAS_CRYPTO("drbg_nopr_sha384");
+MODULE_ALIAS_CRYPTO("drbg_pr_sha256");
+MODULE_ALIAS_CRYPTO("drbg_nopr_sha256");
+MODULE_ALIAS_CRYPTO("drbg_pr_sha1");
+MODULE_ALIAS_CRYPTO("drbg_nopr_sha1");
+
+/*
+ * Increment buffer
+ *
+ * @dst buffer to increment
+ * @add value to add
+ */
+static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
+ const unsigned char *add, size_t addlen)
+{
+ /* implied: dstlen > addlen */
+ unsigned char *dstptr;
+ const unsigned char *addptr;
+ unsigned int remainder = 0;
+ size_t len = addlen;
+
+ dstptr = dst + (dstlen-1);
+ addptr = add + (addlen-1);
+ while (len) {
+ remainder += *dstptr + *addptr;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--; addptr--;
+ }
+ len = dstlen - addlen;
+ while (len && remainder > 0) {
+ remainder = *dstptr + 1;
+ *dstptr = remainder & 0xff;
+ remainder >>= 8;
+ len--; dstptr--;
+ }
+}
+
/*
* scratchpad usage: as drbg_hash_update and drbg_hash_df are used
* interlinked, the scratchpad is used as follows:
@@ -862,7 +850,7 @@ static int drbg_hash_df(struct drbg_state *drbg,
/* 10.4.1 step 3 */
input[0] = 1;
- drbg_int2byte(&input[1], (outlen * 8), 4);
+ drbg_cpu_to_be32((outlen * 8), &input[1]);
/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
drbg_string_fill(&data, input, 5);
@@ -884,7 +872,7 @@ static int drbg_hash_df(struct drbg_state *drbg,
}
out:
- memset(tmp, 0, drbg_blocklen(drbg));
+ memzero_explicit(tmp, drbg_blocklen(drbg));
return ret;
}
@@ -928,7 +916,7 @@ static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
out:
- memset(drbg->scratchpad, 0, drbg_statelen(drbg));
+ memzero_explicit(drbg->scratchpad, drbg_statelen(drbg));
return ret;
}
@@ -963,7 +951,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
drbg->scratchpad, drbg_blocklen(drbg));
out:
- memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg));
return ret;
}
@@ -978,7 +966,6 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
struct drbg_string data;
LIST_HEAD(datalist);
- unsigned char prefix = DRBG_PREFIX1;
memset(src, 0, drbg_statelen(drbg));
memset(dst, 0, drbg_blocklen(drbg));
@@ -999,7 +986,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
drbg_blocklen(drbg) : (buflen - len);
if (!drbg_fips_continuous_test(drbg, dst)) {
- drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ crypto_inc(src, drbg_statelen(drbg));
continue;
}
/* 10.1.1.4 step hashgen 4.2 */
@@ -1007,11 +994,11 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
len += outlen;
/* 10.1.1.4 hashgen step 4.3 */
if (len < buflen)
- drbg_add_buf(src, drbg_statelen(drbg), &prefix, 1);
+ crypto_inc(src, drbg_statelen(drbg));
}
out:
- memset(drbg->scratchpad, 0,
+ memzero_explicit(drbg->scratchpad,
(drbg_statelen(drbg) + drbg_blocklen(drbg)));
return len;
}
@@ -1023,7 +1010,10 @@ static int drbg_hash_generate(struct drbg_state *drbg,
{
int len = 0;
int ret = 0;
- unsigned char req[8];
+ union {
+ unsigned char req[8];
+ __be64 req_int;
+ } u;
unsigned char prefix = DRBG_PREFIX3;
struct drbg_string data1, data2;
LIST_HEAD(datalist);
@@ -1053,11 +1043,11 @@ static int drbg_hash_generate(struct drbg_state *drbg,
drbg->scratchpad, drbg_blocklen(drbg));
drbg_add_buf(drbg->V, drbg_statelen(drbg),
drbg->C, drbg_statelen(drbg));
- drbg_int2byte(req, drbg->reseed_ctr, sizeof(req));
- drbg_add_buf(drbg->V, drbg_statelen(drbg), req, 8);
+ u.req_int = cpu_to_be64(drbg->reseed_ctr);
+ drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8);
out:
- memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
+ memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg));
return len;
}
@@ -1142,6 +1132,11 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
pr_devel("DRBG: using personalization string\n");
}
+ if (!reseed) {
+ memset(drbg->V, 0, drbg_statelen(drbg));
+ memset(drbg->C, 0, drbg_statelen(drbg));
+ }
+
ret = drbg->d_ops->update(drbg, &seedlist, reseed);
if (ret)
goto out;
@@ -1151,8 +1146,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
drbg->reseed_ctr = 1;
out:
- if (entropy)
- kzfree(entropy);
+ kzfree(entropy);
return ret;
}
@@ -1161,19 +1155,15 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
{
if (!drbg)
return;
- if (drbg->V)
- kzfree(drbg->V);
+ kzfree(drbg->V);
drbg->V = NULL;
- if (drbg->C)
- kzfree(drbg->C);
+ kzfree(drbg->C);
drbg->C = NULL;
- if (drbg->scratchpad)
- kzfree(drbg->scratchpad);
+ kzfree(drbg->scratchpad);
drbg->scratchpad = NULL;
drbg->reseed_ctr = 0;
#ifdef CONFIG_CRYPTO_FIPS
- if (drbg->prev)
- kzfree(drbg->prev);
+ kzfree(drbg->prev);
drbg->prev = NULL;
drbg->fips_primed = false;
#endif
@@ -1188,17 +1178,14 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
int ret = -ENOMEM;
unsigned int sb_size = 0;
- if (!drbg)
- return -EINVAL;
-
- drbg->V = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ drbg->V = kmalloc(drbg_statelen(drbg), GFP_KERNEL);
if (!drbg->V)
goto err;
- drbg->C = kzalloc(drbg_statelen(drbg), GFP_KERNEL);
+ drbg->C = kmalloc(drbg_statelen(drbg), GFP_KERNEL);
if (!drbg->C)
goto err;
#ifdef CONFIG_CRYPTO_FIPS
- drbg->prev = kzalloc(drbg_blocklen(drbg), GFP_KERNEL);
+ drbg->prev = kmalloc(drbg_blocklen(drbg), GFP_KERNEL);
if (!drbg->prev)
goto err;
drbg->fips_primed = false;
@@ -1263,15 +1250,6 @@ static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
int ret = -ENOMEM;
struct drbg_state *tmp = NULL;
- if (!drbg || !drbg->core || !drbg->V || !drbg->C) {
- pr_devel("DRBG: attempt to generate shadow copy for "
- "uninitialized DRBG state rejected\n");
- return -EINVAL;
- }
- /* HMAC does not have a scratchpad */
- if (!(drbg->core->flags & DRBG_HMAC) && NULL == drbg->scratchpad)
- return -EINVAL;
-
tmp = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
@@ -1293,8 +1271,7 @@ static int drbg_make_shadow(struct drbg_state *drbg, struct drbg_state **shadow)
return 0;
err:
- if (tmp)
- kzfree(tmp);
+ kzfree(tmp);
return ret;
}
@@ -1385,11 +1362,9 @@ static int drbg_generate(struct drbg_state *drbg,
shadow->seeded = false;
/* allocate cipher handle */
- if (shadow->d_ops->crypto_init) {
- len = shadow->d_ops->crypto_init(shadow);
- if (len)
- goto err;
- }
+ len = shadow->d_ops->crypto_init(shadow);
+ if (len)
+ goto err;
if (shadow->pr || !shadow->seeded) {
pr_devel("DRBG: reseeding before generation (prediction "
@@ -1471,8 +1446,7 @@ static int drbg_generate(struct drbg_state *drbg,
#endif
err:
- if (shadow->d_ops->crypto_fini)
- shadow->d_ops->crypto_fini(shadow);
+ shadow->d_ops->crypto_fini(shadow);
drbg_restore_shadow(drbg, &shadow);
return len;
}
@@ -1566,11 +1540,10 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
return ret;
ret = -EFAULT;
- if (drbg->d_ops->crypto_init && drbg->d_ops->crypto_init(drbg))
+ if (drbg->d_ops->crypto_init(drbg))
goto err;
ret = drbg_seed(drbg, pers, false);
- if (drbg->d_ops->crypto_fini)
- drbg->d_ops->crypto_fini(drbg);
+ drbg->d_ops->crypto_fini(drbg);
if (ret)
goto err;
diff --git a/crypto/ecb.c b/crypto/ecb.c
index 935cfef4aa84..12011aff0971 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -185,3 +185,4 @@ module_exit(crypto_ecb_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ECB block cipher algorithm");
+MODULE_ALIAS_CRYPTO("ecb");
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index bf7ab4a89493..f116fae766f8 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -267,3 +267,4 @@ module_exit(eseqiv_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
+MODULE_ALIAS_CRYPTO("eseqiv");
diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
index 021d7fec6bc8..77286ea28865 100644
--- a/crypto/fcrypt.c
+++ b/crypto/fcrypt.c
@@ -420,3 +420,4 @@ module_exit(fcrypt_mod_fini);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
+MODULE_ALIAS_CRYPTO("fcrypt");
diff --git a/crypto/gcm.c b/crypto/gcm.c
index 276cdac567b6..2e403f6138c1 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -1441,6 +1441,7 @@ module_exit(crypto_gcm_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Galois/Counter Mode");
MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
-MODULE_ALIAS("gcm_base");
-MODULE_ALIAS("rfc4106");
-MODULE_ALIAS("rfc4543");
+MODULE_ALIAS_CRYPTO("gcm_base");
+MODULE_ALIAS_CRYPTO("rfc4106");
+MODULE_ALIAS_CRYPTO("rfc4543");
+MODULE_ALIAS_CRYPTO("gcm");
diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
index 9d3f0c69a86f..4e97fae9666f 100644
--- a/crypto/ghash-generic.c
+++ b/crypto/ghash-generic.c
@@ -172,4 +172,4 @@ module_exit(ghash_mod_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("GHASH Message Digest Algorithm");
-MODULE_ALIAS("ghash");
+MODULE_ALIAS_CRYPTO("ghash");
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 8d9544cf8169..72e38c098bb3 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -52,20 +52,17 @@ static int hmac_setkey(struct crypto_shash *parent,
struct hmac_ctx *ctx = align_ptr(opad + ss,
crypto_tfm_ctx_alignment());
struct crypto_shash *hash = ctx->hash;
- struct {
- struct shash_desc shash;
- char ctx[crypto_shash_descsize(hash)];
- } desc;
+ SHASH_DESC_ON_STACK(shash, hash);
unsigned int i;
- desc.shash.tfm = hash;
- desc.shash.flags = crypto_shash_get_flags(parent) &
- CRYPTO_TFM_REQ_MAY_SLEEP;
+ shash->tfm = hash;
+ shash->flags = crypto_shash_get_flags(parent)
+ & CRYPTO_TFM_REQ_MAY_SLEEP;
if (keylen > bs) {
int err;
- err = crypto_shash_digest(&desc.shash, inkey, keylen, ipad);
+ err = crypto_shash_digest(shash, inkey, keylen, ipad);
if (err)
return err;
@@ -81,12 +78,12 @@ static int hmac_setkey(struct crypto_shash *parent,
opad[i] ^= 0x5c;
}
- return crypto_shash_init(&desc.shash) ?:
- crypto_shash_update(&desc.shash, ipad, bs) ?:
- crypto_shash_export(&desc.shash, ipad) ?:
- crypto_shash_init(&desc.shash) ?:
- crypto_shash_update(&desc.shash, opad, bs) ?:
- crypto_shash_export(&desc.shash, opad);
+ return crypto_shash_init(shash) ?:
+ crypto_shash_update(shash, ipad, bs) ?:
+ crypto_shash_export(shash, ipad) ?:
+ crypto_shash_init(shash) ?:
+ crypto_shash_update(shash, opad, bs) ?:
+ crypto_shash_export(shash, opad);
}
static int hmac_export(struct shash_desc *pdesc, void *out)
@@ -271,3 +268,4 @@ module_exit(hmac_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("HMAC hash algorithm");
+MODULE_ALIAS_CRYPTO("hmac");
diff --git a/crypto/khazad.c b/crypto/khazad.c
index 60e7cd66facc..873eb5ded6d7 100644
--- a/crypto/khazad.c
+++ b/crypto/khazad.c
@@ -880,3 +880,4 @@ module_exit(khazad_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Khazad Cryptographic Algorithm");
+MODULE_ALIAS_CRYPTO("khazad");
diff --git a/crypto/krng.c b/crypto/krng.c
index a2d2b72fc135..67c88b331210 100644
--- a/crypto/krng.c
+++ b/crypto/krng.c
@@ -62,4 +62,4 @@ module_exit(krng_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Kernel Random Number Generator");
-MODULE_ALIAS("stdrng");
+MODULE_ALIAS_CRYPTO("stdrng");
diff --git a/crypto/lrw.c b/crypto/lrw.c
index ba42acc4deba..6f9908a7ebcb 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -400,3 +400,4 @@ module_exit(crypto_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LRW block cipher mode");
+MODULE_ALIAS_CRYPTO("lrw");
diff --git a/crypto/lz4.c b/crypto/lz4.c
index 4586dd15b0d8..aefbceaf3104 100644
--- a/crypto/lz4.c
+++ b/crypto/lz4.c
@@ -68,7 +68,7 @@ static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
size_t tmp_len = *dlen;
size_t __slen = slen;
- err = lz4_decompress(src, &__slen, dst, tmp_len);
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
if (err < 0)
return -EINVAL;
@@ -104,3 +104,4 @@ module_exit(lz4_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZ4 Compression Algorithm");
+MODULE_ALIAS_CRYPTO("lz4");
diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c
index 151ba31d34e3..a1d3b5bd3d85 100644
--- a/crypto/lz4hc.c
+++ b/crypto/lz4hc.c
@@ -68,7 +68,7 @@ static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
size_t tmp_len = *dlen;
size_t __slen = slen;
- err = lz4_decompress(src, &__slen, dst, tmp_len);
+ err = lz4_decompress_unknownoutputsize(src, __slen, dst, &tmp_len);
if (err < 0)
return -EINVAL;
@@ -104,3 +104,4 @@ module_exit(lz4hc_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZ4HC Compression Algorithm");
+MODULE_ALIAS_CRYPTO("lz4hc");
diff --git a/crypto/lzo.c b/crypto/lzo.c
index a8ff2f778dc4..4b3e92525dac 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -107,3 +107,4 @@ module_exit(lzo_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO Compression Algorithm");
+MODULE_ALIAS_CRYPTO("lzo");
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
new file mode 100644
index 000000000000..a8e870444ea9
--- /dev/null
+++ b/crypto/mcryptd.c
@@ -0,0 +1,706 @@
+/*
+ * Software multibuffer async crypto daemon.
+ *
+ * Copyright (c) 2014 Tim Chen <tim.c.chen@linux.intel.com>
+ *
+ * Adapted from crypto daemon.
+ *
+ * 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 <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/aead.h>
+#include <crypto/mcryptd.h>
+#include <crypto/crypto_wq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/hardirq.h>
+
+#define MCRYPTD_MAX_CPU_QLEN 100
+#define MCRYPTD_BATCH 9
+
+static void *mcryptd_alloc_instance(struct crypto_alg *alg, unsigned int head,
+ unsigned int tail);
+
+struct mcryptd_flush_list {
+ struct list_head list;
+ struct mutex lock;
+};
+
+static struct mcryptd_flush_list __percpu *mcryptd_flist;
+
+struct hashd_instance_ctx {
+ struct crypto_shash_spawn spawn;
+ struct mcryptd_queue *queue;
+};
+
+static void mcryptd_queue_worker(struct work_struct *work);
+
+void mcryptd_arm_flusher(struct mcryptd_alg_cstate *cstate, unsigned long delay)
+{
+ struct mcryptd_flush_list *flist;
+
+ if (!cstate->flusher_engaged) {
+ /* put the flusher on the flush list */
+ flist = per_cpu_ptr(mcryptd_flist, smp_processor_id());
+ mutex_lock(&flist->lock);
+ list_add_tail(&cstate->flush_list, &flist->list);
+ cstate->flusher_engaged = true;
+ cstate->next_flush = jiffies + delay;
+ queue_delayed_work_on(smp_processor_id(), kcrypto_wq,
+ &cstate->flush, delay);
+ mutex_unlock(&flist->lock);
+ }
+}
+EXPORT_SYMBOL(mcryptd_arm_flusher);
+
+static int mcryptd_init_queue(struct mcryptd_queue *queue,
+ unsigned int max_cpu_qlen)
+{
+ int cpu;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ queue->cpu_queue = alloc_percpu(struct mcryptd_cpu_queue);
+ pr_debug("mqueue:%p mcryptd_cpu_queue %p\n", queue, queue->cpu_queue);
+ if (!queue->cpu_queue)
+ return -ENOMEM;
+ for_each_possible_cpu(cpu) {
+ cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+ pr_debug("cpu_queue #%d %p\n", cpu, queue->cpu_queue);
+ crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
+ INIT_WORK(&cpu_queue->work, mcryptd_queue_worker);
+ }
+ return 0;
+}
+
+static void mcryptd_fini_queue(struct mcryptd_queue *queue)
+{
+ int cpu;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ for_each_possible_cpu(cpu) {
+ cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+ BUG_ON(cpu_queue->queue.qlen);
+ }
+ free_percpu(queue->cpu_queue);
+}
+
+static int mcryptd_enqueue_request(struct mcryptd_queue *queue,
+ struct crypto_async_request *request,
+ struct mcryptd_hash_request_ctx *rctx)
+{
+ int cpu, err;
+ struct mcryptd_cpu_queue *cpu_queue;
+
+ cpu = get_cpu();
+ cpu_queue = this_cpu_ptr(queue->cpu_queue);
+ rctx->tag.cpu = cpu;
+
+ err = crypto_enqueue_request(&cpu_queue->queue, request);
+ pr_debug("enqueue request: cpu %d cpu_queue %p request %p\n",
+ cpu, cpu_queue, request);
+ queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
+ put_cpu();
+
+ return err;
+}
+
+/*
+ * Try to opportunisticlly flush the partially completed jobs if
+ * crypto daemon is the only task running.
+ */
+static void mcryptd_opportunistic_flush(void)
+{
+ struct mcryptd_flush_list *flist;
+ struct mcryptd_alg_cstate *cstate;
+
+ flist = per_cpu_ptr(mcryptd_flist, smp_processor_id());
+ while (single_task_running()) {
+ mutex_lock(&flist->lock);
+ if (list_empty(&flist->list)) {
+ mutex_unlock(&flist->lock);
+ return;
+ }
+ cstate = list_entry(flist->list.next,
+ struct mcryptd_alg_cstate, flush_list);
+ if (!cstate->flusher_engaged) {
+ mutex_unlock(&flist->lock);
+ return;
+ }
+ list_del(&cstate->flush_list);
+ cstate->flusher_engaged = false;
+ mutex_unlock(&flist->lock);
+ cstate->alg_state->flusher(cstate);
+ }
+}
+
+/*
+ * Called in workqueue context, do one real cryption work (via
+ * req->complete) and reschedule itself if there are more work to
+ * do.
+ */
+static void mcryptd_queue_worker(struct work_struct *work)
+{
+ struct mcryptd_cpu_queue *cpu_queue;
+ struct crypto_async_request *req, *backlog;
+ int i;
+
+ /*
+ * Need to loop through more than once for multi-buffer to
+ * be effective.
+ */
+
+ cpu_queue = container_of(work, struct mcryptd_cpu_queue, work);
+ i = 0;
+ while (i < MCRYPTD_BATCH || single_task_running()) {
+ /*
+ * preempt_disable/enable is used to prevent
+ * being preempted by mcryptd_enqueue_request()
+ */
+ local_bh_disable();
+ preempt_disable();
+ backlog = crypto_get_backlog(&cpu_queue->queue);
+ req = crypto_dequeue_request(&cpu_queue->queue);
+ preempt_enable();
+ local_bh_enable();
+
+ if (!req) {
+ mcryptd_opportunistic_flush();
+ return;
+ }
+
+ if (backlog)
+ backlog->complete(backlog, -EINPROGRESS);
+ req->complete(req, 0);
+ if (!cpu_queue->queue.qlen)
+ return;
+ ++i;
+ }
+ if (cpu_queue->queue.qlen)
+ queue_work(kcrypto_wq, &cpu_queue->work);
+}
+
+void mcryptd_flusher(struct work_struct *__work)
+{
+ struct mcryptd_alg_cstate *alg_cpu_state;
+ struct mcryptd_alg_state *alg_state;
+ struct mcryptd_flush_list *flist;
+ int cpu;
+
+ cpu = smp_processor_id();
+ alg_cpu_state = container_of(to_delayed_work(__work),
+ struct mcryptd_alg_cstate, flush);
+ alg_state = alg_cpu_state->alg_state;
+ if (alg_cpu_state->cpu != cpu)
+ pr_debug("mcryptd error: work on cpu %d, should be cpu %d\n",
+ cpu, alg_cpu_state->cpu);
+
+ if (alg_cpu_state->flusher_engaged) {
+ flist = per_cpu_ptr(mcryptd_flist, cpu);
+ mutex_lock(&flist->lock);
+ list_del(&alg_cpu_state->flush_list);
+ alg_cpu_state->flusher_engaged = false;
+ mutex_unlock(&flist->lock);
+ alg_state->flusher(alg_cpu_state);
+ }
+}
+EXPORT_SYMBOL_GPL(mcryptd_flusher);
+
+static inline struct mcryptd_queue *mcryptd_get_queue(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct mcryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+
+ return ictx->queue;
+}
+
+static void *mcryptd_alloc_instance(struct crypto_alg *alg, unsigned int head,
+ unsigned int tail)
+{
+ char *p;
+ struct crypto_instance *inst;
+ int err;
+
+ p = kzalloc(head + sizeof(*inst) + tail, GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ inst = (void *)(p + head);
+
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "mcryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+ goto out_free_inst;
+
+ memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+
+ inst->alg.cra_priority = alg->cra_priority + 50;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+
+out:
+ return p;
+
+out_free_inst:
+ kfree(p);
+ p = ERR_PTR(err);
+ goto out;
+}
+
+static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+ struct hashd_instance_ctx *ictx = crypto_instance_ctx(inst);
+ struct crypto_shash_spawn *spawn = &ictx->spawn;
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_shash *hash;
+
+ hash = crypto_spawn_shash(spawn);
+ if (IS_ERR(hash))
+ return PTR_ERR(hash);
+
+ ctx->child = hash;
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct mcryptd_hash_request_ctx) +
+ crypto_shash_descsize(hash));
+ return 0;
+}
+
+static void mcryptd_hash_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_shash(ctx->child);
+}
+
+static int mcryptd_hash_setkey(struct crypto_ahash *parent,
+ const u8 *key, unsigned int keylen)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(parent);
+ struct crypto_shash *child = ctx->child;
+ int err;
+
+ crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) &
+ CRYPTO_TFM_REQ_MASK);
+ err = crypto_shash_setkey(child, key, keylen);
+ crypto_ahash_set_flags(parent, crypto_shash_get_flags(child) &
+ CRYPTO_TFM_RES_MASK);
+ return err;
+}
+
+static int mcryptd_hash_enqueue(struct ahash_request *req,
+ crypto_completion_t complete)
+{
+ int ret;
+
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct mcryptd_queue *queue =
+ mcryptd_get_queue(crypto_ahash_tfm(tfm));
+
+ rctx->complete = req->base.complete;
+ req->base.complete = complete;
+
+ ret = mcryptd_enqueue_request(queue, &req->base, rctx);
+
+ return ret;
+}
+
+static void mcryptd_hash_init(struct crypto_async_request *req_async, int err)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
+ struct crypto_shash *child = ctx->child;
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct shash_desc *desc = &rctx->desc;
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ desc->tfm = child;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ err = crypto_shash_init(desc);
+
+ req->base.complete = rctx->complete;
+
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_init_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_init);
+}
+
+static void mcryptd_hash_update(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_update(req, &rctx->desc);
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_update_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_update);
+}
+
+static void mcryptd_hash_final(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_final(req, &rctx->desc);
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_final_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_final);
+}
+
+static void mcryptd_hash_finup(struct crypto_async_request *req_async, int err)
+{
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ err = shash_ahash_mcryptd_finup(req, &rctx->desc);
+
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_finup_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_finup);
+}
+
+static void mcryptd_hash_digest(struct crypto_async_request *req_async, int err)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
+ struct crypto_shash *child = ctx->child;
+ struct ahash_request *req = ahash_request_cast(req_async);
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ struct shash_desc *desc = &rctx->desc;
+
+ if (unlikely(err == -EINPROGRESS))
+ goto out;
+
+ desc->tfm = child;
+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; /* check this again */
+
+ err = shash_ahash_mcryptd_digest(req, desc);
+
+ if (err) {
+ req->base.complete = rctx->complete;
+ goto out;
+ }
+
+ return;
+out:
+ local_bh_disable();
+ rctx->complete(&req->base, err);
+ local_bh_enable();
+}
+
+static int mcryptd_hash_digest_enqueue(struct ahash_request *req)
+{
+ return mcryptd_hash_enqueue(req, mcryptd_hash_digest);
+}
+
+static int mcryptd_hash_export(struct ahash_request *req, void *out)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ return crypto_shash_export(&rctx->desc, out);
+}
+
+static int mcryptd_hash_import(struct ahash_request *req, const void *in)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+
+ return crypto_shash_import(&rctx->desc, in);
+}
+
+static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
+ struct mcryptd_queue *queue)
+{
+ struct hashd_instance_ctx *ctx;
+ struct ahash_instance *inst;
+ struct shash_alg *salg;
+ struct crypto_alg *alg;
+ int err;
+
+ salg = shash_attr_alg(tb[1], 0, 0);
+ if (IS_ERR(salg))
+ return PTR_ERR(salg);
+
+ alg = &salg->base;
+ pr_debug("crypto: mcryptd hash alg: %s\n", alg->cra_name);
+ inst = mcryptd_alloc_instance(alg, ahash_instance_headroom(),
+ sizeof(*ctx));
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ ctx = ahash_instance_ctx(inst);
+ ctx->queue = queue;
+
+ err = crypto_init_shash_spawn(&ctx->spawn, salg,
+ ahash_crypto_instance(inst));
+ if (err)
+ goto out_free_inst;
+
+ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC;
+
+ inst->alg.halg.digestsize = salg->digestsize;
+ inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx);
+
+ inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm;
+ inst->alg.halg.base.cra_exit = mcryptd_hash_exit_tfm;
+
+ inst->alg.init = mcryptd_hash_init_enqueue;
+ inst->alg.update = mcryptd_hash_update_enqueue;
+ inst->alg.final = mcryptd_hash_final_enqueue;
+ inst->alg.finup = mcryptd_hash_finup_enqueue;
+ inst->alg.export = mcryptd_hash_export;
+ inst->alg.import = mcryptd_hash_import;
+ inst->alg.setkey = mcryptd_hash_setkey;
+ inst->alg.digest = mcryptd_hash_digest_enqueue;
+
+ err = ahash_register_instance(tmpl, inst);
+ if (err) {
+ crypto_drop_shash(&ctx->spawn);
+out_free_inst:
+ kfree(inst);
+ }
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return err;
+}
+
+static struct mcryptd_queue mqueue;
+
+static int mcryptd_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ struct crypto_attr_type *algt;
+
+ algt = crypto_get_attr_type(tb);
+ if (IS_ERR(algt))
+ return PTR_ERR(algt);
+
+ switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_DIGEST:
+ return mcryptd_create_hash(tmpl, tb, &mqueue);
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static void mcryptd_free(struct crypto_instance *inst)
+{
+ struct mcryptd_instance_ctx *ctx = crypto_instance_ctx(inst);
+ struct hashd_instance_ctx *hctx = crypto_instance_ctx(inst);
+
+ switch (inst->alg.cra_flags & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_AHASH:
+ crypto_drop_shash(&hctx->spawn);
+ kfree(ahash_instance(inst));
+ return;
+ default:
+ crypto_drop_spawn(&ctx->spawn);
+ kfree(inst);
+ }
+}
+
+static struct crypto_template mcryptd_tmpl = {
+ .name = "mcryptd",
+ .create = mcryptd_create,
+ .free = mcryptd_free,
+ .module = THIS_MODULE,
+};
+
+struct mcryptd_ahash *mcryptd_alloc_ahash(const char *alg_name,
+ u32 type, u32 mask)
+{
+ char mcryptd_alg_name[CRYPTO_MAX_ALG_NAME];
+ struct crypto_ahash *tfm;
+
+ if (snprintf(mcryptd_alg_name, CRYPTO_MAX_ALG_NAME,
+ "mcryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
+ return ERR_PTR(-EINVAL);
+ tfm = crypto_alloc_ahash(mcryptd_alg_name, type, mask);
+ if (IS_ERR(tfm))
+ return ERR_CAST(tfm);
+ if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
+ crypto_free_ahash(tfm);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return __mcryptd_ahash_cast(tfm);
+}
+EXPORT_SYMBOL_GPL(mcryptd_alloc_ahash);
+
+int shash_ahash_mcryptd_digest(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ int err;
+
+ err = crypto_shash_init(desc) ?:
+ shash_ahash_mcryptd_finup(req, desc);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_digest);
+
+int shash_ahash_mcryptd_update(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->update(desc, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_update);
+
+int shash_ahash_mcryptd_finup(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->finup(desc, NULL, 0, req->result);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_finup);
+
+int shash_ahash_mcryptd_final(struct ahash_request *req,
+ struct shash_desc *desc)
+{
+ struct crypto_shash *tfm = desc->tfm;
+ struct shash_alg *shash = crypto_shash_alg(tfm);
+
+ /* alignment is to be done by multi-buffer crypto algorithm if needed */
+
+ return shash->final(desc, req->result);
+}
+EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_final);
+
+struct crypto_shash *mcryptd_ahash_child(struct mcryptd_ahash *tfm)
+{
+ struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
+
+ return ctx->child;
+}
+EXPORT_SYMBOL_GPL(mcryptd_ahash_child);
+
+struct shash_desc *mcryptd_shash_desc(struct ahash_request *req)
+{
+ struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+ return &rctx->desc;
+}
+EXPORT_SYMBOL_GPL(mcryptd_shash_desc);
+
+void mcryptd_free_ahash(struct mcryptd_ahash *tfm)
+{
+ crypto_free_ahash(&tfm->base);
+}
+EXPORT_SYMBOL_GPL(mcryptd_free_ahash);
+
+
+static int __init mcryptd_init(void)
+{
+ int err, cpu;
+ struct mcryptd_flush_list *flist;
+
+ mcryptd_flist = alloc_percpu(struct mcryptd_flush_list);
+ for_each_possible_cpu(cpu) {
+ flist = per_cpu_ptr(mcryptd_flist, cpu);
+ INIT_LIST_HEAD(&flist->list);
+ mutex_init(&flist->lock);
+ }
+
+ err = mcryptd_init_queue(&mqueue, MCRYPTD_MAX_CPU_QLEN);
+ if (err) {
+ free_percpu(mcryptd_flist);
+ return err;
+ }
+
+ err = crypto_register_template(&mcryptd_tmpl);
+ if (err) {
+ mcryptd_fini_queue(&mqueue);
+ free_percpu(mcryptd_flist);
+ }
+
+ return err;
+}
+
+static void __exit mcryptd_exit(void)
+{
+ mcryptd_fini_queue(&mqueue);
+ crypto_unregister_template(&mcryptd_tmpl);
+ free_percpu(mcryptd_flist);
+}
+
+subsys_initcall(mcryptd_init);
+module_exit(mcryptd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Software async multibuffer crypto daemon");
+MODULE_ALIAS_CRYPTO("mcryptd");
diff --git a/crypto/md4.c b/crypto/md4.c
index 0477a6a01d58..3515af425cc9 100644
--- a/crypto/md4.c
+++ b/crypto/md4.c
@@ -255,4 +255,4 @@ module_exit(md4_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MD4 Message Digest Algorithm");
-
+MODULE_ALIAS_CRYPTO("md4");
diff --git a/crypto/md5.c b/crypto/md5.c
index 7febeaab923b..36f5e5b103f3 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -168,3 +168,4 @@ module_exit(md5_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MD5 Message Digest Algorithm");
+MODULE_ALIAS_CRYPTO("md5");
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 079b761bc70d..46195e0d0f4d 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -184,3 +184,4 @@ module_exit(michael_mic_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Michael MIC");
MODULE_AUTHOR("Jouni Malinen <j@w1.fi>");
+MODULE_ALIAS_CRYPTO("michael_mic");
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
index d1b8bdfb5855..f654965f0933 100644
--- a/crypto/pcbc.c
+++ b/crypto/pcbc.c
@@ -295,3 +295,4 @@ module_exit(crypto_pcbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCBC block cipher algorithm");
+MODULE_ALIAS_CRYPTO("pcbc");
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
index 309d345ead95..c305d4112735 100644
--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -565,3 +565,4 @@ module_exit(pcrypt_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
MODULE_DESCRIPTION("Parallel crypto wrapper");
+MODULE_ALIAS_CRYPTO("pcrypt");
diff --git a/crypto/rmd128.c b/crypto/rmd128.c
index 8a0f68b7f257..049486ede938 100644
--- a/crypto/rmd128.c
+++ b/crypto/rmd128.c
@@ -327,3 +327,4 @@ module_exit(rmd128_mod_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
MODULE_DESCRIPTION("RIPEMD-128 Message Digest");
+MODULE_ALIAS_CRYPTO("rmd128");
diff --git a/crypto/rmd160.c b/crypto/rmd160.c
index 525d7bb752cf..de585e51d455 100644
--- a/crypto/rmd160.c
+++ b/crypto/rmd160.c
@@ -371,3 +371,4 @@ module_exit(rmd160_mod_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
MODULE_DESCRIPTION("RIPEMD-160 Message Digest");
+MODULE_ALIAS_CRYPTO("rmd160");
diff --git a/crypto/rmd256.c b/crypto/rmd256.c
index 69293d9b56e0..4ec02a754e09 100644
--- a/crypto/rmd256.c
+++ b/crypto/rmd256.c
@@ -346,3 +346,4 @@ module_exit(rmd256_mod_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
MODULE_DESCRIPTION("RIPEMD-256 Message Digest");
+MODULE_ALIAS_CRYPTO("rmd256");
diff --git a/crypto/rmd320.c b/crypto/rmd320.c
index 09f97dfdfbba..770f2cb369f8 100644
--- a/crypto/rmd320.c
+++ b/crypto/rmd320.c
@@ -395,3 +395,4 @@ module_exit(rmd320_mod_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Adrian-Ken Rueegsegger <ken@codelabs.ch>");
MODULE_DESCRIPTION("RIPEMD-320 Message Digest");
+MODULE_ALIAS_CRYPTO("rmd320");
diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
index 9a4770c02284..3d0f9df30ac9 100644
--- a/crypto/salsa20_generic.c
+++ b/crypto/salsa20_generic.c
@@ -248,4 +248,4 @@ module_exit(salsa20_generic_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
-MODULE_ALIAS("salsa20");
+MODULE_ALIAS_CRYPTO("salsa20");
diff --git a/crypto/seed.c b/crypto/seed.c
index 9c904d6d2151..c6ba8438be43 100644
--- a/crypto/seed.c
+++ b/crypto/seed.c
@@ -476,3 +476,4 @@ module_exit(seed_fini);
MODULE_DESCRIPTION("SEED Cipher Algorithm");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Hye-Shik Chang <perky@FreeBSD.org>, Kim Hyun <hkim@kisa.or.kr>");
+MODULE_ALIAS_CRYPTO("seed");
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index ee190fcedcd2..9daa854cc485 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -362,3 +362,4 @@ module_exit(seqiv_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Sequence Number IV Generator");
+MODULE_ALIAS_CRYPTO("seqiv");
diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c
index 7ddbd7e88859..a53b5e2af335 100644
--- a/crypto/serpent_generic.c
+++ b/crypto/serpent_generic.c
@@ -665,5 +665,5 @@ module_exit(serpent_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm");
MODULE_AUTHOR("Dag Arne Osvik <osvik@ii.uib.no>");
-MODULE_ALIAS("tnepres");
-MODULE_ALIAS("serpent");
+MODULE_ALIAS_CRYPTO("tnepres");
+MODULE_ALIAS_CRYPTO("serpent");
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 42794803c480..039e58cfa155 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -64,7 +64,7 @@ int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
src = data + done;
} while (done + SHA1_BLOCK_SIZE <= len);
- memset(temp, 0, sizeof(temp));
+ memzero_explicit(temp, sizeof(temp));
partial = 0;
}
memcpy(sctx->buffer + partial, src, len - done);
@@ -153,4 +153,4 @@ module_exit(sha1_generic_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
-MODULE_ALIAS("sha1");
+MODULE_ALIAS_CRYPTO("sha1");
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index 543366779524..5eb21b120033 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -24,6 +24,7 @@
#include <linux/types.h>
#include <crypto/sha.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
static inline u32 Ch(u32 x, u32 y, u32 z)
{
@@ -42,7 +43,7 @@ static inline u32 Maj(u32 x, u32 y, u32 z)
static inline void LOAD_OP(int I, u32 *W, const u8 *input)
{
- W[I] = __be32_to_cpu( ((__be32*)(input))[I] );
+ W[I] = get_unaligned_be32((__u32 *)input + I);
}
static inline void BLEND_OP(int I, u32 *W)
@@ -210,10 +211,9 @@ static void sha256_transform(u32 *state, const u8 *input)
/* clear any sensitive info... */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
- memset(W, 0, 64 * sizeof(u32));
+ memzero_explicit(W, 64 * sizeof(u32));
}
-
static int sha224_init(struct shash_desc *desc)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
@@ -316,7 +316,7 @@ static int sha224_final(struct shash_desc *desc, u8 *hash)
sha256_final(desc, D);
memcpy(hash, D, SHA224_DIGEST_SIZE);
- memset(D, 0, SHA256_DIGEST_SIZE);
+ memzero_explicit(D, SHA256_DIGEST_SIZE);
return 0;
}
@@ -384,5 +384,5 @@ module_exit(sha256_generic_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
-MODULE_ALIAS("sha224");
-MODULE_ALIAS("sha256");
+MODULE_ALIAS_CRYPTO("sha224");
+MODULE_ALIAS_CRYPTO("sha256");
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 6ed124f3ea0f..8d0b19ed4f4b 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -20,6 +20,7 @@
#include <crypto/sha.h>
#include <linux/percpu.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
static inline u64 Ch(u64 x, u64 y, u64 z)
{
@@ -68,7 +69,7 @@ static const u64 sha512_K[80] = {
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
- W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
+ W[I] = get_unaligned_be64((__u64 *)input + I);
}
static inline void BLEND_OP(int I, u64 *W)
@@ -238,7 +239,7 @@ static int sha384_final(struct shash_desc *desc, u8 *hash)
sha512_final(desc, D);
memcpy(hash, D, 48);
- memset(D, 0, 64);
+ memzero_explicit(D, 64);
return 0;
}
@@ -287,5 +288,5 @@ module_exit(sha512_generic_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms");
-MODULE_ALIAS("sha384");
-MODULE_ALIAS("sha512");
+MODULE_ALIAS_CRYPTO("sha384");
+MODULE_ALIAS_CRYPTO("sha512");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 890449e6e7ef..1d864e988ea9 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1225,15 +1225,22 @@ static inline int tcrypt_test(const char *alg)
return ret;
}
-static int do_test(int m)
+static int do_test(const char *alg, u32 type, u32 mask, int m)
{
int i;
int ret = 0;
switch (m) {
case 0:
+ if (alg) {
+ if (!crypto_has_alg(alg, type,
+ mask ?: CRYPTO_ALG_TYPE_MASK))
+ ret = -ENOENT;
+ break;
+ }
+
for (i = 1; i < 200; i++)
- ret += do_test(i);
+ ret += do_test(NULL, 0, 0, i);
break;
case 1:
@@ -1752,6 +1759,11 @@ static int do_test(int m)
break;
case 300:
+ if (alg) {
+ test_hash_speed(alg, sec, generic_hash_speed_template);
+ break;
+ }
+
/* fall through */
case 301:
@@ -1838,6 +1850,11 @@ static int do_test(int m)
break;
case 400:
+ if (alg) {
+ test_ahash_speed(alg, sec, generic_hash_speed_template);
+ break;
+ }
+
/* fall through */
case 401:
@@ -2127,12 +2144,6 @@ static int do_test(int m)
return ret;
}
-static int do_alg_test(const char *alg, u32 type, u32 mask)
-{
- return crypto_has_alg(alg, type, mask ?: CRYPTO_ALG_TYPE_MASK) ?
- 0 : -ENOENT;
-}
-
static int __init tcrypt_mod_init(void)
{
int err = -ENOMEM;
@@ -2144,10 +2155,7 @@ static int __init tcrypt_mod_init(void)
goto err_free_tv;
}
- if (alg)
- err = do_alg_test(alg, type, mask);
- else
- err = do_test(mode);
+ err = do_test(alg, type, mask, mode);
if (err) {
printk(KERN_ERR "tcrypt: one or more tests failed!\n");
diff --git a/crypto/tea.c b/crypto/tea.c
index 0a572323ee4a..495be2d0077d 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -270,8 +270,8 @@ static void __exit tea_mod_fini(void)
crypto_unregister_algs(tea_algs, ARRAY_SIZE(tea_algs));
}
-MODULE_ALIAS("xtea");
-MODULE_ALIAS("xeta");
+MODULE_ALIAS_CRYPTO("xtea");
+MODULE_ALIAS_CRYPTO("xeta");
module_init(tea_mod_init);
module_exit(tea_mod_fini);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ac2b63105afc..037368d34586 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -178,9 +178,7 @@ static void testmgr_free_buf(char *buf[XBUFSIZE])
free_page((unsigned long)buf[i]);
}
-static int do_one_async_hash_op(struct ahash_request *req,
- struct tcrypt_result *tr,
- int ret)
+static int wait_async_op(struct tcrypt_result *tr, int ret)
{
if (ret == -EINPROGRESS || ret == -EBUSY) {
ret = wait_for_completion_interruptible(&tr->completion);
@@ -264,30 +262,26 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
ahash_request_set_crypt(req, sg, result, template[i].psize);
if (use_digest) {
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_digest(req));
+ ret = wait_async_op(&tresult, crypto_ahash_digest(req));
if (ret) {
pr_err("alg: hash: digest failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
} else {
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_init(req));
+ ret = wait_async_op(&tresult, crypto_ahash_init(req));
if (ret) {
pr_err("alt: hash: init failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_update(req));
+ ret = wait_async_op(&tresult, crypto_ahash_update(req));
if (ret) {
pr_err("alt: hash: update failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
goto out;
}
- ret = do_one_async_hash_op(req, &tresult,
- crypto_ahash_final(req));
+ ret = wait_async_op(&tresult, crypto_ahash_final(req));
if (ret) {
pr_err("alt: hash: final failed on test %d "
"for %s: ret=%d\n", j, algo, -ret);
@@ -311,78 +305,75 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template,
if (align_offset != 0)
break;
- if (template[i].np) {
- j++;
- memset(result, 0, MAX_DIGEST_SIZE);
+ if (!template[i].np)
+ continue;
- temp = 0;
- sg_init_table(sg, template[i].np);
- ret = -EINVAL;
- for (k = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
- sg_set_buf(&sg[k],
- memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].plaintext + temp,
- template[i].tap[k]),
- template[i].tap[k]);
- temp += template[i].tap[k];
- }
-
- if (template[i].ksize) {
- if (template[i].ksize > MAX_KEYLEN) {
- pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
- j, algo, template[i].ksize,
- MAX_KEYLEN);
- ret = -EINVAL;
- goto out;
- }
- crypto_ahash_clear_flags(tfm, ~0);
- memcpy(key, template[i].key, template[i].ksize);
- ret = crypto_ahash_setkey(tfm, key,
- template[i].ksize);
-
- if (ret) {
- printk(KERN_ERR "alg: hash: setkey "
- "failed on chunking test %d "
- "for %s: ret=%d\n", j, algo,
- -ret);
- goto out;
- }
- }
-
- ahash_request_set_crypt(req, sg, result,
- template[i].psize);
- ret = crypto_ahash_digest(req);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &tresult.completion);
- if (!ret && !(ret = tresult.err)) {
- reinit_completion(&tresult.completion);
- break;
- }
- /* fall through */
- default:
- printk(KERN_ERR "alg: hash: digest failed "
- "on chunking test %d for %s: "
- "ret=%d\n", j, algo, -ret);
+ j++;
+ memset(result, 0, MAX_DIGEST_SIZE);
+
+ temp = 0;
+ sg_init_table(sg, template[i].np);
+ ret = -EINVAL;
+ for (k = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
goto out;
- }
+ sg_set_buf(&sg[k],
+ memcpy(xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]),
+ template[i].plaintext + temp,
+ template[i].tap[k]),
+ template[i].tap[k]);
+ temp += template[i].tap[k];
+ }
- if (memcmp(result, template[i].digest,
- crypto_ahash_digestsize(tfm))) {
- printk(KERN_ERR "alg: hash: Chunking test %d "
- "failed for %s\n", j, algo);
- hexdump(result, crypto_ahash_digestsize(tfm));
+ if (template[i].ksize) {
+ if (template[i].ksize > MAX_KEYLEN) {
+ pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n",
+ j, algo, template[i].ksize, MAX_KEYLEN);
ret = -EINVAL;
goto out;
}
+ crypto_ahash_clear_flags(tfm, ~0);
+ memcpy(key, template[i].key, template[i].ksize);
+ ret = crypto_ahash_setkey(tfm, key, template[i].ksize);
+
+ if (ret) {
+ printk(KERN_ERR "alg: hash: setkey "
+ "failed on chunking test %d "
+ "for %s: ret=%d\n", j, algo, -ret);
+ goto out;
+ }
+ }
+
+ ahash_request_set_crypt(req, sg, result, template[i].psize);
+ ret = crypto_ahash_digest(req);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &tresult.completion);
+ if (!ret && !(ret = tresult.err)) {
+ reinit_completion(&tresult.completion);
+ break;
+ }
+ /* fall through */
+ default:
+ printk(KERN_ERR "alg: hash: digest failed "
+ "on chunking test %d for %s: "
+ "ret=%d\n", j, algo, -ret);
+ goto out;
+ }
+
+ if (memcmp(result, template[i].digest,
+ crypto_ahash_digestsize(tfm))) {
+ printk(KERN_ERR "alg: hash: Chunking test %d "
+ "failed for %s\n", j, algo);
+ hexdump(result, crypto_ahash_digestsize(tfm));
+ ret = -EINVAL;
+ goto out;
}
}
@@ -492,121 +483,116 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
tcrypt_complete, &result);
for (i = 0, j = 0; i < tcount; i++) {
- if (!template[i].np) {
- j++;
+ if (template[i].np)
+ continue;
- /* some templates have no input data but they will
- * touch input
- */
- input = xbuf[0];
- input += align_offset;
- assoc = axbuf[0];
+ j++;
- ret = -EINVAL;
- if (WARN_ON(align_offset + template[i].ilen >
- PAGE_SIZE || template[i].alen > PAGE_SIZE))
- goto out;
+ /* some templates have no input data but they will
+ * touch input
+ */
+ input = xbuf[0];
+ input += align_offset;
+ assoc = axbuf[0];
- memcpy(input, template[i].input, template[i].ilen);
- memcpy(assoc, template[i].assoc, template[i].alen);
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
+ ret = -EINVAL;
+ if (WARN_ON(align_offset + template[i].ilen >
+ PAGE_SIZE || template[i].alen > PAGE_SIZE))
+ goto out;
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ memcpy(input, template[i].input, template[i].ilen);
+ memcpy(assoc, template[i].assoc, template[i].alen);
+ if (template[i].iv)
+ memcpy(iv, template[i].iv, MAX_IVLEN);
+ else
+ memset(iv, 0, MAX_IVLEN);
- if (template[i].klen > MAX_KEYLEN) {
- pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
- d, j, algo, template[i].klen,
- MAX_KEYLEN);
- ret = -EINVAL;
- goto out;
- }
- memcpy(key, template[i].key, template[i].klen);
+ crypto_aead_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- ret = crypto_aead_setkey(tfm, key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
- d, j, algo, crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen,
+ MAX_KEYLEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
- authsize = abs(template[i].rlen - template[i].ilen);
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
- d, authsize, j, algo);
- goto out;
- }
+ ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: flags=%x\n",
+ d, j, algo, crypto_aead_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- if (diff_dst) {
- output = xoutbuf[0];
- output += align_offset;
- sg_init_one(&sg[0], input, template[i].ilen);
- sg_init_one(&sgout[0], output,
- template[i].rlen);
- } else {
- sg_init_one(&sg[0], input,
- template[i].ilen +
- (enc ? authsize : 0));
- output = input;
- }
+ authsize = abs(template[i].rlen - template[i].ilen);
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n",
+ d, authsize, j, algo);
+ goto out;
+ }
- sg_init_one(&asg[0], assoc, template[i].alen);
+ if (diff_dst) {
+ output = xoutbuf[0];
+ output += align_offset;
+ sg_init_one(&sg[0], input, template[i].ilen);
+ sg_init_one(&sgout[0], output, template[i].rlen);
+ } else {
+ sg_init_one(&sg[0], input,
+ template[i].ilen + (enc ? authsize : 0));
+ output = input;
+ }
- aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
+ sg_init_one(&asg[0], assoc, template[i].alen);
- aead_request_set_assoc(req, asg, template[i].alen);
+ aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
+ aead_request_set_assoc(req, asg, template[i].alen);
- switch (ret) {
- case 0:
- if (template[i].novrfy) {
- /* verification was supposed to fail */
- pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
- d, e, j, algo);
- /* so really, we got a bad message */
- ret = -EBADMSG;
- goto out;
- }
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- reinit_completion(&result.completion);
- break;
- }
- case -EBADMSG:
- if (template[i].novrfy)
- /* verification failure was expected */
- continue;
- /* fall through */
- default:
- pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
- }
+ ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
- q = output;
- if (memcmp(q, template[i].result, template[i].rlen)) {
- pr_err("alg: aead%s: Test %d failed on %s for %s\n",
- d, j, e, algo);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
+ switch (ret) {
+ case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ pr_err("alg: aead%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n",
+ d, e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
goto out;
}
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ reinit_completion(&result.completion);
+ break;
+ }
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
+ /* fall through */
+ default:
+ pr_err("alg: aead%s: %s failed on test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
+
+ q = output;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ pr_err("alg: aead%s: Test %d failed on %s for %s\n",
+ d, j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
}
}
@@ -615,191 +601,182 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
if (align_offset != 0)
break;
- if (template[i].np) {
- j++;
-
- if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
- else
- memset(iv, 0, MAX_IVLEN);
-
- crypto_aead_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_aead_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- if (template[i].klen > MAX_KEYLEN) {
- pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
- d, j, algo, template[i].klen,
- MAX_KEYLEN);
- ret = -EINVAL;
- goto out;
- }
- memcpy(key, template[i].key, template[i].klen);
+ if (!template[i].np)
+ continue;
- ret = crypto_aead_setkey(tfm, key, template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
- d, j, algo, crypto_aead_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ j++;
- authsize = abs(template[i].rlen - template[i].ilen);
+ if (template[i].iv)
+ memcpy(iv, template[i].iv, MAX_IVLEN);
+ else
+ memset(iv, 0, MAX_IVLEN);
+ crypto_aead_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ if (template[i].klen > MAX_KEYLEN) {
+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n",
+ d, j, algo, template[i].klen, MAX_KEYLEN);
ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- if (diff_dst)
- sg_init_table(sgout, template[i].np);
- for (k = 0, temp = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
-
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ goto out;
+ }
+ memcpy(key, template[i].key, template[i].klen);
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
+ ret = crypto_aead_setkey(tfm, key, template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: aead%s: setkey failed on chunk test %d for %s: flags=%x\n",
+ d, j, algo, crypto_aead_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- sg_set_buf(&sg[k], q, template[i].tap[k]);
+ authsize = abs(template[i].rlen - template[i].ilen);
- if (diff_dst) {
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ ret = -EINVAL;
+ sg_init_table(sg, template[i].np);
+ if (diff_dst)
+ sg_init_table(sgout, template[i].np);
+ for (k = 0, temp = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
+ goto out;
- memset(q, 0, template[i].tap[k]);
+ q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
+ memcpy(q, template[i].input + temp, template[i].tap[k]);
+ sg_set_buf(&sg[k], q, template[i].tap[k]);
- sg_set_buf(&sgout[k], q,
- template[i].tap[k]);
- }
+ if (diff_dst) {
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- n = template[i].tap[k];
- if (k == template[i].np - 1 && enc)
- n += authsize;
- if (offset_in_page(q) + n < PAGE_SIZE)
- q[n] = 0;
+ memset(q, 0, template[i].tap[k]);
- temp += template[i].tap[k];
+ sg_set_buf(&sgout[k], q, template[i].tap[k]);
}
- ret = crypto_aead_setauthsize(tfm, authsize);
- if (ret) {
- pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
- d, authsize, j, algo);
+ n = template[i].tap[k];
+ if (k == template[i].np - 1 && enc)
+ n += authsize;
+ if (offset_in_page(q) + n < PAGE_SIZE)
+ q[n] = 0;
+
+ temp += template[i].tap[k];
+ }
+
+ ret = crypto_aead_setauthsize(tfm, authsize);
+ if (ret) {
+ pr_err("alg: aead%s: Failed to set authsize to %u on chunk test %d for %s\n",
+ d, authsize, j, algo);
+ goto out;
+ }
+
+ if (enc) {
+ if (WARN_ON(sg[k - 1].offset +
+ sg[k - 1].length + authsize >
+ PAGE_SIZE)) {
+ ret = -EINVAL;
goto out;
}
- if (enc) {
- if (WARN_ON(sg[k - 1].offset +
- sg[k - 1].length + authsize >
- PAGE_SIZE)) {
- ret = -EINVAL;
- goto out;
- }
+ if (diff_dst)
+ sgout[k - 1].length += authsize;
+ else
+ sg[k - 1].length += authsize;
+ }
- if (diff_dst)
- sgout[k - 1].length += authsize;
- else
- sg[k - 1].length += authsize;
+ sg_init_table(asg, template[i].anp);
+ ret = -EINVAL;
+ for (k = 0, temp = 0; k < template[i].anp; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].atap[k] > PAGE_SIZE))
+ goto out;
+ sg_set_buf(&asg[k],
+ memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]),
+ template[i].assoc + temp,
+ template[i].atap[k]),
+ template[i].atap[k]);
+ temp += template[i].atap[k];
+ }
+
+ aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen,
+ iv);
+
+ aead_request_set_assoc(req, asg, template[i].alen);
+
+ ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
+
+ switch (ret) {
+ case 0:
+ if (template[i].novrfy) {
+ /* verification was supposed to fail */
+ pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
+ d, e, j, algo);
+ /* so really, we got a bad message */
+ ret = -EBADMSG;
+ goto out;
}
-
- sg_init_table(asg, template[i].anp);
- ret = -EINVAL;
- for (k = 0, temp = 0; k < template[i].anp; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].atap[k] > PAGE_SIZE))
- goto out;
- sg_set_buf(&asg[k],
- memcpy(axbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]),
- template[i].assoc + temp,
- template[i].atap[k]),
- template[i].atap[k]);
- temp += template[i].atap[k];
- }
-
- aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
- template[i].ilen,
- iv);
-
- aead_request_set_assoc(req, asg, template[i].alen);
-
- ret = enc ?
- crypto_aead_encrypt(req) :
- crypto_aead_decrypt(req);
-
- switch (ret) {
- case 0:
- if (template[i].novrfy) {
- /* verification was supposed to fail */
- pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret was 0, expected -EBADMSG\n",
- d, e, j, algo);
- /* so really, we got a bad message */
- ret = -EBADMSG;
- goto out;
- }
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !(ret = result.err)) {
+ reinit_completion(&result.completion);
break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !(ret = result.err)) {
- reinit_completion(&result.completion);
- break;
- }
- case -EBADMSG:
- if (template[i].novrfy)
- /* verification failure was expected */
- continue;
- /* fall through */
- default:
- pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
}
+ case -EBADMSG:
+ if (template[i].novrfy)
+ /* verification failure was expected */
+ continue;
+ /* fall through */
+ default:
+ pr_err("alg: aead%s: %s failed on chunk test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- ret = -EINVAL;
- for (k = 0, temp = 0; k < template[i].np; k++) {
- if (diff_dst)
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
- else
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- n = template[i].tap[k];
- if (k == template[i].np - 1)
- n += enc ? authsize : -authsize;
+ ret = -EINVAL;
+ for (k = 0, temp = 0; k < template[i].np; k++) {
+ if (diff_dst)
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
+ else
+ q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- if (memcmp(q, template[i].result + temp, n)) {
- pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
- d, j, e, k, algo);
- hexdump(q, n);
- goto out;
- }
+ n = template[i].tap[k];
+ if (k == template[i].np - 1)
+ n += enc ? authsize : -authsize;
- q += n;
- if (k == template[i].np - 1 && !enc) {
- if (!diff_dst &&
- memcmp(q, template[i].input +
- temp + n, authsize))
- n = authsize;
- else
- n = 0;
- } else {
- for (n = 0; offset_in_page(q + n) &&
- q[n]; n++)
- ;
- }
- if (n) {
- pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
- d, j, e, k, algo, n);
- hexdump(q, n);
- goto out;
- }
+ if (memcmp(q, template[i].result + temp, n)) {
+ pr_err("alg: aead%s: Chunk test %d failed on %s at page %u for %s\n",
+ d, j, e, k, algo);
+ hexdump(q, n);
+ goto out;
+ }
- temp += template[i].tap[k];
+ q += n;
+ if (k == template[i].np - 1 && !enc) {
+ if (!diff_dst &&
+ memcmp(q, template[i].input +
+ temp + n, authsize))
+ n = authsize;
+ else
+ n = 0;
+ } else {
+ for (n = 0; offset_in_page(q + n) && q[n]; n++)
+ ;
+ }
+ if (n) {
+ pr_err("alg: aead%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
+ d, j, e, k, algo, n);
+ hexdump(q, n);
+ goto out;
}
+
+ temp += template[i].tap[k];
}
}
@@ -978,78 +955,73 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
j = 0;
for (i = 0; i < tcount; i++) {
+ if (template[i].np && !template[i].also_non_np)
+ continue;
+
if (template[i].iv)
memcpy(iv, template[i].iv, MAX_IVLEN);
else
memset(iv, 0, MAX_IVLEN);
- if (!(template[i].np) || (template[i].also_non_np)) {
- j++;
+ j++;
+ ret = -EINVAL;
+ if (WARN_ON(align_offset + template[i].ilen > PAGE_SIZE))
+ goto out;
- ret = -EINVAL;
- if (WARN_ON(align_offset + template[i].ilen >
- PAGE_SIZE))
- goto out;
+ data = xbuf[0];
+ data += align_offset;
+ memcpy(data, template[i].input, template[i].ilen);
- data = xbuf[0];
- data += align_offset;
- memcpy(data, template[i].input, template[i].ilen);
-
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-
- ret = crypto_ablkcipher_setkey(tfm, template[i].key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
- d, j, algo,
- crypto_ablkcipher_get_flags(tfm));
- goto out;
- } else if (ret)
- continue;
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- sg_init_one(&sg[0], data, template[i].ilen);
- if (diff_dst) {
- data = xoutbuf[0];
- data += align_offset;
- sg_init_one(&sgout[0], data, template[i].ilen);
- }
+ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+ template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: skcipher%s: setkey failed on test %d for %s: flags=%x\n",
+ d, j, algo, crypto_ablkcipher_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
+
+ sg_init_one(&sg[0], data, template[i].ilen);
+ if (diff_dst) {
+ data = xoutbuf[0];
+ data += align_offset;
+ sg_init_one(&sgout[0], data, template[i].ilen);
+ }
- ablkcipher_request_set_crypt(req, sg,
- (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
+ ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
+ ret = enc ? crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
- switch (ret) {
- case 0:
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !((ret = result.err))) {
+ reinit_completion(&result.completion);
break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- reinit_completion(&result.completion);
- break;
- }
- /* fall through */
- default:
- pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
- goto out;
}
+ /* fall through */
+ default:
+ pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- q = data;
- if (memcmp(q, template[i].result, template[i].rlen)) {
- pr_err("alg: skcipher%s: Test %d failed on %s for %s\n",
- d, j, e, algo);
- hexdump(q, template[i].rlen);
- ret = -EINVAL;
- goto out;
- }
+ q = data;
+ if (memcmp(q, template[i].result, template[i].rlen)) {
+ pr_err("alg: skcipher%s: Test %d failed on %s for %s\n",
+ d, j, e, algo);
+ hexdump(q, template[i].rlen);
+ ret = -EINVAL;
+ goto out;
}
}
@@ -1059,121 +1031,113 @@ static int __test_skcipher(struct crypto_ablkcipher *tfm, int enc,
if (align_offset != 0)
break;
+ if (!template[i].np)
+ continue;
+
if (template[i].iv)
memcpy(iv, template[i].iv, MAX_IVLEN);
else
memset(iv, 0, MAX_IVLEN);
- if (template[i].np) {
- j++;
+ j++;
+ crypto_ablkcipher_clear_flags(tfm, ~0);
+ if (template[i].wk)
+ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
- crypto_ablkcipher_clear_flags(tfm, ~0);
- if (template[i].wk)
- crypto_ablkcipher_set_flags(
- tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+ ret = crypto_ablkcipher_setkey(tfm, template[i].key,
+ template[i].klen);
+ if (!ret == template[i].fail) {
+ pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
+ d, j, algo, crypto_ablkcipher_get_flags(tfm));
+ goto out;
+ } else if (ret)
+ continue;
- ret = crypto_ablkcipher_setkey(tfm, template[i].key,
- template[i].klen);
- if (!ret == template[i].fail) {
- pr_err("alg: skcipher%s: setkey failed on chunk test %d for %s: flags=%x\n",
- d, j, algo,
- crypto_ablkcipher_get_flags(tfm));
+ temp = 0;
+ ret = -EINVAL;
+ sg_init_table(sg, template[i].np);
+ if (diff_dst)
+ sg_init_table(sgout, template[i].np);
+ for (k = 0; k < template[i].np; k++) {
+ if (WARN_ON(offset_in_page(IDX[k]) +
+ template[i].tap[k] > PAGE_SIZE))
goto out;
- } else if (ret)
- continue;
- temp = 0;
- ret = -EINVAL;
- sg_init_table(sg, template[i].np);
- if (diff_dst)
- sg_init_table(sgout, template[i].np);
- for (k = 0; k < template[i].np; k++) {
- if (WARN_ON(offset_in_page(IDX[k]) +
- template[i].tap[k] > PAGE_SIZE))
- goto out;
+ q = xbuf[IDX[k] >> PAGE_SHIFT] + offset_in_page(IDX[k]);
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ memcpy(q, template[i].input + temp, template[i].tap[k]);
+
+ if (offset_in_page(q) + template[i].tap[k] < PAGE_SIZE)
+ q[template[i].tap[k]] = 0;
+
+ sg_set_buf(&sg[k], q, template[i].tap[k]);
+ if (diff_dst) {
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
offset_in_page(IDX[k]);
- memcpy(q, template[i].input + temp,
- template[i].tap[k]);
+ sg_set_buf(&sgout[k], q, template[i].tap[k]);
- if (offset_in_page(q) + template[i].tap[k] <
- PAGE_SIZE)
+ memset(q, 0, template[i].tap[k]);
+ if (offset_in_page(q) +
+ template[i].tap[k] < PAGE_SIZE)
q[template[i].tap[k]] = 0;
+ }
- sg_set_buf(&sg[k], q, template[i].tap[k]);
- if (diff_dst) {
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
+ temp += template[i].tap[k];
+ }
- sg_set_buf(&sgout[k], q,
- template[i].tap[k]);
+ ablkcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg,
+ template[i].ilen, iv);
- memset(q, 0, template[i].tap[k]);
- if (offset_in_page(q) +
- template[i].tap[k] < PAGE_SIZE)
- q[template[i].tap[k]] = 0;
- }
+ ret = enc ? crypto_ablkcipher_encrypt(req) :
+ crypto_ablkcipher_decrypt(req);
- temp += template[i].tap[k];
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &result.completion);
+ if (!ret && !((ret = result.err))) {
+ reinit_completion(&result.completion);
+ break;
}
+ /* fall through */
+ default:
+ pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
+ d, e, j, algo, -ret);
+ goto out;
+ }
- ablkcipher_request_set_crypt(req, sg,
- (diff_dst) ? sgout : sg,
- template[i].ilen, iv);
-
- ret = enc ?
- crypto_ablkcipher_encrypt(req) :
- crypto_ablkcipher_decrypt(req);
+ temp = 0;
+ ret = -EINVAL;
+ for (k = 0; k < template[i].np; k++) {
+ if (diff_dst)
+ q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
+ else
+ q = xbuf[IDX[k] >> PAGE_SHIFT] +
+ offset_in_page(IDX[k]);
- switch (ret) {
- case 0:
- break;
- case -EINPROGRESS:
- case -EBUSY:
- ret = wait_for_completion_interruptible(
- &result.completion);
- if (!ret && !((ret = result.err))) {
- reinit_completion(&result.completion);
- break;
- }
- /* fall through */
- default:
- pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n",
- d, e, j, algo, -ret);
+ if (memcmp(q, template[i].result + temp,
+ template[i].tap[k])) {
+ pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
+ d, j, e, k, algo);
+ hexdump(q, template[i].tap[k]);
goto out;
}
- temp = 0;
- ret = -EINVAL;
- for (k = 0; k < template[i].np; k++) {
- if (diff_dst)
- q = xoutbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
- else
- q = xbuf[IDX[k] >> PAGE_SHIFT] +
- offset_in_page(IDX[k]);
-
- if (memcmp(q, template[i].result + temp,
- template[i].tap[k])) {
- pr_err("alg: skcipher%s: Chunk test %d failed on %s at page %u for %s\n",
- d, j, e, k, algo);
- hexdump(q, template[i].tap[k]);
- goto out;
- }
-
- q += template[i].tap[k];
- for (n = 0; offset_in_page(q + n) && q[n]; n++)
- ;
- if (n) {
- pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
- d, j, e, k, algo, n);
- hexdump(q, n);
- goto out;
- }
- temp += template[i].tap[k];
+ q += template[i].tap[k];
+ for (n = 0; offset_in_page(q + n) && q[n]; n++)
+ ;
+ if (n) {
+ pr_err("alg: skcipher%s: Result buffer corruption in chunk test %d on %s at page %u for %s: %u bytes:\n",
+ d, j, e, k, algo, n);
+ hexdump(q, n);
+ goto out;
}
+ temp += template[i].tap[k];
}
}
@@ -1714,16 +1678,14 @@ static int alg_test_crc32c(const struct alg_test_desc *desc,
}
do {
- struct {
- struct shash_desc shash;
- char ctx[crypto_shash_descsize(tfm)];
- } sdesc;
+ SHASH_DESC_ON_STACK(shash, tfm);
+ u32 *ctx = (u32 *)shash_desc_ctx(shash);
- sdesc.shash.tfm = tfm;
- sdesc.shash.flags = 0;
+ shash->tfm = tfm;
+ shash->flags = 0;
- *(u32 *)sdesc.ctx = le32_to_cpu(420553207);
- err = crypto_shash_final(&sdesc.shash, (u8 *)&val);
+ *ctx = le32_to_cpu(420553207);
+ err = crypto_shash_final(shash, (u8 *)&val);
if (err) {
printk(KERN_ERR "alg: crc32c: Operation failed for "
"%s: %d\n", driver, err);
@@ -3213,6 +3175,38 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}, {
+ .alg = "lz4",
+ .test = alg_test_comp,
+ .fips_allowed = 1,
+ .suite = {
+ .comp = {
+ .comp = {
+ .vecs = lz4_comp_tv_template,
+ .count = LZ4_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = lz4_decomp_tv_template,
+ .count = LZ4_DECOMP_TEST_VECTORS
+ }
+ }
+ }
+ }, {
+ .alg = "lz4hc",
+ .test = alg_test_comp,
+ .fips_allowed = 1,
+ .suite = {
+ .comp = {
+ .comp = {
+ .vecs = lz4hc_comp_tv_template,
+ .count = LZ4HC_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = lz4hc_decomp_tv_template,
+ .count = LZ4HC_DECOMP_TEST_VECTORS
+ }
+ }
+ }
+ }, {
.alg = "lzo",
.test = alg_test_comp,
.fips_allowed = 1,
@@ -3714,8 +3708,7 @@ test_done:
panic("%s: %s alg self test failed in fips mode!\n", driver, alg);
if (fips_enabled && !rc)
- pr_info(KERN_INFO "alg: self-tests for %s (%s) passed\n",
- driver, alg);
+ pr_info("alg: self-tests for %s (%s) passed\n", driver, alg);
return rc;
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 6597203eccfa..62e2485bb428 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -29473,4 +29473,70 @@ static struct hash_testvec bfin_crc_tv_template[] = {
};
+#define LZ4_COMP_TEST_VECTORS 1
+#define LZ4_DECOMP_TEST_VECTORS 1
+
+static struct comp_testvec lz4_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 45,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ },
+};
+
+static struct comp_testvec lz4_decomp_tv_template[] = {
+ {
+ .inlen = 45,
+ .outlen = 70,
+ .input = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
+#define LZ4HC_COMP_TEST_VECTORS 1
+#define LZ4HC_DECOMP_TEST_VECTORS 1
+
+static struct comp_testvec lz4hc_comp_tv_template[] = {
+ {
+ .inlen = 70,
+ .outlen = 45,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ },
+};
+
+static struct comp_testvec lz4hc_decomp_tv_template[] = {
+ {
+ .inlen = 45,
+ .outlen = 70,
+ .input = "\xf0\x10\x4a\x6f\x69\x6e\x20\x75"
+ "\x73\x20\x6e\x6f\x77\x20\x61\x6e"
+ "\x64\x20\x73\x68\x61\x72\x65\x20"
+ "\x74\x68\x65\x20\x73\x6f\x66\x74"
+ "\x77\x0d\x00\x0f\x23\x00\x0b\x50"
+ "\x77\x61\x72\x65\x20",
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
#endif /* _CRYPTO_TESTMGR_H */
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index 87403556fd0b..6e5651c66cf8 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -612,7 +612,7 @@ static int tgr160_final(struct shash_desc *desc, u8 * out)
tgr192_final(desc, D);
memcpy(out, D, TGR160_DIGEST_SIZE);
- memset(D, 0, TGR192_DIGEST_SIZE);
+ memzero_explicit(D, TGR192_DIGEST_SIZE);
return 0;
}
@@ -623,7 +623,7 @@ static int tgr128_final(struct shash_desc *desc, u8 * out)
tgr192_final(desc, D);
memcpy(out, D, TGR128_DIGEST_SIZE);
- memset(D, 0, TGR192_DIGEST_SIZE);
+ memzero_explicit(D, TGR192_DIGEST_SIZE);
return 0;
}
@@ -676,8 +676,8 @@ static void __exit tgr192_mod_fini(void)
crypto_unregister_shashes(tgr_algs, ARRAY_SIZE(tgr_algs));
}
-MODULE_ALIAS("tgr160");
-MODULE_ALIAS("tgr128");
+MODULE_ALIAS_CRYPTO("tgr160");
+MODULE_ALIAS_CRYPTO("tgr128");
module_init(tgr192_mod_init);
module_exit(tgr192_mod_fini);
diff --git a/crypto/twofish_generic.c b/crypto/twofish_generic.c
index 2d5000552d0f..523ad8c4e359 100644
--- a/crypto/twofish_generic.c
+++ b/crypto/twofish_generic.c
@@ -211,4 +211,4 @@ module_exit(twofish_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION ("Twofish Cipher Algorithm");
-MODULE_ALIAS("twofish");
+MODULE_ALIAS_CRYPTO("twofish");
diff --git a/crypto/vmac.c b/crypto/vmac.c
index 2eb11a30c29c..df76a816cfb2 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -613,7 +613,7 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
}
mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
memcpy(out, &mac, sizeof(vmac_t));
- memset(&mac, 0, sizeof(vmac_t));
+ memzero_explicit(&mac, sizeof(vmac_t));
memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
ctx->partial_size = 0;
return 0;
@@ -713,3 +713,4 @@ module_exit(vmac_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VMAC hash algorithm");
+MODULE_ALIAS_CRYPTO("vmac");
diff --git a/crypto/wp512.c b/crypto/wp512.c
index 180f1d6e03f4..0de42eb3d040 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -1102,8 +1102,8 @@ static int wp384_final(struct shash_desc *desc, u8 *out)
u8 D[64];
wp512_final(desc, D);
- memcpy (out, D, WP384_DIGEST_SIZE);
- memset (D, 0, WP512_DIGEST_SIZE);
+ memcpy(out, D, WP384_DIGEST_SIZE);
+ memzero_explicit(D, WP512_DIGEST_SIZE);
return 0;
}
@@ -1113,8 +1113,8 @@ static int wp256_final(struct shash_desc *desc, u8 *out)
u8 D[64];
wp512_final(desc, D);
- memcpy (out, D, WP256_DIGEST_SIZE);
- memset (D, 0, WP512_DIGEST_SIZE);
+ memcpy(out, D, WP256_DIGEST_SIZE);
+ memzero_explicit(D, WP512_DIGEST_SIZE);
return 0;
}
@@ -1167,8 +1167,8 @@ static void __exit wp512_mod_fini(void)
crypto_unregister_shashes(wp_algs, ARRAY_SIZE(wp_algs));
}
-MODULE_ALIAS("wp384");
-MODULE_ALIAS("wp256");
+MODULE_ALIAS_CRYPTO("wp384");
+MODULE_ALIAS_CRYPTO("wp256");
module_init(wp512_mod_init);
module_exit(wp512_mod_fini);
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index a5fbdf3738cf..df90b332554c 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -286,3 +286,4 @@ module_exit(crypto_xcbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("XCBC keyed hash algorithm");
+MODULE_ALIAS_CRYPTO("xcbc");
diff --git a/crypto/xts.c b/crypto/xts.c
index ca1608f44cb5..f6fd43f100c8 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -362,3 +362,4 @@ module_exit(crypto_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("XTS block cipher mode");
+MODULE_ALIAS_CRYPTO("xts");
diff --git a/crypto/zlib.c b/crypto/zlib.c
index c9ee681d57fd..0eefa9d237ac 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -378,3 +378,4 @@ module_exit(zlib_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Zlib Compression Algorithm");
MODULE_AUTHOR("Sony Corporation");
+MODULE_ALIAS_CRYPTO("zlib");