Merge remote-tracking branch 'mbedtls-3.6' into tls-defragmentation-merge-3.6-20250303

This commit is contained in:
Gilles Peskine 2025-03-02 21:16:08 +01:00
commit e0f1240cd5
23 changed files with 76 additions and 964 deletions

View File

@ -61,6 +61,7 @@ endif()
# Set the project root directory.
set(MBEDTLS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(MBEDTLS_FRAMEWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/framework)
option(ENABLE_PROGRAMS "Build Mbed TLS programs." ON)

View File

@ -144,3 +144,22 @@ Policy](https://github.com/hacl-star/hacl-star/blob/main/SECURITY.md).)
The Everest variant is only used when `MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED`
configuration option is defined. This option is off by default.
#### Formatting of X.509 certificates and certificate signing requests
When parsing X.509 certificates and certificate signing requests (CSRs),
Mbed TLS does not check that they are strictly compliant with X.509 and other
relevant standards. In the case of signed certificates, the signing party is
assumed to have performed this validation (and the certificate is trusted to
be correctly formatted as long as the signature is correct).
Similarly, CSRs are implicitly trusted by Mbed TLS to be standards-compliant.
**Warning!** Mbed TLS must not be used to sign untrusted CSRs unless extra
validation is performed separately to ensure that they are compliant to the
relevant specifications. This makes Mbed TLS on its own unsuitable for use in
a Certificate Authority (CA).
However, Mbed TLS aims to protect against memory corruption and other
undefined behavior when parsing certificates and CSRs. If a CSR or signed
certificate causes undefined behavior when it is parsed by Mbed TLS, that
is considered a security vulnerability.

View File

@ -275,7 +275,7 @@ This section lists some strategies that are currently used for invasive testing,
Goal: test that `mbedtls_platform_zeroize` does wipe the memory buffer.
Solution ([debugger](#debugger-based-testing)): implemented in `tests/scripts/test_zeroize.gdb`.
Solution ([debugger](#debugger-based-testing)): implemented in `framework/tests/programs/test_zeroize.gdb`.
Rationale: this cannot be tested by adding C code, because the danger is that the compiler optimizes the zeroization away, and any C code that observes the zeroization would cause the compiler not to optimize it away.

@ -1 +1 @@
Subproject commit 2000db429553aa38e5875c621daf32aa8b63c340
Subproject commit 523a12d05b91301b020e2aa560d9774135e3a801

View File

@ -1,4 +1,5 @@
MBEDTLS_TEST_PATH = ../tests
FRAMEWORK = ${MBEDTLS_PATH}/framework
include ../scripts/common.make
ifeq ($(shell uname -s),Linux)
@ -24,6 +25,8 @@ else
BUILD_DLOPEN =
endif
LOCAL_CFLAGS += -I$(FRAMEWORK)/tests/programs
## The following assignment is the list of base names of applications that
## will be built on Windows. Extra Linux/Unix/POSIX-only applications can
## be declared by appending with `APPS += ...` afterwards.
@ -298,7 +301,7 @@ ssl/ssl_client1$(EXEXT): ssl/ssl_client1.c $(DEP)
SSL_TEST_OBJECTS = test/query_config.o ssl/ssl_test_lib.o
SSL_TEST_DEPS = $(SSL_TEST_OBJECTS) \
test/query_config.h \
$(FRAMEWORK)/tests/programs/query_config.h \
ssl/ssl_test_lib.h \
ssl/ssl_test_common_source.c \
$(DEP)
@ -319,7 +322,7 @@ ssl/ssl_server2$(EXEXT): ssl/ssl_server2.c $(SSL_TEST_DEPS)
echo " CC ssl/ssl_server2.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server2.c $(SSL_TEST_OBJECTS) $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
ssl/ssl_context_info$(EXEXT): ssl/ssl_context_info.c test/query_config.o test/query_config.h $(DEP)
ssl/ssl_context_info$(EXEXT): ssl/ssl_context_info.c test/query_config.o $(FRAMEWORK)/tests/programs/query_config.h $(DEP)
echo " CC ssl/ssl_context_info.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_context_info.c test/query_config.o $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@ -360,17 +363,17 @@ test/dlopen$(EXEXT): test/dlopen.c $(DEP)
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/dlopen.c $(LDFLAGS) $(DLOPEN_LDFLAGS) -o $@
endif
test/metatest$(EXEXT): test/metatest.c $(DEP)
echo " CC test/metatest.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -I ../library test/metatest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/metatest$(EXEXT): $(FRAMEWORK)/tests/programs/metatest.c $(DEP)
echo " CC $(FRAMEWORK)/tests/programs/metatest.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -I ../library $(FRAMEWORK)/tests/programs/metatest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/query_config.o: test/query_config.c test/query_config.h $(DEP)
echo " CC test/query_config.c"
test/query_config.o: test/query_config.c $(FRAMEWORK)/tests/programs/query_config.h $(DEP)
echo " CC $(FRAMEWORK)/tests/programs/query_config.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c test/query_config.c -o $@
test/query_included_headers$(EXEXT): test/query_included_headers.c $(DEP)
echo " CC test/query_included_headers.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_included_headers.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/query_included_headers$(EXEXT): $(FRAMEWORK)/tests/programs/query_included_headers.c $(DEP)
echo " CC $(FRAMEWORK)/tests/programs/query_included_headers.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $(FRAMEWORK)/tests/programs/query_included_headers.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/selftest$(EXEXT): test/selftest.c $(DEP)
echo " CC test/selftest.c"
@ -380,13 +383,13 @@ test/udp_proxy$(EXEXT): test/udp_proxy.c $(DEP)
echo " CC test/udp_proxy.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/udp_proxy.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/zeroize$(EXEXT): test/zeroize.c $(DEP)
echo " CC test/zeroize.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/zeroize.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/zeroize$(EXEXT): $(FRAMEWORK)/tests/programs/zeroize.c $(DEP)
echo " CC $(FRAMEWORK)/tests/programs/zeroize.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $(FRAMEWORK)/tests/programs/zeroize.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/query_compile_time_config$(EXEXT): test/query_compile_time_config.c test/query_config.o test/query_config.h $(DEP)
echo " CC test/query_compile_time_config.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_compile_time_config.c test/query_config.o $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
test/query_compile_time_config$(EXEXT): $(FRAMEWORK)/tests/programs/query_compile_time_config.c test/query_config.o $(FRAMEWORK)/tests/programs/query_config.h $(DEP)
echo " CC $(FRAMEWORK)/tests/programs/query_compile_time_config.c"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $(FRAMEWORK)/tests/programs/query_compile_time_config.c test/query_config.o $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
util/pem2der$(EXEXT): util/pem2der.c $(DEP)
echo " CC util/pem2der.c"

View File

@ -53,7 +53,7 @@ This subdirectory mostly contains sample programs that illustrate specific featu
## Random number generator (RNG) examples
* [`random/gen_entropy.c`](random/gen_entropy.c): shows how to use the default entropy sources to generate random data.
* [`random/gen_entropy.c`](random/gen_entropy.c): shows how to use the default entropy sources to generate random data.
Note: most applications should only use the entropy generator to seed a cryptographic pseudorandom generator, as illustrated by `random/gen_random_ctr_drbg.c`.
* [`random/gen_random_ctr_drbg.c`](random/gen_random_ctr_drbg.c): shows how to use the default entropy sources to seed a pseudorandom generator, and how to use the resulting random generator to generate random data.
@ -96,7 +96,7 @@ In addition to providing options for testing client-side features, the `ssl_clie
* [`test/udp_proxy.c`](test/udp_proxy.c): a UDP proxy that can inject certain failures (delay, duplicate, drop). Useful for testing DTLS.
* [`test/zeroize.c`](test/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`tests/scripts/test_zeroize.gdb`](tests/scripts/test_zeroize.gdb).
* [`test/zeroize.c`](../framework/tests/programs/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`test_zeroize.gdb`](../framework/tests/programs/test_zeroize.gdb).
## Development utilities

View File

@ -1,137 +0,0 @@
## Common shell functions used by demo scripts programs/*/*.sh.
## How to write a demo script
## ==========================
##
## Include this file near the top of each demo script:
## . "${0%/*}/../demo_common.sh"
##
## Start with a "msg" call that explains the purpose of the script.
## Then call the "depends_on" function to ensure that all config
## dependencies are met.
##
## As the last thing in the script, call the cleanup function.
##
## You can use the functions and variables described below.
set -e -u
## $root_dir is the root directory of the Mbed TLS source tree.
root_dir="${0%/*}"
# Find a nice path to the root directory, avoiding unnecessary "../".
# The code supports demo scripts nested up to 4 levels deep.
# The code works no matter where the demo script is relative to the current
# directory, even if it is called with a relative path.
n=4 # limit the search depth
while ! [ -d "$root_dir/programs" ] || ! [ -d "$root_dir/library" ]; do
if [ $n -eq 0 ]; then
echo >&2 "This doesn't seem to be an Mbed TLS source tree."
exit 125
fi
n=$((n - 1))
case $root_dir in
.) root_dir="..";;
..|?*/..) root_dir="$root_dir/..";;
?*/*) root_dir="${root_dir%/*}";;
/*) root_dir="/";;
*) root_dir=".";;
esac
done
## $programs_dir is the directory containing the sample programs.
# Assume an in-tree build.
programs_dir="$root_dir/programs"
## msg LINE...
## msg <TEXT_ORIGIN
## Display an informational message.
msg () {
if [ $# -eq 0 ]; then
sed 's/^/# /'
else
for x in "$@"; do
echo "# $x"
done
fi
}
## run "Message" COMMAND ARGUMENT...
## Display the message, then run COMMAND with the specified arguments.
run () {
echo
echo "# $1"
shift
echo "+ $*"
"$@"
}
## Like '!', but stop on failure with 'set -e'
not () {
if "$@"; then false; fi
}
## run_bad "Message" COMMAND ARGUMENT...
## Like run, but the command is expected to fail.
run_bad () {
echo
echo "$1 This must fail."
shift
echo "+ ! $*"
not "$@"
}
## config_has SYMBOL...
## Succeeds if the library configuration has all SYMBOLs set.
config_has () {
for x in "$@"; do
"$programs_dir/test/query_compile_time_config" "$x"
done
}
## depends_on SYMBOL...
## Exit if the library configuration does not have all SYMBOLs set.
depends_on () {
m=
for x in "$@"; do
if ! config_has "$x"; then
m="$m $x"
fi
done
if [ -n "$m" ]; then
cat >&2 <<EOF
$0: this demo requires the following
configuration options to be enabled at compile time:
$m
EOF
# Exit with a success status so that this counts as a pass for run_demos.py.
exit
fi
}
## Add the names of files to clean up to this whitespace-separated variable.
## The file names must not contain whitespace characters.
files_to_clean=
## Call this function at the end of each script.
## It is called automatically if the script is killed by a signal.
cleanup () {
rm -f -- $files_to_clean
}
################################################################
## End of the public interfaces. Code beyond this point is not
## meant to be called directly from a demo script.
trap 'cleanup; trap - HUP; kill -HUP $$' HUP
trap 'cleanup; trap - INT; kill -INT $$' INT
trap 'cleanup; trap - TERM; kill -TERM $$' TERM
if config_has MBEDTLS_ENTROPY_NV_SEED; then
# Create a seedfile that's sufficiently long in all library configurations.
# This is necessary for programs that use randomness.
# Assume that the name of the seedfile is the default name.
files_to_clean="$files_to_clean seedfile"
dd if=/dev/urandom of=seedfile ibs=64 obs=64 count=1
fi

View File

@ -3,7 +3,7 @@
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
. "${0%/*}/../demo_common.sh"
. "${0%/*}/../../framework/scripts/demo_common.sh"
msg <<'EOF'
This script demonstrates the use of the PSA cryptography interface to

View File

@ -3,7 +3,7 @@
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
. "${0%/*}/../demo_common.sh"
. "${0%/*}/../../framework/scripts/demo_common.sh"
msg <<'EOF'
This program demonstrates the use of the PSA cryptography interface to

View File

@ -35,20 +35,19 @@ foreach(exe IN LISTS executables)
if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
list(APPEND extra_sources
ssl_test_lib.c
${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.h
${MBEDTLS_FRAMEWORK_DIR}/tests/programs/query_config.h
${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c)
endif()
add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
${extra_sources})
target_link_libraries(${exe} ${libs} ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../framework/tests/include
target_include_directories(${exe} PRIVATE ${MBEDTLS_FRAMEWORK_DIR}/tests/programs
${MBEDTLS_FRAMEWORK_DIR}/tests/include
${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
if(GEN_FILES)
add_dependencies(${exe} generate_query_config_c)
endif()
target_include_directories(${exe}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../test)
endif()
endforeach()

View File

@ -66,7 +66,7 @@
#include <test/helpers.h>
#include "../test/query_config.h"
#include "query_config.h"
#define ALPN_LIST_SIZE 10
#define GROUP_LIST_SIZE 25

View File

@ -68,15 +68,22 @@ else()
endif()
foreach(exe IN LISTS executables_libs executables_mbedcrypto)
set(source ${exe}.c)
set(extra_sources "")
if(NOT EXISTS ${source} AND
EXISTS ${MBEDTLS_FRAMEWORK_DIR}/tests/programs/${source})
set(source ${MBEDTLS_FRAMEWORK_DIR}/tests/programs/${source})
endif()
if(exe STREQUAL "query_compile_time_config")
list(APPEND extra_sources
${CMAKE_CURRENT_SOURCE_DIR}/query_config.h
${MBEDTLS_FRAMEWORK_DIR}/tests/programs/query_config.h
${CMAKE_CURRENT_BINARY_DIR}/query_config.c)
endif()
add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
add_executable(${exe} ${source} $<TARGET_OBJECTS:mbedtls_test>
${extra_sources})
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../framework/tests/include)
target_include_directories(${exe} PRIVATE ${MBEDTLS_FRAMEWORK_DIR}/tests/include)
target_include_directories(${exe} PRIVATE ${MBEDTLS_FRAMEWORK_DIR}/tests/programs)
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../library)
if(exe STREQUAL "query_compile_time_config")
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -1,42 +0,0 @@
#!/bin/sh
# Run the shared library dynamic loading demo program.
# This is only expected to work when Mbed TLS is built as a shared library.
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
. "${0%/*}/../demo_common.sh"
msg "Test the dynamic loading of libmbed*"
program="$programs_dir/test/dlopen"
library_dir="$root_dir/library"
# Skip this test if we don't have a shared library build. Detect this
# through the absence of the demo program.
if [ ! -e "$program" ]; then
msg "$0: this demo requires a shared library build."
# Exit with a success status so that this counts as a pass for run_demos.py.
exit
fi
# ELF-based Unix-like (Linux, *BSD, Solaris, ...)
if [ -n "${LD_LIBRARY_PATH-}" ]; then
LD_LIBRARY_PATH="$library_dir:$LD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$library_dir"
fi
export LD_LIBRARY_PATH
# OSX/macOS
if [ -n "${DYLD_LIBRARY_PATH-}" ]; then
DYLD_LIBRARY_PATH="$library_dir:$DYLD_LIBRARY_PATH"
else
DYLD_LIBRARY_PATH="$library_dir"
fi
export DYLD_LIBRARY_PATH
msg "Running dynamic loading test program: $program"
msg "Loading libraries from: $library_dir"
"$program"

View File

@ -1,484 +0,0 @@
/** \file metatest.c
*
* \brief Test features of the test framework.
*
* When you run this program, it runs a single "meta-test". A meta-test
* performs an operation which should be caught as a failure by our
* test framework. The meta-test passes if this program calls `exit` with
* a nonzero status, or aborts, or is terminated by a signal, or if the
* framework running the program considers the run an error (this happens
* with Valgrind for a memory leak). The non-success of the meta-test
* program means that the test failure has been caught correctly.
*
* Some failures are purely functional: the logic of the code causes the
* test result to be set to FAIL. Other failures come from extra
* instrumentation which is not present in a normal build; for example,
* Asan or Valgrind to detect memory leaks. This is reflected by the
* "platform" associated with each meta-test.
*
* Use the companion script `tests/scripts/run-metatests.sh` to run all
* the meta-tests for a given platform and validate that they trigger a
* detected failure as expected.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <mbedtls/debug.h>
#include <mbedtls/platform.h>
#include <mbedtls/platform_util.h>
#include "test/helpers.h"
#include "test/threading_helpers.h"
#include "test/macros.h"
#include "test/memory.h"
#include "common.h"
#include <stdio.h>
#include <string.h>
#if defined(MBEDTLS_THREADING_C)
#include <mbedtls/threading.h>
#endif
/* This is an external variable, so the compiler doesn't know that we're never
* changing its value.
*/
volatile int false_but_the_compiler_does_not_know = 0;
/* Hide calls to calloc/free from static checkers such as
* `gcc-12 -Wuse-after-free`, to avoid compile-time complaints about
* code where we do mean to cause a runtime error. */
void * (* volatile calloc_but_the_compiler_does_not_know)(size_t, size_t) = mbedtls_calloc;
void(*volatile free_but_the_compiler_does_not_know)(void *) = mbedtls_free;
/* Set n bytes at the address p to all-bits-zero, in such a way that
* the compiler should not know that p is all-bits-zero. */
static void set_to_zero_but_the_compiler_does_not_know(volatile void *p, size_t n)
{
memset((void *) p, false_but_the_compiler_does_not_know, n);
}
/* Simulate an access to the given object, to avoid compiler optimizations
* in code that prepares or consumes the object. */
static void do_nothing_with_object(void *p)
{
(void) p;
}
void(*volatile do_nothing_with_object_but_the_compiler_does_not_know)(void *) =
do_nothing_with_object;
/****************************************************************/
/* Test framework features */
/****************************************************************/
static void meta_test_fail(const char *name)
{
(void) name;
mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
}
static void meta_test_not_equal(const char *name)
{
int left = 20;
int right = 10;
(void) name;
TEST_EQUAL(left, right);
exit:
;
}
static void meta_test_not_le_s(const char *name)
{
int left = 20;
int right = 10;
(void) name;
TEST_LE_S(left, right);
exit:
;
}
static void meta_test_not_le_u(const char *name)
{
size_t left = 20;
size_t right = 10;
(void) name;
TEST_LE_U(left, right);
exit:
;
}
/****************************************************************/
/* Platform features */
/****************************************************************/
static void null_pointer_dereference(const char *name)
{
(void) name;
volatile char *volatile p;
set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
/* Undefined behavior (read from null data pointer) */
mbedtls_printf("%p -> %u\n", (void *) p, (unsigned) *p);
}
static void null_pointer_call(const char *name)
{
(void) name;
unsigned(*volatile p)(void);
set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
/* Undefined behavior (execute null function pointer) */
/* The pointer representation may be truncated, but we don't care:
* the only point of printing it is to have some use of the pointer
* to dissuade the compiler from optimizing it away. */
mbedtls_printf("%lx() -> %u\n", (unsigned long) (uintptr_t) p, p());
}
/****************************************************************/
/* Memory */
/****************************************************************/
static void read_after_free(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
*p = 'a';
free_but_the_compiler_does_not_know((void *) p);
/* Undefined behavior (read after free) */
mbedtls_printf("%u\n", (unsigned) *p);
}
static void double_free(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
*p = 'a';
free_but_the_compiler_does_not_know((void *) p);
/* Undefined behavior (double free) */
free_but_the_compiler_does_not_know((void *) p);
}
static void read_uninitialized_stack(const char *name)
{
(void) name;
char buf[1];
if (false_but_the_compiler_does_not_know) {
buf[0] = '!';
}
char *volatile p = buf;
if (*p != 0) {
/* Unspecified result (read from uninitialized memory) */
mbedtls_printf("%u\n", (unsigned) *p);
}
}
static void memory_leak(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
mbedtls_printf("%u\n", (unsigned) *p);
/* Leak of a heap object */
}
/* name = "test_memory_poison_%(start)_%(offset)_%(count)_%(direction)"
* Poison a region starting at start from an 8-byte aligned origin,
* encompassing count bytes. Access the region at offset from the start.
* %(start), %(offset) and %(count) are decimal integers.
* %(direction) is either the character 'r' for read or 'w' for write.
*/
static void test_memory_poison(const char *name)
{
size_t start = 0, offset = 0, count = 0;
char direction = 'r';
if (sscanf(name,
"%*[^0-9]%" MBEDTLS_PRINTF_SIZET
"%*[^0-9]%" MBEDTLS_PRINTF_SIZET
"%*[^0-9]%" MBEDTLS_PRINTF_SIZET
"_%c",
&start, &offset, &count, &direction) != 4) {
mbedtls_fprintf(stderr, "%s: Bad name format: %s\n", __func__, name);
return;
}
union {
long long ll;
unsigned char buf[32];
} aligned;
memset(aligned.buf, 'a', sizeof(aligned.buf));
if (start > sizeof(aligned.buf)) {
mbedtls_fprintf(stderr,
"%s: start=%" MBEDTLS_PRINTF_SIZET
" > size=%" MBEDTLS_PRINTF_SIZET,
__func__, start, sizeof(aligned.buf));
return;
}
if (start + count > sizeof(aligned.buf)) {
mbedtls_fprintf(stderr,
"%s: start+count=%" MBEDTLS_PRINTF_SIZET
" > size=%" MBEDTLS_PRINTF_SIZET,
__func__, start + count, sizeof(aligned.buf));
return;
}
if (offset >= count) {
mbedtls_fprintf(stderr,
"%s: offset=%" MBEDTLS_PRINTF_SIZET
" >= count=%" MBEDTLS_PRINTF_SIZET,
__func__, offset, count);
return;
}
MBEDTLS_TEST_MEMORY_POISON(aligned.buf + start, count);
if (direction == 'w') {
aligned.buf[start + offset] = 'b';
do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
} else {
do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
mbedtls_printf("%u\n", (unsigned) aligned.buf[start + offset]);
}
}
/****************************************************************/
/* Threading */
/****************************************************************/
static void mutex_lock_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
TEST_ASSERT(mbedtls_mutex_lock(&mutex) == 0);
exit:
;
#endif
}
static void mutex_unlock_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
TEST_ASSERT(mbedtls_mutex_unlock(&mutex) == 0);
exit:
;
#endif
}
static void mutex_free_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_free(&mutex);
#endif
}
static void mutex_double_init(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_init(&mutex);
mbedtls_mutex_free(&mutex);
#endif
}
static void mutex_double_free(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
mbedtls_mutex_free(&mutex);
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_free(&mutex);
#endif
}
static void mutex_leak(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
#endif
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
}
/****************************************************************/
/* Command line entry point */
/****************************************************************/
typedef struct {
/** Command line argument that will trigger that metatest.
*
* Conventionally matches "[a-z0-9_]+". */
const char *name;
/** Platform under which that metatest is valid.
*
* - "any": should work anywhere.
* - "asan": triggers ASan (Address Sanitizer).
* - "msan": triggers MSan (Memory Sanitizer).
* - "pthread": requires MBEDTLS_THREADING_PTHREAD and MBEDTLS_TEST_HOOKS,
* which enables MBEDTLS_TEST_MUTEX_USAGE internally in the test
* framework (see framework/tests/src/threading_helpers.c).
*/
const char *platform;
/** Function that performs the metatest.
*
* The function receives the name as an argument. This allows using the
* same function to perform multiple variants of a test based on the name.
*
* When executed on a conforming platform, the function is expected to
* either cause a test failure (mbedtls_test_fail()), or cause the
* program to abort in some way (e.g. by causing a segfault or by
* triggering a sanitizer).
*
* When executed on a non-conforming platform, the function may return
* normally or may have unpredictable behavior.
*/
void (*entry_point)(const char *name);
} metatest_t;
/* The list of available meta-tests. Remember to register new functions here!
*
* Note that we always compile all the functions, so that `metatest --list`
* will always list all the available meta-tests.
*
* See the documentation of metatest_t::platform for the meaning of
* platform values.
*/
metatest_t metatests[] = {
{ "test_fail", "any", meta_test_fail },
{ "test_not_equal", "any", meta_test_not_equal },
{ "test_not_le_s", "any", meta_test_not_le_s },
{ "test_not_le_u", "any", meta_test_not_le_u },
{ "null_dereference", "any", null_pointer_dereference },
{ "null_call", "any", null_pointer_call },
{ "read_after_free", "asan", read_after_free },
{ "double_free", "asan", double_free },
{ "read_uninitialized_stack", "msan", read_uninitialized_stack },
{ "memory_leak", "asan", memory_leak },
{ "test_memory_poison_0_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_w", "poison", test_memory_poison },
{ "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
{ "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
{ "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
{ "mutex_double_init", "pthread", mutex_double_init },
{ "mutex_double_free", "pthread", mutex_double_free },
{ "mutex_leak", "pthread", mutex_leak },
{ NULL, NULL, NULL }
};
static void help(FILE *out, const char *argv0)
{
mbedtls_fprintf(out, "Usage: %s list|TEST\n", argv0);
mbedtls_fprintf(out, "Run a meta-test that should cause a test failure.\n");
mbedtls_fprintf(out, "With 'list', list the available tests and their platform requirement.\n");
}
int main(int argc, char *argv[])
{
const char *argv0 = argc > 0 ? argv[0] : "metatest";
if (argc != 2) {
help(stderr, argv0);
mbedtls_exit(MBEDTLS_EXIT_FAILURE);
}
/* Support "-help", "--help", "--list", etc. */
const char *command = argv[1];
while (*command == '-') {
++command;
}
if (strcmp(argv[1], "help") == 0) {
help(stdout, argv0);
mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
}
if (strcmp(argv[1], "list") == 0) {
for (const metatest_t *p = metatests; p->name != NULL; p++) {
mbedtls_printf("%s %s\n", p->name, p->platform);
}
mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
}
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
mbedtls_test_mutex_usage_init();
#endif
for (const metatest_t *p = metatests; p->name != NULL; p++) {
if (strcmp(argv[1], p->name) == 0) {
mbedtls_printf("Running metatest %s...\n", argv[1]);
p->entry_point(argv[1]);
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
mbedtls_test_mutex_usage_check();
#endif
int result = (int) mbedtls_test_get_result();
mbedtls_printf("Running metatest %s... done, result=%d\n",
argv[1], result);
mbedtls_exit(result == MBEDTLS_TEST_RESULT_SUCCESS ?
MBEDTLS_EXIT_SUCCESS :
MBEDTLS_EXIT_FAILURE);
}
}
mbedtls_fprintf(stderr, "%s: FATAL: No such metatest: %s\n",
argv0, command);
mbedtls_exit(MBEDTLS_EXIT_FAILURE);
}

View File

@ -1,66 +0,0 @@
/*
* Query the Mbed TLS compile time configuration
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#define USAGE \
"usage: %s [ -all | -any | -l ] <MBEDTLS_CONFIG> ...\n\n" \
"This program takes command line arguments which correspond to\n" \
"the string representation of Mbed TLS compile time configurations.\n\n" \
"If \"--all\" and \"--any\" are not used, then, if all given arguments\n" \
"are defined in the Mbed TLS build, 0 is returned; otherwise 1 is\n" \
"returned. Macro expansions of configurations will be printed (if any).\n" \
"-l\tPrint all available configuration.\n" \
"-all\tReturn 0 if all configurations are defined. Otherwise, return 1\n" \
"-any\tReturn 0 if any configuration is defined. Otherwise, return 1\n" \
"-h\tPrint this usage\n"
#include <string.h>
#include "query_config.h"
int main(int argc, char *argv[])
{
int i;
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
mbedtls_printf(USAGE, argv[0]);
return MBEDTLS_EXIT_FAILURE;
}
if (strcmp(argv[1], "-l") == 0) {
list_config();
return 0;
}
if (strcmp(argv[1], "-all") == 0) {
for (i = 2; i < argc; i++) {
if (query_config(argv[i]) != 0) {
return 1;
}
}
return 0;
}
if (strcmp(argv[1], "-any") == 0) {
for (i = 2; i < argc; i++) {
if (query_config(argv[i]) == 0) {
return 0;
}
}
return 1;
}
for (i = 1; i < argc; i++) {
if (query_config(argv[i]) != 0) {
return 1;
}
}
return 0;
}

View File

@ -1,34 +0,0 @@
/*
* Query Mbed TLS compile time configurations from mbedtls_config.h
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
#define MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
#include "mbedtls/build_info.h"
/** Check whether a given configuration symbol is enabled.
*
* \param config The symbol to query (e.g. "MBEDTLS_RSA_C").
* \return \c 0 if the symbol was defined at compile time
* (in MBEDTLS_CONFIG_FILE or mbedtls_config.h),
* \c 1 otherwise.
*
* \note This function is defined in `programs/test/query_config.c`
* which is automatically generated by
* `scripts/generate_query_config.pl`.
*/
int query_config(const char *config);
/** List all enabled configuration symbols
*
* \note This function is defined in `programs/test/query_config.c`
* which is automatically generated by
* `scripts/generate_query_config.pl`.
*/
void list_config(void);
#endif /* MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H */

View File

@ -1,29 +0,0 @@
/* Ad hoc report on included headers. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <psa/crypto.h>
#include <mbedtls/platform.h>
int main(void)
{
/* Which PSA platform header? */
#if defined(PSA_CRYPTO_PLATFORM_H)
mbedtls_printf("PSA_CRYPTO_PLATFORM_H\n");
#endif
#if defined(PSA_CRYPTO_PLATFORM_ALT_H)
mbedtls_printf("PSA_CRYPTO_PLATFORM_ALT_H\n");
#endif
/* Which PSA struct header? */
#if defined(PSA_CRYPTO_STRUCT_H)
mbedtls_printf("PSA_CRYPTO_STRUCT_H\n");
#endif
#if defined(PSA_CRYPTO_STRUCT_ALT_H)
mbedtls_printf("PSA_CRYPTO_STRUCT_ALT_H\n");
#endif
}

View File

@ -1,72 +0,0 @@
/*
* Zeroize application for debugger-driven testing
*
* This is a simple test application used for debugger-driven testing to check
* whether calls to mbedtls_platform_zeroize() are being eliminated by compiler
* optimizations. This application is used by the GDB script at
* tests/scripts/test_zeroize.gdb: the script sets a breakpoint at the last
* return statement in the main() function of this program. The debugger
* facilities are then used to manually inspect the memory and verify that the
* call to mbedtls_platform_zeroize() was not eliminated.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include <stdio.h>
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#define BUFFER_LEN 1024
static void usage(void)
{
mbedtls_printf("Zeroize is a simple program to assist with testing\n");
mbedtls_printf("the mbedtls_platform_zeroize() function by using the\n");
mbedtls_printf("debugger. This program takes a file as input and\n");
mbedtls_printf("prints the first %d characters. Usage:\n\n", BUFFER_LEN);
mbedtls_printf(" zeroize <FILE>\n");
}
int main(int argc, char **argv)
{
int exit_code = MBEDTLS_EXIT_FAILURE;
FILE *fp;
char buf[BUFFER_LEN];
char *p = buf;
char *end = p + BUFFER_LEN;
int c;
if (argc != 2) {
mbedtls_printf("This program takes exactly 1 argument\n");
usage();
mbedtls_exit(exit_code);
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
mbedtls_printf("Could not open file '%s'\n", argv[1]);
mbedtls_exit(exit_code);
}
while ((c = fgetc(fp)) != EOF && p < end - 1) {
*p++ = (char) c;
}
*p = '\0';
if (p - buf != 0) {
mbedtls_printf("%s\n", buf);
exit_code = MBEDTLS_EXIT_SUCCESS;
} else {
mbedtls_printf("The file is empty!\n");
}
fclose(fp);
mbedtls_platform_zeroize(buf, sizeof(buf));
mbedtls_exit(exit_code); // GDB_BREAK_HERE -- don't remove this comment!
}

View File

@ -22,6 +22,7 @@ my $vsx_sln_tpl_file = "scripts/data_files/vs2017-sln-template.sln";
my $vsx_sln_file = "$vsx_dir/mbedTLS.sln";
my $programs_dir = 'programs';
my $framework_programs_dir = 'framework/tests/programs';
my $mbedtls_header_dir = 'include/mbedtls';
my $psa_header_dir = 'include/psa';
my $source_dir = 'library';
@ -52,6 +53,7 @@ my @include_directories = qw(
3rdparty/everest/include/everest/kremlib
tests/include
framework/tests/include
framework/tests/programs
);
my $include_directories = join(';', map {"../../$_"} @include_directories);
@ -112,7 +114,8 @@ sub check_dirs {
&& -d $test_header_dir
&& -d $tls_test_header_dir
&& -d $test_drivers_header_dir
&& -d $programs_dir;
&& -d $programs_dir
&& -d $framework_programs_dir;
}
sub slurp_file {
@ -151,7 +154,14 @@ sub gen_app {
(my $appname = $path) =~ s/.*\\//;
my $is_test_app = ($path =~ m/^test\\/);
my $srcs = "<ClCompile Include=\"..\\..\\programs\\$path.c\" \/>";
my $srcs;
if( $appname eq "metatest" or $appname eq "query_compile_time_config" or
$appname eq "query_included_headers" or $appname eq "zeroize" ) {
$srcs = "<ClCompile Include=\"..\\..\\framework\\tests\\programs\\$appname.c\" \/>";
} else {
$srcs = "<ClCompile Include=\"..\\..\\programs\\$path.c\" \/>";
}
if( $appname eq "ssl_client2" or $appname eq "ssl_server2" or
$appname eq "query_compile_time_config" ) {
$srcs .= "\n <ClCompile Include=\"..\\..\\programs\\test\\query_config.c\" \/>";
@ -267,6 +277,7 @@ sub main {
$tls_test_header_dir,
$test_drivers_header_dir,
$source_dir,
$framework_programs_dir,
@thirdparty_header_dirs,
);
my @headers = (map { <$_/*.h> } @header_dirs);

View File

@ -13,7 +13,7 @@ component_test_make_shared () {
msg "build/test: make shared" # ~ 40s
make SHARED=1 TEST_CPP=1 all check
ldd programs/util/strerror | grep libmbedcrypto
programs/test/dlopen_demo.sh
$FRAMEWORK/tests/programs/dlopen_demo.sh
}
component_test_cmake_shared () {
@ -22,7 +22,7 @@ component_test_cmake_shared () {
make
ldd programs/util/strerror | grep libmbedcrypto
make test
programs/test/dlopen_demo.sh
$FRAMEWORK/tests/programs/dlopen_demo.sh
}
support_test_cmake_out_of_source () {

View File

@ -135,7 +135,7 @@ component_test_zeroize () {
for compiler in clang gcc; do
msg "test: $compiler $optimization_flag, mbedtls_platform_zeroize()"
make programs CC="$compiler" DEBUG=1 CFLAGS="$optimization_flag"
gdb -ex "$gdb_disable_aslr" -x tests/scripts/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
gdb -ex "$gdb_disable_aslr" -x $FRAMEWORK/tests/programs/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
grep "The buffer was correctly zeroized" test_zeroize.log
not grep -i "error" test_zeroize.log
rm -f test_zeroize.log

View File

@ -1,64 +0,0 @@
# test_zeroize.gdb
#
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
#
# Purpose
#
# Run a test using the debugger to check that the mbedtls_platform_zeroize()
# function in platform_util.h is not being optimized out by the compiler. To do
# so, the script loads the test program at programs/test/zeroize.c and sets a
# breakpoint at the last return statement in main(). When the breakpoint is
# hit, the debugger manually checks the contents to be zeroized and checks that
# it is actually cleared.
#
# The mbedtls_platform_zeroize() test is debugger driven because there does not
# seem to be a mechanism to reliably check whether the zeroize calls are being
# eliminated by compiler optimizations from within the compiled program. The
# problem is that a compiler would typically remove what it considers to be
# "unnecessary" assignments as part of redundant code elimination. To identify
# such code, the compilar will create some form dependency graph between
# reads and writes to variables (among other situations). It will then use this
# data structure to remove redundant code that does not have an impact on the
# program's observable behavior. In the case of mbedtls_platform_zeroize(), an
# intelligent compiler could determine that this function clears a block of
# memory that is not accessed later in the program, so removing the call to
# mbedtls_platform_zeroize() does not have an observable behavior. However,
# inserting a test after a call to mbedtls_platform_zeroize() to check whether
# the block of memory was correctly zeroed would force the compiler to not
# eliminate the mbedtls_platform_zeroize() call. If this does not occur, then
# the compiler potentially has a bug.
#
# Note: This test requires that the test program is compiled with -g3.
set confirm off
file ./programs/test/zeroize
search GDB_BREAK_HERE
break $_
set args ./programs/test/zeroize.c
run
set $i = 0
set $len = sizeof(buf)
set $buf = buf
while $i < $len
if $buf[$i++] != 0
echo The buffer at was not zeroized\n
quit 1
end
end
echo The buffer was correctly zeroized\n
continue
if $_exitcode != 0
echo The program did not terminate correctly\n
quit 1
end
quit 0

View File

@ -15,7 +15,7 @@
/* Test that poison+unpoison leaves the memory accessible. */
/* We can't test that poisoning makes the memory inaccessible:
* there's no sane way to catch an Asan/Valgrind complaint.
* That negative testing is done in programs/test/metatest.c. */
* That negative testing is done in framework/tests/programs/metatest.c. */
void memory_poison_unpoison(int align, int size)
{
unsigned char *buf = NULL;