From b9f8974c6cc89b2273e2334e274d651d2339148a Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 25 Apr 2023 04:48:15 -0400 Subject: [PATCH 01/15] Document mbedtls_calloc zeroization Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 2 +- include/mbedtls/platform.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index e15104216..bb2d66deb 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3680,7 +3680,7 @@ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined. Please note that it should zeroize the buffer after allocation. */ //#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h index 768c756b9..490cedb4a 100644 --- a/include/mbedtls/platform.h +++ b/include/mbedtls/platform.h @@ -135,6 +135,7 @@ extern "C" { /* * The function pointers for calloc and free. + * mbedtls_calloc will allocate and zeroize the buffer. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ From c08ccd00f3592477fe50945b7958d4b4956039c9 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 25 Apr 2023 05:19:42 -0400 Subject: [PATCH 02/15] Add a test for calloc zeroization Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 2 +- tests/suites/test_suite_platform.data | 3 +++ tests/suites/test_suite_platform.function | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index bb2d66deb..7e87946a9 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3680,7 +3680,7 @@ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined. Please note that it should zeroize the buffer after allocation. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined. Please note that it should zeroize the allocated buffer. */ //#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ diff --git a/tests/suites/test_suite_platform.data b/tests/suites/test_suite_platform.data index 4276b8fb7..64992820c 100644 --- a/tests/suites/test_suite_platform.data +++ b/tests/suites/test_suite_platform.data @@ -4,3 +4,6 @@ time_get_milliseconds: Time: get seconds time_get_seconds: + +Check mbedtls_calloc zeroization +check_mbedtls_calloc_zeroization: \ No newline at end of file diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function index 61681b878..82c656d2d 100644 --- a/tests/suites/test_suite_platform.function +++ b/tests/suites/test_suite_platform.function @@ -120,3 +120,17 @@ void time_delay_seconds(int delay_secs) goto exit; } /* END_CASE */ + +/* BEGIN_CASE */ +void check_mbedtls_calloc_zeroization() +{ + unsigned int buf_size = 256; + unsigned char *buf; + buf = mbedtls_calloc(buf_size, sizeof(unsigned char)); + for (unsigned int i = 0; i < buf_size; i++) { + TEST_EQUAL(buf[i], 0); + } +exit: + mbedtls_free(buf); +} +/* END_CASE */ \ No newline at end of file From 2d981f092e5b27db9a2379101973816c526fa2b9 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Thu, 27 Apr 2023 09:19:35 -0400 Subject: [PATCH 03/15] Extend mbedtls_calloc and mbedtls_free documentation Co-authored-by: Gilles Peskine Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 23 +++++++++++++++++++---- include/mbedtls/platform.h | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 7e87946a9..a08f9d865 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3680,8 +3680,23 @@ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined. Please note that it should zeroize the allocated buffer. */ -//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +/** \def MBEDTLS_PLATFORM_STD_CALLOC + * + * Default allocator to use, can be undefined. + * It should initialize the allocated buffer memory to zeroes. + * The size of the buffer is the product of the two parameters. + * The behavior is undefined if the product of the two parameters overflows size_t. + * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function. + * The corresponding deallocation function is MBEDTLS_PLATFORM_STD_FREE. + */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc +/** \def MBEDTLS_PLATFORM_STD_FREE + * + * Default free to use, can be undefined. + * NULL is a valid parameter, and the function must do nothing. + * A non-null parameter will always be a pointer previously returned by MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. + */ +//#define MBEDTLS_PLATFORM_STD_FREE free //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ @@ -3697,8 +3712,8 @@ /* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ /* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ -//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */ //#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_SETBUF_MACRO setbuf /**< Default setbuf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h index 490cedb4a..fb7bc1b6a 100644 --- a/include/mbedtls/platform.h +++ b/include/mbedtls/platform.h @@ -135,7 +135,8 @@ extern "C" { /* * The function pointers for calloc and free. - * mbedtls_calloc will allocate and zeroize the buffer. + * please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE + * in mbedtls_config.h for more information about behaviour and requirements. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ From 9032711dc7dad879348fb2850cdbda0e81fe13f2 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Thu, 27 Apr 2023 09:30:18 -0400 Subject: [PATCH 04/15] Move the calloc buffer initialization test to selftest.c This way it's more in line with the 2.28 version. Signed-off-by: Andrzej Kurek --- programs/test/selftest.c | 45 +++++++++++++++++++++-- tests/suites/test_suite_platform.data | 3 -- tests/suites/test_suite_platform.function | 14 ------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index f896d4f9d..d3127553d 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -73,23 +73,49 @@ static int calloc_self_test(int verbose) void *empty2 = mbedtls_calloc(0, 1); void *buffer1 = mbedtls_calloc(1, 1); void *buffer2 = mbedtls_calloc(1, 1); + unsigned int buf_size = 256; + unsigned char *buffer3 = mbedtls_calloc(buf_size, sizeof(unsigned char)); if (empty1 == NULL && empty2 == NULL) { if (verbose) { - mbedtls_printf(" CALLOC(0): passed (NULL)\n"); + mbedtls_printf(" CALLOC(0,1): passed (NULL)\n"); } } else if (empty1 == NULL || empty2 == NULL) { if (verbose) { - mbedtls_printf(" CALLOC(0): failed (mix of NULL and non-NULL)\n"); + mbedtls_printf(" CALLOC(0,1): failed (mix of NULL and non-NULL)\n"); } ++failures; } else if (empty1 == empty2) { if (verbose) { - mbedtls_printf(" CALLOC(0): passed (same non-null)\n"); + mbedtls_printf(" CALLOC(0,1): passed (same non-null)\n"); } } else { if (verbose) { - mbedtls_printf(" CALLOC(0): passed (distinct non-null)\n"); + mbedtls_printf(" CALLOC(0,1): passed (distinct non-null)\n"); + } + } + + mbedtls_free(empty1); + mbedtls_free(empty2); + + empty1 = mbedtls_calloc(1, 0); + empty2 = mbedtls_calloc(1, 0); + if (empty1 == NULL && empty2 == NULL) { + if (verbose) { + mbedtls_printf(" CALLOC(1,0): passed (NULL)\n"); + } + } else if (empty1 == NULL || empty2 == NULL) { + if (verbose) { + mbedtls_printf(" CALLOC(1,0): failed (mix of NULL and non-NULL)\n"); + } + ++failures; + } else if (empty1 == empty2) { + if (verbose) { + mbedtls_printf(" CALLOC(1,0): passed (same non-null)\n"); + } + } else { + if (verbose) { + mbedtls_printf(" CALLOC(1,0): passed (distinct non-null)\n"); } } @@ -122,6 +148,16 @@ static int calloc_self_test(int verbose) } } + for (unsigned int i = 0; i < buf_size; i++) { + if (buffer3[i] != 0) { + ++failures; + if (verbose) { + mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", buf_size); + } + break; + } + } + if (verbose) { mbedtls_printf("\n"); } @@ -129,6 +165,7 @@ static int calloc_self_test(int verbose) mbedtls_free(empty2); mbedtls_free(buffer1); mbedtls_free(buffer2); + mbedtls_free(buffer3); return failures; } #endif /* MBEDTLS_SELF_TEST */ diff --git a/tests/suites/test_suite_platform.data b/tests/suites/test_suite_platform.data index 64992820c..4276b8fb7 100644 --- a/tests/suites/test_suite_platform.data +++ b/tests/suites/test_suite_platform.data @@ -4,6 +4,3 @@ time_get_milliseconds: Time: get seconds time_get_seconds: - -Check mbedtls_calloc zeroization -check_mbedtls_calloc_zeroization: \ No newline at end of file diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function index 82c656d2d..61681b878 100644 --- a/tests/suites/test_suite_platform.function +++ b/tests/suites/test_suite_platform.function @@ -120,17 +120,3 @@ void time_delay_seconds(int delay_secs) goto exit; } /* END_CASE */ - -/* BEGIN_CASE */ -void check_mbedtls_calloc_zeroization() -{ - unsigned int buf_size = 256; - unsigned char *buf; - buf = mbedtls_calloc(buf_size, sizeof(unsigned char)); - for (unsigned int i = 0; i < buf_size; i++) { - TEST_EQUAL(buf[i], 0); - } -exit: - mbedtls_free(buf); -} -/* END_CASE */ \ No newline at end of file From ecaf6fb8b264c2d4676c32c5abb1630a608d8fcb Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Thu, 4 May 2023 17:07:57 -0400 Subject: [PATCH 05/15] Documentation and cosmetic fixes Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 10 +++++----- include/mbedtls/platform.h | 2 +- programs/test/selftest.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index a08f9d865..7aea34ce6 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3683,18 +3683,18 @@ /** \def MBEDTLS_PLATFORM_STD_CALLOC * * Default allocator to use, can be undefined. - * It should initialize the allocated buffer memory to zeroes. + * It must initialize the allocated buffer memory to zeroes. * The size of the buffer is the product of the two parameters. - * The behavior is undefined if the product of the two parameters overflows size_t. + * The calloc function returns either a null pointer or a pointer to the allocated space. * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function. - * The corresponding deallocation function is MBEDTLS_PLATFORM_STD_FREE. + * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE. */ //#define MBEDTLS_PLATFORM_STD_CALLOC calloc /** \def MBEDTLS_PLATFORM_STD_FREE * * Default free to use, can be undefined. * NULL is a valid parameter, and the function must do nothing. - * A non-null parameter will always be a pointer previously returned by MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. + * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. */ //#define MBEDTLS_PLATFORM_STD_FREE free //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ @@ -3710,7 +3710,7 @@ //#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ -/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* To use the following function macros, MBEDTLS_PLATFORM_C must be enabled. */ /* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ //#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */ //#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */ diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h index fb7bc1b6a..87e880fbb 100644 --- a/include/mbedtls/platform.h +++ b/include/mbedtls/platform.h @@ -135,7 +135,7 @@ extern "C" { /* * The function pointers for calloc and free. - * please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE + * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE * in mbedtls_config.h for more information about behaviour and requirements. */ #if defined(MBEDTLS_PLATFORM_MEMORY) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index d3127553d..88c018855 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -74,7 +74,7 @@ static int calloc_self_test(int verbose) void *buffer1 = mbedtls_calloc(1, 1); void *buffer2 = mbedtls_calloc(1, 1); unsigned int buf_size = 256; - unsigned char *buffer3 = mbedtls_calloc(buf_size, sizeof(unsigned char)); + unsigned char *buffer3 = mbedtls_calloc(buf_size, 1); if (empty1 == NULL && empty2 == NULL) { if (verbose) { From e35f3a23bef66e578d4c605e4729b221d948679d Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Thu, 4 May 2023 17:29:55 -0400 Subject: [PATCH 06/15] Add a calloc selftest for more than a page Signed-off-by: Andrzej Kurek --- programs/test/selftest.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 88c018855..cc5e00ed3 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -73,8 +73,10 @@ static int calloc_self_test(int verbose) void *empty2 = mbedtls_calloc(0, 1); void *buffer1 = mbedtls_calloc(1, 1); void *buffer2 = mbedtls_calloc(1, 1); - unsigned int buf_size = 256; - unsigned char *buffer3 = mbedtls_calloc(buf_size, 1); + unsigned int buffer_3_size = 256; + unsigned int buffer_4_size = 4097; /* Allocate more than the usual page size */ + unsigned char *buffer3 = mbedtls_calloc(buffer_3_size, 1); + unsigned char *buffer4 = mbedtls_calloc(buffer_4_size, 1); if (empty1 == NULL && empty2 == NULL) { if (verbose) { @@ -148,11 +150,23 @@ static int calloc_self_test(int verbose) } } - for (unsigned int i = 0; i < buf_size; i++) { + for (unsigned int i = 0; i < buffer_3_size; i++) { if (buffer3[i] != 0) { ++failures; if (verbose) { - mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", buf_size); + mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", + buffer_3_size); + } + break; + } + } + + for (unsigned int i = 0; i < buffer_4_size; i++) { + if (buffer4[i] != 0) { + ++failures; + if (verbose) { + mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", + buffer_4_size); } break; } @@ -166,6 +180,7 @@ static int calloc_self_test(int verbose) mbedtls_free(buffer1); mbedtls_free(buffer2); mbedtls_free(buffer3); + mbedtls_free(buffer4); return failures; } #endif /* MBEDTLS_SELF_TEST */ From 84356a16e9dd0bd0ba30ef0742cb985767116249 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Sat, 6 May 2023 08:33:56 -0400 Subject: [PATCH 07/15] Add a description of how mbedtls_calloc is determined Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 7aea34ce6..4f389e081 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3680,9 +3680,39 @@ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ + +/* An overview of how the value of mbedtls_calloc is determined: + * + * if !MBEDTLS_PLATFORM_MEMORY + * mbedtls_calloc = calloc + * if MBEDTLS_PLATFORM_MEMORY + * if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): + * mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO + * if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): + * Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC. + * How is MBEDTLS_PLATFORM_STD_CALLOC handled? + * if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: + * MBEDTLS_PLATFORM_STD_CALLOC is not set to anything; + * MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present; + * if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: + * if MBEDTLS_PLATFORM_STD_CALLOC is present: + * User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected; + * if !MBEDTLS_PLATFORM_STD_CALLOC: + * MBEDTLS_PLATFORM_STD_CALLOC = calloc + * + * At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked. + * if !MBEDTLS_PLATFORM_STD_CALLOC + * MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc + * + * mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC. + * + * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible. + * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time. + * MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. + */ /** \def MBEDTLS_PLATFORM_STD_CALLOC * - * Default allocator to use, can be undefined. + * Default allocator to use, can be undefined. See the description above for details. * It must initialize the allocated buffer memory to zeroes. * The size of the buffer is the product of the two parameters. * The calloc function returns either a null pointer or a pointer to the allocated space. From aae3208c29ef88c6a44797e3fafc62c4ab8fccea Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Sat, 6 May 2023 08:52:50 -0400 Subject: [PATCH 08/15] Add an mbedtls_calloc(SIZE_MAX/2, SIZE_MAX/2) test It should return NULL and not a valid pointer. Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 5 +++-- programs/test/selftest.c | 13 ++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 4f389e081..55b94ced7 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3708,7 +3708,8 @@ * * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible. * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time. - * MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. + * MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, + * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. */ /** \def MBEDTLS_PLATFORM_STD_CALLOC * @@ -3722,7 +3723,7 @@ //#define MBEDTLS_PLATFORM_STD_CALLOC calloc /** \def MBEDTLS_PLATFORM_STD_FREE * - * Default free to use, can be undefined. + * Default free to use, can be undefined. See the description above for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). * NULL is a valid parameter, and the function must do nothing. * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. */ diff --git a/programs/test/selftest.c b/programs/test/selftest.c index cc5e00ed3..933d06b21 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -77,7 +77,10 @@ static int calloc_self_test(int verbose) unsigned int buffer_4_size = 4097; /* Allocate more than the usual page size */ unsigned char *buffer3 = mbedtls_calloc(buffer_3_size, 1); unsigned char *buffer4 = mbedtls_calloc(buffer_4_size, 1); - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Walloc-size-larger-than=" + unsigned char *buffer5 = mbedtls_calloc(SIZE_MAX/2, SIZE_MAX/2); +#pragma GCC diagnostic pop if (empty1 == NULL && empty2 == NULL) { if (verbose) { mbedtls_printf(" CALLOC(0,1): passed (NULL)\n"); @@ -172,6 +175,13 @@ static int calloc_self_test(int verbose) } } + if (buffer5 != NULL) { + ++failures; + if (verbose) { + mbedtls_printf(" CALLOC(SIZE_MAX/2, SIZE_MAX/2): failed (returned a valid pointer)\n"); + } + } + if (verbose) { mbedtls_printf("\n"); } @@ -181,6 +191,7 @@ static int calloc_self_test(int verbose) mbedtls_free(buffer2); mbedtls_free(buffer3); mbedtls_free(buffer4); + mbedtls_free(buffer5); return failures; } #endif /* MBEDTLS_SELF_TEST */ From 60de0b198a2ef6caf1abfd3273f4f7dde70dd727 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 9 May 2023 16:38:04 -0400 Subject: [PATCH 09/15] Move the overallocation test to test suites This way the compiler does not complain about an overly large allocation made. Signed-off-by: Andrzej Kurek --- programs/test/selftest.c | 13 +------------ tests/suites/test_suite_platform.data | 3 +++ tests/suites/test_suite_platform.function | 12 ++++++++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 933d06b21..cc5e00ed3 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -77,10 +77,7 @@ static int calloc_self_test(int verbose) unsigned int buffer_4_size = 4097; /* Allocate more than the usual page size */ unsigned char *buffer3 = mbedtls_calloc(buffer_3_size, 1); unsigned char *buffer4 = mbedtls_calloc(buffer_4_size, 1); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Walloc-size-larger-than=" - unsigned char *buffer5 = mbedtls_calloc(SIZE_MAX/2, SIZE_MAX/2); -#pragma GCC diagnostic pop + if (empty1 == NULL && empty2 == NULL) { if (verbose) { mbedtls_printf(" CALLOC(0,1): passed (NULL)\n"); @@ -175,13 +172,6 @@ static int calloc_self_test(int verbose) } } - if (buffer5 != NULL) { - ++failures; - if (verbose) { - mbedtls_printf(" CALLOC(SIZE_MAX/2, SIZE_MAX/2): failed (returned a valid pointer)\n"); - } - } - if (verbose) { mbedtls_printf("\n"); } @@ -191,7 +181,6 @@ static int calloc_self_test(int verbose) mbedtls_free(buffer2); mbedtls_free(buffer3); mbedtls_free(buffer4); - mbedtls_free(buffer5); return failures; } #endif /* MBEDTLS_SELF_TEST */ diff --git a/tests/suites/test_suite_platform.data b/tests/suites/test_suite_platform.data index 4276b8fb7..4d5745076 100644 --- a/tests/suites/test_suite_platform.data +++ b/tests/suites/test_suite_platform.data @@ -4,3 +4,6 @@ time_get_milliseconds: Time: get seconds time_get_seconds: + +Check mbedtls_calloc overallocation +check_mbedtls_calloc_overallocation:SIZE_MAX/2:SIZE_MAX/2 diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function index 61681b878..bc397357f 100644 --- a/tests/suites/test_suite_platform.function +++ b/tests/suites/test_suite_platform.function @@ -120,3 +120,15 @@ void time_delay_seconds(int delay_secs) goto exit; } /* END_CASE */ + +/* BEGIN_CASE */ +void check_mbedtls_calloc_overallocation(intmax_t num, intmax_t size) +{ + unsigned char *buf; + buf = mbedtls_calloc((size_t) num, (size_t) size); + TEST_ASSERT(buf == NULL); + +exit: + mbedtls_free(buf); +} +/* END_CASE */ From 04bfe5797b953c43fb3f3213e7e9b54c084065b3 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 27 Jun 2023 10:02:09 -0400 Subject: [PATCH 10/15] Disable asan errors on null allocation in all.sh Such error was raised in platform tests, and it's a valid test case. Signed-off-by: Andrzej Kurek --- tests/scripts/all.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 45f7e982f..46d249d66 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -189,6 +189,9 @@ pre_initialize_variables () { # default to -O2, use -Ox _after_ this if you want another level ASAN_CFLAGS='-O2 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all' + # Platform tests have an allocation that returns null + export ASAN_OPTIONS="allocator_may_return_null=1" + # Gather the list of available components. These are the functions # defined in this script whose name starts with "component_". # Parse the script with sed. This way we get the functions in the order From 2b3c06edb3b055e2fb81e574d992d718e75873c8 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Mon, 3 Jul 2023 06:52:37 -0400 Subject: [PATCH 11/15] Enable certain documented defines only when generating doxygen Avoid an "unrecognized define" error. Signed-off-by: Andrzej Kurek --- doxygen/mbedtls.doxyfile | 1 + include/mbedtls/mbedtls_config.h | 2 ++ include/mbedtls/platform.h | 9 +++++++++ 3 files changed, 12 insertions(+) diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index 393fd41ad..4c95c61e7 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -51,4 +51,5 @@ PREDEFINED = "MBEDTLS_CHECK_RETURN_CRITICAL=" \ "MBEDTLS_CHECK_RETURN_TYPICAL=" \ "MBEDTLS_CHECK_RETURN_OPTIONAL=" \ "MBEDTLS_PRINTF_ATTRIBUTE(a,b)=" \ + "__DOXYGEN__" \ diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 55b94ced7..ddbef7a66 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3711,6 +3711,7 @@ * MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. */ + /** \def MBEDTLS_PLATFORM_STD_CALLOC * * Default allocator to use, can be undefined. See the description above for details. @@ -3721,6 +3722,7 @@ * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE. */ //#define MBEDTLS_PLATFORM_STD_CALLOC calloc + /** \def MBEDTLS_PLATFORM_STD_FREE * * Default free to use, can be undefined. See the description above for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h index 87e880fbb..3fc1fd0c1 100644 --- a/include/mbedtls/platform.h +++ b/include/mbedtls/platform.h @@ -130,6 +130,15 @@ extern "C" { #endif #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +/* Enable certain documented defines only when generating doxygen to avoid + * an "unrecognized define" error. */ +#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC +#endif + +#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE +#endif /** \} name SECTION: Module settings */ From cf669b058b92d706367db91263b7f9bacb75178d Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Mon, 3 Jul 2023 09:49:07 -0400 Subject: [PATCH 12/15] Add a dummy usage of a pointer in tests This way clang with O1 doesn't optimize it. Signed-off-by: Andrzej Kurek --- tests/suites/test_suite_platform.function | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function index bc397357f..c65d011f0 100644 --- a/tests/suites/test_suite_platform.function +++ b/tests/suites/test_suite_platform.function @@ -126,6 +126,8 @@ void check_mbedtls_calloc_overallocation(intmax_t num, intmax_t size) { unsigned char *buf; buf = mbedtls_calloc((size_t) num, (size_t) size); + /* Dummy usage of the pointer to prevent optimizing it */ + mbedtls_printf("calloc pointer : %p\n", buf); TEST_ASSERT(buf == NULL); exit: From 026235c4ec17e52e88b0b6b5a7fb40247a6a2e9e Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Wed, 5 Jul 2023 08:32:43 -0400 Subject: [PATCH 13/15] Disable msan errors on null allocation in all.sh Such error was raised in platform tests, and it's a valid test case. Signed-off-by: Andrzej Kurek --- tests/scripts/all.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 46d249d66..604b457c3 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -191,6 +191,7 @@ pre_initialize_variables () { # Platform tests have an allocation that returns null export ASAN_OPTIONS="allocator_may_return_null=1" + export MSAN_OPTIONS="allocator_may_return_null=1" # Gather the list of available components. These are the functions # defined in this script whose name starts with "component_". From 548894fea1e6ef8046ed4e16ee90dc1a0b5208ca Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Wed, 5 Jul 2023 08:50:25 -0400 Subject: [PATCH 14/15] Add msan and asan env variables to .travis.yml This way the CI tests don't fail on a null allocation. Signed-off-by: Andrzej Kurek --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index bf5ccd96e..8313317b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,10 @@ jobs: packages: - clang-10 - gnutls-bin + env: + # Platform tests have an allocation that returns null + - ASAN_OPTIONS="allocator_may_return_null=1" + - MSAN_OPTIONS="allocator_may_return_null=1" script: # Do a manual build+test sequence rather than using all.sh, # because there's no all.sh component that does what we want, @@ -89,6 +93,10 @@ jobs: apt: packages: - gcc + env: + # Platform tests have an allocation that returns null + - ASAN_OPTIONS="allocator_may_return_null=1" + - MSAN_OPTIONS="allocator_may_return_null=1" script: # Do a manual build+test sequence rather than using all.sh. # @@ -115,6 +123,10 @@ jobs: packages: - clang - gnutls-bin + env: + # Platform tests have an allocation that returns null + - ASAN_OPTIONS="allocator_may_return_null=1" + - MSAN_OPTIONS="allocator_may_return_null=1" script: # Do a manual build+test sequence rather than using all.sh. # From f14a5c3fcb54ae2dae758c39ee3137eca19d88de Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Fri, 14 Jul 2023 06:15:15 -0400 Subject: [PATCH 15/15] Improve the documentation of MBEDTLS_PLATFORM_MEMORY Introduce requests from review comments. Signed-off-by: Andrzej Kurek --- include/mbedtls/mbedtls_config.h | 75 +++++++++++++++++--------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index ddbef7a66..d0f8c4655 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -172,15 +172,47 @@ * This allows different allocators (self-implemented or provided) to be * provided to the platform abstraction layer. * - * Enabling MBEDTLS_PLATFORM_MEMORY without the + * Enabling #MBEDTLS_PLATFORM_MEMORY without the * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and * free() function pointer at runtime. * - * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * Enabling #MBEDTLS_PLATFORM_MEMORY and specifying * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the * alternate function at compile time. * + * An overview of how the value of mbedtls_calloc is determined: + * + * - if !MBEDTLS_PLATFORM_MEMORY + * - mbedtls_calloc = calloc + * - if MBEDTLS_PLATFORM_MEMORY + * - if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): + * - mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO + * - if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): + * - Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC. + * - How is MBEDTLS_PLATFORM_STD_CALLOC handled? + * - if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: + * - MBEDTLS_PLATFORM_STD_CALLOC is not set to anything; + * - MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present; + * - if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: + * - if MBEDTLS_PLATFORM_STD_CALLOC is present: + * - User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected; + * - if !MBEDTLS_PLATFORM_STD_CALLOC: + * - MBEDTLS_PLATFORM_STD_CALLOC = calloc + * + * - At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked. + * - if !MBEDTLS_PLATFORM_STD_CALLOC + * - MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc + * + * - mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC. + * + * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and #MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible. + * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time. + * #MBEDTLS_PLATFORM_STD_CALLOC and #MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, + * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. + * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer. + * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything. + * * Requires: MBEDTLS_PLATFORM_C * * Enable this layer to allow use of alternative memory allocators. @@ -3681,53 +3713,26 @@ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -/* An overview of how the value of mbedtls_calloc is determined: - * - * if !MBEDTLS_PLATFORM_MEMORY - * mbedtls_calloc = calloc - * if MBEDTLS_PLATFORM_MEMORY - * if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): - * mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO - * if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): - * Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC. - * How is MBEDTLS_PLATFORM_STD_CALLOC handled? - * if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: - * MBEDTLS_PLATFORM_STD_CALLOC is not set to anything; - * MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present; - * if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: - * if MBEDTLS_PLATFORM_STD_CALLOC is present: - * User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected; - * if !MBEDTLS_PLATFORM_STD_CALLOC: - * MBEDTLS_PLATFORM_STD_CALLOC = calloc - * - * At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked. - * if !MBEDTLS_PLATFORM_STD_CALLOC - * MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc - * - * mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC. - * - * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible. - * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time. - * MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, - * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. - */ - /** \def MBEDTLS_PLATFORM_STD_CALLOC * - * Default allocator to use, can be undefined. See the description above for details. + * Default allocator to use, can be undefined. * It must initialize the allocated buffer memory to zeroes. * The size of the buffer is the product of the two parameters. * The calloc function returns either a null pointer or a pointer to the allocated space. * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function. + * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer. + * See the description of #MBEDTLS_PLATFORM_MEMORY for more details. * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE. */ //#define MBEDTLS_PLATFORM_STD_CALLOC calloc /** \def MBEDTLS_PLATFORM_STD_FREE * - * Default free to use, can be undefined. See the description above for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). + * Default free to use, can be undefined. * NULL is a valid parameter, and the function must do nothing. * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. + * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything. + * See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). */ //#define MBEDTLS_PLATFORM_STD_FREE free //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */