Limit --reneg-bytes to 64MB when using small block ciphers

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>
This commit is contained in:
Steffan Karger 2016-10-28 13:57:01 +02:00 committed by David Sommerseth
parent f93b763980
commit 752caece99
4 changed files with 33 additions and 3 deletions

View 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

View 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);
}
}

View 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;

View 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)