From 956c9e063db14fa3f52f8fee2fb5e597c43742c4 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Thu, 19 Dec 2013 14:42:28 +0100 Subject: [PATCH] Reduced the input / output overhead with 200+ bytes and covered corner case The actual input / output buffer overhead is only 301 instead of 512. This requires a proper check on the padding_idx to prevent out of bounds reads. Previously a remote party could potentially trigger an access error and thus stop the application when sending a malicious packet having MAX_CONTENT_LEN of data, 32 bytes of MAC and a decrypted padlen of . This would result in reading from in_ctr + 13 + 32 + MAX_CONTENT_LEN - 1 - 1 for 256 bytes (including fake padding check). Or 13 + 32 bytes over the buffer length. We now reset padding_idx to 0, if it's clear that it will never be a valid padding (padlen > msg_len || msg_len + padlen + 256 > buffer_len) --- ChangeLog | 4 ++++ include/polarssl/ssl.h | 8 ++++---- library/ssl_tls.c | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7df5fa39a..3078c58e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,10 @@ Bugfix * Memory leak in benchmark application * Fixed x509_crt_parse_path() bug on Windows platforms +Security + * Possible remotely-triggered out-of-bounds memory access fixed (found by + TrustInSoft) + = PolarSSL 1.3.2 released on 2013-11-04 Features * PK tests added to test framework diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 4b0c5f8bb..7e668f93b 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -237,8 +237,8 @@ #endif /* !POLARSSL_CONFIG_OPTIONS */ /* - * Allow an extra 512 bytes for the record header - * and encryption overhead (counter + MAC + padding) + * Allow an extra 301 bytes for the record header + * and encryption overhead: counter (8) + header (5) + MAC (32) + padding (256) * and allow for a maximum of 1024 of compression expansion if * enabled. */ @@ -248,9 +248,9 @@ #define SSL_COMPRESSION_ADD 0 #endif -#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 512) +#define SSL_BUFFER_LEN (SSL_MAX_CONTENT_LEN + SSL_COMPRESSION_ADD + 301) -#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ /* * Supported Signature and Hash algorithms (For TLS 1.2) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 75ba9075a..6ea282180 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1610,6 +1610,21 @@ static int ssl_decrypt_buf( ssl_context *ssl ) size_t pad_count = 0, real_count = 1; size_t padding_idx = ssl->in_msglen - padlen - 1; + /* + * Padding is guaranteed to be incorrect if: + * 1. padlen - 1 > ssl->in_msglen + * + * 2. ssl->in_msglen + padlen > + * SSL_MAX_CONTENT_LEN + 256 (max padding) + * + * In both cases we reset padding_idx to a safe value (0) to + * prevent out-of-buffer reads. + */ + correct &= ( ssl->in_msglen >= padlen - 1 ); + correct &= ( ssl->in_msglen + padlen <= SSL_MAX_CONTENT_LEN + 256 ); + + padding_idx *= correct; + for( i = 1; i <= 256; i++ ) { real_count &= ( i <= padlen );