Merge pull request #5697 from gilles-peskine-arm/psa-test-op-fail-2.28

Backport 2.28: PSA: systematically test operation failure
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bec84a1..cea12f1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -52,11 +52,6 @@
 The list of maintained branches can be found in the [Current Branches section
 of BRANCHES.md](BRANCHES.md#current-branches).
 
-Currently maintained LTS branches are:
-1. [mbedtls-2.7](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.7)
-1. [mbedtls-2.16](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.16)
-
-
 Tests
 -----
 As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.
diff --git a/ChangeLog.d/alert_reentrant.txt b/ChangeLog.d/alert_reentrant.txt
new file mode 100644
index 0000000..691d64c
--- /dev/null
+++ b/ChangeLog.d/alert_reentrant.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix bug in the alert sending function mbedtls_ssl_send_alert_message()
+     potentially leading to corrupted alert messages being sent in case
+     the function needs to be re-called after initially returning
+     MBEDTLS_SSL_WANT_WRITE. Fixes #1916.
diff --git a/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt b/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
new file mode 100644
index 0000000..6878645
--- /dev/null
+++ b/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix compilation on Windows when building shared library, by setting
+     library search path to CMAKE_CURRENT_BINARY_DIR.
diff --git a/configs/config-no-entropy.h b/configs/config-no-entropy.h
index 04c1213..63f9411 100644
--- a/configs/config-no-entropy.h
+++ b/configs/config-no-entropy.h
@@ -21,7 +21,7 @@
  */
 /*
  * Minimal configuration of features that do not require an entropy source
- * Distinguishing reatures:
+ * Distinguishing features:
  * - no entropy module
  * - no TLS protocol implementation available due to absence of an entropy
  *   source
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index b0296eb..a93e38a 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -128,7 +128,12 @@
  * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
  * MBEDTLS_PLATFORM_STD_TIME.
  *
- * Comment if your system does not support time functions
+ * Comment if your system does not support time functions.
+ *
+ * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing
+ *       interface - timing.c will include time.h on suitable platforms
+ *       regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ *       MBEDTLS_TIMING_ALT is used. See timing.c for more information.
  */
 #define MBEDTLS_HAVE_TIME
 
@@ -1493,7 +1498,7 @@
  * Enable an implementation of SHA-256 that has lower ROM footprint but also
  * lower performance.
  *
- * The default implementation is meant to be a reasonnable compromise between
+ * The default implementation is meant to be a reasonable compromise between
  * performance and size. This version optimizes more aggressively for size at
  * the expense of performance. Eg on Cortex-M4 it reduces the size of
  * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
@@ -3466,6 +3471,10 @@
  * your own implementation of the whole module by setting
  * \c MBEDTLS_TIMING_ALT in the current file.
  *
+ * \note The timing module will include time.h on suitable platforms
+ *       regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ *       MBEDTLS_TIMING_ALT is used. See timing.c for more information.
+ *
  * \note See also our Knowledge Base article about porting to a new
  * environment:
  * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 610b8b1..328f861 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -4357,7 +4357,7 @@
 void mbedtls_ssl_config_init( mbedtls_ssl_config *conf );
 
 /**
- * \brief          Load reasonnable default SSL configuration values.
+ * \brief          Load reasonable default SSL configuration values.
  *                 (You need to call mbedtls_ssl_config_init() first.)
  *
  * \param conf     SSL configuration context
diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index a882eed..8221051 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -101,7 +101,7 @@
  *                  supported. Usually that means a 256-bit key.
  *
  * \note            The lifetime of the keys is twice the lifetime of tickets.
- *                  It is recommended to pick a reasonnable lifetime so as not
+ *                  It is recommended to pick a reasonable lifetime so as not
  *                  to negate the benefits of forward secrecy.
  *
  * \return          0 if successful,
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 0a60067..cde9cf4 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -202,6 +202,7 @@
 endif(USE_STATIC_MBEDTLS_LIBRARY)
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
+    set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
     set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.0 SOVERSION 7)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 0b696dd..0b1322d 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -4918,6 +4918,9 @@
     if( ssl == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
+    if( ssl->out_left != 0 )
+        return( mbedtls_ssl_flush_output( ssl ) );
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
 
@@ -5790,9 +5793,6 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
 
-    if( ssl->out_left != 0 )
-        return( mbedtls_ssl_flush_output( ssl ) );
-
     if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
     {
         if( ( ret = mbedtls_ssl_send_alert_message( ssl,
diff --git a/library/timing.c b/library/timing.c
index a5a55d6..57bc9bc 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -57,17 +57,16 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <signal.h>
-#if defined(MBEDTLS_HAVE_TIME)
+/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the
+ * platform matches the ifdefs above, it will be used. */
 #include <time.h>
 #include <sys/time.h>
 struct _hr_time
 {
     struct timeval start;
 };
-#endif
 #endif /* _WIN32 && !EFIX64 && !EFI32 */
 
-#if defined(MBEDTLS_HAVE_TIME)
 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
     ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
 
@@ -526,45 +525,5 @@
 }
 
 #endif /* MBEDTLS_SELF_TEST */
-
-#else
-volatile int mbedtls_timing_alarmed = 0;
-int mbedtls_timing_get_delay( void *data )
-{
-    (void) data;
-    return( 0 );
-}
-
-void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
-{
-    (void) data;
-    (void) int_ms;
-    (void) fin_ms;
-}
-
-unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
-{
-    (void) val;
-    (void) reset;
-    return( 0 );
-}
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    return( 0 );
-}
-
-void mbedtls_set_alarm( int seconds )
-{
-    (void) seconds;
-}
-#if defined(MBEDTLS_SELF_TEST)
-int mbedtls_timing_self_test( int verbose )
-{
-    (void) verbose;
-    return( 0 );
-}
-#endif /* MBEDTLS_SELF_TEST */
-#endif /* MBEDTLS_HAVE_TIME */
 #endif /* !MBEDTLS_TIMING_ALT */
 #endif /* MBEDTLS_TIMING_C */
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index 9a6087c..a50da1a 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -827,7 +827,6 @@
 
     get_options( argc, argv );
 
-#if defined(MBEDTLS_HAVE_TIME)
     /*
      * Decisions to drop/delay/duplicate packets are pseudo-random: dropping
      * exactly 1 in N packets would lead to problems when a flight has exactly
@@ -838,12 +837,15 @@
      */
     if( opt.seed == 0 )
     {
+#if defined(MBEDTLS_HAVE_TIME)
         opt.seed = (unsigned int) mbedtls_time( NULL );
+#else
+        opt.seed = 1;
+#endif /* MBEDTLS_HAVE_TIME */
         mbedtls_printf( "  . Pseudo-random seed: %u\n", opt.seed );
     }
 
     srand( opt.seed );
-#endif /* MBEDTLS_HAVE_TIME */
 
     /*
      * 0. "Connect" to the server
diff --git a/scripts/config.py b/scripts/config.py
index 01f570e..ded7785 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -272,6 +272,24 @@
         return True
     return include_in_full(name) and keep_in_baremetal(name)
 
+# This set contains options that are mostly for debugging or test purposes,
+# and therefore should be excluded when doing code size measurements.
+# Options that are their own module (such as MBEDTLS_CERTS_C and
+# MBEDTLS_ERROR_C) are not listed and therefore will be included when doing
+# code size measurements.
+EXCLUDE_FOR_SIZE = frozenset([
+    'MBEDTLS_CHECK_PARAMS', # increases the size of many modules
+    'MBEDTLS_CHECK_PARAMS_ASSERT', # no effect without MBEDTLS_CHECK_PARAMS
+    'MBEDTLS_DEBUG_C', # large code size increase in TLS
+    'MBEDTLS_SELF_TEST', # increases the size of many modules
+    'MBEDTLS_TEST_HOOKS', # only useful with the hosted test framework, increases code size
+])
+
+def baremetal_size_adapter(name, active, section):
+    if name in EXCLUDE_FOR_SIZE:
+        return False
+    return baremetal_adapter(name, active, section)
+
 def include_in_crypto(name):
     """Rules for symbols in a crypto configuration."""
     if name.startswith('MBEDTLS_X509_') or \
@@ -483,6 +501,9 @@
         add_adapter('baremetal', baremetal_adapter,
                     """Like full, but exclude features that require platform
                     features such as file input-output.""")
+        add_adapter('baremetal_size', baremetal_size_adapter,
+                    """Like baremetal, but exclude debugging features.
+                    Useful for code size measurements.""")
         add_adapter('full', full_adapter,
                     """Uncomment most features.
                     Exclude alternative implementations and platform support
diff --git a/tests/compat.sh b/tests/compat.sh
index a03407c..560af59 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -67,17 +67,19 @@
 fi
 
 # default values for options
-MODES="tls1 tls1_1 tls12 dtls1 dtls12"
+# /!\ keep this synchronised with:
+# - basic-build-test.sh
+# - all.sh (multiple components)
+MODES="tls1 tls1_1 tls12 dtls1 dtls12" # ssl3 not in default config
 VERIFIES="NO YES"
 TYPES="ECDSA RSA PSK"
 FILTER=""
 # exclude:
-# - NULL: excluded from our default config
+# - NULL: excluded from our default config + requires OpenSSL legacy
 # - RC4, single-DES: requires legacy OpenSSL/GnuTLS versions
-#   avoid plain DES but keep 3DES-EDE-CBC (mbedTLS), DES-CBC3 (OpenSSL)
+# - 3DES: not in default config
 # - ARIA: not in default config.h + requires OpenSSL >= 1.1.1
 # - ChachaPoly: requires OpenSSL >= 1.1.0
-# - 3DES: not in default config
 EXCLUDE='NULL\|DES\|RC4\|ARCFOUR\|ARIA\|CHACHA20-POLY1305'
 VERBOSE=""
 MEMCHECK=0
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 1bde003..a517f2b 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -2770,16 +2770,16 @@
 }
 
 component_build_arm_none_eabi_gcc () {
-    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1, baremetal+debug" # ~ 10s
     scripts/config.py baremetal
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -O1' lib
 
-    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1"
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1, baremetal+debug"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
 component_build_arm_linux_gnueabi_gcc_arm5vte () {
-    msg "build: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
+    msg "build: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte, baremetal+debug" # ~ 10s
     scripts/config.py baremetal
     # Build for a target platform that's close to what Debian uses
     # for its "armel" distribution (https://wiki.debian.org/ArmEabiPort).
@@ -2788,7 +2788,7 @@
     # https://github.com/Mbed-TLS/mbedtls/pull/3449#issuecomment-675313720
     make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" AR="${ARM_LINUX_GNUEABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te'
 
-    msg "size: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=armv5te -O1"
+    msg "size: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=armv5te -O1, baremetal+debug"
     ${ARM_LINUX_GNUEABI_GCC_PREFIX}size library/*.o
 }
 support_build_arm_linux_gnueabi_gcc_arm5vte () {
@@ -2796,23 +2796,23 @@
 }
 
 component_build_arm_none_eabi_gcc_arm5vte () {
-    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte, baremetal+debug" # ~ 10s
     scripts/config.py baremetal
     # This is an imperfect substitute for
     # component_build_arm_linux_gnueabi_gcc_arm5vte
     # in case the gcc-arm-linux-gnueabi toolchain is not available
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-std=c99 -Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
 
-    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1"
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1, baremetal+debug"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
 component_build_arm_none_eabi_gcc_m0plus () {
-    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus" # ~ 10s
-    scripts/config.py baremetal
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus, baremetal_size" # ~ 10s
+    scripts/config.py baremetal_size
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -mthumb -mcpu=cortex-m0plus -Os' lib
 
-    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os"
+    msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os, baremetal_size"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index 8756634..56fd5b9 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -121,7 +121,7 @@
 echo '################ compat.sh ################'
 {
     echo '#### compat.sh: Default versions'
-    sh compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2'
+    sh compat.sh -m 'tls1 tls1_1 tls12 dtls1 dtls12'
     echo
 
     echo '#### compat.sh: legacy (SSLv3)'
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 654de32..ced863a 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1082,7 +1082,8 @@
 
     analyze_test_commands "$@"
 
-    TIMES_LEFT=2
+    # One regular run and two retries
+    TIMES_LEFT=3
     while [ $TIMES_LEFT -gt 0 ]; do
         TIMES_LEFT=$(( $TIMES_LEFT - 1 ))
 
diff --git a/tests/suites/test_suite_timing.data b/tests/suites/test_suite_timing.data
index b7b089c..2522da1 100644
--- a/tests/suites/test_suite_timing.data
+++ b/tests/suites/test_suite_timing.data
@@ -1,23 +1,17 @@
 Timing: hardclock
-depends_on:MBEDTLS_HAVE_TIME
 timing_hardclock:
 
 Timing: get timer
-depends_on:MBEDTLS_HAVE_TIME
 timing_get_timer:
 
 Timing: set alarm with no delay
-depends_on:MBEDTLS_HAVE_TIME
 timing_set_alarm:0:
 
 Timing: set alarm with 1s delay
-depends_on:MBEDTLS_HAVE_TIME
 timing_set_alarm:1:
 
 Timing: delay 0ms
-depends_on:MBEDTLS_HAVE_TIME
 timing_delay:0:
 
 Timing: delay 100ms
-depends_on:MBEDTLS_HAVE_TIME
 timing_delay:100: