summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-10 14:04:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-10 14:04:16 -0700
commit30066ce675d3af350bc5a53858991c0b518dda00 (patch)
tree75db2274cd0887b11b4e297771287f0fb4c14b81
parent6763afe4b9f39142bda2a92d69e62fe85f67251c (diff)
parentc3afafa47898e34eb49828ec4ac92bcdc81c8f0c (diff)
downloadlinux-30066ce675d3af350bc5a53858991c0b518dda00.tar.gz
linux-30066ce675d3af350bc5a53858991c0b518dda00.tar.bz2
linux-30066ce675d3af350bc5a53858991c0b518dda00.zip
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu: "Here is the crypto update for 4.9: API: - The crypto engine code now supports hashes. Algorithms: - Allow keys >= 2048 bits in FIPS mode for RSA. Drivers: - Memory overwrite fix for vmx ghash. - Add support for building ARM sha1-neon in Thumb2 mode. - Reenable ARM ghash-ce code by adding import/export. - Reenable img-hash by adding import/export. - Add support for multiple cores in omap-aes. - Add little-endian support for sha1-powerpc. - Add Cavium HWRNG driver for ThunderX SoC" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (137 commits) crypto: caam - treat SGT address pointer as u64 crypto: ccp - Make syslog errors human-readable crypto: ccp - clean up data structure crypto: vmx - Ensure ghash-generic is enabled crypto: testmgr - add guard to dst buffer for ahash_export crypto: caam - Unmap region obtained by of_iomap crypto: sha1-powerpc - little-endian support crypto: gcm - Fix IV buffer size in crypto_gcm_setkey crypto: vmx - Fix memory corruption caused by p8_ghash crypto: ghash-generic - move common definitions to a new header file crypto: caam - fix sg dump hwrng: omap - Only fail if pm_runtime_get_sync returns < 0 crypto: omap-sham - shrink the internal buffer size crypto: omap-sham - add support for export/import crypto: omap-sham - convert driver logic to use sgs for data xmit crypto: omap-sham - change the DMA threshold value to a define crypto: omap-sham - add support functions for sg based data handling crypto: omap-sham - rename sgl to sgl_tmp for deprecation crypto: omap-sham - align algorithms on word offset crypto: omap-sham - add context export/import stubs ...
-rw-r--r--Documentation/DocBook/crypto-API.tmpl38
-rw-r--r--arch/arm/crypto/ghash-ce-glue.c26
-rw-r--r--arch/arm/crypto/sha1-armv7-neon.S1
-rw-r--r--arch/powerpc/crypto/sha1-powerpc-asm.S13
-rw-r--r--crypto/algif_hash.c73
-rw-r--r--crypto/crct10dif_generic.c5
-rw-r--r--crypto/crypto_engine.c187
-rw-r--r--crypto/drbg.c31
-rw-r--r--crypto/gcm.c2
-rw-r--r--crypto/ghash-generic.c13
-rw-r--r--crypto/mcryptd.c7
-rw-r--r--crypto/rsa_helper.c4
-rw-r--r--crypto/testmgr.c24
-rw-r--r--crypto/testmgr.h4
-rw-r--r--crypto/xor.c41
-rw-r--r--crypto/xts.c2
-rw-r--r--drivers/char/hw_random/Kconfig13
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/amd-rng.c140
-rw-r--r--drivers/char/hw_random/bcm2835-rng.c5
-rw-r--r--drivers/char/hw_random/cavium-rng-vf.c99
-rw-r--r--drivers/char/hw_random/cavium-rng.c94
-rw-r--r--drivers/char/hw_random/core.c37
-rw-r--r--drivers/char/hw_random/geode-rng.c58
-rw-r--r--drivers/char/hw_random/meson-rng.c3
-rw-r--r--drivers/char/hw_random/omap-rng.c4
-rw-r--r--drivers/char/hw_random/omap3-rom-rng.c10
-rw-r--r--drivers/char/hw_random/pasemi-rng.c37
-rw-r--r--drivers/char/hw_random/pic32-rng.c1
-rw-r--r--drivers/char/hw_random/st-rng.c4
-rw-r--r--drivers/char/hw_random/tx4939-rng.c11
-rw-r--r--drivers/crypto/Kconfig3
-rw-r--r--drivers/crypto/caam/caamalg.c161
-rw-r--r--drivers/crypto/caam/caamhash.c581
-rw-r--r--drivers/crypto/caam/ctrl.c3
-rw-r--r--drivers/crypto/caam/desc.h6
-rw-r--r--drivers/crypto/caam/desc_constr.h17
-rw-r--r--drivers/crypto/caam/intern.h1
-rw-r--r--drivers/crypto/caam/jr.c26
-rw-r--r--drivers/crypto/caam/regs.h8
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h2
-rw-r--r--drivers/crypto/ccp/Makefile1
-rw-r--r--drivers/crypto/ccp/ccp-crypto-sha.c18
-rw-r--r--drivers/crypto/ccp/ccp-dev-v3.c182
-rw-r--r--drivers/crypto/ccp/ccp-dev-v5.c1017
-rw-r--r--drivers/crypto/ccp/ccp-dev.c113
-rw-r--r--drivers/crypto/ccp/ccp-dev.h312
-rw-r--r--drivers/crypto/ccp/ccp-dmaengine.c11
-rw-r--r--drivers/crypto/ccp/ccp-ops.c576
-rw-r--r--drivers/crypto/ccp/ccp-pci.c23
-rw-r--r--drivers/crypto/hifn_795x.c12
-rw-r--r--drivers/crypto/img-hash.c108
-rw-r--r--drivers/crypto/ixp4xx_crypto.c9
-rw-r--r--drivers/crypto/marvell/cesa.c1
-rw-r--r--drivers/crypto/marvell/hash.c44
-rw-r--r--drivers/crypto/marvell/tdma.c1
-rw-r--r--drivers/crypto/mv_cesa.c7
-rw-r--r--drivers/crypto/mxc-scc.c4
-rw-r--r--drivers/crypto/omap-aes.c141
-rw-r--r--drivers/crypto/omap-des.c35
-rw-r--r--drivers/crypto/omap-sham.c568
-rw-r--r--drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.h2
-rw-r--r--drivers/crypto/qat/qat_common/adf_admin.c20
-rw-r--r--drivers/crypto/qat/qat_common/qat_uclo.c8
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.c6
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-cipher.c6
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-core.c68
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-hash.c165
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss.h2
-rw-r--r--drivers/crypto/vmx/Kconfig1
-rw-r--r--drivers/crypto/vmx/ghash.c31
-rw-r--r--drivers/pci/quirks.c11
-rw-r--r--include/crypto/algapi.h70
-rw-r--r--include/crypto/engine.h107
-rw-r--r--include/crypto/ghash.h23
-rw-r--r--include/linux/ccp.h3
-rw-r--r--include/linux/hw_random.h4
77 files changed, 3852 insertions, 1654 deletions
diff --git a/Documentation/DocBook/crypto-API.tmpl b/Documentation/DocBook/crypto-API.tmpl
index fb2a1526f6ec..088b79c341ff 100644
--- a/Documentation/DocBook/crypto-API.tmpl
+++ b/Documentation/DocBook/crypto-API.tmpl
@@ -797,7 +797,8 @@ kernel crypto API | Caller
include/linux/crypto.h and their definition can be seen below.
The former function registers a single transformation, while
the latter works on an array of transformation descriptions.
- The latter is useful when registering transformations in bulk.
+ The latter is useful when registering transformations in bulk,
+ for example when a driver implements multiple transformations.
</para>
<programlisting>
@@ -822,18 +823,31 @@ kernel crypto API | Caller
</para>
<para>
- The bulk registration / unregistration functions require
- that struct crypto_alg is an array of count size. These
- functions simply loop over that array and register /
- unregister each individual algorithm. If an error occurs,
- the loop is terminated at the offending algorithm definition.
- That means, the algorithms prior to the offending algorithm
- are successfully registered. Note, the caller has no way of
- knowing which cipher implementations have successfully
- registered. If this is important to know, the caller should
- loop through the different implementations using the single
- instance *_alg functions for each individual implementation.
+ The bulk registration/unregistration functions
+ register/unregister each transformation in the given array of
+ length count. They handle errors as follows:
</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ crypto_register_algs() succeeds if and only if it
+ successfully registers all the given transformations. If an
+ error occurs partway through, then it rolls back successful
+ registrations before returning the error code. Note that if
+ a driver needs to handle registration errors for individual
+ transformations, then it will need to use the non-bulk
+ function crypto_register_alg() instead.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ crypto_unregister_algs() tries to unregister all the given
+ transformations, continuing on error. It logs errors and
+ always returns zero.
+ </para>
+ </listitem>
+ </itemizedlist>
+
</sect1>
<sect1><title>Single-Block Symmetric Ciphers [CIPHER]</title>
diff --git a/arch/arm/crypto/ghash-ce-glue.c b/arch/arm/crypto/ghash-ce-glue.c
index 1568cb5cd870..7546b3c02466 100644
--- a/arch/arm/crypto/ghash-ce-glue.c
+++ b/arch/arm/crypto/ghash-ce-glue.c
@@ -138,7 +138,7 @@ static struct shash_alg ghash_alg = {
.setkey = ghash_setkey,
.descsize = sizeof(struct ghash_desc_ctx),
.base = {
- .cra_name = "ghash",
+ .cra_name = "__ghash",
.cra_driver_name = "__driver-ghash-ce",
.cra_priority = 0,
.cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_INTERNAL,
@@ -220,6 +220,27 @@ static int ghash_async_digest(struct ahash_request *req)
}
}
+static int ghash_async_import(struct ahash_request *req, const void *in)
+{
+ struct ahash_request *cryptd_req = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+
+ desc->tfm = cryptd_ahash_child(ctx->cryptd_tfm);
+ desc->flags = req->base.flags;
+
+ return crypto_shash_import(desc, in);
+}
+
+static int ghash_async_export(struct ahash_request *req, void *out)
+{
+ struct ahash_request *cryptd_req = ahash_request_ctx(req);
+ struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+
+ return crypto_shash_export(desc, out);
+}
+
static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
@@ -268,7 +289,10 @@ static struct ahash_alg ghash_async_alg = {
.final = ghash_async_final,
.setkey = ghash_async_setkey,
.digest = ghash_async_digest,
+ .import = ghash_async_import,
+ .export = ghash_async_export,
.halg.digestsize = GHASH_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct ghash_desc_ctx),
.halg.base = {
.cra_name = "ghash",
.cra_driver_name = "ghash-ce",
diff --git a/arch/arm/crypto/sha1-armv7-neon.S b/arch/arm/crypto/sha1-armv7-neon.S
index dcd01f3f0bb0..2468fade49cf 100644
--- a/arch/arm/crypto/sha1-armv7-neon.S
+++ b/arch/arm/crypto/sha1-armv7-neon.S
@@ -12,7 +12,6 @@
#include <asm/assembler.h>
.syntax unified
-.code 32
.fpu neon
.text
diff --git a/arch/powerpc/crypto/sha1-powerpc-asm.S b/arch/powerpc/crypto/sha1-powerpc-asm.S
index 125e16520061..82ddc9bdfeb1 100644
--- a/arch/powerpc/crypto/sha1-powerpc-asm.S
+++ b/arch/powerpc/crypto/sha1-powerpc-asm.S
@@ -7,6 +7,15 @@
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
+#ifdef __BIG_ENDIAN__
+#define LWZ(rt, d, ra) \
+ lwz rt,d(ra)
+#else
+#define LWZ(rt, d, ra) \
+ li rt,d; \
+ lwbrx rt,rt,ra
+#endif
+
/*
* We roll the registers for T, A, B, C, D, E around on each
* iteration; T on iteration t is A on iteration t+1, and so on.
@@ -23,7 +32,7 @@
#define W(t) (((t)%16)+16)
#define LOADW(t) \
- lwz W(t),(t)*4(r4)
+ LWZ(W(t),(t)*4,r4)
#define STEPD0_LOAD(t) \
andc r0,RD(t),RB(t); \
@@ -33,7 +42,7 @@
add r0,RE(t),r15; \
add RT(t),RT(t),r6; \
add r14,r0,W(t); \
- lwz W((t)+4),((t)+4)*4(r4); \
+ LWZ(W((t)+4),((t)+4)*4,r4); \
rotlwi RB(t),RB(t),30; \
add RT(t),RT(t),r14
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 68a5ceaa04c8..2d8466f9e49b 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -39,6 +39,37 @@ struct algif_hash_tfm {
bool has_key;
};
+static int hash_alloc_result(struct sock *sk, struct hash_ctx *ctx)
+{
+ unsigned ds;
+
+ if (ctx->result)
+ return 0;
+
+ ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
+
+ ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
+ if (!ctx->result)
+ return -ENOMEM;
+
+ memset(ctx->result, 0, ds);
+
+ return 0;
+}
+
+static void hash_free_result(struct sock *sk, struct hash_ctx *ctx)
+{
+ unsigned ds;
+
+ if (!ctx->result)
+ return;
+
+ ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
+
+ sock_kzfree_s(sk, ctx->result, ds);
+ ctx->result = NULL;
+}
+
static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
size_t ignored)
{
@@ -54,6 +85,9 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
if (!ctx->more) {
+ if ((msg->msg_flags & MSG_MORE))
+ hash_free_result(sk, ctx);
+
err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
&ctx->completion);
if (err)
@@ -90,6 +124,10 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
ctx->more = msg->msg_flags & MSG_MORE;
if (!ctx->more) {
+ err = hash_alloc_result(sk, ctx);
+ if (err)
+ goto unlock;
+
ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
&ctx->completion);
@@ -116,6 +154,13 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
sg_init_table(ctx->sgl.sg, 1);
sg_set_page(ctx->sgl.sg, page, size, offset);
+ if (!(flags & MSG_MORE)) {
+ err = hash_alloc_result(sk, ctx);
+ if (err)
+ goto unlock;
+ } else if (!ctx->more)
+ hash_free_result(sk, ctx);
+
ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
if (!(flags & MSG_MORE)) {
@@ -153,6 +198,7 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
struct alg_sock *ask = alg_sk(sk);
struct hash_ctx *ctx = ask->private;
unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
+ bool result;
int err;
if (len > ds)
@@ -161,17 +207,29 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
msg->msg_flags |= MSG_TRUNC;
lock_sock(sk);
+ result = ctx->result;
+ err = hash_alloc_result(sk, ctx);
+ if (err)
+ goto unlock;
+
+ ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
+
if (ctx->more) {
ctx->more = 0;
- ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
&ctx->completion);
if (err)
goto unlock;
+ } else if (!result) {
+ err = af_alg_wait_for_completion(
+ crypto_ahash_digest(&ctx->req),
+ &ctx->completion);
}
err = memcpy_to_msg(msg, ctx->result, len);
+ hash_free_result(sk, ctx);
+
unlock:
release_sock(sk);
@@ -394,8 +452,7 @@ static void hash_sock_destruct(struct sock *sk)
struct alg_sock *ask = alg_sk(sk);
struct hash_ctx *ctx = ask->private;
- sock_kzfree_s(sk, ctx->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
+ hash_free_result(sk, ctx);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);
}
@@ -407,20 +464,12 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk)
struct algif_hash_tfm *tfm = private;
struct crypto_ahash *hash = tfm->hash;
unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
- unsigned ds = crypto_ahash_digestsize(hash);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
- if (!ctx->result) {
- sock_kfree_s(sk, ctx, len);
- return -ENOMEM;
- }
-
- memset(ctx->result, 0, ds);
-
+ ctx->result = NULL;
ctx->len = len;
ctx->more = 0;
af_alg_init_completion(&ctx->completion);
diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c
index c1229614c7e3..8e94e29dc6fc 100644
--- a/crypto/crct10dif_generic.c
+++ b/crypto/crct10dif_generic.c
@@ -107,10 +107,7 @@ static struct shash_alg alg = {
static int __init crct10dif_mod_init(void)
{
- int ret;
-
- ret = crypto_register_shash(&alg);
- return ret;
+ return crypto_register_shash(&alg);
}
static void __exit crct10dif_mod_fini(void)
diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
index a55c82dd48ef..bfb92ace2c91 100644
--- a/crypto/crypto_engine.c
+++ b/crypto/crypto_engine.c
@@ -14,13 +14,12 @@
#include <linux/err.h>
#include <linux/delay.h>
+#include <crypto/engine.h>
+#include <crypto/internal/hash.h>
#include "internal.h"
#define CRYPTO_ENGINE_MAX_QLEN 10
-void crypto_finalize_request(struct crypto_engine *engine,
- struct ablkcipher_request *req, int err);
-
/**
* crypto_pump_requests - dequeue one request from engine queue to process
* @engine: the hardware engine
@@ -34,10 +33,11 @@ static void crypto_pump_requests(struct crypto_engine *engine,
bool in_kthread)
{
struct crypto_async_request *async_req, *backlog;
- struct ablkcipher_request *req;
+ struct ahash_request *hreq;
+ struct ablkcipher_request *breq;
unsigned long flags;
bool was_busy = false;
- int ret;
+ int ret, rtype;
spin_lock_irqsave(&engine->queue_lock, flags);
@@ -82,9 +82,7 @@ static void crypto_pump_requests(struct crypto_engine *engine,
if (!async_req)
goto out;
- req = ablkcipher_request_cast(async_req);
-
- engine->cur_req = req;
+ engine->cur_req = async_req;
if (backlog)
backlog->complete(backlog, -EINPROGRESS);
@@ -95,6 +93,7 @@ static void crypto_pump_requests(struct crypto_engine *engine,
spin_unlock_irqrestore(&engine->queue_lock, flags);
+ rtype = crypto_tfm_alg_type(engine->cur_req->tfm);
/* Until here we get the request need to be encrypted successfully */
if (!was_busy && engine->prepare_crypt_hardware) {
ret = engine->prepare_crypt_hardware(engine);
@@ -104,24 +103,55 @@ static void crypto_pump_requests(struct crypto_engine *engine,
}
}
- if (engine->prepare_request) {
- ret = engine->prepare_request(engine, engine->cur_req);
+ switch (rtype) {
+ case CRYPTO_ALG_TYPE_AHASH:
+ hreq = ahash_request_cast(engine->cur_req);
+ if (engine->prepare_hash_request) {
+ ret = engine->prepare_hash_request(engine, hreq);
+ if (ret) {
+ pr_err("failed to prepare request: %d\n", ret);
+ goto req_err;
+ }
+ engine->cur_req_prepared = true;
+ }
+ ret = engine->hash_one_request(engine, hreq);
if (ret) {
- pr_err("failed to prepare request: %d\n", ret);
+ pr_err("failed to hash one request from queue\n");
goto req_err;
}
- engine->cur_req_prepared = true;
- }
-
- ret = engine->crypt_one_request(engine, engine->cur_req);
- if (ret) {
- pr_err("failed to crypt one request from queue\n");
- goto req_err;
+ return;
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ breq = ablkcipher_request_cast(engine->cur_req);
+ if (engine->prepare_cipher_request) {
+ ret = engine->prepare_cipher_request(engine, breq);
+ if (ret) {
+ pr_err("failed to prepare request: %d\n", ret);
+ goto req_err;
+ }
+ engine->cur_req_prepared = true;
+ }
+ ret = engine->cipher_one_request(engine, breq);
+ if (ret) {
+ pr_err("failed to cipher one request from queue\n");
+ goto req_err;
+ }
+ return;
+ default:
+ pr_err("failed to p