]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Limit --reneg-bytes to 64MB when using small block ciphers
authorSteffan Karger <steffan.karger@fox-it.com>
Fri, 28 Oct 2016 11:57:01 +0000 (13:57 +0200)
committerDavid Sommerseth <davids@openvpn.net>
Fri, 28 Oct 2016 12:40:15 +0000 (14:40 +0200)
Following the earlier warning about small block ciphers, now limit the
--reneg-bytes value when using a cipher that susceptible to SWEET32-like
attacks.  The 64 MB value has been selected with the researchers who
published the SWEET32 paper.

Note that this will not change a user-set --reneg-bytes value, to allow a
user to align a gun with his feet^w^w^w^w^w^w override this behaviour if
really needed.

v2: obey user-set --reneg-bytes 0 to revert to old behaviour, use more firm
    language in warning message, and add URL to man page.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: David Sommerseth <davids@openvpn.net>
Message-Id: <1477655821-6711-1-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg12798.html
Signed-off-by: David Sommerseth <davids@openvpn.net>
doc/openvpn.8
src/openvpn/crypto.c
src/openvpn/options.c
src/openvpn/ssl.c

index 2e58f33df0b00f585e30f5c1272ef8024b9af1ca..0ac81847932e1a900340010f62edbec77e2e61cc 100644 (file)
@@ -4101,6 +4101,7 @@ an abbreviation for Blowfish in Cipher Block Chaining mode.
 
 Using BF-CBC is no longer recommended, because of it's 64-bit block size.  This
 small block size allows attacks based on collisions, as demonstrated by SWEET32.
+See https://community.openvpn.net/openvpn/wiki/SWEET32 for details.
 
 To see other ciphers that are available with OpenVPN, use the
 .B \-\-show\-ciphers
index 026d9aeb2a0defef90f4d5991192b3e7b6011b5b..6e1e46bd1c128a2b80b52aa885d154bb281fce16 100644 (file)
@@ -819,8 +819,9 @@ init_key_ctx (struct key_ctx *ctx, struct key *key,
          cipher_kt_iv_size(kt->cipher));
       if (cipher_kt_block_size(kt->cipher) < 128/8)
        {
-         msg (M_WARN, "WARNING: this cipher's block size is less than 128 bit "
-             "(%d bit).  Consider using a --cipher with a larger block size.",
+         msg (M_WARN, "WARNING: INSECURE cipher with block size less than 128"
+             " bit (%d bit).  This allows attacks like SWEET32.  Mitigate by "
+             "using a --cipher with a larger block size (e.g. AES-256-CBC).",
              cipher_kt_block_size(kt->cipher)*8);
        }
     }
index 281ef0b5e59d387d4726095af9e8a27eaac8dc7b..996c26e44763df1865e70783ade77db070f7ba4f 100644 (file)
@@ -852,6 +852,7 @@ init_options (struct options *o, const bool init_gc)
 #endif
   o->key_method = 2;
   o->tls_timeout = 2;
+  o->renegotiate_bytes = -1;
   o->renegotiate_seconds = 3600;
   o->handshake_window = 60;
   o->transition_window = 3600;
index 6703fa2da88f0d80b26e2c4ffb75734ce33424e1..cbe925f2b0534bdbbb7f10b9e3342a8f35fb98c7 100644 (file)
@@ -283,6 +283,27 @@ tls_get_cipher_name_pair (const char * cipher_name, size_t len) {
   return NULL;
 }
 
+/**
+ * Limit the reneg_bytes value when using a small-block (<128 bytes) cipher.
+ *
+ * @param cipher       The current cipher (may be NULL).
+ * @param reneg_bytes  Pointer to the current reneg_bytes, updated if needed.
+ *                     May *not* be NULL.
+ */
+static void
+tls_limit_reneg_bytes (const cipher_kt_t *cipher, int *reneg_bytes)
+{
+  if (cipher && (cipher_kt_block_size(cipher) < 128/8))
+    {
+      if (*reneg_bytes == -1) /* Not user-specified */
+       {
+         msg (M_WARN, "WARNING: cipher with small block size in use, "
+              "reducing reneg-bytes to 64MB to mitigate SWEET32 attacks.");
+         *reneg_bytes = 64 * 1024 * 1024;
+       }
+    }
+}
+
 /*
  * Max number of bytes we will add
  * for data structures common to both
@@ -1704,6 +1725,8 @@ tls_session_update_crypto_params(struct tls_session *session,
       msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed");
       goto cleanup;
     }
+  tls_limit_reneg_bytes (session->opt->key_type.cipher,
+                        &session->opt->renegotiate_bytes);
   ret = true;
 cleanup:
   CLEAR (*ks->key_src);
@@ -2088,6 +2111,8 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
        }
                      
       CLEAR (*ks->key_src);
+      tls_limit_reneg_bytes (session->opt->key_type.cipher,
+                            &session->opt->renegotiate_bytes);
     }
 
   return true;
@@ -2316,6 +2341,8 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
        }
 
       CLEAR (*ks->key_src);
+      tls_limit_reneg_bytes (session->opt->key_type.cipher,
+                            &session->opt->renegotiate_bytes);
     }
 
   gc_free (&gc);
@@ -2372,7 +2399,7 @@ tls_process (struct tls_multi *multi,
   if (ks->state >= S_ACTIVE &&
       ((session->opt->renegotiate_seconds
        && now >= ks->established + session->opt->renegotiate_seconds)
-       || (session->opt->renegotiate_bytes
+       || (session->opt->renegotiate_bytes > 0
           && ks->n_bytes >= session->opt->renegotiate_bytes)
        || (session->opt->renegotiate_packets
           && ks->n_packets >= session->opt->renegotiate_packets)