From 5bad6afd8c72b2c3a6574dff01ca5f8f2f04800a Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Tue, 8 Jul 2014 17:51:29 +0200
Subject: [PATCH] Fix length checking for AEAD ciphersuites
---
ChangeLog | 3 +++
library/ssl_tls.c | 18 +++++++++++++-----
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 83613b906..a174aebc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,9 @@ Security
* Forbid sequence number wrapping
* Prevent potential NULL pointer dereference in ssl_read_record() (found by
TrustInSoft)
+ * Fix length checking for AEAD ciphersuites (found by Codenomicon).
+ It was possible to crash the server (and client) using crafted messages
+ when a GCM suite was chosen.
Bugfix
* Fixed X.509 hostname comparison (with non-regular characters)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 4add6a280..bad3188b9 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1254,6 +1254,9 @@ static int ssl_decrypt_buf( ssl_context *ssl )
size_t dec_msglen;
unsigned char add_data[13];
int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
+ unsigned char taglen = 16;
+ unsigned char explicit_iv_len = ssl->transform_in->ivlen -
+ ssl->transform_in->fixed_ivlen;
#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C)
if( ssl->session_in->ciphersuite == TLS_RSA_WITH_AES_128_GCM_SHA256 ||
@@ -1261,11 +1264,16 @@ static int ssl_decrypt_buf( ssl_context *ssl )
ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ||
ssl->session_in->ciphersuite == TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 )
{
- dec_msglen = ssl->in_msglen - ( ssl->transform_in->ivlen -
- ssl->transform_in->fixed_ivlen );
- dec_msglen -= 16;
- dec_msg = ssl->in_msg + ( ssl->transform_in->ivlen -
- ssl->transform_in->fixed_ivlen );
+ if( ssl->in_msglen < explicit_iv_len + taglen )
+ {
+ SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
+ "+ taglen (%d)", ssl->in_msglen,
+ explicit_iv_len, taglen ) );
+ return( POLARSSL_ERR_SSL_INVALID_MAC );
+ }
+ dec_msglen = ssl->in_msglen - explicit_iv_len - taglen;
+
+ dec_msg = ssl->in_msg + explicit_iv_len;
dec_msg_result = ssl->in_msg;
ssl->in_msglen = dec_msglen;