Merge of multiple security fixes

This commit is contained in:
Simon Butcher 2015-10-05 17:18:59 +01:00
commit c047c74b95
7 changed files with 59 additions and 11 deletions

View file

@ -6,6 +6,25 @@ Security
* Fix possible heap buffer overflow in SSL if a very long hostname is used. * Fix possible heap buffer overflow in SSL if a very long hostname is used.
Can be trigerred remotely if you accept hostnames from untrusted parties. Can be trigerred remotely if you accept hostnames from untrusted parties.
Found by Guido Vranken. Found by Guido Vranken.
* Fix stack buffer overflow in pkcs12 decryption (used by
mbedtls_pk_parse_key(file)() when the password is > 129 bytes.
Found by Guido Vranken. Not triggerable remotely.
* Fix potential buffer overflow in mbedtls_mpi_read_string().
Found by Guido Vranken. 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.
Not triggerable remotely in TLS. Triggerable remotely if you accept PEM
data from an untrusted source.
* Fix possible heap buffer overflow in base64_encode() when the input
buffer is 512MB or larger on 32-bit platforms.
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.
Changes Changes
* ssl_set_hostname() now rejects host names longer that 255 bytes (maximum * ssl_set_hostname() now rejects host names longer that 255 bytes (maximum

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

@ -61,6 +61,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
*/ */
@ -77,15 +79,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;
@ -176,7 +179,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

@ -45,11 +45,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
@ -287,6 +290,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

@ -287,6 +287,9 @@ int pem_read_buffer( pem_context *ctx, char *header, char *footer, const unsigne
#endif /* POLARSSL_MD5_C && (POLARSSL_AES_C || POLARSSL_DES_C) */ #endif /* POLARSSL_MD5_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

@ -80,6 +80,8 @@ static int pkcs12_parse_pbe_params( unsigned char **p,
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,
@ -89,7 +91,10 @@ static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
asn1_buf salt; asn1_buf salt;
size_t i; size_t i;
unsigned char *p, *end; unsigned char *p, *end;
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));
@ -122,6 +127,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

@ -923,6 +923,7 @@ static int ssl_write_certificate_request( ssl_context *ssl )
size_t n = 0, dn_size, total_dn_size; size_t n = 0, dn_size, total_dn_size;
unsigned char *buf, *p; unsigned char *buf, *p;
const x509_cert *crt; const x509_cert *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" ) );
@ -987,10 +988,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 );