Add an option to test constant-flow with valgrind

Currently the new component in all.sh fails because
mbedtls_ssl_cf_memcpy_offset() is not actually constant flow - this is on
purpose to be able to verify that the new test works.

Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
This commit is contained in:
Manuel Pégourié-Gonnard 2020-08-25 11:26:37 +02:00
parent 3b490a0a01
commit 426c2d4a38
5 changed files with 74 additions and 1 deletions

View File

@ -458,6 +458,23 @@
*/ */
//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN //#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
/**
* \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
*
* Enable testing of the constant-flow nature of some sensitive functions with
* valgrind's memcheck tool. This causes some existing tests to also test
* non-functional properties of the code under test.
*
* This setting requires valgrind headers for building, and is only useful for
* testing if the tests suites are run with valgrind's memcheck.
*
* \warning This macro is only used for extended testing; it is not considered
* part of the library's API, so it may change or disappear at any time.
*
* Uncomment to enable testing of the constant-flow nature of selected code.
*/
//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
/** /**
* \def MBEDTLS_TEST_NULL_ENTROPY * \def MBEDTLS_TEST_NULL_ENTROPY
* *

View File

@ -256,6 +256,9 @@ static const char *features[] = {
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
"MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN",
#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ #endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND)
"MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND",
#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
"MBEDTLS_TEST_NULL_ENTROPY", "MBEDTLS_TEST_NULL_ENTROPY",
#endif /* MBEDTLS_TEST_NULL_ENTROPY */ #endif /* MBEDTLS_TEST_NULL_ENTROPY */

View File

@ -125,6 +125,7 @@ MBEDTLS_REMOVE_ARC4_CIPHERSUITES
MBEDTLS_RSA_NO_CRT MBEDTLS_RSA_NO_CRT
MBEDTLS_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL
MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
MBEDTLS_TEST_NULL_ENTROPY MBEDTLS_TEST_NULL_ENTROPY
MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
MBEDTLS_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT

View File

@ -979,6 +979,28 @@ component_test_memsan_constant_flow () {
make test make test
} }
component_test_valgrind_constant_flow () {
# This tests both (1) everything that valgrind's memcheck usually checks
# (heap buffer overflows, use of uninitialized memory, use-after-free,
# etc.) and (2) branches or memory access depending on secret values,
# which will be reported as uninitialized memory. To distinguish between
# secret and actually uninitialized:
# - unset MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND - does the failure persist?
# - or alternatively, build with debug info and manually run the offending
# test suite with valgrind --track-origins=yes, then check if the origin
# was TEST_CF_SECRET() or something else.
msg "build: cmake release GCC, full config with constant flow testing"
scripts/config.pl full
scripts/config.pl set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
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)"
make memcheck
}
component_test_default_no_deprecated () { component_test_default_no_deprecated () {
# Test that removing the deprecated features from the default # Test that removing the deprecated features from the default
# configuration leaves something consistent. # configuration leaves something consistent.

View File

@ -38,6 +38,27 @@ typedef UINT32 uint32_t;
#include <unistd.h> #include <unistd.h>
#endif #endif
/*
* Define the two macros
*
* #define TEST_CF_SECRET(ptr, size)
* #define TEST_CF_PUBLIC(ptr, size)
*
* that can be used in tests to mark a memory area as secret (no branch or
* memory access should depend on it) or public (default, only needs to be
* marked explicitly when it was derived from secret data).
*
* Arguments:
* - ptr: a pointer to the memory area to be marked
* - size: the size in bytes of the memory area
*
* Implementation:
* The basic idea is that of ctgrind <https://github.com/agl/ctgrind>: we can
* re-use tools that were designed for checking use of uninitialized memory.
* 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.
*/
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
#include <sanitizer/msan_interface.h> #include <sanitizer/msan_interface.h>
@ -47,7 +68,16 @@ typedef UINT32 uint32_t;
#define TEST_CF_PUBLIC __msan_unpoison #define TEST_CF_PUBLIC __msan_unpoison
// void __msan_unpoison(const volatile void *a, size_t size); // void __msan_unpoison(const volatile void *a, size_t size);
#else /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ #elif defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND)
#include <valgrind/memcheck.h>
#define TEST_CF_SECRET VALGRIND_MAKE_MEM_UNDEFINED
// VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
#define TEST_CF_PUBLIC VALGRIND_MAKE_MEM_DEFINED
// VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
#else /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN ||
MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */
#define TEST_CF_SECRET(ptr, size) #define TEST_CF_SECRET(ptr, size)
#define TEST_CF_PUBLIC(ptr, size) #define TEST_CF_PUBLIC(ptr, size)