Add an acceptance test for memory usage after handshake Signed-off-by: Piotr Nowicki <piotr.nowicki@arm.com> Signed-off-by: Andrzej Kurek <andrzej.kurek@arm.com>
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index d23a700..13031d5 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c
@@ -1838,7 +1838,10 @@ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); -#endif +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t current_heap_memory, peak_heap_memory, heap_blocks; +#endif /* MBEDTLS_MEMORY_DEBUG */ +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ /* * Make sure memory references are valid in case we exit early. @@ -3742,6 +3745,13 @@ } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_memory_buffer_alloc_cur_get( ¤t_heap_memory, &heap_blocks ); + mbedtls_memory_buffer_alloc_max_get( &peak_heap_memory, &heap_blocks ); + mbedtls_printf( "Heap memory usage after handshake: %lu bytes. Peak memory usage was %lu\n", + (unsigned long) current_heap_memory, (unsigned long) peak_heap_memory ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + if( opt.exchanges == 0 ) goto close_notify;
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index a6fbb67..9246eae 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh
@@ -1194,6 +1194,23 @@ if_build_succeeded tests/compat.sh } +component_test_ssl_alloc_buffer_and_mfl () { + msg "build: default config with memory buffer allocator and MFL extension" + scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C + scripts/config.py set MBEDTLS_PLATFORM_MEMORY + scripts/config.py set MBEDTLS_MEMORY_DEBUG + scripts/config.py set MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + CC=gcc cmake . + make + + msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH" + make test + + msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH" + if_build_succeeded tests/ssl-opt.sh -f "Handshake memory usage" +} + component_test_when_no_ciphersuites_have_mac () { msg "build: when no ciphersuites have MAC" scripts/config.py unset MBEDTLS_CIPHER_NULL_CIPHER
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index e65b8ec..cc6bc13 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh
@@ -223,7 +223,7 @@ } requires_ciphersuite_enabled() { - if [ -z "$($P_CLI --help | grep $1)" ]; then + if [ -z "$($P_CLI --help 2>/dev/null | grep $1)" ]; then SKIP_NEXT="YES" fi } @@ -525,6 +525,45 @@ fi } +# Get handshake memory usage from server or client output and put it into the variable specified by the first argument +handshake_memory_get() { + OUTPUT_VARIABLE="$1" + OUTPUT_FILE="$2" + + # Get memory usage from a pattern like "Heap memory usage after handshake: 23112 bytes. Peak memory usage was 33112" + MEM_USAGE=$(sed -n 's/.*Heap memory usage after handshake: //p' < "$OUTPUT_FILE" | grep -o "[0-9]*" | head -1) + + # Check if memory usage was read + if [ -z "$MEM_USAGE" ]; then + echo "Error: Can not read the value of handshake memory usage" + return 1 + else + eval "$OUTPUT_VARIABLE=$MEM_USAGE" + return 0 + fi +} + +# Get handshake memory usage from server or client output and check if this value +# is not higher than the maximum given by the first argument +handshake_memory_check() { + MAX_MEMORY="$1" + OUTPUT_FILE="$2" + + # Get memory usage + if ! handshake_memory_get "MEMORY_USAGE" "$OUTPUT_FILE"; then + return 1 + fi + + # Check if memory usage is below max value + if [ "$MEMORY_USAGE" -gt "$MAX_MEMORY" ]; then + echo "\nFailed: Handshake memory usage was $MEMORY_USAGE bytes," \ + "but should be below $MAX_MEMORY bytes" + return 1 + else + return 0 + fi +} + # wait for client to terminate and set CLI_EXIT # must be called right after starting the client wait_client_done() { @@ -865,6 +904,58 @@ -C "error" } +# Test that the server's memory usage after a handshake is reduced when a client specifies +# a maximum fragment length. +# first argument ($1) is MFL for SSL client +# second argument ($2) is memory usage for SSL client with default MFL (16k) +run_test_memory_after_hanshake_with_mfl() +{ + # The test passes if the difference is around 2*(16k-MFL) + local MEMORY_USAGE_LIMIT="$(( $2 - ( 2 * ( 16384 - $1 )) ))" + + # Leave some margin for robustness + MEMORY_USAGE_LIMIT="$(( ( MEMORY_USAGE_LIMIT * 110 ) / 100 ))" + + run_test "Handshake memory usage (MFL $1)" \ + "$P_SRV debug_level=3 auth_mode=required force_version=tls1_2" \ + "$P_CLI debug_level=3 force_version=tls1_2 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key \ + force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM max_frag_len=$1" \ + 0 \ + -F "handshake_memory_check $MEMORY_USAGE_LIMIT" +} + + +# Test that the server's memory usage after a handshake is reduced when a client specifies +# different values of Maximum Fragment Length: default (16k), 4k, 2k, 1k and 512 bytes +run_tests_memory_after_hanshake() +{ + # all tests in this sequence requires the same configuration (see requires_config_enabled()) + SKIP_THIS_TESTS="$SKIP_NEXT" + + # first test with default MFU is to get reference memory usage + MEMORY_USAGE_MFL_16K=0 + run_test "Handshake memory usage initial (MFL 16384 - default)" \ + "$P_SRV debug_level=3 auth_mode=required force_version=tls1_2" \ + "$P_CLI debug_level=3 force_version=tls1_2 \ + crt_file=data_files/server5.crt key_file=data_files/server5.key \ + force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM" \ + 0 \ + -F "handshake_memory_get MEMORY_USAGE_MFL_16K" + + SKIP_NEXT="$SKIP_THIS_TESTS" + run_test_memory_after_hanshake_with_mfl 4096 "$MEMORY_USAGE_MFL_16K" + + SKIP_NEXT="$SKIP_THIS_TESTS" + run_test_memory_after_hanshake_with_mfl 2048 "$MEMORY_USAGE_MFL_16K" + + SKIP_NEXT="$SKIP_THIS_TESTS" + run_test_memory_after_hanshake_with_mfl 1024 "$MEMORY_USAGE_MFL_16K" + + SKIP_NEXT="$SKIP_THIS_TESTS" + run_test_memory_after_hanshake_with_mfl 512 "$MEMORY_USAGE_MFL_16K" +} + cleanup() { rm -f $CLI_OUT $SRV_OUT $PXY_OUT $SESSION test -n "${SRV_PID:-}" && kill $SRV_PID >/dev/null 2>&1 @@ -8820,6 +8911,12 @@ -c "exported keylen is " \ -c "exported ivlen is " +# Test heap memory usage after handshake +requires_config_enabled MBEDTLS_MEMORY_DEBUG +requires_config_enabled MBEDTLS_MEMORY_BUFFER_ALLOC_C +requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +run_tests_memory_after_hanshake + # Final report echo "------------------------------------------------------------------------"