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
This commit is contained in:
John Baldwin 2021-02-18 09:23:59 -08:00
parent 1bd9fc96d4
commit 9c64fc4029
2 changed files with 63 additions and 14 deletions

View File

@ -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");
@ -507,6 +522,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);
}
@ -538,15 +562,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:
@ -575,10 +590,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,
@ -602,9 +632,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;
@ -613,8 +643,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.
@ -679,6 +709,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;
@ -690,6 +723,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);
@ -703,6 +739,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
@ -761,6 +800,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);
@ -883,6 +925,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);
@ -926,6 +971,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);
}

View File

@ -44,6 +44,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 */