diff mbox series

[v3,31/31] crypto: salsa20-generic - dd support for chaining

Message ID E1k0Jtu-0006YO-7O@fornost.hmeau.com (mailing list archive)
State Changes Requested
Delegated to: Herbert Xu
Headers show
Series crypto: skcipher - Add support for no chaining and partial chaining | expand

Commit Message

Herbert Xu July 28, 2020, 7:19 a.m. UTC
As it stands salsa20 cannot do chaining.  That is, it has to handle
each request as a whole.  This patch adds support for chaining when
the CRYPTO_TFM_REQ_MORE flag is set.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/salsa20_generic.c |   20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
index 3418869dabefd..dd4b4cc8e76b9 100644
--- a/crypto/salsa20_generic.c
+++ b/crypto/salsa20_generic.c
@@ -21,7 +21,10 @@ 
 
 #include <asm/unaligned.h>
 #include <crypto/internal/skcipher.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/string.h>
 
 #define SALSA20_IV_SIZE        8
 #define SALSA20_MIN_KEY_SIZE  16
@@ -32,6 +35,11 @@  struct salsa20_ctx {
 	u32 initial_state[16];
 };
 
+struct salsa20_reqctx {
+	u32 state[16];
+	bool init;
+};
+
 static void salsa20_block(u32 *state, __le32 *stream)
 {
 	u32 x[16];
@@ -154,13 +162,16 @@  static int salsa20_crypt(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	const struct salsa20_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct salsa20_reqctx *rctx = skcipher_request_ctx(req);
 	struct skcipher_walk walk;
-	u32 state[16];
 	int err;
 
 	err = skcipher_walk_virt(&walk, req, false);
 
-	salsa20_init(state, ctx, req->iv);
+	if (!rctx->init)
+		salsa20_init(rctx->state, ctx, req->iv);
+
+	rctx->init = req->base.flags & CRYPTO_TFM_REQ_MORE;
 
 	while (walk.nbytes > 0) {
 		unsigned int nbytes = walk.nbytes;
@@ -168,8 +179,8 @@  static int salsa20_crypt(struct skcipher_request *req)
 		if (nbytes < walk.total)
 			nbytes = round_down(nbytes, walk.stride);
 
-		salsa20_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr,
-				nbytes);
+		salsa20_docrypt(rctx->state, walk.dst.virt.addr,
+				walk.src.virt.addr, nbytes);
 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
 	}
 
@@ -188,6 +199,7 @@  static struct skcipher_alg alg = {
 	.max_keysize		= SALSA20_MAX_KEY_SIZE,
 	.ivsize			= SALSA20_IV_SIZE,
 	.chunksize		= SALSA20_BLOCK_SIZE,
+	.reqsize		= sizeof(struct salsa20_reqctx),
 	.setkey			= salsa20_setkey,
 	.encrypt		= salsa20_crypt,
 	.decrypt		= salsa20_crypt,