Merge multiple backported vulnerability fixes

This commit is contained in:
Simon Butcher 2015-10-05 16:44:59 +01:00
commit 36abef4c5c
8 changed files with 68 additions and 14 deletions

View file

@ -3,14 +3,37 @@ mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS 1.3.14 released 2015-10-xx = mbed TLS 1.3.14 released 2015-10-xx
Security Security
* Added fix for CVE-2015-xxxxx to prevent heap corruption due to buffer * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer
overflow of the hostname or session ticket. (Found by Guido Vranken) overflow of the hostname or session ticket. Found by Guido Vranken,
Intelworks.
* Fix stack buffer overflow in pkcs12 decryption (used by
mbedtls_pk_parse_key(file)() when the password is > 129 bytes. Found by
Guido Vranken, Intelworks. Not triggerable remotely.
* Fix potential buffer overflow in mbedtls_mpi_read_string().
Found by Guido Vranken, Intelworks. Not exploitable remotely in the context
of TLS, but might be in other uses. On 32 bit machines, requires reading a
string of close to or larger than 1GB to exploit; on 64 bit machines, would
require reading a string of close to or larger than 2^62 bytes.
* Fix potential random memory allocation in mbedtls_pem_read_buffer()
on crafted PEM input data. Found and fix provided by Guido Vranken,
Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you
accept PEM data from an untrusted source.
* Fix potential double-free if ssl_set_psk() is called repeatedly on
the same ssl_context object and some memory allocations fail. Found by
Guido Vranken, Intelworks. Can not be forced remotely.
* Fix possible heap buffer overflow in base64_encode() when the input
buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken,
Intelworks. Found by Guido Vranken. Not trigerrable remotely in TLS.
* Fix potential heap buffer overflow in servers that perform client
authentication against a crafted CA cert. Cannot be triggered remotely
unless you allow third parties to pick trust CAs for client auth. Found by
Guido Vranken, Intelworks.
Changes Changes
* Added checking of hostname length in ssl_set_hostname() to ensure domain * Added checking of hostname length in ssl_set_hostname() to ensure domain
names are compliant with RFC 1035. names are compliant with RFC 1035.
= mbed TLS 1.3.13 reladsed 2015-09-17 = mbed TLS 1.3.13 released 2015-09-17
Security Security
* Fix possible client-side NULL pointer dereference (read) when the client * Fix possible client-side NULL pointer dereference (read) when the client

View file

@ -44,6 +44,8 @@ extern "C" {
* \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
* *dlen is always updated to reflect the amount * *dlen is always updated to reflect the amount
* of data that has (or would have) been written. * of data that has (or would have) been written.
* If that length cannot be represented, then no data is
* written to the buffer and *dlen is set to SIZE_T_MAX.
* *
* \note Call this function with *dlen = 0 to obtain the * \note Call this function with *dlen = 0 to obtain the
* required buffer size in *dlen * required buffer size in *dlen

View file

@ -75,6 +75,8 @@ static const unsigned char base64_dec_map[128] =
49, 50, 51, 127, 127, 127, 127, 127 49, 50, 51, 127, 127, 127, 127, 127
}; };
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
/* /*
* Encode a buffer into base64 format * Encode a buffer into base64 format
*/ */
@ -91,15 +93,16 @@ int base64_encode( unsigned char *dst, size_t *dlen,
return( 0 ); return( 0 );
} }
n = ( slen << 3 ) / 6; n = slen / 3 + ( slen % 3 != 0 );
switch( ( slen << 3 ) - ( n * 6 ) ) if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
{ {
case 2: n += 3; break; *dlen = BASE64_SIZE_T_MAX;
case 4: n += 2; break; return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
default: break;
} }
n *= 4;
if( *dlen < n + 1 ) if( *dlen < n + 1 )
{ {
*dlen = n + 1; *dlen = n + 1;
@ -190,7 +193,10 @@ int base64_decode( unsigned char *dst, size_t *dlen,
} }
if( n == 0 ) if( n == 0 )
{
*dlen = 0;
return( 0 ); return( 0 );
}
n = ( ( n * 6 ) + 7 ) >> 3; n = ( ( n * 6 ) + 7 ) >> 3;
n -= j; n -= j;

View file

@ -59,11 +59,14 @@ static void polarssl_zeroize( void *v, size_t n ) {
#define biL (ciL << 3) /* bits in limb */ #define biL (ciL << 3) /* bits in limb */
#define biH (ciL << 2) /* half limb size */ #define biH (ciL << 2) /* half limb size */
#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
/* /*
* Convert between bits/chars and number of limbs * Convert between bits/chars and number of limbs
* Divide first in order to avoid potential overflows
*/ */
#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
/* /*
* Initialize one MPI * Initialize one MPI
@ -414,6 +417,9 @@ int mpi_read_string( mpi *X, int radix, const char *s )
if( radix == 16 ) if( radix == 16 )
{ {
if( slen > MPI_SIZE_T_MAX >> 2 )
return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
n = BITS_TO_LIMBS( slen << 2 ); n = BITS_TO_LIMBS( slen << 2 );
MPI_CHK( mpi_grow( X, n ) ); MPI_CHK( mpi_grow( X, n ) );

View file

@ -317,6 +317,9 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
( POLARSSL_AES_C || POLARSSL_DES_C ) */ ( POLARSSL_AES_C || POLARSSL_DES_C ) */
} }
if( s1 == s2 )
return( POLARSSL_ERR_PEM_INVALID_DATA );
len = 0; len = 0;
ret = base64_decode( NULL, &len, s1, s2 - s1 ); ret = base64_decode( NULL, &len, s1, s2 - s1 );

View file

@ -87,6 +87,8 @@ static int pkcs12_parse_pbe_params( asn1_buf *params,
return( 0 ); return( 0 );
} }
#define PKCS12_MAX_PWDLEN 128
static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type, static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
const unsigned char *pwd, size_t pwdlen, const unsigned char *pwd, size_t pwdlen,
unsigned char *key, size_t keylen, unsigned char *key, size_t keylen,
@ -95,7 +97,10 @@ static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
int ret, iterations; int ret, iterations;
asn1_buf salt; asn1_buf salt;
size_t i; size_t i;
unsigned char unipwd[258]; unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
if( pwdlen > PKCS12_MAX_PWDLEN )
return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
memset( &salt, 0, sizeof(asn1_buf) ); memset( &salt, 0, sizeof(asn1_buf) );
memset( &unipwd, 0, sizeof(unipwd) ); memset( &unipwd, 0, sizeof(unipwd) );
@ -126,6 +131,8 @@ static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
return( 0 ); return( 0 );
} }
#undef PKCS12_MAX_PWDLEN
int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode, int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen, const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t len, const unsigned char *data, size_t len,

View file

@ -2300,6 +2300,7 @@ static int ssl_write_certificate_request( ssl_context *ssl )
size_t ct_len, sa_len; /* including length bytes */ size_t ct_len, sa_len; /* including length bytes */
unsigned char *buf, *p; unsigned char *buf, *p;
const x509_crt *crt; const x509_crt *crt;
const unsigned char * const end = ssl->out_msg + SSL_MAX_CONTENT_LEN;
SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
@ -2406,10 +2407,14 @@ static int ssl_write_certificate_request( ssl_context *ssl )
total_dn_size = 0; total_dn_size = 0;
while( crt != NULL && crt->version != 0 ) while( crt != NULL && crt->version != 0 )
{ {
if( p - buf > 4096 )
break;
dn_size = crt->subject_raw.len; dn_size = crt->subject_raw.len;
if( end < p || (size_t)( end - p ) < 2 + dn_size )
{
SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
break;
}
*p++ = (unsigned char)( dn_size >> 8 ); *p++ = (unsigned char)( dn_size >> 8 );
*p++ = (unsigned char)( dn_size ); *p++ = (unsigned char)( dn_size );
memcpy( p, crt->subject_raw.p, dn_size ); memcpy( p, crt->subject_raw.p, dn_size );

View file

@ -4064,7 +4064,9 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
( ssl->psk_identity = polarssl_malloc( psk_identity_len ) ) == NULL ) ( ssl->psk_identity = polarssl_malloc( psk_identity_len ) ) == NULL )
{ {
polarssl_free( ssl->psk ); polarssl_free( ssl->psk );
polarssl_free( ssl->psk_identity );
ssl->psk = NULL; ssl->psk = NULL;
ssl->psk_identity = NULL;
return( POLARSSL_ERR_SSL_MALLOC_FAILED ); return( POLARSSL_ERR_SSL_MALLOC_FAILED );
} }