Add MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN

This option allows to test the constant-flow nature of selected code, using
MemSan and the fundamental observation behind ctgrind that the set of
operations allowed on undefined memory by dynamic analysers is the same as the
set of operations allowed on secret data to avoid leaking it to a local
attacker via side channels, namely, any operation except branching and
dereferencing.

(This isn't the full story, as on some CPUs some instructions have variable
execution depending on the inputs, most notably division and on some cores
multiplication. However, testing that no branch or memory access depends on
secret data is already a good start.)

Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
This commit is contained in:
Manuel Pégourié-Gonnard 2020-07-10 09:35:54 +02:00
parent 65a6fa3e26
commit 6240defd17
8 changed files with 99 additions and 0 deletions

View File

@ -186,6 +186,16 @@
#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
#endif #endif
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#define MBEDTLS_HAS_MEMSAN
#endif
#endif
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN)
#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer"
#endif
#undef MBEDTLS_HAS_MEMSAN
#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ #if defined(MBEDTLS_TEST_NULL_ENTROPY) && \
( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) )
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" #error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites"

View File

@ -1906,6 +1906,19 @@
*/ */
//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH //#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
/**
* \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
*
* Enable testing of the constant-flow nature of some sensitive functions with
* clang's MemorySanitizer. This causes some existing tests to also test
* non-functional properties of the code under test.
*
* This setting requires compiling with clang -fsanitize=memory.
*
* Uncomment to enable testing of the constant-flow nature of seletected code.
*/
//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
/** /**
* \def MBEDTLS_TEST_HOOKS * \def MBEDTLS_TEST_HOOKS
* *

View File

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

View File

@ -1538,6 +1538,14 @@ int query_config( const char *config )
} }
#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
if( strcmp( "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", config ) == 0 )
{
MACRO_EXPANSION_TO_STR( MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN );
return( 0 );
}
#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */
#if defined(MBEDTLS_TEST_HOOKS) #if defined(MBEDTLS_TEST_HOOKS)
if( strcmp( "MBEDTLS_TEST_HOOKS", config ) == 0 ) if( strcmp( "MBEDTLS_TEST_HOOKS", config ) == 0 )
{ {

View File

@ -194,6 +194,7 @@ EXCLUDE_FROM_FULL = frozenset([
'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS 'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS
'MBEDTLS_SHA512_NO_SHA384', # removes a feature 'MBEDTLS_SHA512_NO_SHA384', # removes a feature
'MBEDTLS_SSL_HW_RECORD_ACCEL', # build dependency (hook functions) 'MBEDTLS_SSL_HW_RECORD_ACCEL', # build dependency (hook functions)
'MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN', # build dependency (clang+memsan)
'MBEDTLS_TEST_NULL_ENTROPY', # removes a feature 'MBEDTLS_TEST_NULL_ENTROPY', # removes a feature
'MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION', # influences the use of X.509 in TLS 'MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION', # influences the use of X.509 in TLS
'MBEDTLS_ZLIB_SUPPORT', # build dependency (libz) 'MBEDTLS_ZLIB_SUPPORT', # build dependency (libz)

View File

@ -0,0 +1,51 @@
/**
* \file constant_flow.h
*
* \brief This file contains tools to ensure tested code has constant flow.
*/
/*
* Copyright (C) 2020, 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 TEST_CONSTANT_FLOW_H
#define TEST_CONSTANT_FLOW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
#include <sanitizer/msan_interface.h>
/* Use macros to avoid messing up with origin tracking */
#define TEST_CF_SECRET __msan_allocated_memory
// void __msan_allocated_memory(const volatile void* data, size_t size);
#define TEST_CF_PUBLIC __msan_unpoison
// void __msan_unpoison(const volatile void *a, size_t size);
#else /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */
#define TEST_CF_SECRET(ptr, size)
#define TEST_CF_PUBLIC(ptr, size)
#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */
#endif /* TEST_CONSTANT_FLOW_H */

View File

@ -1074,6 +1074,18 @@ component_test_full_cmake_clang () {
if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA' if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
} }
component_test_memsan_constant_flow () {
msg "build: cmake memsan, full config with constant flow testing"
scripts/config.py full
scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
scripts/config.py unset MBEDTLS_AESNI_C # memsan doesn't grok asm
CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
make
msg "test: main suites (memsan constant flow)"
make test
}
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

@ -232,6 +232,7 @@
<ClInclude Include="..\..\include\psa\crypto_struct.h" /> <ClInclude Include="..\..\include\psa\crypto_struct.h" />
<ClInclude Include="..\..\include\psa\crypto_types.h" /> <ClInclude Include="..\..\include\psa\crypto_types.h" />
<ClInclude Include="..\..\include\psa\crypto_values.h" /> <ClInclude Include="..\..\include\psa\crypto_values.h" />
<ClInclude Include="..\..\tests\include\test\constant_flow.h" />
<ClInclude Include="..\..\tests\include\test\helpers.h" /> <ClInclude Include="..\..\tests\include\test\helpers.h" />
<ClInclude Include="..\..\tests\include\test\macros.h" /> <ClInclude Include="..\..\tests\include\test\macros.h" />
<ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" /> <ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" />