Merge remote-tracking branch 'upstream-public/pr/1009' into mbedtls-2.1-proposed

This commit is contained in:
Gilles Peskine 2018-03-12 23:44:48 +01:00
commit 8da4f864a5
10 changed files with 429 additions and 59 deletions

View file

@ -37,6 +37,8 @@ Bugfix
Nick Wilson on issue #355
* In test_suite_pk, pass valid parameters when testing for hash length
overflow. #1179
* Fix memory allocation corner cases in memory_buffer_alloc.c module. Found
by Guido Vranken. #639
Changes
* Clarified the documentation of mbedtls_ssl_setup.

View file

@ -182,9 +182,9 @@ static int verify_header( memory_header *hdr )
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( prv == NULL || verify_header( prv ) != 0 )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: verification of first header "
@ -202,6 +202,8 @@ static int verify_chain()
return( 1 );
}
cur = heap.first->next;
while( cur != NULL )
{
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;
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 );
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 )
return;
if( p < heap.buf || p > heap.buf + heap.len )
if( p < heap.buf || p >= heap.buf + heap.len )
{
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
@ -570,8 +574,7 @@ static void buffer_alloc_free_mutexed( void *ptr )
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
{
memset( &heap, 0, sizeof(buffer_alloc_ctx) );
memset( buf, 0, len );
memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &heap.mutex );
@ -581,20 +584,24 @@ void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
#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 */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
- (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
- (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
memset( buf, 0, len );
heap.buf = buf;
heap.len = len;
heap.first = (memory_header *) buf;
heap.first->size = len - sizeof(memory_header);
heap.first = (memory_header *)buf;
heap.first->size = len - sizeof( memory_header );
heap.first->magic1 = MAGIC1;
heap.first->magic2 = MAGIC2;
heap.first_free = heap.first;

View file

@ -429,7 +429,7 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer,
unsigned char *buf, size_t buf_len, size_t *olen )
{
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;
mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
@ -441,7 +441,8 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer,
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 );
if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,

View file

@ -1213,6 +1213,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
{
unsigned char *key_copy;
if( keylen == 0 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );

View file

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

View file

@ -1,4 +1,49 @@
#!/usr/bin/env perl
# generate_code.pl
#
# Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
#
# Purpose
#
# Generates the test suite code given inputs of the test suite directory that
# contain the test suites, and the test suite file names for the test code and
# test data.
#
# Usage: generate_code.pl <suite dir> <code file> <data file> [main code file]
#
# Structure of files
#
# - main code file - 'main_test.function'
# Template file that contains the main() function for the test suite,
# test dispatch code as well as support functions. It contains the
# following symbols which are substituted by this script during
# processing:
# TEST_FILENAME
# SUITE_PRE_DEP
# MAPPING_CODE
# FUNCTION CODE
# SUITE_POST_DEP
# DEP_CHECK_CODE
# DISPATCH_FUNCTION
#
# - common helper code file - 'helpers.function'
# Common helper functions
#
# - test suite code file - file name in the form 'test_suite_xxx.function'
# Code file that contains the actual test cases. The file contains a
# series of code sequences delimited by the following:
# BEGIN_HEADER / END_HEADER - list of headers files
# BEGIN_SUITE_HELPERS / END_SUITE_HELPERS - helper functions common to
# the test suite
# BEGIN_CASE / END_CASE - the test cases in the test suite. Each test
# case contains at least one function that is used to create the
# dispatch code.
#
# - test data file - file name in the form 'test_suite_xxxx.data'
# The test case parameters to to be used in execution of the test. The
# file name is used to replace the symbol 'TEST_FILENAME' in the main
# code file above.
#
# A test data file consists of a sequence of paragraphs separated by
# a single empty line. Line breaks may be in Unix (LF) or Windows (CRLF)
@ -29,15 +74,16 @@ my $suite_name = shift or die "Missing suite name";
my $data_name = shift or die "Missing data name";
my $test_main_file = do { my $arg = shift; defined($arg) ? $arg : $suite_dir."/main_test.function" };
my $test_file = $data_name.".c";
my $test_helper_file = $suite_dir."/helpers.function";
my $test_common_helper_file = $suite_dir."/helpers.function";
my $test_case_file = $suite_dir."/".$suite_name.".function";
my $test_case_data = $suite_dir."/".$data_name.".data";
my $line_separator = $/;
undef $/;
open(TEST_HELPERS, "$test_helper_file") or die "Opening test helpers '$test_helper_file': $!";
my $test_helpers = <TEST_HELPERS>;
open(TEST_HELPERS, "$test_common_helper_file") or die "Opening test helpers
'$test_common_helper_file': $!";
my $test_common_helpers = <TEST_HELPERS>;
close(TEST_HELPERS);
open(TEST_MAIN, "$test_main_file") or die "Opening test main '$test_main_file': $!";
@ -54,6 +100,7 @@ close(TEST_DATA);
my ( $suite_header ) = $test_cases =~ /\/\* BEGIN_HEADER \*\/\n(.*?)\n\/\* END_HEADER \*\//s;
my ( $suite_defines ) = $test_cases =~ /\/\* BEGIN_DEPENDENCIES\n \* (.*?)\n \* END_DEPENDENCIES/s;
my ( $suite_helpers ) = $test_cases =~ /\/\* BEGIN_SUITE_HELPERS \*\/\n(.*?)\n\/\* END_SUITE_HELPERS \*\//s;
my $requirements;
if ($suite_defines =~ /^depends_on:/)
@ -81,16 +128,43 @@ $/ = $line_separator;
open(TEST_FILE, ">$test_file") or die "Opening destination file '$test_file': $!";
print TEST_FILE << "END";
/*
* *** THIS FILE HAS BEEN MACHINE GENERATED ***
*
* This file has been machine generated using the script: $0
*
* Test file : $test_file
*
* The following files were used to create this file.
*
* Main code file : $test_main_file
* Helper file : $test_common_helper_file
* Test suite file : $test_case_file
* Test suite data : $test_case_data
*
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include <mbedtls/config.h>
#else
#include MBEDTLS_CONFIG_FILE
#endif
$test_helpers
/*----------------------------------------------------------------------------*/
/* Common helper code */
$test_common_helpers
/*----------------------------------------------------------------------------*/
/* Test Suite Code */
$suite_pre_code
$suite_header
$suite_helpers
$suite_post_code
END

View file

@ -1,3 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Headers */
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@ -12,6 +15,10 @@
#define mbedtls_snprintf snprintf
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT32 uint32_t;
@ -25,6 +32,25 @@ typedef UINT32 uint32_t;
#include <stdlib.h>
#include <string.h>
/*----------------------------------------------------------------------------*/
/* Global variables */
static int test_errors = 0;
/*----------------------------------------------------------------------------*/
/* Macros */
#define TEST_ASSERT( TEST ) \
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST ); \
goto exit; \
} \
} while( 0 )
#define assert(a) if( !( a ) ) \
{ \
mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n", \
@ -66,11 +92,14 @@ typedef UINT32 uint32_t;
#define ENTROPY_HAVE_STRONG
#endif
/*----------------------------------------------------------------------------*/
/* Helper Functions */
static int unhexify( unsigned char *obuf, const char *ibuf )
{
unsigned char c, c2;
int len = strlen( ibuf ) / 2;
assert( strlen( ibuf ) % 2 == 0 ); // must be even number of bytes
assert( strlen( ibuf ) % 2 == 0 ); /* must be even number of bytes */
while( *ibuf != 0 )
{
@ -311,3 +340,12 @@ static int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len )
return( 0 );
}
static void test_fail( const char *test )
{
test_errors++;
if( test_errors == 1 )
mbedtls_printf( "FAILED\n" );
mbedtls_printf( " %s\n", test );
}

View file

@ -1,44 +1,6 @@
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_exit exit
#define mbedtls_free free
#define mbedtls_calloc calloc
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_snprintf snprintf
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
static int test_errors = 0;
SUITE_PRE_DEP
#define TEST_SUITE_ACTIVE
static void test_fail( const char *test )
{
test_errors++;
if( test_errors == 1 )
mbedtls_printf( "FAILED\n" );
mbedtls_printf( " %s\n", test );
}
#define TEST_ASSERT( TEST ) \
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST ); \
goto exit; \
} \
} while( 0 )
int verify_string( char **str )
{
if( (*str)[0] != '"' ||
@ -101,9 +63,17 @@ MAPPING_CODE
return( -1 );
}
/*----------------------------------------------------------------------------*/
/* Test Case code */
FUNCTION_CODE
SUITE_POST_DEP
/*----------------------------------------------------------------------------*/
/* Test dispatch code */
int dep_check( char *str )
{
if( str == NULL )
@ -133,6 +103,10 @@ DISPATCH_FUNCTION
return( ret );
}
/*----------------------------------------------------------------------------*/
/* Main Test code */
/** Retrieve one input line into buf, which must have room for len
* bytes. The trailing line break (if any) is stripped from the result.
* Lines beginning with the character '#' are skipped. Lines that are
@ -191,7 +165,7 @@ int parse_arguments( char *buf, size_t len, char *params[50] )
p++;
}
// Replace newlines, question marks and colons in strings
/* Replace newlines, question marks and colons in strings */
for( i = 0; i < cnt; i++ )
{
p = params[i];

View file

@ -1,2 +1,23 @@
Memory buffer alloc self test
mbedtls_memory_buffer_alloc_self_test:
Memory buffer alloc - free in middle, alloc at end
memory_buffer_alloc_free_alloc:100:100:100:0:0:1:0:0:200:0
Memory buffer alloc - free in middle, realloc
memory_buffer_alloc_free_alloc:100:100:100:0:0:1:0:0:100:0
Memory buffer alloc - free in middle, merge, realloc
memory_buffer_alloc_free_alloc:100:100:100:100:0:1:1:0:201:0
Memory buffer alloc - free at end, merge, realloc
memory_buffer_alloc_free_alloc:100:64:100:100:0:0:0:1:200:0
Memory buffer alloc - Out of Memory test
memory_buffer_alloc_oom_test:
Memory buffer small buffer
memory_buffer_small_buffer:
Memory buffer underalloc
memory_buffer_underalloc:

View file

@ -1,6 +1,7 @@
/* BEGIN_HEADER */
#include "mbedtls/memory_buffer_alloc.h"
#define TEST_SUITE_MEMORY_BUFFER_ALLOC
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@ -8,9 +9,254 @@
* END_DEPENDENCIES
*/
/* BEGIN_SUITE_HELPERS */
static int check_pointer( void *p )
{
if( p == NULL )
return( -1 );
if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
return( -1 );
return( 0 );
}
/* END_SUITE_HELPERS */
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mbedtls_memory_buffer_alloc_self_test( )
{
TEST_ASSERT( mbedtls_memory_buffer_alloc_self_test( 0 ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes,
int d_bytes,
int free_a, int free_b, int free_c,
int free_d,
int e_bytes, int f_bytes )
{
unsigned char buf[1024];
unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_d = NULL,
*ptr_e = NULL, *ptr_f = NULL;
size_t reported_blocks;
size_t allocated_bytes = 0, reported_bytes;
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
mbedtls_memory_buffer_set_verify( MBEDTLS_MEMORY_VERIFY_ALWAYS );
if( a_bytes > 0 )
{
ptr_a = mbedtls_calloc( a_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_a ) == 0 );
allocated_bytes += a_bytes * sizeof(char);
}
if( b_bytes > 0 )
{
ptr_b = mbedtls_calloc( b_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_b ) == 0 );
allocated_bytes += b_bytes * sizeof(char);
}
if( c_bytes > 0 )
{
ptr_c = mbedtls_calloc( c_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_c ) == 0 );
allocated_bytes += c_bytes * sizeof(char);
}
if( d_bytes > 0 )
{
ptr_d = mbedtls_calloc( d_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_d ) == 0 );
allocated_bytes += d_bytes * sizeof(char);
}
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == allocated_bytes );
if( free_a )
{
mbedtls_free( ptr_a );
ptr_a = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
allocated_bytes -= a_bytes * sizeof(char);
}
if( free_b )
{
mbedtls_free( ptr_b );
ptr_b = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
allocated_bytes -= b_bytes * sizeof(char);
}
if( free_c )
{
mbedtls_free( ptr_c );
ptr_c = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
allocated_bytes -= c_bytes * sizeof(char);
}
if( free_d )
{
mbedtls_free( ptr_d );
ptr_d = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
allocated_bytes -= d_bytes * sizeof(char);
}
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == allocated_bytes );
if( e_bytes > 0 )
{
ptr_e = mbedtls_calloc( e_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_e ) == 0 );
}
if( f_bytes > 0 )
{
ptr_f = mbedtls_calloc( f_bytes, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_f ) == 0 );
}
/* Once blocks are reallocated, the block allocated to the memory request
* may be bigger than the request itself, which is indicated by the reported
* bytes, and makes it hard to know what the reported size will be, so
* we don't check the size after blocks have been reallocated. */
if( ptr_a != NULL )
{
mbedtls_free( ptr_a );
ptr_a = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
if( ptr_b != NULL )
{
mbedtls_free( ptr_b );
ptr_b = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
if( ptr_c != NULL )
{
mbedtls_free( ptr_c );
ptr_c = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
if( ptr_d != NULL )
{
mbedtls_free( ptr_d );
ptr_d = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
if( ptr_e != NULL )
{
mbedtls_free( ptr_e );
ptr_e = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
if( ptr_f != NULL )
{
mbedtls_free( ptr_f );
ptr_f = NULL;
}
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == 0 );
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
exit:
mbedtls_memory_buffer_alloc_free( );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
void memory_buffer_alloc_oom_test()
{
unsigned char buf[1024];
unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL;
size_t reported_blocks, reported_bytes;
(void)ptr_c;
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
mbedtls_memory_buffer_set_verify( MBEDTLS_MEMORY_VERIFY_ALWAYS );
ptr_a = mbedtls_calloc( 432, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_a ) == 0 );
ptr_b = mbedtls_calloc( 432, sizeof(char) );
TEST_ASSERT( check_pointer( ptr_b ) == 0 );
ptr_c = mbedtls_calloc( 431, sizeof(char) );
TEST_ASSERT( ptr_c == NULL );
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes >= 864 && reported_bytes <= sizeof(buf) );
mbedtls_free( ptr_a );
ptr_a = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
mbedtls_free( ptr_b );
ptr_b = NULL;
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
TEST_ASSERT( reported_bytes == 0 );
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
exit:
mbedtls_memory_buffer_alloc_free( );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
void memory_buffer_small_buffer( )
{
unsigned char buf[1];
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() != 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
void memory_buffer_underalloc( )
{
unsigned char buf[100];
size_t i;
mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
for( i = 1; i < MBEDTLS_MEMORY_ALIGN_MULTIPLE; i++ )
{
TEST_ASSERT( mbedtls_calloc( 1,
(size_t)-( MBEDTLS_MEMORY_ALIGN_MULTIPLE - i ) ) == NULL );
TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
}
exit:
mbedtls_memory_buffer_alloc_free();
}
/* END_CASE */