git: ec3872a696a9 - stable/13 - Add an OCF algorithm for ChaCha20-Poly1305 AEAD.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 21 Oct 2021 17:06:50 UTC
The branch stable/13 has been updated by jhb:

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

commit ec3872a696a9b931ca8366c616bf9efc2dbfe8f8
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-02-18 17:21:56 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-10-21 15:51:22 +0000

    Add an OCF algorithm for ChaCha20-Poly1305 AEAD.
    
    Note that this algorithm implements the mode defined in RFC 8439.
    
    Reviewed by:    cem
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D27836
    
    (cherry picked from commit fc8fc743d89388c0c5b97a491428fab2b36beac8)
---
 share/man/man7/crypto.7                  |  4 +++-
 sys/conf/files                           |  1 +
 sys/modules/crypto/Makefile              |  1 +
 sys/opencrypto/crypto.c                  | 12 +++++-----
 sys/opencrypto/cryptodev.c               | 11 +++++++++
 sys/opencrypto/cryptodev.h               |  5 +++-
 sys/opencrypto/xform_chacha20_poly1305.c | 41 ++++++++++++++++++++++++++++++++
 sys/opencrypto/xform_enc.h               |  1 +
 8 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/share/man/man7/crypto.7 b/share/man/man7/crypto.7
index d6cae1e39819..ccc2d1fc9be3 100644
--- a/share/man/man7/crypto.7
+++ b/share/man/man7/crypto.7
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 20, 2021
+.Dd February 18, 2021
 .Dt CRYPTO 7
 .Os
 .Sh NAME
@@ -161,6 +161,8 @@ The following AEAD algorithms are supported:
 AES Galois/Counter Mode
 .It Dv CRYPTO_AES_CCM_16 Ta 12 Ta 16, 24, 32 Ta 16 Ta
 AES Counter with CBC-MAC
+.It Dv CRYPTO_CHACHA20_POLY1305 Ta 12 Ta 32 Ta 16 Ta
+ChaCha20-Poly1305
 .El
 .Sh SEE ALSO
 .Xr crypto 4 ,
diff --git a/sys/conf/files b/sys/conf/files
index 2d3ae104753d..a352a0759c99 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4948,6 +4948,7 @@ opencrypto/gfmult.c		optional crypto | ipsec | ipsec_support
 opencrypto/rmd160.c		optional crypto | ipsec | ipsec_support
 opencrypto/xform.c		optional crypto | ipsec | ipsec_support
 opencrypto/xform_cbc_mac.c	optional crypto
+opencrypto/xform_chacha20_poly1305.c	optional crypto
 opencrypto/xform_poly1305.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \
diff --git a/sys/modules/crypto/Makefile b/sys/modules/crypto/Makefile
index 01ade43a0e51..89af6ab8fc61 100644
--- a/sys/modules/crypto/Makefile
+++ b/sys/modules/crypto/Makefile
@@ -67,6 +67,7 @@ SRCS	+= randombytes.c
 CFLAGS.randombytes.c		+= -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
 SRCS	+= utils.c
 CFLAGS.utils.c			+= -I${LIBSODIUM_INC} -I${LIBSODIUM_COMPAT}
+SRCS	+= xform_chacha20_poly1305.c
 
 SRCS	+= opt_param.h cryptodev_if.h bus_if.h device_if.h
 SRCS	+= opt_compat.h
diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c
index 59c74c86de00..704077043bb8 100644
--- a/sys/opencrypto/crypto.c
+++ b/sys/opencrypto/crypto.c
@@ -602,6 +602,8 @@ crypto_cipher(const struct crypto_session_params *csp)
 		return (&enc_xform_chacha20);
 	case CRYPTO_AES_CCM_16:
 		return (&enc_xform_ccm);
+	case CRYPTO_CHACHA20_POLY1305:
+		return (&enc_xform_chacha20_poly1305);
 	default:
 		return (NULL);
 	}
@@ -693,6 +695,7 @@ static enum alg_type {
 	[CRYPTO_POLY1305] = ALG_KEYED_DIGEST,
 	[CRYPTO_AES_CCM_CBC_MAC] = ALG_KEYED_DIGEST,
 	[CRYPTO_AES_CCM_16] = ALG_AEAD,
+	[CRYPTO_CHACHA20_POLY1305] = ALG_AEAD,
 };
 
 static enum alg_type
@@ -837,6 +840,7 @@ check_csp(const struct crypto_session_params *csp)
 		switch (csp->csp_cipher_alg) {
 		case CRYPTO_AES_NIST_GCM_16:
 		case CRYPTO_AES_CCM_16:
+		case CRYPTO_CHACHA20_POLY1305:
 			if (csp->csp_auth_mlen > 16)
 				return (false);
 			break;
@@ -1310,12 +1314,8 @@ crp_sanity(struct cryptop *crp)
 		    crp->crp_op ==
 		    (CRYPTO_OP_DECRYPT | CRYPTO_OP_VERIFY_DIGEST),
 		    ("invalid AEAD op %x", crp->crp_op));
-		if (csp->csp_cipher_alg == CRYPTO_AES_NIST_GCM_16)
-			KASSERT(crp->crp_flags & CRYPTO_F_IV_SEPARATE,
-			    ("GCM without a separate IV"));
-		if (csp->csp_cipher_alg == CRYPTO_AES_CCM_16)
-			KASSERT(crp->crp_flags & CRYPTO_F_IV_SEPARATE,
-			    ("CCM without a separate IV"));
+		KASSERT(crp->crp_flags & CRYPTO_F_IV_SEPARATE,
+		    ("AEAD without a separate IV"));
 		break;
 	case CSP_MODE_ETA:
 		KASSERT(crp->crp_op ==
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 61f8f332e1ca..81c6dcd01e2a 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -428,6 +428,9 @@ cse_create(struct fcrypt *fcr, struct session2_op *sop)
 	case CRYPTO_AES_CCM_16:
 		txform = &enc_xform_ccm;
 		break;
+	case CRYPTO_CHACHA20_POLY1305:
+		txform = &enc_xform_chacha20_poly1305;
+		break;
 	default:
 		CRYPTDEB("invalid cipher");
 		SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
@@ -586,6 +589,12 @@ cse_create(struct fcrypt *fcr, struct session2_op *sop)
 			return (EINVAL);
 		}
 		csp.csp_mode = CSP_MODE_AEAD;
+	} else if (sop->cipher == CRYPTO_CHACHA20_POLY1305) {
+		if (sop->mac != 0) {
+			SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
+			return (EINVAL);
+		}
+		csp.csp_mode = CSP_MODE_AEAD;
 	} else if (txform != NULL && thash != NULL)
 		csp.csp_mode = CSP_MODE_ETA;
 	else if (txform != NULL)
@@ -679,6 +688,8 @@ cse_create(struct fcrypt *fcr, struct session2_op *sop)
 		cse->hashsize = AES_GMAC_HASH_LEN;
 	else if (csp.csp_cipher_alg == CRYPTO_AES_CCM_16)
 		cse->hashsize = AES_CBC_MAC_HASH_LEN;
+	else if (csp.csp_cipher_alg == CRYPTO_CHACHA20_POLY1305)
+		cse->hashsize = POLY1305_HASH_LEN;
 	cse->ivsize = csp.csp_ivlen;
 
 	mtx_lock(&fcr->lock);
diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
index ecb1d929d1db..277867734841 100644
--- a/sys/opencrypto/cryptodev.h
+++ b/sys/opencrypto/cryptodev.h
@@ -124,6 +124,7 @@
 #define	AES_CCM_IV_LEN		12
 #define	AES_XTS_IV_LEN		8
 #define	AES_XTS_ALPHA		0x87	/* GF(2^128) generator polynomial */
+#define	CHACHA20_POLY1305_IV_LEN	12
 
 /* Min and Max Encryption Key Sizes */
 #define	NULL_MIN_KEY		0
@@ -136,6 +137,7 @@
 #define	AES_XTS_MAX_KEY		(2 * AES_MAX_KEY)
 #define	CAMELLIA_MIN_KEY	16
 #define	CAMELLIA_MAX_KEY	32
+#define	CHACHA20_POLY1305_KEY	32
 
 /* Maximum hash algorithm result length */
 #define	AALG_MAX_RESULT_LEN	64 /* Keep this updated */
@@ -184,7 +186,8 @@
 #define	CRYPTO_POLY1305		38
 #define	CRYPTO_AES_CCM_CBC_MAC	39	/* auth side */
 #define	CRYPTO_AES_CCM_16	40	/* cipher side */
-#define	CRYPTO_ALGORITHM_MAX	40	/* Keep updated - see below */
+#define	CRYPTO_CHACHA20_POLY1305 41	/* combined AEAD cipher per RFC 8439 */
+#define	CRYPTO_ALGORITHM_MAX	41	/* Keep updated - see below */
 
 #define	CRYPTO_ALGO_VALID(x)	((x) >= CRYPTO_ALGORITHM_MIN && \
 				 (x) <= CRYPTO_ALGORITHM_MAX)
diff --git a/sys/opencrypto/xform_chacha20_poly1305.c b/sys/opencrypto/xform_chacha20_poly1305.c
new file mode 100644
index 000000000000..e568e76cad51
--- /dev/null
+++ b/sys/opencrypto/xform_chacha20_poly1305.c
@@ -0,0 +1,41 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Netflix Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <crypto/chacha20/chacha.h>
+#include <opencrypto/xform_enc.h>
+
+struct enc_xform enc_xform_chacha20_poly1305 = {
+	.type = CRYPTO_CHACHA20_POLY1305,
+	.name = "ChaCha20-Poly1305",
+	.ctxsize = sizeof(struct chacha_ctx),
+	.blocksize = 1,
+	.native_blocksize = CHACHA_BLOCKLEN,
+	.ivsize = CHACHA20_POLY1305_IV_LEN,
+	.minkey = CHACHA20_POLY1305_KEY,
+	.maxkey = CHACHA20_POLY1305_KEY,
+};
+
diff --git a/sys/opencrypto/xform_enc.h b/sys/opencrypto/xform_enc.h
index b44f1ff0c270..e8325f20917b 100644
--- a/sys/opencrypto/xform_enc.h
+++ b/sys/opencrypto/xform_enc.h
@@ -81,6 +81,7 @@ extern struct enc_xform enc_xform_aes_nist_gmac;
 extern struct enc_xform enc_xform_aes_xts;
 extern struct enc_xform enc_xform_camellia;
 extern struct enc_xform enc_xform_chacha20;
+extern struct enc_xform enc_xform_chacha20_poly1305;
 extern struct enc_xform enc_xform_ccm;
 
 struct aes_icm_ctx {