git: cfb7b942bed7 - main - cryptosoft: Use multi-block encrypt/decrypt for non-AEAD ciphers.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 11 Jan 2022 22:38:11 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=cfb7b942bed72cb798b869d2e36e0097dbd243b2

commit cfb7b942bed72cb798b869d2e36e0097dbd243b2
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-01-11 22:18:57 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-01-11 22:18:57 +0000

    cryptosoft: Use multi-block encrypt/decrypt for non-AEAD ciphers.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D33531
---
 sys/opencrypto/cryptosoft.c | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
index 65eb29bdfd91..78fa786f0f72 100644
--- a/sys/opencrypto/cryptosoft.c
+++ b/sys/opencrypto/cryptosoft.c
@@ -105,7 +105,7 @@ swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
 	const struct enc_xform *exf;
 	const struct swcr_encdec *sw;
 	void *ctx;
-	size_t inlen, outlen;
+	size_t inlen, outlen, todo;
 	int blks, resid;
 	struct crypto_buffer_cursor cc_in, cc_out;
 	const unsigned char *inblk;
@@ -154,7 +154,6 @@ swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
 		cc_out = cc_in;
 	outblk = crypto_cursor_segment(&cc_out, &outlen);
 
-	resid = crp->crp_payload_length;
 	encrypting = CRYPTO_OP_IS_ENCRYPT(crp->crp_op);
 
 	/*
@@ -163,7 +162,7 @@ swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
 	 * 'outlen' is the remaining length of current segment in the
 	 * output buffer.
 	 */
-	while (resid >= blks) {
+	for (resid = crp->crp_payload_length; resid >= blks; resid -= todo) {
 		/*
 		 * If the current block is not contained within the
 		 * current input/output segment, use 'blk' as a local
@@ -172,33 +171,41 @@ swcr_encdec(const struct swcr_session *ses, struct cryptop *crp)
 		if (inlen < blks) {
 			crypto_cursor_copydata(&cc_in, blks, blk);
 			inblk = blk;
+			inlen = blks;
 		}
-		if (outlen < blks)
+		if (outlen < blks) {
 			outblk = blk;
+			outlen = blks;
+		}
+
+		todo = rounddown2(MIN(resid, MIN(inlen, outlen)), blks);
 
 		if (encrypting)
-			exf->encrypt(ctx, inblk, outblk);
+			exf->encrypt_multi(ctx, inblk, outblk, todo);
 		else
-			exf->decrypt(ctx, inblk, outblk);
+			exf->decrypt_multi(ctx, inblk, outblk, todo);
 
-		if (inlen < blks) {
+		if (inblk == blk) {
 			inblk = crypto_cursor_segment(&cc_in, &inlen);
 		} else {
-			crypto_cursor_advance(&cc_in, blks);
-			inlen -= blks;
-			inblk += blks;
+			crypto_cursor_advance(&cc_in, todo);
+			inlen -= todo;
+			inblk += todo;
+			if (inlen == 0)
+				inblk = crypto_cursor_segment(&cc_in, &inlen);
 		}
 
-		if (outlen < blks) {
+		if (outblk == blk) {
 			crypto_cursor_copyback(&cc_out, blks, blk);
 			outblk = crypto_cursor_segment(&cc_out, &outlen);
 		} else {
-			crypto_cursor_advance(&cc_out, blks);
-			outlen -= blks;
-			outblk += blks;
+			crypto_cursor_advance(&cc_out, todo);
+			outlen -= todo;
+			outblk += todo;
+			if (outlen == 0)
+				outblk = crypto_cursor_segment(&cc_out,
+				    &outlen);
 		}
-
-		resid -= blks;
 	}
 
 	/* Handle trailing partial block for stream ciphers. */