From 28a31a0a10f41ef855cabab4e18c994c44225125 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 3 Feb 2017 14:06:20 +0000 Subject: Don't change the state of the ETM flags until CCS processing In 1.1.0 changing the ciphersuite during a renegotiation can result in a crash leading to a DoS attack. In master this does not occur with TLS (instead you get an internal error, which is still wrong but not a security issue) - but the problem still exists in the DTLS code. The problem is caused by changing the flag indicating whether to use ETM or not immediately on negotiation of ETM, rather than at CCS. Therefore, during a renegotiation, if the ETM state is changing (usually due to a change of ciphersuite), then an error/crash will occur. Due to the fact that there are separate CCS messages for read and write we actually now need two flags to determine whether to use ETM or not. CVE-2017-3733 Reviewed-by: Richard Levitte --- ssl/t1_enc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'ssl/t1_enc.c') diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index ebdc0fbd52..4158548568 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -129,6 +129,11 @@ int tls1_change_cipher_state(SSL *s, int which) #endif if (which & SSL3_CC_READ) { + if (s->ext.use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; else @@ -167,6 +172,11 @@ int tls1_change_cipher_state(SSL *s, int which) mac_secret = &(s->s3->read_mac_secret[0]); mac_secret_size = &(s->s3->read_mac_secret_size); } else { + if (s->ext.use_etm) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + else + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE; + if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; else @@ -369,9 +379,8 @@ int tls1_setup_key_block(SSL *s) if (s->s3->tmp.key_block_length != 0) return (1); - if (!ssl_cipher_get_evp - (s->session, &c, &hash, &mac_type, &mac_secret_size, &comp, - SSL_USE_ETM(s))) { + if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, &mac_secret_size, + &comp, s->ext.use_etm)) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return (0); } -- cgit v1.2.3