@@ -1,3 +1,13 @@
+Overview of changes in 2.5
+==========================
+
+New features
+------------
+ChaCha20-Poly1305 cipher support
+ Added support for using the ChaCha20-Poly1305 cipher in the OpenVPN data
+ channel.
+
+
Overview of changes in 2.4
==========================
@@ -841,7 +841,7 @@ init_key_ctx(struct key_ctx *ctx, const struct key *key,
dmsg(D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d",
prefix, cipher_kt_block_size(kt->cipher),
cipher_kt_iv_size(kt->cipher));
- if (cipher_kt_block_size(kt->cipher) < 128/8)
+ if (cipher_kt_insecure(kt->cipher))
{
msg(M_WARN, "WARNING: INSECURE cipher with block size less than 128"
" bit (%d bit). This allows attacks like SWEET32. Mitigate by "
@@ -284,6 +284,11 @@ int cipher_kt_block_size(const cipher_kt_t *cipher_kt);
*/
int cipher_kt_tag_size(const cipher_kt_t *cipher_kt);
+/**
+ * Returns true if we consider this cipher to be insecure.
+ */
+bool cipher_kt_insecure(const cipher_kt_t *cipher);
+
/**
* Returns the mode that the cipher runs in.
*
@@ -175,7 +175,7 @@ show_available_ciphers(void)
while (*ciphers != 0)
{
const cipher_kt_t *info = mbedtls_cipher_info_from_type(*ciphers);
- if (info && cipher_kt_block_size(info) >= 128/8)
+ if (info && !cipher_kt_insecure(info))
{
print_cipher(info);
}
@@ -188,7 +188,7 @@ show_available_ciphers(void)
while (*ciphers != 0)
{
const cipher_kt_t *info = mbedtls_cipher_info_from_type(*ciphers);
- if (info && cipher_kt_block_size(info) < 128/8)
+ if (info && cipher_kt_insecure(info))
{
print_cipher(info);
}
@@ -550,6 +550,16 @@ cipher_kt_tag_size(const mbedtls_cipher_info_t *cipher_kt)
return 0;
}
+bool
+cipher_kt_insecure(const mbedtls_cipher_info_t *cipher_kt)
+{
+ return !(cipher_kt_block_size(cipher_kt) >= 128 / 8
+#ifdef MBEDTLS_CHACHAPOLY_C
+ || cipher_kt->type == MBEDTLS_CIPHER_CHACHA20_POLY1305
+#endif
+ );
+}
+
int
cipher_kt_mode(const mbedtls_cipher_info_t *cipher_kt)
{
@@ -573,7 +583,11 @@ cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
bool
cipher_kt_mode_aead(const cipher_kt_t *cipher)
{
- return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_GCM;
+ return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_GCM
+#ifdef MBEDTLS_CHACHAPOLY_C
+ || cipher_kt_mode(cipher) == MBEDTLS_MODE_CHACHAPOLY
+#endif
+ );
}
@@ -245,6 +245,7 @@ const cipher_name_pair cipher_name_translation_table[] = {
{ "AES-128-GCM", "id-aes128-GCM" },
{ "AES-192-GCM", "id-aes192-GCM" },
{ "AES-256-GCM", "id-aes256-GCM" },
+ { "CHACHA20-POLY1305", "ChaCha20-Poly1305" },
};
const size_t cipher_name_translation_table_count =
sizeof(cipher_name_translation_table) / sizeof(*cipher_name_translation_table);
@@ -321,7 +322,7 @@ show_available_ciphers(void)
qsort(cipher_list, num_ciphers, sizeof(*cipher_list), cipher_name_cmp);
for (i = 0; i < num_ciphers; i++) {
- if (cipher_kt_block_size(cipher_list[i]) >= 128/8)
+ if (!cipher_kt_insecure(cipher_list[i]))
{
print_cipher(cipher_list[i]);
}
@@ -330,7 +331,7 @@ show_available_ciphers(void)
printf("\nThe following ciphers have a block size of less than 128 bits, \n"
"and are therefore deprecated. Do not use unless you have to.\n\n");
for (i = 0; i < num_ciphers; i++) {
- if (cipher_kt_block_size(cipher_list[i]) < 128/8)
+ if (cipher_kt_insecure(cipher_list[i]))
{
print_cipher(cipher_list[i]);
}
@@ -686,6 +687,16 @@ cipher_kt_tag_size(const EVP_CIPHER *cipher_kt)
}
}
+bool
+cipher_kt_insecure(const EVP_CIPHER *cipher)
+{
+ return !(cipher_kt_block_size(cipher) >= 128 / 8
+#ifdef NID_chacha20_poly1305
+ || EVP_CIPHER_nid(cipher) == NID_chacha20_poly1305
+#endif
+ );
+}
+
int
cipher_kt_mode(const EVP_CIPHER *cipher_kt)
{
@@ -720,10 +731,22 @@ bool
cipher_kt_mode_aead(const cipher_kt_t *cipher)
{
#ifdef HAVE_AEAD_CIPHER_MODES
- return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_GCM);
-#else
- return false;
+ if (cipher)
+ {
+ switch (EVP_CIPHER_nid(cipher))
+ {
+ case NID_aes_128_gcm:
+ case NID_aes_192_gcm:
+ case NID_aes_256_gcm:
+#ifdef NID_chacha20_poly1305
+ case NID_chacha20_poly1305:
#endif
+ return true;
+ }
+ }
+#endif
+
+ return false;
}
/*
@@ -294,7 +294,7 @@ tls_get_cipher_name_pair(const char *cipher_name, size_t len)
static void
tls_limit_reneg_bytes(const cipher_kt_t *cipher, int *reneg_bytes)
{
- if (cipher && (cipher_kt_block_size(cipher) < 128/8))
+ if (cipher && cipher_kt_insecure(cipher))
{
if (*reneg_bytes == -1) /* Not user-specified */
{
We explicitly only supported GCM as a valid AEAD mode, change that to also allow ChaCha20-Poly1305 as an AEAD cipher. That works nicely with our new (GCM) data channel format, because is has the same 96-bit IV. Note that we need some tricks to not treat the cipher as insecure, because we used to only look at the block size of a cipher to determine if find a cipher insecure. But ChaCha20-Poly1305 is a stream cipher, which essentially has a 'block size' of 1 byte and is reported as such. So, special-case this cipher to be in the list of secure ciphers. Signed-off-by: Steffan Karger <steffan@karger.me> --- v2: code style fixes, remove unneeded version check Changes.rst | 10 ++++++++++ src/openvpn/crypto.c | 2 +- src/openvpn/crypto_backend.h | 5 +++++ src/openvpn/crypto_mbedtls.c | 20 +++++++++++++++++--- src/openvpn/crypto_openssl.c | 33 ++++++++++++++++++++++++++++----- src/openvpn/ssl.c | 2 +- 6 files changed, 62 insertions(+), 10 deletions(-)