git: b7f27a60ac72 - stable/13 - Add Chacha20-Poly1305 as a KTLS cipher suite.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 23 Nov 2021 23:12:46 UTC
The branch stable/13 has been updated by jhb:

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

commit b7f27a60ac72c4d0f7740a6d48356c3fc68360d5
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-02-18 17:23:59 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-11-23 23:11:44 +0000

    Add Chacha20-Poly1305 as a KTLS cipher suite.
    
    Chacha20-Poly1305 for TLS is an AEAD cipher suite for both TLS 1.2 and
    TLS 1.3 (RFCs 7905 and 8446).  For both versions, Chacha20 uses the
    server and client IVs as implicit nonces xored with the record
    sequence number to generate the per-record nonce matching the
    construction used with AES-GCM for TLS 1.3.
    
    Reviewed by:    gallatin
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D27839
    
    (cherry picked from commit 9c64fc40290e08f6dc6b75aa04084b04e48a61af)
---
 sys/kern/uipc_ktls.c | 76 ++++++++++++++++++++++++++++++++++++++++++----------
 sys/sys/ktls.h       |  1 +
 2 files changed, 63 insertions(+), 14 deletions(-)

diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
index 17c199230d0a..567d3d04a6f0 100644
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -199,6 +199,11 @@ static COUNTER_U64_DEFINE_EARLY(ktls_sw_gcm);
 SYSCTL_COUNTER_U64(_kern_ipc_tls_sw, OID_AUTO, gcm, CTLFLAG_RD, &ktls_sw_gcm,
     "Active number of software TLS sessions using AES-GCM");
 
+static COUNTER_U64_DEFINE_EARLY(ktls_sw_chacha20);
+SYSCTL_COUNTER_U64(_kern_ipc_tls_sw, OID_AUTO, chacha20, CTLFLAG_RD,
+    &ktls_sw_chacha20,
+    "Active number of software TLS sessions using Chacha20-Poly1305");
+
 static COUNTER_U64_DEFINE_EARLY(ktls_ifnet_cbc);
 SYSCTL_COUNTER_U64(_kern_ipc_tls_ifnet, OID_AUTO, cbc, CTLFLAG_RD,
     &ktls_ifnet_cbc,
@@ -209,6 +214,11 @@ SYSCTL_COUNTER_U64(_kern_ipc_tls_ifnet, OID_AUTO, gcm, CTLFLAG_RD,
     &ktls_ifnet_gcm,
     "Active number of ifnet TLS sessions using AES-GCM");
 
+static COUNTER_U64_DEFINE_EARLY(ktls_ifnet_chacha20);
+SYSCTL_COUNTER_U64(_kern_ipc_tls_ifnet, OID_AUTO, chacha20, CTLFLAG_RD,
+    &ktls_ifnet_chacha20,
+    "Active number of ifnet TLS sessions using Chacha20-Poly1305");
+
 static COUNTER_U64_DEFINE_EARLY(ktls_ifnet_reset);
 SYSCTL_COUNTER_U64(_kern_ipc_tls_ifnet, OID_AUTO, reset, CTLFLAG_RD,
     &ktls_ifnet_reset, "TLS sessions updated to a new ifnet send tag");
@@ -238,6 +248,11 @@ static COUNTER_U64_DEFINE_EARLY(ktls_toe_gcm);
 SYSCTL_COUNTER_U64(_kern_ipc_tls_toe, OID_AUTO, gcm, CTLFLAG_RD,
     &ktls_toe_gcm,
     "Active number of TOE TLS sessions using AES-GCM");
+
+static counter_u64_t ktls_toe_chacha20;
+SYSCTL_COUNTER_U64(_kern_ipc_tls_toe, OID_AUTO, chacha20, CTLFLAG_RD,
+    &ktls_toe_chacha20,
+    "Active number of TOE TLS sessions using Chacha20-Poly1305");
 #endif
 
 static MALLOC_DEFINE(M_KTLS, "ktls", "Kernel TLS");
@@ -508,6 +523,15 @@ ktls_create_session(struct socket *so, struct tls_enable *en,
 		if (en->auth_key_len == 0)
 			return (EINVAL);
 		break;
+	case CRYPTO_CHACHA20_POLY1305:
+		if (en->auth_algorithm != 0 || en->auth_key_len != 0)
+			return (EINVAL);
+		if (en->tls_vminor != TLS_MINOR_VER_TWO &&
+		    en->tls_vminor != TLS_MINOR_VER_THREE)
+			return (EINVAL);
+		if (en->iv_len != TLS_CHACHA20_IV_LEN)
+			return (EINVAL);
+		break;
 	default:
 		return (EINVAL);
 	}
@@ -539,15 +563,6 @@ ktls_create_session(struct socket *so, struct tls_enable *en,
 		if (en->tls_vminor < TLS_MINOR_VER_THREE)
 			tls->params.tls_hlen += sizeof(uint64_t);
 		tls->params.tls_tlen = AES_GMAC_HASH_LEN;
-
-		/*
-		 * TLS 1.3 includes optional padding which we
-		 * do not support, and also puts the "real" record
-		 * type at the end of the encrypted data.
-		 */
-		if (en->tls_vminor == TLS_MINOR_VER_THREE)
-			tls->params.tls_tlen += sizeof(uint8_t);
-
 		tls->params.tls_bs = 1;
 		break;
 	case CRYPTO_AES_CBC:
@@ -576,10 +591,25 @@ ktls_create_session(struct socket *so, struct tls_enable *en,
 		}
 		tls->params.tls_bs = AES_BLOCK_LEN;
 		break;
+	case CRYPTO_CHACHA20_POLY1305:
+		/*
+		 * Chacha20 uses a 12 byte implicit IV.
+		 */
+		tls->params.tls_tlen = POLY1305_HASH_LEN;
+		tls->params.tls_bs = 1;
+		break;
 	default:
 		panic("invalid cipher");
 	}
 
+	/*
+	 * TLS 1.3 includes optional padding which we do not support,
+	 * and also puts the "real" record type at the end of the
+	 * encrypted data.
+	 */
+	if (en->tls_vminor == TLS_MINOR_VER_THREE)
+		tls->params.tls_tlen += sizeof(uint8_t);
+
 	KASSERT(tls->params.tls_hlen <= MBUF_PEXT_HDR_LEN,
 	    ("TLS header length too long: %d", tls->params.tls_hlen));
 	KASSERT(tls->params.tls_tlen <= MBUF_PEXT_TRAIL_LEN,
@@ -603,9 +633,9 @@ ktls_create_session(struct socket *so, struct tls_enable *en,
 		goto out;
 
 	/*
-	 * This holds the implicit portion of the nonce for GCM and
-	 * the initial implicit IV for TLS 1.0.  The explicit portions
-	 * of the IV are generated in ktls_frame().
+	 * This holds the implicit portion of the nonce for AEAD
+	 * ciphers and the initial implicit IV for TLS 1.0.  The
+	 * explicit portions of the IV are generated in ktls_frame().
 	 */
 	if (en->iv_len != 0) {
 		tls->params.iv_len = en->iv_len;
@@ -614,8 +644,8 @@ ktls_create_session(struct socket *so, struct tls_enable *en,
 			goto out;
 
 		/*
-		 * For TLS 1.2, generate an 8-byte nonce as a counter
-		 * to generate unique explicit IVs.
+		 * For TLS 1.2 with GCM, generate an 8-byte nonce as a
+		 * counter to generate unique explicit IVs.
 		 *
 		 * Store this counter in the last 8 bytes of the IV
 		 * array so that it is 8-byte aligned.
@@ -681,6 +711,9 @@ ktls_cleanup(struct ktls_session *tls)
 		case CRYPTO_AES_NIST_GCM_16:
 			counter_u64_add(ktls_sw_gcm, -1);
 			break;
+		case CRYPTO_CHACHA20_POLY1305:
+			counter_u64_add(ktls_sw_chacha20, -1);
+			break;
 		}
 		tls->free(tls);
 		break;
@@ -692,6 +725,9 @@ ktls_cleanup(struct ktls_session *tls)
 		case CRYPTO_AES_NIST_GCM_16:
 			counter_u64_add(ktls_ifnet_gcm, -1);
 			break;
+		case CRYPTO_CHACHA20_POLY1305:
+			counter_u64_add(ktls_ifnet_chacha20, -1);
+			break;
 		}
 		if (tls->snd_tag != NULL)
 			m_snd_tag_rele(tls->snd_tag);
@@ -705,6 +741,9 @@ ktls_cleanup(struct ktls_session *tls)
 		case CRYPTO_AES_NIST_GCM_16:
 			counter_u64_add(ktls_toe_gcm, -1);
 			break;
+		case CRYPTO_CHACHA20_POLY1305:
+			counter_u64_add(ktls_toe_chacha20, -1);
+			break;
 		}
 		break;
 #endif
@@ -763,6 +802,9 @@ ktls_try_toe(struct socket *so, struct ktls_session *tls, int direction)
 		case CRYPTO_AES_NIST_GCM_16:
 			counter_u64_add(ktls_toe_gcm, 1);
 			break;
+		case CRYPTO_CHACHA20_POLY1305:
+			counter_u64_add(ktls_toe_chacha20, 1);
+			break;
 		}
 	}
 	return (error);
@@ -885,6 +927,9 @@ ktls_try_ifnet(struct socket *so, struct ktls_session *tls, bool force)
 		case CRYPTO_AES_NIST_GCM_16:
 			counter_u64_add(ktls_ifnet_gcm, 1);
 			break;
+		case CRYPTO_CHACHA20_POLY1305:
+			counter_u64_add(ktls_ifnet_chacha20, 1);
+			break;
 		}
 	}
 	return (error);
@@ -928,6 +973,9 @@ ktls_try_sw(struct socket *so, struct ktls_session *tls, int direction)
 	case CRYPTO_AES_NIST_GCM_16:
 		counter_u64_add(ktls_sw_gcm, 1);
 		break;
+	case CRYPTO_CHACHA20_POLY1305:
+		counter_u64_add(ktls_sw_chacha20, 1);
+		break;
 	}
 	return (0);
 }
diff --git a/sys/sys/ktls.h b/sys/sys/ktls.h
index 2f15cce3fc55..3cde75f9edf6 100644
--- a/sys/sys/ktls.h
+++ b/sys/sys/ktls.h
@@ -46,6 +46,7 @@ struct tls_record_layer {
 #define	TLS_MAX_PARAM_SIZE	1024	/* Max key/mac/iv in sockopt */
 #define	TLS_AEAD_GCM_LEN	4
 #define	TLS_1_3_GCM_IV_LEN	12
+#define	TLS_CHACHA20_IV_LEN	12
 #define	TLS_CBC_IMPLICIT_IV_LEN	16
 
 /* Type values for the record layer */