Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rationalize Valgrind tests #6685

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions tests/include/test/constant_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
* This file contains two implementations: one based on MemorySanitizer, the
* other on valgrind's memcheck. If none of them is enabled, dummy macros that
* do nothing are defined for convenience.
*
* \note #TEST_CF_SECRET must be called directly from within a .function file,
* not indirectly via a macro defined under tests/include or a function
* under tests/src. This is because we only run Valgrind for constant
* flow on test suites that have greppable annotations inside them (see
* `skip_suites_without_constant_flow` in `tests/scripts/all.sh`).
*/

#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
Expand Down
38 changes: 32 additions & 6 deletions tests/scripts/all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,17 @@ component_test_full_cmake_clang () {
env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
}

skip_suites_without_constant_flow () {
# Skip the test suites that don't have any constant-flow annotations.
# This will need to be adjusted if we ever start declaring things as
# secret from macros or functions inside tests/include or tests/src.
SKIP_TEST_SUITES=$(
git -C tests/suites grep -L TEST_CF_ 'test_suite_*.function' |
sed 's/test_suite_//; s/\.function$//' |
tr '\n' ,)
export SKIP_TEST_SUITES
}

component_test_memsan_constant_flow () {
# This tests both (1) accesses to undefined memory, and (2) branches or
# memory access depending on secret values. To distinguish between those:
Expand Down Expand Up @@ -1642,12 +1653,13 @@ component_test_valgrind_constant_flow () {
scripts/config.py full
scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
skip_suites_without_constant_flow
cmake -D CMAKE_BUILD_TYPE:String=Release .
make

# this only shows a summary of the results (how many of each type)
# details are left in Testing/<date>/DynamicAnalysis.xml
msg "test: main suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
msg "test: some suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
make memcheck
}

Expand All @@ -1664,12 +1676,13 @@ component_test_valgrind_constant_flow_psa () {
msg "build: cmake release GCC, full config with constant flow testing"
scripts/config.py full
scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
skip_suites_without_constant_flow
cmake -D CMAKE_BUILD_TYPE:String=Release .
make

# this only shows a summary of the results (how many of each type)
# details are left in Testing/<date>/DynamicAnalysis.xml
msg "test: main suites (valgrind + constant flow)"
msg "test: some suites (valgrind + constant flow)"
make memcheck
}

Expand Down Expand Up @@ -3444,30 +3457,43 @@ component_test_memsan () {

component_test_valgrind () {
msg "build: Release (clang)"
# default config, in particular without MBEDTLS_USE_PSA_CRYPTO
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
make

msg "test: main suites valgrind (Release)"
msg "test: main suites, Valgrind (default config)"
make memcheck

# Optional parts (slow; currently broken on OS X because programs don't
# seem to receive signals under valgrind on OS X).
# These optional parts don't run on the CI.
if [ "$MEMORY" -gt 0 ]; then
msg "test: ssl-opt.sh --memcheck (Release)"
msg "test: ssl-opt.sh --memcheck (default config)"
tests/ssl-opt.sh --memcheck
fi

if [ "$MEMORY" -gt 1 ]; then
msg "test: compat.sh --memcheck (Release)"
msg "test: compat.sh --memcheck (default config)"
tests/compat.sh --memcheck
fi

if [ "$MEMORY" -gt 0 ]; then
msg "test: context-info.sh --memcheck (Release)"
msg "test: context-info.sh --memcheck (default config)"
tests/context-info.sh --memcheck
fi
}

component_test_valgrind_psa () {
msg "build: Release, full (clang)"
# full config, in particular with MBEDTLS_USE_PSA_CRYPTO
scripts/config.py full
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
make

msg "test: main suites, Valgrind (full config)"
make memcheck
}

support_test_cmake_out_of_source () {
distrib_id=""
distrib_ver=""
Expand Down
11 changes: 11 additions & 0 deletions tests/suites/test_suite_constant_time.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# these are the numbers we'd get with an empty plaintext and truncated HMAC
Constant-flow memcpy from offset: small
ssl_cf_memcpy_offset:0:5:10

# we could get this with 255-bytes plaintext and untruncated SHA-256
Constant-flow memcpy from offset: medium
ssl_cf_memcpy_offset:0:255:32

# we could get this with 255-bytes plaintext and untruncated SHA-384
Constant-flow memcpy from offset: large
ssl_cf_memcpy_offset:100:339:48
49 changes: 49 additions & 0 deletions tests/suites/test_suite_constant_time.function
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* BEGIN_HEADER */
/** \file test_suite_constant_time.function
*
* Functional testing of functions in the constant_time module.
*
* The tests are instrumented with #TEST_CF_SECRET and #TEST_CF_PUBLIC
* (see tests/include/test/constant_flow.h) so that running the tests
* under MSan or Valgrind will detect a non-constant-time implementation.
*/

#include <mbedtls/constant_time.h>
#include <constant_time_internal.h>
#include <constant_time_invasive.h>

#include <test/constant_flow.h>
/* END_HEADER */

/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
void ssl_cf_memcpy_offset( int offset_min, int offset_max, int len )
{
unsigned char *dst = NULL;
unsigned char *src = NULL;
size_t src_len = offset_max + len;
size_t secret;

ASSERT_ALLOC( dst, len );
ASSERT_ALLOC( src, src_len );

/* Fill src in a way that we can detect if we copied the right bytes */
mbedtls_test_rnd_std_rand( NULL, src, src_len );

for( secret = offset_min; secret <= (size_t) offset_max; secret++ )
{
mbedtls_test_set_step( (int) secret );

TEST_CF_SECRET( &secret, sizeof( secret ) );
mbedtls_ct_memcpy_offset( dst, src, secret,
offset_min, offset_max, len );
TEST_CF_PUBLIC( &secret, sizeof( secret ) );
TEST_CF_PUBLIC( dst, len );

ASSERT_COMPARE( dst, len, src + secret, len );
}

exit:
mbedtls_free( dst );
mbedtls_free( src );
}
/* END_CASE */
15 changes: 15 additions & 0 deletions tests/suites/test_suite_constant_time_hmac.data
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Constant-flow HMAC: MD5
depends_on:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_MD5

Constant-flow HMAC: SHA1
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA1

Constant-flow HMAC: SHA256
depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA256

Constant-flow HMAC: SHA384
depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA384
160 changes: 160 additions & 0 deletions tests/suites/test_suite_constant_time_hmac.function
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/* BEGIN_HEADER */

#include <mbedtls/constant_time.h>
#include <mbedtls/legacy_or_psa.h>
#include <mbedtls/md.h>
#include <constant_time_internal.h>
#include <hash_info.h>

#include <test/constant_flow.h>
/* END_HEADER */

/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
void ssl_cf_hmac( int hash )
{
/*
* Test the function mbedtls_ct_hmac() against a reference
* implementation.
*/
#if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t alg;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
#else
mbedtls_md_context_t ctx, ref_ctx;
const mbedtls_md_info_t *md_info;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
size_t out_len, block_size;
size_t min_in_len, in_len, max_in_len, i;
/* TLS additional data is 13 bytes (hence the "lucky 13" name) */
unsigned char add_data[13];
unsigned char ref_out[MBEDTLS_HASH_MAX_SIZE];
unsigned char *data = NULL;
unsigned char *out = NULL;
unsigned char rec_num = 0;

USE_PSA_INIT( );

#if defined(MBEDTLS_USE_PSA_CRYPTO)
alg = PSA_ALG_HMAC( mbedtls_hash_info_psa_from_md( hash ) );

out_len = PSA_HASH_LENGTH( alg );
block_size = PSA_HASH_BLOCK_LENGTH( alg );

/* mbedtls_ct_hmac() requires the key to be exportable */
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT |
PSA_KEY_USAGE_VERIFY_HASH );
psa_set_key_algorithm( &attributes, PSA_ALG_HMAC( alg ) );
psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
#else
mbedtls_md_init( &ctx );
mbedtls_md_init( &ref_ctx );

md_info = mbedtls_md_info_from_type( hash );
TEST_ASSERT( md_info != NULL );
out_len = mbedtls_md_get_size( md_info );
TEST_ASSERT( out_len != 0 );
block_size = hash == MBEDTLS_MD_SHA384 ? 128 : 64;
#endif /* MBEDTLS_USE_PSA_CRYPTO */

/* Use allocated out buffer to catch overwrites */
ASSERT_ALLOC( out, out_len );

#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Set up dummy key */
memset( ref_out, 42, sizeof( ref_out ) );
TEST_EQUAL( PSA_SUCCESS, psa_import_key( &attributes,
ref_out, out_len,
&key ) );
#else
/* Set up contexts with the given hash and a dummy key */
TEST_EQUAL( 0, mbedtls_md_setup( &ctx, md_info, 1 ) );
TEST_EQUAL( 0, mbedtls_md_setup( &ref_ctx, md_info, 1 ) );
memset( ref_out, 42, sizeof( ref_out ) );
TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ctx, ref_out, out_len ) );
TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ref_ctx, ref_out, out_len ) );
memset( ref_out, 0, sizeof( ref_out ) );
#endif

/*
* Test all possible lengths up to a point. The difference between
* max_in_len and min_in_len is at most 255, and make sure they both vary
* by at least one block size.
*/
for( max_in_len = 0; max_in_len <= 255 + block_size; max_in_len++ )
{
mbedtls_test_set_step( max_in_len * 10000 );

/* Use allocated in buffer to catch overreads */
ASSERT_ALLOC( data, max_in_len );

min_in_len = max_in_len > 255 ? max_in_len - 255 : 0;
for( in_len = min_in_len; in_len <= max_in_len; in_len++ )
{
mbedtls_test_set_step( max_in_len * 10000 + in_len );

/* Set up dummy data and add_data */
rec_num++;
memset( add_data, rec_num, sizeof( add_data ) );
for( i = 0; i < in_len; i++ )
data[i] = ( i & 0xff ) ^ rec_num;

/* Get the function's result */
TEST_CF_SECRET( &in_len, sizeof( in_len ) );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
TEST_EQUAL( 0, mbedtls_ct_hmac( key, PSA_ALG_HMAC( alg ),
add_data, sizeof( add_data ),
data, in_len,
min_in_len, max_in_len,
out ) );
#else
TEST_EQUAL( 0, mbedtls_ct_hmac( &ctx, add_data, sizeof( add_data ),
data, in_len,
min_in_len, max_in_len,
out ) );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
TEST_CF_PUBLIC( &in_len, sizeof( in_len ) );
TEST_CF_PUBLIC( out, out_len );

#if defined(MBEDTLS_USE_PSA_CRYPTO)
TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_setup( &operation,
key, alg ) );
TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation, add_data,
sizeof( add_data ) ) );
TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation,
data, in_len ) );
TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_finish( &operation,
out, out_len ) );
#else
/* Compute the reference result */
TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, add_data,
sizeof( add_data ) ) );
TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, data, in_len ) );
TEST_EQUAL( 0, mbedtls_md_hmac_finish( &ref_ctx, ref_out ) );
TEST_EQUAL( 0, mbedtls_md_hmac_reset( &ref_ctx ) );

/* Compare */
ASSERT_COMPARE( out, out_len, ref_out, out_len );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
}

mbedtls_free( data );
data = NULL;
}

exit:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_mac_abort( &operation );
psa_destroy_key( key );
#else
mbedtls_md_free( &ref_ctx );
mbedtls_md_free( &ctx );
#endif /* MBEDTLS_USE_PSA_CRYPTO */

mbedtls_free( data );
mbedtls_free( out );

USE_PSA_DONE( );
}
/* END_CASE */
28 changes: 0 additions & 28 deletions tests/suites/test_suite_ssl.data
Original file line number Diff line number Diff line change
Expand Up @@ -3378,34 +3378,6 @@ TLS 1.3: SRV: Session serialization, load buffer size
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
ssl_serialize_session_load_buf_size:0:"":MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3

Constant-flow HMAC: MD5
depends_on:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_MD5

Constant-flow HMAC: SHA1
depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA1

Constant-flow HMAC: SHA256
depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA256

Constant-flow HMAC: SHA384
depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA
ssl_cf_hmac:MBEDTLS_MD_SHA384

# these are the numbers we'd get with an empty plaintext and truncated HMAC
Constant-flow memcpy from offset: small
ssl_cf_memcpy_offset:0:5:10

# we could get this with 255-bytes plaintext and untruncated SHA-256
Constant-flow memcpy from offset: medium
ssl_cf_memcpy_offset:0:255:32

# we could get this with 255-bytes plaintext and untruncated SHA-384
Constant-flow memcpy from offset: large
ssl_cf_memcpy_offset:100:339:48

Test configuration of groups for DHE through mbedtls_ssl_conf_curves()
conf_curve:

Expand Down
Loading