From d3afd1757fa31360a79fb94aa9ce945113345d3e Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 30 Jan 2015 15:39:34 +0100 Subject: crypto: ppc/sha256 - kernel config Integrate the module into the kernel config tree. Signed-off-by: Markus Stockhausen Signed-off-by: Herbert Xu --- crypto/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 50f4da44..2ca8d15e 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -610,6 +610,15 @@ config CRYPTO_SHA256 This code also includes SHA-224, a 224 bit hash with 112 bits of security against collision attacks. +config CRYPTO_SHA256_PPC_SPE + tristate "SHA224 and SHA256 digest algorithm (PPC SPE)" + depends on PPC && SPE + select CRYPTO_SHA256 + select CRYPTO_HASH + help + SHA224 and SHA256 secure hash standard (DFIPS 180-2) + implemented using powerpc SPE SIMD instruction set. + config CRYPTO_SHA256_SPARC64 tristate "SHA224 and SHA256 digest algorithm (SPARC64)" depends on SPARC64 -- cgit v1.2.3 From 999604a9f22b23cfd841090c6624b8a4e831d7e9 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sun, 22 Feb 2015 10:00:10 +0100 Subject: crypto: powerpc/aes - kernel config Integrate the module into the kernel configuration Signed-off-by: Markus Stockhausen Signed-off-by: Herbert Xu --- crypto/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 2ca8d15e..14106b26 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -866,6 +866,19 @@ config CRYPTO_AES_ARM_BS This implementation does not rely on any lookup tables so it is believed to be invulnerable to cache timing attacks. +config CRYPTO_AES_PPC_SPE + tristate "AES cipher algorithms (PPC SPE)" + depends on PPC && SPE + help + AES cipher algorithms (FIPS-197). Additionally the acceleration + for popular block cipher modes ECB, CBC, CTR and XTS is supported. + This module should only be used for low power (router) devices + without hardware AES acceleration (e.g. caam crypto). It reduces the + size of the AES tables from 16KB to 8KB + 256 bytes and mitigates + timining attacks. Nevertheless it might be not as secure as other + architecture specific assembler implementations that work on 1KB + tables or 256 bytes S-boxes. + config CRYPTO_ANUBIS tristate "Anubis cipher algorithm" select CRYPTO_ALGAPI -- cgit v1.2.3 From 67e370c8e3379a30653817718f99cc401aa2fe32 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Tue, 24 Feb 2015 20:36:50 +0100 Subject: crypto: powerpc/sha1 - kernel config Integrate the module into the kernel config tree. Signed-off-by: Markus Stockhausen Signed-off-by: Herbert Xu --- crypto/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 14106b26..67275b7f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -582,6 +582,13 @@ 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_PPC_SPE + tristate "SHA1 digest algorithm (PPC SPE)" + depends on PPC && SPE + help + SHA-1 secure hash standard (DFIPS 180-4) implemented + using powerpc SPE SIMD instruction set. + config CRYPTO_SHA1_MB tristate "SHA1 digest algorithm (x86_64 Multi-Buffer, Experimental)" depends on X86 && 64BIT -- cgit v1.2.3 From 92b2f5482ada0c28b7cfdd11a7ef9d23c059bede Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sat, 28 Feb 2015 20:50:00 +0100 Subject: crypto: algif - add AEAD support This patch adds the AEAD support for AF_ALG. The implementation is based on algif_skcipher, but contains heavy modifications to streamline the interface for AEAD uses. To use AEAD, the user space consumer has to use the salg_type named "aead". The AEAD implementation includes some overhead to calculate the size of the ciphertext, because the AEAD implementation of the kernel crypto API makes implied assumption on the location of the authentication tag. When performing an encryption, the tag will be added to the created ciphertext (note, the tag is placed adjacent to the ciphertext). For decryption, the caller must hand in the ciphertext with the tag appended to the ciphertext. Therefore, the selection of the used memory needs to add/subtract the tag size from the source/destination buffers depending on the encryption type. The code is provided with comments explaining when and how that operation is performed. A fully working example using all aspects of AEAD is provided at http://www.chronox.de/libkcapi.html Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/algif_aead.c | 666 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 666 insertions(+) create mode 100644 crypto/algif_aead.c diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c new file mode 100644 index 00000000..527d27b0 --- /dev/null +++ b/crypto/algif_aead.c @@ -0,0 +1,666 @@ +/* + * algif_aead: User-space interface for AEAD algorithms + * + * Copyright (C) 2014, Stephan Mueller + * + * This file provides the user-space API for AEAD ciphers. + * + * This file is derived from algif_skcipher.c. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +struct aead_sg_list { + unsigned int cur; + struct scatterlist sg[ALG_MAX_PAGES]; +}; + +struct aead_ctx { + struct aead_sg_list tsgl; + /* + * RSGL_MAX_ENTRIES is an artificial limit where user space at maximum + * can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES + * bytes + */ +#define RSGL_MAX_ENTRIES ALG_MAX_PAGES + struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES]; + + void *iv; + + struct af_alg_completion completion; + + unsigned long used; + + unsigned int len; + bool more; + bool merge; + bool enc; + + size_t aead_assoclen; + struct aead_request aead_req; +}; + +static inline int aead_sndbuf(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + + return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) - + ctx->used, 0); +} + +static inline bool aead_writable(struct sock *sk) +{ + return PAGE_SIZE <= aead_sndbuf(sk); +} + +static inline bool aead_sufficient_data(struct aead_ctx *ctx) +{ + unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); + + return (ctx->used >= (ctx->aead_assoclen + (ctx->enc ? 0 : as))); +} + +static void aead_put_sgl(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + struct aead_sg_list *sgl = &ctx->tsgl; + struct scatterlist *sg = sgl->sg; + unsigned int i; + + for (i = 0; i < sgl->cur; i++) { + if (!sg_page(sg + i)) + continue; + + put_page(sg_page(sg + i)); + sg_assign_page(sg + i, NULL); + } + sgl->cur = 0; + ctx->used = 0; + ctx->more = 0; + ctx->merge = 0; +} + +static void aead_wmem_wakeup(struct sock *sk) +{ + struct socket_wq *wq; + + if (!aead_writable(sk)) + return; + + rcu_read_lock(); + wq = rcu_dereference(sk->sk_wq); + if (wq_has_sleeper(wq)) + wake_up_interruptible_sync_poll(&wq->wait, POLLIN | + POLLRDNORM | + POLLRDBAND); + sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); + rcu_read_unlock(); +} + +static int aead_wait_for_data(struct sock *sk, unsigned flags) +{ + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + long timeout; + DEFINE_WAIT(wait); + int err = -ERESTARTSYS; + + if (flags & MSG_DONTWAIT) + return -EAGAIN; + + set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + + for (;;) { + if (signal_pending(current)) + break; + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + timeout = MAX_SCHEDULE_TIMEOUT; + if (sk_wait_event(sk, &timeout, !ctx->more)) { + err = 0; + break; + } + } + finish_wait(sk_sleep(sk), &wait); + + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + + return err; +} + +static void aead_data_wakeup(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + struct socket_wq *wq; + + if (ctx->more) + return; + if (!ctx->used) + return; + + rcu_read_lock(); + wq = rcu_dereference(sk->sk_wq); + if (wq_has_sleeper(wq)) + wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | + POLLRDNORM | + POLLRDBAND); + sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); + rcu_read_unlock(); +} + +static int aead_sendmsg(struct kiocb *unused, struct socket *sock, + struct msghdr *msg, size_t size) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + unsigned ivsize = + crypto_aead_ivsize(crypto_aead_reqtfm(&ctx->aead_req)); + struct aead_sg_list *sgl = &ctx->tsgl; + struct af_alg_control con = {}; + long copied = 0; + bool enc = 0; + bool init = 0; + int err = -EINVAL; + + if (msg->msg_controllen) { + err = af_alg_cmsg_send(msg, &con); + if (err) + return err; + + init = 1; + switch (con.op) { + case ALG_OP_ENCRYPT: + enc = 1; + break; + case ALG_OP_DECRYPT: + enc = 0; + break; + default: + return -EINVAL; + } + + if (con.iv && con.iv->ivlen != ivsize) + return -EINVAL; + } + + lock_sock(sk); + if (!ctx->more && ctx->used) + goto unlock; + + if (init) { + ctx->enc = enc; + if (con.iv) + memcpy(ctx->iv, con.iv->iv, ivsize); + + ctx->aead_assoclen = con.aead_assoclen; + } + + while (size) { + unsigned long len = size; + struct scatterlist *sg = NULL; + + /* use the existing memory in an allocated page */ + if (ctx->merge) { + sg = sgl->sg + sgl->cur - 1; + len = min_t(unsigned long, len, + PAGE_SIZE - sg->offset - sg->length); + err = memcpy_from_msg(page_address(sg_page(sg)) + + sg->offset + sg->length, + msg, len); + if (err) + goto unlock; + + sg->length += len; + ctx->merge = (sg->offset + sg->length) & + (PAGE_SIZE - 1); + + ctx->used += len; + copied += len; + size -= len; + continue; + } + + if (!aead_writable(sk)) { + /* user space sent too much data */ + aead_put_sgl(sk); + err = -EMSGSIZE; + goto unlock; + } + + /* allocate a new page */ + len = min_t(unsigned long, size, aead_sndbuf(sk)); + while (len) { + int plen = 0; + + if (sgl->cur >= ALG_MAX_PAGES) { + aead_put_sgl(sk); + err = -E2BIG; + goto unlock; + } + + sg = sgl->sg + sgl->cur; + plen = min_t(int, len, PAGE_SIZE); + + sg_assign_page(sg, alloc_page(GFP_KERNEL)); + err = -ENOMEM; + if (!sg_page(sg)) + goto unlock; + + err = memcpy_from_msg(page_address(sg_page(sg)), + msg, plen); + if (err) { + __free_page(sg_page(sg)); + sg_assign_page(sg, NULL); + goto unlock; + } + + sg->offset = 0; + sg->length = plen; + len -= plen; + ctx->used += plen; + copied += plen; + sgl->cur++; + size -= plen; + ctx->merge = plen & (PAGE_SIZE - 1); + } + } + + err = 0; + + ctx->more = msg->msg_flags & MSG_MORE; + if (!ctx->more && !aead_sufficient_data(ctx)) { + aead_put_sgl(sk); + err = -EMSGSIZE; + } + +unlock: + aead_data_wakeup(sk); + release_sock(sk); + + return err ?: copied; +} + +static ssize_t aead_sendpage(struct socket *sock, struct page *page, + int offset, size_t size, int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + struct aead_sg_list *sgl = &ctx->tsgl; + int err = -EINVAL; + + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + + if (sgl->cur >= ALG_MAX_PAGES) + return -E2BIG; + + lock_sock(sk); + if (!ctx->more && ctx->used) + goto unlock; + + if (!size) + goto done; + + if (!aead_writable(sk)) { + /* user space sent too much data */ + aead_put_sgl(sk); + err = -EMSGSIZE; + goto unlock; + } + + ctx->merge = 0; + + get_page(page); + sg_set_page(sgl->sg + sgl->cur, page, size, offset); + sgl->cur++; + ctx->used += size; + + err = 0; + +done: + ctx->more = flags & MSG_MORE; + if (!ctx->more && !aead_sufficient_data(ctx)) { + aead_put_sgl(sk); + err = -EMSGSIZE; + } + +unlock: + aead_data_wakeup(sk); + release_sock(sk); + + return err ?: size; +} + +static int aead_recvmsg(struct kiocb *unused, struct socket *sock, + struct msghdr *msg, size_t ignored, int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + unsigned bs = crypto_aead_blocksize(crypto_aead_reqtfm(&ctx->aead_req)); + unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); + struct aead_sg_list *sgl = &ctx->tsgl; + struct scatterlist *sg = NULL; + struct scatterlist assoc[ALG_MAX_PAGES]; + size_t assoclen = 0; + unsigned int i = 0; + int err = -EINVAL; + unsigned long used = 0; + size_t outlen = 0; + size_t usedpages = 0; + unsigned int cnt = 0; + + /* Limit number of IOV blocks to be accessed below */ + if (msg->msg_iter.nr_segs > RSGL_MAX_ENTRIES) + return -ENOMSG; + + lock_sock(sk); + + /* + * AEAD memory structure: For encryption, the tag is appended to the + * ciphertext which implies that the memory allocated for the ciphertext + * must be increased by the tag length. For decryption, the tag + * is expected to be concatenated to the ciphertext. The plaintext + * therefore has a memory size of the ciphertext minus the tag length. + * + * The memory structure for cipher operation has the following + * structure: + * AEAD encryption input: assoc data || plaintext + * AEAD encryption output: cipherntext || auth tag + * AEAD decryption input: assoc data || ciphertext || auth tag + * AEAD decryption output: plaintext + */ + + if (ctx->more) { + err = aead_wait_for_data(sk, flags); + if (err) + goto unlock; + } + + used = ctx->used; + + /* + * Make sure sufficient data is present -- note, the same check is + * is also present in sendmsg/sendpage. The checks in sendpage/sendmsg + * shall provide an information to the data sender that something is + * wrong, but they are irrelevant to maintain the kernel integrity. + * We need this check here too in case user space decides to not honor + * the error message in sendmsg/sendpage and still call recvmsg. This + * check here protects the kernel integrity. + */ + if (!aead_sufficient_data(ctx)) + goto unlock; + + /* + * The cipher operation input data is reduced by the associated data + * length as this data is processed separately later on. + */ + used -= ctx->aead_assoclen; + + if (ctx->enc) { + /* round up output buffer to multiple of block size */ + outlen = ((used + bs - 1) / bs * bs); + /* add the size needed for the auth tag to be created */ + outlen += as; + } else { + /* output data size is input without the authentication tag */ + outlen = used - as; + /* round up output buffer to multiple of block size */ + outlen = ((outlen + bs - 1) / bs * bs); + } + + /* convert iovecs of output buffers into scatterlists */ + while (iov_iter_count(&msg->msg_iter)) { + size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), + (outlen - usedpages)); + + /* make one iovec available as scatterlist */ + err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter, + seglen); + if (err < 0) + goto unlock; + usedpages += err; + /* chain the new scatterlist with initial list */ + if (cnt) + scatterwalk_crypto_chain(ctx->rsgl[0].sg, + ctx->rsgl[cnt].sg, 1, + sg_nents(ctx->rsgl[cnt-1].sg)); + /* we do not need more iovecs as we have sufficient memory */ + if (outlen <= usedpages) + break; + iov_iter_advance(&msg->msg_iter, err); + cnt++; + } + + err = -EINVAL; + /* ensure output buffer is sufficiently large */ + if (usedpages < outlen) + goto unlock; + + sg_init_table(assoc, ALG_MAX_PAGES); + assoclen = ctx->aead_assoclen; + /* + * Split scatterlist into two: first part becomes AD, second part + * is plaintext / ciphertext. The first part is assigned to assoc + * scatterlist. When this loop finishes, sg points to the start of the + * plaintext / ciphertext. + */ + for (i = 0; i < ctx->tsgl.cur; i++) { + sg = sgl->sg + i; + if (sg->length <= assoclen) { + /* AD is larger than one page */ + sg_set_page(assoc + i, sg_page(sg), + sg->length, sg->offset); + assoclen -= sg->length; + if (i >= ctx->tsgl.cur) + goto unlock; + } else if (!assoclen) { + /* current page is to start of plaintext / ciphertext */ + if (i) + /* AD terminates at page boundary */ + sg_mark_end(assoc + i - 1); + else + /* AD size is zero */ + sg_mark_end(assoc); + break; + } else { + /* AD does not terminate at page boundary */ + sg_set_page(assoc + i, sg_page(sg), + assoclen, sg->offset); + sg_mark_end(assoc + i); + /* plaintext / ciphertext starts after AD */ + sg->length -= assoclen; + sg->offset += assoclen; + break; + } + } + + aead_request_set_assoc(&ctx->aead_req, assoc, ctx->aead_assoclen); + aead_request_set_crypt(&ctx->aead_req, sg, ctx->rsgl[0].sg, used, + ctx->iv); + + err = af_alg_wait_for_completion(ctx->enc ? + crypto_aead_encrypt(&ctx->aead_req) : + crypto_aead_decrypt(&ctx->aead_req), + &ctx->completion); + + if (err) { + /* EBADMSG implies a valid cipher operation took place */ + if (err == -EBADMSG) + aead_put_sgl(sk); + goto unlock; + } + + aead_put_sgl(sk); + + err = 0; + +unlock: + for (i = 0; i < cnt; i++) + af_alg_free_sg(&ctx->rsgl[i]); + + aead_wmem_wakeup(sk); + release_sock(sk); + + return err ? err : outlen; +} + +static unsigned int aead_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + unsigned int mask; + + sock_poll_wait(file, sk_sleep(sk), wait); + mask = 0; + + if (!ctx->more) + mask |= POLLIN | POLLRDNORM; + + if (aead_writable(sk)) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; +} + +static struct proto_ops algif_aead_ops = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .accept = sock_no_accept, + .setsockopt = sock_no_setsockopt, + + .release = af_alg_release, + .sendmsg = aead_sendmsg, + .sendpage = aead_sendpage, + .recvmsg = aead_recvmsg, + .poll = aead_poll, +}; + +static void *aead_bind(const char *name, u32 type, u32 mask) +{ + return crypto_alloc_aead(name, type, mask); +} + +static void aead_release(void *private) +{ + crypto_free_aead(private); +} + +static int aead_setauthsize(void *private, unsigned int authsize) +{ + return crypto_aead_setauthsize(private, authsize); +} + +static int aead_setkey(void *private, const u8 *key, unsigned int keylen) +{ + return crypto_aead_setkey(private, key, keylen); +} + +static void aead_sock_destruct(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct aead_ctx *ctx = ask->private; + unsigned int ivlen = crypto_aead_ivsize( + crypto_aead_reqtfm(&ctx->aead_req)); + + aead_put_sgl(sk); + sock_kzfree_s(sk, ctx->iv, ivlen); + sock_kfree_s(sk, ctx, ctx->len); + af_alg_release_parent(sk); +} + +static int aead_accept_parent(void *private, struct sock *sk) +{ + struct aead_ctx *ctx; + struct alg_sock *ask = alg_sk(sk); + unsigned int len = sizeof(*ctx) + crypto_aead_reqsize(private); + unsigned int ivlen = crypto_aead_ivsize(private); + + ctx = sock_kmalloc(sk, len, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + memset(ctx, 0, len); + + ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL); + if (!ctx->iv) { + sock_kfree_s(sk, ctx, len); + return -ENOMEM; + } + memset(ctx->iv, 0, ivlen); + + ctx->len = len; + ctx->used = 0; + ctx->more = 0; + ctx->merge = 0; + ctx->enc = 0; + ctx->tsgl.cur = 0; + ctx->aead_assoclen = 0; + af_alg_init_completion(&ctx->completion); + sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES); + + ask->private = ctx; + + aead_request_set_tfm(&ctx->aead_req, private); + aead_request_set_callback(&ctx->aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, + af_alg_complete, &ctx->completion); + + sk->sk_destruct = aead_sock_destruct; + + return 0; +} + +static const struct af_alg_type algif_type_aead = { + .bind = aead_bind, + .release = aead_release, + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .accept = aead_accept_parent, + .ops = &algif_aead_ops, + .name = "aead", + .owner = THIS_MODULE +}; + +static int __init algif_aead_init(void) +{ + return af_alg_register_type(&algif_type_aead); +} + +static void __exit algif_aead_exit(void) +{ + int err = af_alg_unregister_type(&algif_type_aead); + BUG_ON(err); +} + +module_init(algif_aead_init); +module_exit(algif_aead_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("AEAD kernel crypto API user space interface"); -- cgit v1.2.3 From ab062b467c4f980ebb40001038fac1535803331c Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sat, 28 Feb 2015 20:50:40 +0100 Subject: crypto: algif - enable AEAD interface compilation Enable compilation of the AEAD AF_ALG support and provide a Kconfig option to compile the AEAD AF_ALG support. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/Kconfig | 9 +++++++++ crypto/Makefile | 1 + 2 files changed, 10 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 67275b7f..e74cecad 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1552,6 +1552,15 @@ config CRYPTO_USER_API_RNG This option enables the user-spaces interface for random number generator algorithms. +config CRYPTO_USER_API_AEAD + tristate "User-space interface for AEAD cipher algorithms" + depends on NET + select CRYPTO_AEAD + select CRYPTO_USER_API + help + This option enables the user-spaces interface for AEAD + cipher algorithms. + config CRYPTO_HASH_INFO bool diff --git a/crypto/Makefile b/crypto/Makefile index ba19465f..97b7d3ac 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o +obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o # # generic algorithms and the async_tx api -- cgit v1.2.3 From 4cb2baf91e96c1549a9aced081f1ea086ae06647 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sun, 1 Mar 2015 19:30:46 +0100 Subject: crypto: powerpc/md5 - kernel config Integrate the module into the kernel config tree. Signed-off-by: Markus Stockhausen Signed-off-by: Herbert Xu --- crypto/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index e74cecad..6918aff7 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -436,6 +436,14 @@ config CRYPTO_MD5_OCTEON MD5 message digest algorithm (RFC1321) implemented using OCTEON crypto instructions, when available. +config CRYPTO_MD5_PPC + tristate "MD5 digest algorithm (PPC)" + depends on PPC + select CRYPTO_HASH + help + MD5 message digest algorithm (RFC1321) implemented + in PPC assembler. + config CRYPTO_MD5_SPARC64 tristate "MD5 digest algorithm (SPARC64)" depends on SPARC64 -- cgit v1.2.3 From cb437ccd61e61b050ea2473041b5c64083162a57 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sun, 1 Mar 2015 20:39:17 +0100 Subject: crypto: drbg - use single block cipher API The CTR DRBG only encrypts one single block at a time. Thus, use the single block crypto API to avoid additional overhead from the block chaining modes. With the patch, the speed of the DRBG increases between 30% and 40%. The DRBG still passes the CTR DRBG CAVS test. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/drbg.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index d8ff16e5..c14274ac 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -119,19 +119,19 @@ static const struct drbg_core drbg_cores[] = { .statelen = 32, /* 256 bits as defined in 10.2.1 */ .blocklen_bytes = 16, .cra_name = "ctr_aes128", - .backend_cra_name = "ecb(aes)", + .backend_cra_name = "aes", }, { .flags = DRBG_CTR | DRBG_STRENGTH192, .statelen = 40, /* 320 bits as defined in 10.2.1 */ .blocklen_bytes = 16, .cra_name = "ctr_aes192", - .backend_cra_name = "ecb(aes)", + .backend_cra_name = "aes", }, { .flags = DRBG_CTR | DRBG_STRENGTH256, .statelen = 48, /* 384 bits as defined in 10.2.1 */ .blocklen_bytes = 16, .cra_name = "ctr_aes256", - .backend_cra_name = "ecb(aes)", + .backend_cra_name = "aes", }, #endif /* CONFIG_CRYPTO_DRBG_CTR */ #ifdef CONFIG_CRYPTO_DRBG_HASH @@ -1644,24 +1644,24 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, static int drbg_init_sym_kernel(struct drbg_state *drbg) { int ret = 0; - struct crypto_blkcipher *tfm; + struct crypto_cipher *tfm; - tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0); + tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0); if (IS_ERR(tfm)) { pr_info("DRBG: could not allocate cipher TFM handle\n"); return PTR_ERR(tfm); } - BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm)); + BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm)); drbg->priv_data = tfm; return ret; } static int drbg_fini_sym_kernel(struct drbg_state *drbg) { - struct crypto_blkcipher *tfm = - (struct crypto_blkcipher *)drbg->priv_data; + struct crypto_cipher *tfm = + (struct crypto_cipher *)drbg->priv_data; if (tfm) - crypto_free_blkcipher(tfm); + crypto_free_cipher(tfm); drbg->priv_data = NULL; return 0; } @@ -1669,21 +1669,14 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg) static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key, unsigned char *outval, const struct drbg_string *in) { - int ret = 0; - struct scatterlist sg_in, sg_out; - struct blkcipher_desc desc; - struct crypto_blkcipher *tfm = - (struct crypto_blkcipher *)drbg->priv_data; - - desc.tfm = tfm; - desc.flags = 0; - crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg))); - /* there is only component in *in */ - sg_init_one(&sg_in, in->buf, in->len); - sg_init_one(&sg_out, outval, drbg_blocklen(drbg)); - ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len); + struct crypto_cipher *tfm = + (struct crypto_cipher *)drbg->priv_data; - return ret; + crypto_cipher_setkey(tfm, key, (drbg_keylen(drbg))); + /* there is only component in *in */ + BUG_ON(in->len < drbg_blocklen(drbg)); + crypto_cipher_encrypt_one(tfm, outval, in->buf); + return 0; } #endif /* CONFIG_CRYPTO_DRBG_CTR */ -- cgit v1.2.3 From ea2481e2469ac9237110827f6aaf64c2302176c0 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sun, 1 Mar 2015 20:40:17 +0100 Subject: crypto: drbg - remove superflowous memsets The DRBG code contains memset(0) calls to initialize a varaible that are not necessary as the variable is always overwritten by the processing. This patch increases the CTR and Hash DRBGs by about 5%. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/drbg.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index c14274ac..56c1d7ec 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -308,9 +308,6 @@ static int drbg_ctr_bcc(struct drbg_state *drbg, drbg_string_fill(&data, out, drbg_blocklen(drbg)); - /* 10.4.3 step 1 */ - memset(out, 0, drbg_blocklen(drbg)); - /* 10.4.3 step 2 / 4 */ list_for_each_entry(curr, in, list) { const unsigned char *pos = curr->buf; @@ -406,7 +403,6 @@ static int drbg_ctr_df(struct drbg_state *drbg, memset(pad, 0, drbg_blocklen(drbg)); memset(iv, 0, drbg_blocklen(drbg)); - memset(temp, 0, drbg_statelen(drbg)); /* 10.4.2 step 1 is implicit as we work byte-wise */ @@ -523,7 +519,6 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, unsigned int len = 0; struct drbg_string cipherin; - memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg)); if (3 > reseed) memset(df_data, 0, drbg_statelen(drbg)); @@ -585,8 +580,6 @@ static int drbg_ctr_generate(struct drbg_state *drbg, int ret = 0; struct drbg_string data; - memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); - /* 10.2.1.5.2 step 2 */ if (addtl && !list_empty(addtl)) { ret = drbg_ctr_update(drbg, addtl, 2); @@ -761,7 +754,6 @@ static struct drbg_state_ops drbg_hmac_ops = { .generate = drbg_hmac_generate, .crypto_init = drbg_init_hash_kernel, .crypto_fini = drbg_fini_hash_kernel, - }; #endif /* CONFIG_CRYPTO_DRBG_HMAC */ @@ -838,8 +830,6 @@ static int drbg_hash_df(struct drbg_state *drbg, unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg); struct drbg_string data; - memset(tmp, 0, drbg_blocklen(drbg)); - /* 10.4.1 step 3 */ input[0] = 1; drbg_cpu_to_be32((outlen * 8), &input[1]); @@ -879,7 +869,6 @@ static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed, unsigned char *V = drbg->scratchpad; unsigned char prefix = DRBG_PREFIX1; - memset(drbg->scratchpad, 0, drbg_statelen(drbg)); if (!seed) return -EINVAL; @@ -921,9 +910,6 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, LIST_HEAD(datalist); unsigned char prefix = DRBG_PREFIX2; - /* this is value w as per documentation */ - memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); - /* 10.1.1.4 step 2 */ if (!addtl || list_empty(addtl)) return 0; @@ -959,9 +945,6 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, struct drbg_string data; LIST_HEAD(datalist); - memset(src, 0, drbg_statelen(drbg)); - memset(dst, 0, drbg_blocklen(drbg)); - /* 10.1.1.4 step hashgen 2 */ memcpy(src, drbg->V, drbg_statelen(drbg)); @@ -1018,7 +1001,6 @@ static int drbg_hash_generate(struct drbg_state *drbg, len = drbg_hash_hashgen(drbg, buf, buflen); /* this is the value H as documented in 10.1.1.4 */ - memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); /* 10.1.1.4 step 4 */ drbg_string_fill(&data1, &prefix, 1); list_add_tail(&data1.list, &datalist); -- cgit v1.2.3 From c3137fb62f2f92f2c7761e6a29dbfee1eb3b64f6 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 6 Mar 2015 08:26:31 +0100 Subject: crypto: rng - RNGs must return 0 in success case Change the RNGs to always return 0 in success case. This patch ensures that seqiv.c works with RNGs other than krng. seqiv expects that any return code other than 0 is an error. Without the patch, rfc4106(gcm(aes)) will not work when using a DRBG or an ANSI X9.31 RNG. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/ansi_cprng.c | 6 +++++- crypto/drbg.c | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index 6f5bebc9..765fe760 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c @@ -210,7 +210,11 @@ static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx, byte_count = DEFAULT_BLK_SZ; } - err = byte_count; + /* + * Return 0 in case of success as mandated by the kernel + * crypto API interface definition. + */ + err = 0; dbgprint(KERN_CRIT "getting %d random bytes for context %p\n", byte_count, ctx); diff --git a/crypto/drbg.c b/crypto/drbg.c index 56c1d7ec..b69409cb 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1280,7 +1280,7 @@ static void drbg_restore_shadow(struct drbg_state *drbg, * as defined in SP800-90A. The additional input is mixed into * the state in addition to the pulled entropy. * - * return: generated number of bytes + * return: 0 when all bytes are generated; < 0 in case of an error */ static int drbg_generate(struct drbg_state *drbg, unsigned char *buf, unsigned int buflen, @@ -1419,6 +1419,11 @@ static int drbg_generate(struct drbg_state *drbg, } #endif + /* + * All operations were successful, return 0 as mandated by + * the kernel crypto API interface. + */ + len = 0; err: shadow->d_ops->crypto_fini(shadow); drbg_restore_shadow(drbg, &shadow); -- cgit v1.2.3 From 11cbf6c9d5bba36725cd7be42820c98bdb6b6810 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 8 Mar 2015 22:07:47 +0200 Subject: crypto: octeon - enable OCTEON SHA1/256/512 module selection Enable user to select OCTEON SHA1/256/512 modules. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- crypto/Kconfig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 6918aff7..1afb0f66 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -554,6 +554,15 @@ config CRYPTO_SHA512_SSSE3 Extensions version 1 (AVX1), or Advanced Vector Extensions version 2 (AVX2) instructions, when available. +config CRYPTO_SHA1_OCTEON + tristate "SHA1 digest algorithm (OCTEON)" + depends on CPU_CAVIUM_OCTEON + select CRYPTO_SHA1 + select CRYPTO_HASH + help + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented + using OCTEON crypto instructions, when available. + config CRYPTO_SHA1_SPARC64 tristate "SHA1 digest algorithm (SPARC64)" depends on SPARC64 @@ -634,6 +643,15 @@ config CRYPTO_SHA256_PPC_SPE SHA224 and SHA256 secure hash standard (DFIPS 180-2) implemented using powerpc SPE SIMD instruction set. +config CRYPTO_SHA256_OCTEON + tristate "SHA224 and SHA256 digest algorithm (OCTEON)" + depends on CPU_CAVIUM_OCTEON + select CRYPTO_SHA256 + select CRYPTO_HASH + help + SHA-256 secure hash standard (DFIPS 180-2) implemented + using OCTEON crypto instructions, when available. + config CRYPTO_SHA256_SPARC64 tristate "SHA224 and SHA256 digest algorithm (SPARC64)" depends on SPARC64 @@ -655,6 +673,15 @@ config CRYPTO_SHA512 This code also includes SHA-384, a 384 bit hash with 192 bits of security against collision attacks. +config CRYPTO_SHA512_OCTEON + tristate "SHA384 and SHA512 digest algorithms (OCTEON)" + depends on CPU_CAVIUM_OCTEON + select CRYPTO_SHA512 + select CRYPTO_HASH + help + SHA-512 secure hash standard (DFIPS 180-2) implemented + using OCTEON crypto instructions, when available. + config CRYPTO_SHA512_SPARC64 tristate "SHA384 and SHA512 digest algorithm (SPARC64)" depends on SPARC64 -- cgit v1.2.3 From 84d260c770bdfe2b55ada91008992428dc5e4174 Mon Sep 17 00:00:00 2001 From: Horia Geant? Date: Mon, 9 Mar 2015 16:14:58 +0200 Subject: crypto: tcrypt - fix uninit sg entries in test_acipher_speed Commit 1206eddfc81b ("crypto: replace scatterwalk_sg_next with sg_next") did not consider the fact that scatterwalk_sg_next() was looking at sg entry length, while sg_next() looks at the "chained" sg bit. This should have no effect in theory. However in practice, there are cases where the sg table is initialized to a number of entries and some of them are not properly configured. While scatterwalk_sg_next() would have returned NULL (since sg length = 0 and sg page_link = 0), sg_next() happily returns the next unconfigured sg entry. insmod tcrypt.ko mode=500 sec=1 testing speed of async cbc(aes) (cbc-aes-talitos) encryption test 0 (128 bit key, 16 byte blocks): Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc00d79e4 Oops: Kernel access of bad area, sig: 11 [#1] SMP NR_CPUS=8 P1022 DS Modules linked in: tcrypt(+) talitos CPU: 0 PID: 2670 Comm: insmod Not tainted 4.0.0-rc1-QorIQ-SDK-V1.6+g904f1ca82209 #1 task: e8de3200 ti: e70bc000 task.ti: e70bc000 NIP: c00d79e4 LR: f92d223c CTR: c00d79c8 REGS: e70bda00 TRAP: 0300 Not tainted (4.0.0-rc1-QorIQ-SDK-V1.6+g904f1ca82209) MSR: 00029000 CR: 84428f22 XER: 00000000 DEAR: 00000000 ESR: 00000000 GPR00: f92d223c e70bdab0 e8de3200 00000000 e70bdbb8 00000001 00000000 00000000 GPR08: 00000000 00000000 c08b0380 27282010 c00d79c8 1003a634 00000000 e70bdf1c GPR16: e70bdef0 00000020 00000000 c08c0000 00000010 00000000 e70bdbb8 00000010 GPR24: e976d3a8 00000010 00000000 e70bdbd8 e8961010 00000001 c086e560 00000000 NIP [c00d79e4] page_address+0x1c/0x110 LR [f92d223c] talitos_map_sg+0x130/0x184 [talitos] Call Trace: [e70bdab0] [00000010] 0x10 (unreliable) [e70bdad0] [f92d223c] talitos_map_sg+0x130/0x184 [talitos] [e70bdb00] [f92d30d8] common_nonsnoop.constprop.13+0xc0/0x304 [talitos] [e70bdb30] [f933fd90] test_acipher_speed+0x434/0x7dc [tcrypt] [e70bdcc0] [f934318c] do_test+0x2478/0x306c [tcrypt] [e70bdd80] [f11fe058] tcrypt_mod_init+0x58/0x100 [tcrypt] [e70bdda0] [c0002354] do_one_initcall+0x90/0x1f4 [e70bde10] [c061fe00] do_init_module+0x60/0x1ac [e70bde30] [c00a79f0] load_module+0x185c/0x1f88 [e70bdee0] [c00a82b0] SyS_finit_module+0x7c/0x98 [e70bdf40] [c000e8b0] ret_from_syscall+0x0/0x3c Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 4b9e23fa..1a280010 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1155,9 +1155,9 @@ static void test_acipher_speed(const char *algo, int enc, unsigned int secs, goto out_free_req; } - sg_init_table(sg, TVMEMSIZE); - k = *keysize + *b_size; + sg_init_table(sg, DIV_ROUND_UP(k, PAGE_SIZE)); + if (k > PAGE_SIZE) { sg_set_buf(sg, tvmem[0] + *keysize, PAGE_SIZE - *keysize); -- cgit v1.2.3 From d02a664c47a18cd4c5b5c3c95bad85c3ef2cb4f2 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 10 Mar 2015 09:47:44 +0100 Subject: crypto: arm - move ARM specific Kconfig definitions to a dedicated file This moves all Kconfig symbols defined in crypto/Kconfig that depend on CONFIG_ARM to a dedicated Kconfig file in arch/arm/crypto, which is where the code that implements those features resides as well. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 75 ---------------------------------------------------------- 1 file changed, 75 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 1afb0f66..88639937 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -572,26 +572,6 @@ config CRYPTO_SHA1_SPARC64 SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented using sparc64 crypto instructions, when available. -config CRYPTO_SHA1_ARM - tristate "SHA1 digest algorithm (ARM-asm)" - depends on ARM - select CRYPTO_SHA1 - select CRYPTO_HASH - help - SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented - using optimized ARM assembler. - -config CRYPTO_SHA1_ARM_NEON - tristate "SHA1 digest algorithm (ARM NEON)" - depends on ARM && KERNEL_MODE_NEON - select CRYPTO_SHA1_ARM - select CRYPTO_SHA1 - select CRYPTO_HASH - help - SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented - using optimized ARM NEON assembly, when NEON instructions are - available. - config CRYPTO_SHA1_PPC tristate "SHA1 digest algorithm (powerpc)" depends on PPC @@ -691,21 +671,6 @@ config CRYPTO_SHA512_SPARC64 SHA-512 secure hash standard (DFIPS 180-2) implemented using sparc64 crypto instructions, when available. -config CRYPTO_SHA512_ARM_NEON - tristate "SHA384 and SHA512 digest algorithm (ARM NEON)" - depends on ARM && KERNEL_MODE_NEON - select CRYPTO_SHA512 - select CRYPTO_HASH - help - SHA-512 secure hash standard (DFIPS 180-2) implemented - using ARM NEON instructions, when available. - - This version of SHA implements a 512 bit hash with 256 bits of - security against collision attacks. - - This code also includes SHA-384, a 384 bit hash with 192 bits - of security against collision attacks. - config CRYPTO_TGR192 tristate "Tiger digest algorithms" select CRYPTO_HASH @@ -868,46 +833,6 @@ config CRYPTO_AES_SPARC64 for some popular block cipher mode is supported too, including ECB and CBC. -config CRYPTO_AES_ARM - tristate "AES cipher algorithms (ARM-asm)" - depends on ARM - select CRYPTO_ALGAPI - select CRYPTO_AES - help - Use optimized AES assembler routines for ARM platforms. - - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - The AES specifies three key sizes: 128, 192 and 256 bits - - See for more information. - -config CRYPTO_AES_ARM_BS - tristate "Bit sliced AES using NEON instructions" - depends on ARM && KERNEL_MODE_NEON - select CRYPTO_ALGAPI - select CRYPTO_AES_ARM - select CRYPTO_ABLK_HELPER - help - Use a faster and more secure NEON based implementation of AES in CBC, - CTR and XTS modes - - Bit sliced AES gives around 45% speedup on Cortex-A15 for CTR mode - and for XTS mode encryption, CBC and XTS mode decryption speedup is - around 25%. (CBC encryption speed is not affected by this driver.) - This implementation does not rely on any lookup tables so it is - believed to be invulnerable to cache timing attacks. - config CRYPTO_AES_PPC_SPE tristate "AES cipher algorithms (PPC SPE)" depends on PPC && SPE -- cgit v1.2.3 From 325a37506289e6015e8278e0ef5efa1d956e4cef Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 10 Mar 2015 17:00:36 +0100 Subject: crypto: testmgr - fix RNG return code enforcement Due to the change to RNGs to always return zero in success case, the invocation of the RNGs in the test manager must be updated as otherwise the RNG self tests are not properly executed any more. Signed-off-by: Stephan Mueller Signed-off-by: Alexander Bergmann Signed-off-by: Herbert Xu --- crypto/testmgr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index f4ed6d42..1f879adf 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1474,11 +1474,11 @@ static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template, for (j = 0; j < template[i].loops; j++) { err = crypto_rng_get_bytes(tfm, result, template[i].rlen); - if (err != template[i].rlen) { + if (err < 0) { printk(KERN_ERR "alg: cprng: Failed to obtain " "the correct amount of random data for " - "%s (requested %d, got %d)\n", algo, - template[i].rlen, err); + "%s (requested %d)\n", algo, + template[i].rlen); goto out; } } @@ -1759,7 +1759,7 @@ static int drbg_cavs_test(struct drbg_testvec *test, int pr, ret = crypto_drbg_get_bytes_addtl(drng, buf, test->expectedlen, &addtl); } - if (ret <= 0) { + if (ret < 0) { printk(KERN_ERR "alg: drbg: could not obtain random data for " "driver %s\n", driver); goto outbuf; @@ -1774,7 +1774,7 @@ static int drbg_cavs_test(struct drbg_testvec *test, int pr, ret = crypto_drbg_get_bytes_addtl(drng, buf, test->expectedlen, &addtl); } - if (ret <= 0) { + if (ret < 0) { printk(KERN_ERR "alg: drbg: could not obtain random data for " "driver %s\n", driver); goto outbuf; -- cgit v1.2.3 From cbcdfe774ae5058e96d0f3dcd6401bce4f74e076 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 13 Mar 2015 11:44:07 +0100 Subject: crypto: algif_rng - zeroize buffer with random data Due to the change to RNGs to always return zero in success case, the RNG interface must zeroize the buffer with the length provided by the caller. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/algif_rng.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index 67f612cf..a3461735 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -87,7 +87,7 @@ static int rng_recvmsg(struct kiocb *unused, struct socket *sock, return genlen; err = memcpy_to_msg(msg, result, len); - memzero_explicit(result, genlen); + memzero_explicit(result, len); return err ? err : len; } -- cgit v1.2.3 From bd1d3731a1ef4464ae8d8dd81c86c2b5ddb8b6b0 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 30 Mar 2015 21:55:52 +0200 Subject: crypto: api - prevent helper ciphers from being used Several hardware related cipher implementations are implemented as follows: a "helper" cipher implementation is registered with the kernel crypto API. Such helper ciphers are never intended to be called by normal users. In some cases, calling them via the normal crypto API may even cause failures including kernel crashes. In a normal case, the "wrapping" ciphers that use the helpers ensure that these helpers are invoked such that they cannot cause any calamity. Considering the AF_ALG user space interface, unprivileged users can call all ciphers registered with the crypto API, including these helper ciphers that are not intended to be called directly. That means, with AF_ALG user space may invoke these helper ciphers and may cause undefined states or side effects. To avoid any potential side effects with such helpers, the patch prevents the helpers to be called directly. A new cipher type flag is added: CRYPTO_ALG_INTERNAL. This flag shall be used to mark helper ciphers. These ciphers can only be used if the caller invoke the cipher with CRYPTO_ALG_INTERNAL in the type and mask field. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/api.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crypto/api.c b/crypto/api.c index 2a81e98a..afe4610a 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -257,6 +257,16 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) mask |= CRYPTO_ALG_TESTED; } + /* + * If the internal flag is set for a cipher, require a caller to + * to invoke the cipher with the internal flag to use that cipher. + * Also, if a caller wants to allocate a cipher that may or may + * not be an internal cipher, use type | CRYPTO_ALG_INTERNAL and + * !(mask & CRYPTO_ALG_INTERNAL). + */ + if (!((type | mask) & CRYPTO_ALG_INTERNAL)) + mask |= CRYPTO_ALG_INTERNAL; + larval = crypto_larval_lookup(name, type, mask); if (IS_ERR(larval) || !crypto_is_larval(larval)) return larval; -- cgit v1.2.3 From 1e71a242c082f18f547eb903cd54a68df2de4b0c Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 30 Mar 2015 21:56:31 +0200 Subject: crypto: testmgr - use CRYPTO_ALG_INTERNAL Allocate the ciphers irrespectively if they are marked as internal or not. As all ciphers, including the internal ciphers will be processed by the testmgr, it needs to be able to allocate those ciphers. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/testmgr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 1f879adf..f9bce3d7 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -1505,7 +1505,7 @@ static int alg_test_aead(const struct alg_test_desc *desc, const char *driver, struct crypto_aead *tfm; int err = 0; - tfm = crypto_alloc_aead(driver, type, mask); + tfm = crypto_alloc_aead(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: aead: Failed to load transform for %s: " "%ld\n", driver, PTR_ERR(tfm)); @@ -1534,7 +1534,7 @@ static int alg_test_cipher(const struct alg_test_desc *desc, struct crypto_cipher *tfm; int err = 0; - tfm = crypto_alloc_cipher(driver, type, mask); + tfm = crypto_alloc_cipher(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: cipher: Failed to load transform for " "%s: %ld\n", driver, PTR_ERR(tfm)); @@ -1563,7 +1563,7 @@ static int alg_test_skcipher(const struct alg_test_desc *desc, struct crypto_ablkcipher *tfm; int err = 0; - tfm = crypto_alloc_ablkcipher(driver, type, mask); + tfm = crypto_alloc_ablkcipher(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: skcipher: Failed to load transform for " "%s: %ld\n", driver, PTR_ERR(tfm)); @@ -1636,7 +1636,7 @@ static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, struct crypto_ahash *tfm; int err; - tfm = crypto_alloc_ahash(driver, type, mask); + tfm = crypto_alloc_ahash(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: hash: Failed to load transform for %s: " "%ld\n", driver, PTR_ERR(tfm)); @@ -1664,7 +1664,7 @@ static int alg_test_crc32c(const struct alg_test_desc *desc, if (err) goto out; - tfm = crypto_alloc_shash(driver, type, mask); + tfm = crypto_alloc_shash(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: " "%ld\n", driver, PTR_ERR(tfm)); @@ -1706,7 +1706,7 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver, struct crypto_rng *rng; int err; - rng = crypto_alloc_rng(driver, type, mask); + rng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(rng)) { printk(KERN_ERR "alg: cprng: Failed to load transform for %s: " "%ld\n", driver, PTR_ERR(rng)); @@ -1733,7 +1733,7 @@ static int drbg_cavs_test(struct drbg_testvec *test, int pr, if (!buf) return -ENOMEM; - drng = crypto_alloc_rng(driver, type, mask); + drng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask); if (IS_ERR(drng)) { printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for " "%s\n", driver); -- cgit v1.2.3 From b760f27b17922669b51740ce8ba50ad42d9d10dd Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 30 Mar 2015 21:57:06 +0200 Subject: crypto: cryptd - process CRYPTO_ALG_INTERNAL The cryptd is used as a wrapper around internal ciphers. Therefore, the cryptd must process the internal cipher by marking cryptd as internal if the underlying cipher is an internal cipher. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/ablk_helper.c | 3 ++- crypto/cryptd.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/crypto/ablk_helper.c b/crypto/ablk_helper.c index ffe7278d..e1fcf53b 100644 --- a/crypto/ablk_helper.c +++ b/crypto/ablk_helper.c @@ -124,7 +124,8 @@ int ablk_init_common(struct crypto_tfm *tfm, const char *drv_name) struct async_helper_ctx *ctx = crypto_tfm_ctx(tfm); struct cryptd_ablkcipher *cryptd_tfm; - cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, 0, 0); + cryptd_tfm = cryptd_alloc_ablkcipher(drv_name, CRYPTO_ALG_INTERNAL, + CRYPTO_ALG_INTERNAL); if (IS_ERR(cryptd_tfm)) return PTR_ERR(cryptd_tfm); diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 650afac1..b0602ba0 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -168,6 +168,20 @@ static inline struct cryptd_queue *cryptd_get_queue(struct crypto_tfm *tfm) return ictx->queue; } +static inline void cryptd_check_internal(struct rtattr **tb, u32 *type, + u32 *mask) +{ + struct crypto_attr_type *algt; + + algt = crypto_get_attr_type(tb); + if (IS_ERR(algt)) + return; + if ((algt->type & CRYPTO_ALG_INTERNAL)) + *type |= CRYPTO_ALG_INTERNAL; + if ((algt->mask & CRYPTO_ALG_INTERNAL)) + *mask |= CRYPTO_ALG_INTERNAL; +} + static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent, const u8 *key, unsigned int keylen) { @@ -321,10 +335,13 @@ static int cryptd_create_blkcipher(struct crypto_template *tmpl, struct cryptd_instance_ctx *ctx; struct crypto_instance *inst; struct crypto_alg *alg; + u32 type = CRYPTO_ALG_TYPE_BLKCIPHER; + u32 mask = CRYPTO_ALG_TYPE_MASK; int err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER, - CRYPTO_ALG_TYPE_MASK); + cryptd_check_internal(tb, &type, &mask); + + alg = crypto_get_attr_alg(tb, type, mask); if (IS_ERR(alg)) return PTR_ERR(alg); @@ -341,7 +358,10 @@ static int cryptd_create_blkcipher(struct crypto_template *tmpl, if (err) goto out_free_inst; - inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; + type = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; + if (alg->cra_flags & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_INTERNAL; + inst->alg.cra_flags = type; inst->alg.cra_type = &crypto_ablkcipher_type; inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize; @@ -577,9 +597,13 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, struct ahash_instance *inst; struct shash_alg *salg; struct crypto_alg *alg; + u32 type = 0; + u32 mask = 0; int err; - salg = shash_attr_alg(tb[1], 0, 0); + cryptd_check_internal(tb, &type, &mask); + + salg = shash_attr_alg(tb[1], type, mask); if (IS_ERR(salg)) return PTR_ERR(salg); @@ -598,7 +622,10 @@ static int cryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, if (err) goto out_free_inst; - inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC; + type = CRYPTO_ALG_ASYNC; + if (alg->cra_flags & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_INTERNAL; + inst->alg.halg.base.cra_flags = type; inst->alg.halg.digestsize = salg->digestsize; inst->alg.halg.base.cra_ctxsize = sizeof(struct cryptd_hash_ctx); @@ -719,10 +746,13 @@ static int cryptd_create_aead(struct crypto_template *tmpl, struct aead_instance_ctx *ctx; struct crypto_instance *inst; struct crypto_alg *alg; + u32 type = CRYPTO_ALG_TYPE_AEAD; + u32 mask = CRYPTO_ALG_TYPE_MASK; int err; - alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_AEAD, - CRYPTO_ALG_TYPE_MASK); + cryptd_check_internal(tb, &type, &mask); + + alg = crypto_get_attr_alg(tb, type, mask); if (IS_ERR(alg)) return PTR_ERR(alg); @@ -739,7 +769,10 @@ static int cryptd_create_aead(struct crypto_template *tmpl, if (err) goto out_free_inst; - inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; + type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; + if (alg->cra_flags & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_INTERNAL; + inst->alg.cra_flags = type; inst->alg.cra_type = alg->cra_type; inst->alg.cra_ctxsize = sizeof(struct cryptd_aead_ctx); inst->alg.cra_init = cryptd_aead_init_tfm; -- cgit v1.2.3 From ebc46b158723822ae6ad58c2aa517353dddb045b Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 30 Mar 2015 21:57:42 +0200 Subject: crypto: proc - identify internal ciphers With ciphers that now cannot be accessed via the kernel crypto API, callers shall be able to identify the ciphers that are not callable. The /proc/crypto file is added a boolean field identifying that such internal ciphers. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/proc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crypto/proc.c b/crypto/proc.c index 4a0a7aad..4ffe73b5 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -89,6 +89,9 @@ static int c_show(struct seq_file *m, void *p) seq_printf(m, "selftest : %s\n", (alg->cra_flags & CRYPTO_ALG_TESTED) ? "passed" : "unknown"); + seq_printf(m, "internal : %s\n", + (alg->cra_flags & CRYPTO_ALG_INTERNAL) ? + "yes" : "no"); if (alg->cra_flags & CRYPTO_ALG_LARVAL) { seq_printf(m, "type : larval\n"); -- cgit v1.2.3 From da4bf302300b6ff56ef73030f5dc07c008921481 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Mon, 30 Mar 2015 22:10:58 +0200 Subject: crypto: mcryptd - process CRYPTO_ALG_INTERNAL The mcryptd is used as a wrapper around internal ciphers. Therefore, the mcryptd must process the internal cipher by marking mcryptd as internal if the underlying cipher is an internal cipher. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/mcryptd.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c index a8e87044..fe5b495a 100644 --- a/crypto/mcryptd.c +++ b/crypto/mcryptd.c @@ -258,6 +258,20 @@ out_free_inst: goto out; } +static inline void mcryptd_check_internal(struct rtattr **tb, u32 *type, + u32 *mask) +{ + struct crypto_attr_type *algt; + + algt = crypto_get_attr_type(tb); + if (IS_ERR(algt)) + return; + if ((algt->type & CRYPTO_ALG_INTERNAL)) + *type |= CRYPTO_ALG_INTERNAL; + if ((algt->mask & CRYPTO_ALG_INTERNAL)) + *mask |= CRYPTO_ALG_INTERNAL; +} + static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm) { struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); @@ -480,9 +494,13 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, struct ahash_instance *inst; struct shash_alg *salg; struct crypto_alg *alg; + u32 type = 0; + u32 mask = 0; int err; - salg = shash_attr_alg(tb[1], 0, 0); + mcryptd_check_internal(tb, &type, &mask); + + salg = shash_attr_alg(tb[1], type, mask); if (IS_ERR(salg)) return PTR_ERR(salg); @@ -502,7 +520,10 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, if (err) goto out_free_inst; - inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC; + type = CRYPTO_ALG_ASYNC; + if (alg->cra_flags & CRYPTO_ALG_INTERNAL) + type |= CRYPTO_ALG_INTERNAL; + inst->alg.halg.base.cra_flags = type; inst->alg.halg.digestsize = salg->digestsize; inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx); -- cgit v1.2.3 From 0c6ae139da9aad73445691476b989e6036c37a20 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 2 Apr 2015 22:31:22 +0800 Subject: crypto: api - Fix races in crypto_unregister_instance There are multiple problems in crypto_unregister_instance: 1) The cra_refcnt BUG_ON check is racy and can cause crashes. 2) The cra_refcnt check shouldn't exist at all. 3) There is no reference on tmpl to protect the tmpl->free call. This patch rewrites the function using crypto_remove_spawn which now morphs into crypto_remove_instance. Signed-off-by: Herbert Xu --- crypto/algapi.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/crypto/algapi.c b/crypto/algapi.c index 83b04e08..0f1976ec 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -99,10 +99,9 @@ static struct list_head *crypto_more_spawns(struct crypto_alg *alg, return &n->list == stack ? top : &n->inst->alg.cra_users; } -static void crypto_remove_spawn(struct crypto_spawn *spawn, - struct list_head *list) +static void crypto_remove_instance(struct crypto_instance *inst, + struct list_head *list) { - struct crypto_instance *inst = spawn->inst; struct crypto_template *tmpl = inst->tmpl; if (crypto_is_dead(&inst->alg)) @@ -167,7 +166,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, if (spawn->alg) list_move(&spawn->list, &spawn->alg->cra_users); else - crypto_remove_spawn(spawn, list); + crypto_remove_instance(spawn->inst, list); } } EXPORT_SYMBOL_GPL(crypto_remove_spawns); @@ -554,28 +553,20 @@ EXPORT_SYMBOL_GPL(crypto_register_instance); int crypto_unregister_instance(struct crypto_alg *alg) { - int err; struct crypto_instance *inst = (void *)alg; - struct crypto_template *tmpl = inst->tmpl; - LIST_HEAD(users); + LIST_HEAD(list); if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE)) return -EINVAL; - BUG_ON(atomic_read(&alg->cra_refcnt) != 1); - down_write(&crypto_alg_sem); - hlist_del_init(&inst->list); - err = crypto_remove_alg(alg, &users); + crypto_remove_spawns(alg, &list, NULL); + crypto_remove_instance(inst, &list); up_write(&crypto_alg_sem); - if (err) - return err; - - tmpl->free(inst); - crypto_remove_final(&users); + crypto_remove_final(&list); return 0; } -- cgit v1.2.3 From 0cec2ad45f07c308b03337b34a02c691ed870f2c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 2 Apr 2015 22:39:40 +0800 Subject: crypto: api - Change crypto_unregister_instance argument type This patch makes crypto_unregister_instance take a crypto_instance instead of a crypto_alg. This allows us to remove a duplicate CRYPTO_ALG_INSTANCE check in crypto_unregister_instance. Signed-off-by: Herbert Xu --- crypto/algapi.c | 8 ++------ crypto/crypto_user.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crypto/algapi.c b/crypto/algapi.c index 0f1976ec..f1d0307b 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -551,17 +551,13 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_instance); -int crypto_unregister_instance(struct crypto_alg *alg) +int crypto_unregister_instance(struct crypto_instance *inst) { - struct crypto_instance *inst = (void *)alg; LIST_HEAD(list); - if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE)) - return -EINVAL; - down_write(&crypto_alg_sem); - crypto_remove_spawns(alg, &list, NULL); + crypto_remove_spawns(&inst->alg, &list, NULL); crypto_remove_instance(inst, &list); up_write(&crypto_alg_sem); diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index c5148a35..eab24972 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -316,7 +316,7 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, if (atomic_read(&alg->cra_refcnt) != 1) return -EBUSY; - return crypto_unregister_instance(alg); + return crypto_unregister_instance((struct crypto_instance *)alg); } static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, -- cgit v1.2.3 From 29924b3e0775b174e639468109e7627fbaa0d07d Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sat, 4 Apr 2015 00:20:30 +0900 Subject: crypto: serpent_sse2 - Fix a typo in Kconfig This patch fix a spelling typo in crypto/Kconfig. Signed-off-by: Masanari Iida Signed-off-by: Herbert Xu --- crypto/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 88639937..8aaf298a 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1188,7 +1188,7 @@ config CRYPTO_SERPENT_SSE2_X86_64 Keys are allowed to be from 0 to 256 bits in length, in steps of 8 bits. - This module provides Serpent cipher algorithm that processes eigth + This module provides Serpent cipher algorithm that processes eight blocks parallel using SSE2 instruction set. See also: -- cgit v1.2.3 From 4224c16a384d2f71569e1b9147cdd5a9ff970c78 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 7 Apr 2015 21:27:01 +0800 Subject: crypto: user - Fix crypto_alg_match race The function crypto_alg_match returns an algorithm without taking any references on it. This means that the algorithm can be freed at any time, therefore all users of crypto_alg_match are buggy. This patch fixes this by taking a reference count on the algorithm to prevent such races. Signed-off-by: Herbert Xu --- crypto/crypto_user.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index eab24972..41dfe762 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -62,10 +62,14 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) else if (!exact) match = !strcmp(q->cra_name, p->cru_name); - if (match) { - alg = q; - break; - } + if (!match) + continue; + + if (unlikely(!crypto_mod_get(q))) + continue; + + alg = q; + break; } up_read(&crypto_alg_sem); @@ -205,9 +209,10 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, if (!alg) return -ENOENT; + err = -ENOMEM; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb) - return -ENOMEM; + goto drop_alg; info.in_skb = in_skb; info.out_skb = skb; @@ -215,6 +220,10 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, info.nlmsg_flags = 0; err = crypto_report_alg(alg, &info); + +drop_alg: + crypto_mod_put(alg); + if (err) return err; @@ -284,6 +293,7 @@ static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh, up_write(&crypto_alg_sem); + crypto_mod_put(alg); crypto_remove_final(&list); return 0; @@ -294,6 +304,7 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, { struct crypto_alg *alg; struct crypto_user_alg *p = nlmsg_data(nlh); + int err; if (!netlink_capable(skb, CAP_NET_ADMIN)) return -EPERM; @@ -310,13 +321,19 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, * if we try to unregister. Unregistering such an algorithm without * removing the module is not possible, so we restrict to crypto * instances that are build from templates. */ + err = -EINVAL; if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE)) - return -EINVAL; + goto drop_alg; - if (atomic_read(&alg->cra_refcnt) != 1) - return -EBUSY; + err = -EBUSY; + if (atomic_read(&alg->cra_refcnt) > 2) + goto drop_alg; - return crypto_unregister_instance((struct crypto_instance *)alg); + err = crypto_unregister_instance((struct crypto_instance *)alg); + +drop_alg: + crypto_mod_put(alg); + return err; } static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, @@ -395,8 +412,10 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; alg = crypto_alg_match(p, exact); - if (alg) + if (alg) { + crypto_mod_put(alg); return -EEXIST; + } if (strlen(p->cru_driver_name)) name = p->cru_driver_name; -- cgit v1.2.3 From 2e25d6e799e4964b15f76dbfd4fe4ffb88b72fd3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 9 Apr 2015 17:40:35 +0800 Subject: crypto: api - Move alg ref count init to crypto_check_alg We currently initialise the crypto_alg ref count in the function __crypto_register_alg. As one of the callers of that function crypto_register_instance needs to obtain a ref count before it calls __crypto_register_alg, we need to move the initialisation out of there. Since both callers of __crypto_register_alg call crypto_check_alg, this is the logical place to perform the initialisation. Signed-off-by: Herbert Xu Acked-by: Stephan Mueller --- crypto/algapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/algapi.c b/crypto/algapi.c index f1d0307b..1462c684 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -64,6 +64,8 @@ static int crypto_check_alg(struct crypto_alg *alg) if (alg->cra_priority < 0) return -EINVAL; + atomic_set(&alg->cra_refcnt, 1); + return crypto_set_driver_name(alg); } @@ -187,7 +189,6 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) ret = -EEXIST; - atomic_set(&alg->cra_refcnt, 1); list_for_each_entry(q, &crypto_alg_list, cra_list) { if (q == alg) goto err; -- cgit v1.2.3 From 8e239e586ec36ec542598dc39587744046834dc4 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Thu, 9 Apr 2015 12:09:55 +0200 Subject: crypto: api - remove instance when test failed A cipher instance is added to the list of instances unconditionally regardless of whether the associated test failed. However, a failed test implies that during another lookup, the cipher instance will be added to the list again as it will not be found by the lookup code. That means that the list can be filled up with instances whose tests failed. Note: tests only fail in reality in FIPS mode when a cipher is not marked as fips_allowed=1. This can be seen with cmac(des3_ede) that does not have a fips_allowed=1. When allocating the cipher, the allocation fails with -ENOENT due to the missing fips_allowed=1 flag (which causes the testmgr to return EINVAL). Yet, the instance of cmac(des3_ede) is shown in /proc/crypto. Allocating the cipher again fails again, but a 2nd instance is listed in /proc/crypto. The patch simply de-registers the instance when the testing failed. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/algapi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crypto/algapi.c b/crypto/algapi.c index 1462c684..2d0a1c64 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -523,7 +523,10 @@ int crypto_register_instance(struct crypto_template *tmpl, err = crypto_check_alg(&inst->alg); if (err) - goto err; + return err; + + if (unlikely(!crypto_mod_get(&inst->alg))) + return -EAGAIN; inst->alg.cra_module = tmpl->module; inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE; @@ -545,9 +548,14 @@ unlock: goto err; crypto_wait_for_test(larval); + + /* Remove instance if test failed */ + if (!(inst->alg.cra_flags & CRYPTO_ALG_TESTED)) + crypto_unregister_instance(inst); err = 0; err: + crypto_mod_put(&inst->alg); return err; } EXPORT_SYMBOL_GPL(crypto_register_instance); -- cgit v1.2.3 From 8858809e496276544f12c905aa20a793448e9079 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 9 Apr 2015 12:55:36 +0200 Subject: crypto: sha1-generic - move to generic glue implementation This updated the generic SHA-1 implementation to use the generic shared SHA-1 glue code. It also implements a .finup hook crypto_sha1_finup() and exports it to other modules. The import and export() functions and the .statesize member are dropped, since the default implementation is perfectly suitable for this module. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/sha1_generic.c | 102 ++++++++++---------------------------------------- 1 file changed, 20 insertions(+), 82 deletions(-) diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c index a3e50c37..39e3acc4 100644 --- a/crypto/sha1_generic.c +++ b/crypto/sha1_generic.c @@ -23,111 +23,49 @@ #include #include #include +#include #include -static int sha1_init(struct shash_desc *desc) +static void sha1_generic_block_fn(struct sha1_state *sst, u8 const *src, + int blocks) { - struct sha1_state *sctx = shash_desc_ctx(desc); + u32 temp[SHA_WORKSPACE_WORDS]; - *sctx = (struct sha1_state){ - .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }, - }; - - return 0; + while (blocks--) { + sha_transform(sst->state, src, temp); + src += SHA1_BLOCK_SIZE; + } + memzero_explicit(temp, sizeof(temp)); } int crypto_sha1_update(struct shash_desc *desc, const u8 *data, - unsigned int len) + unsigned int len) { - struct sha1_state *sctx = shash_desc_ctx(desc); - unsigned int partial, done; - const u8 *src; - - partial = sctx->count % SHA1_BLOCK_SIZE; - sctx->count += len; - done = 0; - src = data; - - if ((partial + len) >= SHA1_BLOCK_SIZE) { - u32 temp[SHA_WORKSPACE_WORDS]; - - if (partial) { - done = -partial; - memcpy(sctx->buffer + partial, data, - done + SHA1_BLOCK_SIZE); - src = sctx->buffer; - } - - do { - sha_transform(sctx->state, src, temp); - done += SHA1_BLOCK_SIZE; - src = data + done; - } while (done + SHA1_BLOCK_SIZE <= len); - - memzero_explicit(temp, sizeof(temp)); - partial = 0; - } - memcpy(sctx->buffer + partial, src, len - done); - - return 0; + return sha1_base_do_update(desc, data, len, sha1_generic_block_fn); } EXPORT_SYMBOL(crypto_sha1_update); - -/* Add padding and return the message digest. */ static int sha1_final(struct shash_desc *desc, u8 *out) { - struct sha1_state *sctx = shash_desc_ctx(desc); - __be32 *dst = (__be32 *)out; - u32 i, index, padlen; - __be64 bits; - static const u8 padding[64] = { 0x80, }; - - bits = cpu_to_be64(sctx->count << 3); - - /* Pad out to 56 mod 64 */ - index = sctx->count & 0x3f; - padlen = (index < 56) ? (56 - index) : ((64+56) - index); - crypto_sha1_update(desc, padding, padlen); - - /* Append length */ - crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits)); - - /* Store state in digest */ - for (i = 0; i < 5; i++) - dst[i] = cpu_to_be32(sctx->state[i]); - - /* Wipe context */ - memset(sctx, 0, sizeof *sctx); - - return 0; + sha1_base_do_finalize(desc, sha1_generic_block_fn); + return sha1_base_finish(desc, out); } -static int sha1_export(struct shash_desc *desc, void *out) +int crypto_sha1_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) { - struct sha1_state *sctx = shash_desc_ctx(desc); - - memcpy(out, sctx, sizeof(*sctx)); - return 0; -} - -static int sha1_import(struct shash_desc *desc, const void *in) -{ - struct sha1_state *sctx = shash_desc_ctx(desc); - - memcpy(sctx, in, sizeof(*sctx)); - return 0; + sha1_base_do_update(desc, data, len, sha1_generic_block_fn); + return sha1_final(desc, out); } +EXPORT_SYMBOL(crypto_sha1_finup); static struct shash_alg alg = { .digestsize = SHA1_DIGEST_SIZE, - .init = sha1_init, + .init = sha1_base_init, .update = crypto_sha1_update, .final = sha1_final, - .export = sha1_export, - .import = sha1_import, + .finup = crypto_sha1_finup, .descsize = sizeof(struct sha1_state), - .statesize = sizeof(struct sha1_state), .base = { .cra_name = "sha1", .cra_driver_name= "sha1-generic", -- cgit v1.2.3 From 33cc5ddacf9c181ac817b0444d93e835a7e0429a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 9 Apr 2015 12:55:37 +0200 Subject: crypto: sha256-generic - move to generic glue implementation This updates the generic SHA-256 implementation to use the new shared SHA-256 glue code. It also implements a .finup hook crypto_sha256_finup() and exports it to other modules. The import and export() functions and the .statesize member are dropped, since the default implementation is perfectly suitable for this module. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/sha256_generic.c | 133 ++++++++---------------------------------------- 1 file changed, 20 insertions(+), 113 deletions(-) diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c index b001ff5c..78431163 100644 --- a/crypto/sha256_generic.c +++ b/crypto/sha256_generic.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -214,138 +215,43 @@ static void sha256_transform(u32 *state, const u8 *input) memzero_explicit(W, 64 * sizeof(u32)); } -static int sha224_init(struct shash_desc *desc) +static void sha256_generic_block_fn(struct sha256_state *sst, u8 const *src, + int blocks) { - struct sha256_state *sctx = shash_desc_ctx(desc); - sctx->state[0] = SHA224_H0; - sctx->state[1] = SHA224_H1; - sctx->state[2] = SHA224_H2; - sctx->state[3] = SHA224_H3; - sctx->state[4] = SHA224_H4; - sctx->state[5] = SHA224_H5; - sctx->state[6] = SHA224_H6; - sctx->state[7] = SHA224_H7; - sctx->count = 0; - - return 0; -} - -static int sha256_init(struct shash_desc *desc) -{ - struct sha256_state *sctx = shash_desc_ctx(desc); - sctx->state[0] = SHA256_H0; - sctx->state[1] = SHA256_H1; - sctx->state[2] = SHA256_H2; - sctx->state[3] = SHA256_H3; - sctx->state[4] = SHA256_H4; - sctx->state[5] = SHA256_H5; - sctx->state[6] = SHA256_H6; - sctx->state[7] = SHA256_H7; - sctx->count = 0; - - return 0; + while (blocks--) { + sha256_transform(sst->state, src); + src += SHA256_BLOCK_SIZE; + } } int crypto_sha256_update(struct shash_desc *desc, const u8 *data, unsigned int len) { - struct sha256_state *sctx = shash_desc_ctx(desc); - unsigned int partial, done; - const u8 *src; - - partial = sctx->count & 0x3f; - sctx->count += len; - done = 0; - src = data; - - if ((partial + len) > 63) { - if (partial) { - done = -partial; - memcpy(sctx->buf + partial, data, done + 64); - src = sctx->buf; - } - - do { - sha256_transform(sctx->state, src); - done += 64; - src = data + done; - } while (done + 63 < len); - - partial = 0; - } - memcpy(sctx->buf + partial, src, len - done); - - return 0; + return sha256_base_do_update(desc, data, len, sha256_generic_block_fn); } EXPORT_SYMBOL(crypto_sha256_update); static int sha256_final(struct shash_desc *desc, u8 *out) { - struct sha256_state *sctx = shash_desc_ctx(desc); - __be32 *dst = (__be32 *)out; - __be64 bits; - unsigned int index, pad_len; - int i; - static const u8 padding[64] = { 0x80, }; - - /* Save number of bits */ - bits = cpu_to_be64(sctx->count << 3); - - /* Pad out to 56 mod 64. */ - index = sctx->count & 0x3f; - pad_len = (index < 56) ? (56 - index) : ((64+56) - index); - crypto_sha256_update(desc, padding, pad_len); - - /* Append length (before padding) */ - crypto_sha256_update(desc, (const u8 *)&bits, sizeof(bits)); - - /* Store state in digest */ - for (i = 0; i < 8; i++) - dst[i] = cpu_to_be32(sctx->state[i]); - - /* Zeroize sensitive information. */ - memset(sctx, 0, sizeof(*sctx)); - - return 0; + sha256_base_do_finalize(desc, sha256_generic_block_fn); + return sha256_base_finish(desc, out); } -static int sha224_final(struct shash_desc *desc, u8 *hash) +int crypto_sha256_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *hash) { - u8 D[SHA256_DIGEST_SIZE]; - - sha256_final(desc, D); - - memcpy(hash, D, SHA224_DIGEST_SIZE); - memzero_explicit(D, SHA256_DIGEST_SIZE); - - return 0; -} - -static int sha256_export(struct shash_desc *desc, void *out) -{ - struct sha256_state *sctx = shash_desc_ctx(desc); - - memcpy(out, sctx, sizeof(*sctx)); - return 0; -} - -static int sha256_import(struct shash_desc *desc, const void *in) -{ - struct sha256_state *sctx = shash_desc_ctx(desc); - - memcpy(sctx, in, sizeof(*sctx)); - return 0; + sha256_base_do_update(desc, data, len, sha256_generic_block_fn); + return sha256_final(desc, hash); } +EXPORT_SYMBOL(crypto_sha256_finup); static struct shash_alg sha256_algs[2] = { { .digestsize = SHA256_DIGEST_SIZE, - .init = sha256_init, + .init = sha256_base_init, .update = crypto_sha256_update, .final = sha256_final, - .export = sha256_export, - .import = sha256_import, + .finup = crypto_sha256_finup, .descsize = sizeof(struct sha256_state), - .statesize = sizeof(struct sha256_state), .base = { .cra_name = "sha256", .cra_driver_name= "sha256-generic", @@ -355,9 +261,10 @@ static struct shash_alg sha256_algs[2] = { { } }, { .digestsize = SHA224_DIGEST_SIZE, - .init = sha224_init, + .init = sha224_base_init, .update = crypto_sha256_update, - .final = sha224_final, + .final = sha256_final, + .finup = crypto_sha256_finup, .descsize = sizeof(struct sha256_state), .base = { .cra_name = "sha224", -- cgit v1.2.3 From 0b06ab44e78db6806262e80eae19ab8cf91903a3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 9 Apr 2015 12:55:38 +0200 Subject: crypto: sha512-generic - move to generic glue implementation This updated the generic SHA-512 implementation to use the generic shared SHA-512 glue code. It also implements a .finup hook crypto_sha512_finup() and exports it to other modules. The import and export() functions and the .statesize member are dropped, since the default implementation is perfectly suitable for this module. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/sha512_generic.c | 123 +++++++++--------------------------------------- 1 file changed, 21 insertions(+), 102 deletions(-) diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 1c3c3767..eba965d1 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -130,125 +131,42 @@ sha512_transform(u64 *state, const u8 *input) a = b = c = d = e = f = g = h = t1 = t2 = 0; } -static int -sha512_init(struct shash_desc *desc) +static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src, + int blocks) { - struct sha512_state *sctx = shash_desc_ctx(desc); - sctx->state[0] = SHA512_H0; - sctx->state[1] = SHA512_H1; - sctx->state[2] = SHA512_H2; - sctx->state[3] = SHA512_H3; - sctx->state[4] = SHA512_H4; - sctx->state[5] = SHA512_H5; - sctx->state[6] = SHA512_H6; - sctx->state[7] = SHA512_H7; - sctx->count[0] = sctx->count[1] = 0; - - return 0; -} - -static int -sha384_init(struct shash_desc *desc) -{ - struct sha512_state *sctx = shash_desc_ctx(desc); - sctx->state[0] = SHA384_H0; - sctx->state[1] = SHA384_H1; - sctx->state[2] = SHA384_H2; - sctx->state[3] = SHA384_H3; - sctx->state[4] = SHA384_H4; - sctx->state[5] = SHA384_H5; - sctx->state[6] = SHA384_H6; - sctx->state[7] = SHA384_H7; - sctx->count[0] = sctx->count[1] = 0; - - return 0; + while (blocks--) { + sha512_transform(sst->state, src); + src += SHA512_BLOCK_SIZE; + } } int crypto_sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len) { - struct sha512_state *sctx = shash_desc_ctx(desc); - - unsigned int i, index, part_len; - - /* Compute number of bytes mod 128 */ - index = sctx->count[0] & 0x7f; - - /* Update number of bytes */ - if ((sctx->count[0] += len) < len) - sctx->count[1]++; - - part_len = 128 - index; - - /* Transform as many times as possible. */ - if (len >= part_len) { - memcpy(&sctx->buf[index], data, part_len); - sha512_transform(sctx->state, sctx->buf); - - for (i = part_len; i + 127 < len; i+=128) - sha512_transform(sctx->state, &data[i]); - - index = 0; - } else { - i = 0; - } - - /* Buffer remaining input */ - memcpy(&sctx->buf[index], &data[i], len - i); - - return 0; + return sha512_base_do_update(desc, data, len, sha512_generic_block_fn); } EXPORT_SYMBOL(crypto_sha512_update); -static int -sha512_final(struct shash_desc *desc, u8 *hash) +static int sha512_final(struct shash_desc *desc, u8 *hash) { - struct sha512_state *sctx = shash_desc_ctx(desc); - static u8 padding[128] = { 0x80, }; - __be64 *dst = (__be64 *)hash; - __be64 bits[2]; - unsigned int index, pad_len; - int i; - - /* Save number of bits */ - bits[1] = cpu_to_be64(sctx->count[0] << 3); - bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); - - /* Pad out to 112 mod 128. */ - index = sctx->count[0] & 0x7f; - pad_len = (index < 112) ? (112 - index) : ((128+112) - index); - crypto_sha512_update(desc, padding, pad_len); - - /* Append length (before padding) */ - crypto_sha512_update(desc, (const u8 *)bits, sizeof(bits)); - - /* Store state in digest */ - for (i = 0; i < 8; i++) - dst[i] = cpu_to_be64(sctx->state[i]); - - /* Zeroize sensitive information. */ - memset(sctx, 0, sizeof(struct sha512_state)); - - return 0; + sha512_base_do_finalize(desc, sha512_generic_block_fn); + return sha512_base_finish(desc, hash); } -static int sha384_final(struct shash_desc *desc, u8 *hash) +int crypto_sha512_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *hash) { - u8 D[64]; - - sha512_final(desc, D); - - memcpy(hash, D, 48); - memzero_explicit(D, 64); - - return 0; + sha512_base_do_update(desc, data, len, sha512_generic_block_fn); + return sha512_final(desc, hash); } +EXPORT_SYMBOL(crypto_sha512_finup); static struct shash_alg sha512_algs[2] = { { .digestsize = SHA512_DIGEST_SIZE, - .init = sha512_init, + .init = sha512_base_init, .update = crypto_sha512_update, .final = sha512_final, + .finup = crypto_sha512_finup, .descsize = sizeof(struct sha512_state), .base = { .cra_name = "sha512", @@ -259,9 +177,10 @@ static struct shash_alg sha512_algs[2] = { { } }, { .digestsize = SHA384_DIGEST_SIZE, - .init = sha384_init, + .init = sha384_base_init, .update = crypto_sha512_update, - .final = sha384_final, + .final = sha512_final, + .finup = crypto_sha512_finup, .descsize = sizeof(struct sha512_state), .base = { .cra_name = "sha384", -- cgit v1.2.3