Fix corner case uses of memory_buffer_alloc.c

The corner cases fixed include:
    * Allocating a buffer of size 0. With this change, the allocator now
      returns a NULL pointer in this case. Note that changes in pem.c and
      x509_crl.c were required to fix tests that did not work under this
      assumption.
    * Initialising the allocator with less memory than required for headers.
    * Fix header chain checks for uninitialised allocator.
This commit is contained in:
Andres AG 2017-01-30 14:34:25 +00:00 committed by Andres Amaya Garcia
parent 6598af0bef
commit 8ad5acd6da
4 changed files with 24 additions and 15 deletions

View File

@ -62,6 +62,8 @@ Bugfix
* Fix issue in RSA key generation program programs/x509/rsa_genkey * Fix issue in RSA key generation program programs/x509/rsa_genkey
where the failure of CTR DRBG initialization lead to freeing an where the failure of CTR DRBG initialization lead to freeing an
RSA context without proper initialization beforehand. RSA context without proper initialization beforehand.
* Fix memory allocation corner cases in memory_buffer_alloc.c module. Found
by Guido Vranken. #639
Changes Changes
* Extend cert_write example program by options to set the CRT version * Extend cert_write example program by options to set the CRT version

View File

@ -182,9 +182,9 @@ static int verify_header( memory_header *hdr )
static int verify_chain() static int verify_chain()
{ {
memory_header *prv = heap.first, *cur = heap.first->next; memory_header *prv = heap.first, *cur;
if( verify_header( heap.first ) != 0 ) if( heap.first == NULL || verify_header( heap.first ) != 0 )
{ {
#if defined(MBEDTLS_MEMORY_DEBUG) #if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification of first header " mbedtls_fprintf( stderr, "FATAL: verification of first header "
@ -202,6 +202,8 @@ static int verify_chain()
return( 1 ); return( 1 );
} }
cur = heap.first->next;
while( cur != NULL ) while( cur != NULL )
{ {
if( verify_header( cur ) != 0 ) if( verify_header( cur ) != 0 )
@ -245,7 +247,9 @@ static void *buffer_alloc_calloc( size_t n, size_t size )
original_len = len = n * size; original_len = len = n * size;
if( n != 0 && len / n != size ) if( n == 0 || size == 0 || len / n != size )
return( NULL );
else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE )
return( NULL ); return( NULL );
if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
@ -386,7 +390,7 @@ static void buffer_alloc_free( void *ptr )
if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
return; return;
if( p < heap.buf || p > heap.buf + heap.len ) if( p < heap.buf || p >= heap.buf + heap.len )
{ {
#if defined(MBEDTLS_MEMORY_DEBUG) #if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
@ -571,7 +575,6 @@ static void buffer_alloc_free_mutexed( void *ptr )
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
{ {
memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
memset( buf, 0, len );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &heap.mutex ); mbedtls_mutex_init( &heap.mutex );
@ -581,7 +584,9 @@ void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
#endif #endif
if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE )
return;
else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{ {
/* Adjust len first since buf is used in the computation */ /* Adjust len first since buf is used in the computation */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
@ -590,6 +595,8 @@ void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
- (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
} }
memset( buf, 0, len );
heap.buf = buf; heap.buf = buf;
heap.len = len; heap.len = len;

View File

@ -423,7 +423,7 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer,
unsigned char *buf, size_t buf_len, size_t *olen ) unsigned char *buf, size_t buf_len, size_t *olen )
{ {
int ret; int ret;
unsigned char *encode_buf, *c, *p = buf; unsigned char *encode_buf = NULL, *c, *p = buf;
size_t len = 0, use_len, add_len = 0; size_t len = 0, use_len, add_len = 0;
mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
@ -435,7 +435,7 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer,
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
} }
if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) if( use_len != 0 && ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL )
return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,

View File

@ -257,7 +257,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
{ {
int ret; int ret;
size_t len; size_t len;
unsigned char *p, *end; unsigned char *p = NULL, *end;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
mbedtls_x509_crl *crl = chain; mbedtls_x509_crl *crl = chain;
@ -294,7 +294,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
/* /*
* Copy raw DER-encoded CRL * Copy raw DER-encoded CRL
*/ */
if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) if( buflen != 0 && ( p = mbedtls_calloc( 1, buflen ) ) == NULL )
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); return( MBEDTLS_ERR_X509_ALLOC_FAILED );
memcpy( p, buf, buflen ); memcpy( p, buf, buflen );