Merge pull request #2894 from gilles-peskine-arm/drbg-set_entropy_len-2.16

Backport 2.16: Allow xxx_drbg_set_entropy_len before xxx_drbg_seed
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 727054e..bd28e9a 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -66,6 +66,8 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
+#define mbedtls_calloc     calloc
+#define mbedtls_free       free
 #define mbedtls_printf     printf
 #define mbedtls_snprintf   snprintf
 #define mbedtls_exit       exit
@@ -78,6 +80,86 @@
 #endif
 
 
+#if defined MBEDTLS_SELF_TEST
+/* Sanity check for malloc. This is not expected to fail, and is rather
+ * intended to display potentially useful information about the platform,
+ * in particular the behavior of malloc(0). */
+static int calloc_self_test( int verbose )
+{
+    int failures = 0;
+    void *empty1 = mbedtls_calloc( 0, 1 );
+    void *empty2 = mbedtls_calloc( 0, 1 );
+    void *buffer1 = mbedtls_calloc( 1, 1 );
+    void *buffer2 = mbedtls_calloc( 1, 1 );
+    uintptr_t old_buffer1;
+
+    if( empty1 == NULL && empty2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (NULL)\n" );
+    }
+    else if( empty1 == NULL || empty2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): failed (mix of NULL and non-NULL)\n" );
+        ++failures;
+    }
+    else if( empty1 == empty2 )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (same non-null)\n" );
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(0): passed (distinct non-null)\n" );
+    }
+
+    if( buffer1 == NULL || buffer2 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): failed (NULL)\n" );
+        ++failures;
+    }
+    else if( buffer1 == buffer2 )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): failed (same buffer twice)\n" );
+        ++failures;
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1): passed\n" );
+    }
+
+    old_buffer1 = (uintptr_t) buffer1;
+    mbedtls_free( buffer1 );
+    buffer1 = mbedtls_calloc( 1, 1 );
+    if( buffer1 == NULL )
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1 again): failed (NULL)\n" );
+        ++failures;
+    }
+    else
+    {
+        if( verbose )
+            mbedtls_printf( "  CALLOC(1 again): passed (%s address)\n",
+                            (uintptr_t) old_buffer1 == (uintptr_t) buffer1 ?
+                            "same" : "different" );
+    }
+
+    if( verbose )
+        mbedtls_printf( "\n" );
+    mbedtls_free( empty1 );
+    mbedtls_free( empty2 );
+    mbedtls_free( buffer1 );
+    mbedtls_free( buffer2 );
+    return( failures );
+}
+#endif /* MBEDTLS_SELF_TEST */
+
 static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
 {
     int ret;
@@ -174,6 +256,7 @@
 
 const selftest_t selftests[] =
 {
+    {"calloc", calloc_self_test},
 #if defined(MBEDTLS_MD2_C)
     {"md2", mbedtls_md2_self_test},
 #endif
diff --git a/tests/configs/config-wrapper-malloc-0-null.h b/tests/configs/config-wrapper-malloc-0-null.h
new file mode 100644
index 0000000..ed74eda
--- /dev/null
+++ b/tests/configs/config-wrapper-malloc-0-null.h
@@ -0,0 +1,39 @@
+/* config.h wrapper that forces calloc(0) to return NULL.
+ * Used for testing.
+ */
+/*
+ *  Copyright (C) 2019, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CONFIG_H
+/* Don't #define MBEDTLS_CONFIG_H, let config.h do it. */
+
+#include "mbedtls/config.h"
+
+#include <stdlib.h>
+static inline void *custom_calloc( size_t nmemb, size_t size )
+{
+    if( nmemb == 0 || size == 0 )
+        return( NULL );
+    return( calloc( nmemb, size ) );
+}
+
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_STD_CALLOC custom_calloc
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 3c4681a..8f25c6b 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -137,6 +137,9 @@
         export MAKEFLAGS="-j"
     fi
 
+    # CFLAGS and LDFLAGS for Asan builds that don't use CMake
+    ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
+
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
     # Parse the script with sed, because in sh there is no way to list
@@ -992,6 +995,21 @@
     make test
 }
 
+component_test_malloc_0_null () {
+    msg "build: malloc(0) returns NULL (ASan+UBSan build)"
+    scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined'
+
+    msg "test: malloc(0) returns NULL (ASan+UBSan build)"
+    make test
+
+    msg "selftest: malloc(0) returns NULL (ASan+UBSan build)"
+    # Just the calloc selftest. "make test" ran the others as part of the
+    # test suites.
+    if_build_succeeded programs/test/selftest calloc
+}
+
 component_test_aes_fewer_tables () {
     msg "build: default config with AES_FEWER_TABLES enabled"
     scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
@@ -1049,7 +1067,7 @@
     # Build once with -O0, to compile out the i386 specific inline assembly
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32 -fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O0 (ASan build)"
     make test
@@ -1065,7 +1083,7 @@
     # Build again with -O1, to compile in the i386 specific inline assembly
     msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
     scripts/config.pl full
-    make CC=gcc CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32 -fsanitize=address'
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O1 (ASan build)"
     make test
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 1c9dc1d..d06badd 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -93,7 +93,7 @@
     $suite_cases_failed = () = $result =~ /.. FAILED/g;
     $suite_cases_skipped = () = $result =~ /.. ----/g;
 
-    if( $result =~ /PASSED/ ) {
+    if( $? == 0 ) {
         print "PASS\n";
         if( $verbose > 2 ) {
             pad_print_center( 72, '-', "Begin $suite" );
diff --git a/tests/suites/test_suite_memory_buffer_alloc.data b/tests/suites/test_suite_memory_buffer_alloc.data
index d59f113..d780fd4 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.data
+++ b/tests/suites/test_suite_memory_buffer_alloc.data
@@ -16,8 +16,8 @@
 Memory buffer alloc - Out of Memory test
 memory_buffer_alloc_oom_test:
 
-Memory buffer small buffer
-memory_buffer_small_buffer:
+Memory buffer: heap too small (header verification should fail)
+memory_buffer_heap_too_small:
 
-Memory buffer underalloc
+Memory buffer: attempt to allocate SIZE_MAX
 memory_buffer_underalloc:
diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function
index bc03436..cc884c2 100644
--- a/tests/suites/test_suite_memory_buffer_alloc.function
+++ b/tests/suites/test_suite_memory_buffer_alloc.function
@@ -29,7 +29,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 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,
@@ -39,8 +39,11 @@
     unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_d = NULL,
                     *ptr_e = NULL, *ptr_f = NULL;
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     size_t reported_blocks;
-    size_t allocated_bytes = 0, reported_bytes;
+    size_t reported_bytes;
+#endif
+    size_t allocated_bytes = 0;
 
     mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
 
@@ -78,8 +81,10 @@
         allocated_bytes += d_bytes * sizeof(char);
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
 
     if( free_a )
     {
@@ -117,8 +122,10 @@
         allocated_bytes -= d_bytes * sizeof(char);
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == allocated_bytes );
+#endif
 
     if( e_bytes > 0 )
     {
@@ -178,8 +185,10 @@
         ptr_f = NULL;
     }
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == 0 );
+#endif
 
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
@@ -188,12 +197,14 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 void memory_buffer_alloc_oom_test(  )
 {
     unsigned char buf[1024];
     unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL;
+#if defined(MBEDTLS_MEMORY_DEBUG)
     size_t reported_blocks, reported_bytes;
+#endif
 
     (void)ptr_c;
 
@@ -210,8 +221,10 @@
     ptr_c = mbedtls_calloc( 431, sizeof(char) );
     TEST_ASSERT( ptr_c == NULL );
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes >= 864 && reported_bytes <= sizeof(buf) );
+#endif
 
     mbedtls_free( ptr_a );
     ptr_a = NULL;
@@ -221,8 +234,10 @@
     ptr_b = NULL;
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
+#if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks );
     TEST_ASSERT( reported_bytes == 0 );
+#endif
 
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 );
 
@@ -231,17 +246,20 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
-void memory_buffer_small_buffer( )
+/* BEGIN_CASE */
+void memory_buffer_heap_too_small( )
 {
     unsigned char buf[1];
 
     mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+    /* With MBEDTLS_MEMORY_DEBUG enabled, this prints a message
+     * "FATAL: verification of first header failed".
+     */
     TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() != 0 );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */
+/* BEGIN_CASE */
 void memory_buffer_underalloc( )
 {
     unsigned char buf[100];