Hi,

On 07/10/18 15:34, Steffan Karger wrote:
> 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.
                                     ^^ it

> 
> 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.

I am so excited we are finally including ChaCha20-Poly1305 support! :)
Thanks!

> 
> Signed-off-by: Steffan Karger <stef...@karger.me>
> ---
>  Changes.rst                  | 10 ++++++++++
>  src/openvpn/crypto.c         |  2 +-
>  src/openvpn/crypto_backend.h |  5 +++++
>  src/openvpn/crypto_mbedtls.c | 21 ++++++++++++++++++---
>  src/openvpn/crypto_openssl.c | 33 ++++++++++++++++++++++++++++-----
>  src/openvpn/ssl.c            |  2 +-
>  6 files changed, 63 insertions(+), 10 deletions(-)
> 
> diff --git a/Changes.rst b/Changes.rst
> index a6090cf5..70ce2e10 100644
> --- a/Changes.rst
> +++ b/Changes.rst
> @@ -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
>  ==========================
>  
> diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
> index c8d95f3b..6d34acd7 100644
> --- a/src/openvpn/crypto.c
> +++ b/src/openvpn/crypto.c
> @@ -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 "
> diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h
> index f917c8d7..38b2c175 100644
> --- a/src/openvpn/crypto_backend.h
> +++ b/src/openvpn/crypto_backend.h
> @@ -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.
>   *
> diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c
> index 82f4e574..a5a096b1 100644
> --- a/src/openvpn/crypto_mbedtls.c
> +++ b/src/openvpn/crypto_mbedtls.c
> @@ -51,6 +51,7 @@
>  #include <mbedtls/cipher.h>
>  #include <mbedtls/havege.h>
>  #include <mbedtls/pem.h>
> +#include <mbedtls/version.h>
>  
>  #include <mbedtls/entropy.h>
>  
> @@ -175,7 +176,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 +189,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 +551,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

Since you are touching the line above (you moved it), please put spaces
around '/'.

> +#if defined(MBEDTLS_CHACHAPOLY_C) && (MBEDTLS_VERSION_NUMBER >= 0x020C0000)

Why do we need the dual condition? Isn't MBEDTLS_CHACHAPOLY_C enough to
know mbedTLS has what we need? Or you feel like we have to demand a
specific mbedTLS version when using ChaCha20?

> +             || cipher_kt->type == MBEDTLS_CIPHER_CHACHA20_POLY1305
> +#endif
> +             );
> +}
> +
>  int
>  cipher_kt_mode(const mbedtls_cipher_info_t *cipher_kt)
>  {
> @@ -573,7 +584,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
> +#if defined(MBEDTLS_CHACHAPOLY_C) && (MBEDTLS_VERSION_NUMBER >= 0x020C0000)

ditto

> +                      || cipher_kt_mode(cipher) == MBEDTLS_MODE_CHACHAPOLY
> +#endif
> +                      );
>  }
>  
>  
> diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
> index 9ec2048d..0004be9e 100644
> --- a/src/openvpn/crypto_openssl.c
> +++ b/src/openvpn/crypto_openssl.c
> @@ -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;
>  }
>  
>  /*
> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index 4257c33d..315303b0 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c
> @@ -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 */
>          {
> 

The code looks good and I like having a opaque function now doing the
"cipher security check" in one place only.

I was just wondering if you want to change the text "8 bit block" to
"stream cipher" in --show-ciphers, in order to make it more clear to the
casual reader. What do you think?

Regards,

-- 
Antonio Quartulli

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to