1a8e1175bSopenharmony_ci/**
2a8e1175bSopenharmony_ci * \file memory.h
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci * \brief   Helper macros and functions related to testing memory management.
5a8e1175bSopenharmony_ci */
6a8e1175bSopenharmony_ci
7a8e1175bSopenharmony_ci/*
8a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
9a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
10a8e1175bSopenharmony_ci */
11a8e1175bSopenharmony_ci
12a8e1175bSopenharmony_ci#ifndef TEST_MEMORY_H
13a8e1175bSopenharmony_ci#define TEST_MEMORY_H
14a8e1175bSopenharmony_ci
15a8e1175bSopenharmony_ci#include "mbedtls/build_info.h"
16a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
17a8e1175bSopenharmony_ci#include "test/helpers.h"
18a8e1175bSopenharmony_ci
19a8e1175bSopenharmony_ci/** \def MBEDTLS_TEST_MEMORY_CAN_POISON
20a8e1175bSopenharmony_ci *
21a8e1175bSopenharmony_ci * This macro is defined if the tests are compiled with a method to mark
22a8e1175bSopenharmony_ci * memory as poisoned, which can be used to enforce some memory access
23a8e1175bSopenharmony_ci * policies.
24a8e1175bSopenharmony_ci *
25a8e1175bSopenharmony_ci * Support for the C11 thread_local keyword is also required.
26a8e1175bSopenharmony_ci *
27a8e1175bSopenharmony_ci * Currently, only Asan (Address Sanitizer) is supported.
28a8e1175bSopenharmony_ci */
29a8e1175bSopenharmony_ci#if defined(MBEDTLS_TEST_HAVE_ASAN) && \
30a8e1175bSopenharmony_ci    (__STDC_VERSION__ >= 201112L) && \
31a8e1175bSopenharmony_ci    !defined(PSA_CRYPTO_DRIVER_TEST)
32a8e1175bSopenharmony_ci#  define MBEDTLS_TEST_MEMORY_CAN_POISON
33a8e1175bSopenharmony_ci#endif
34a8e1175bSopenharmony_ci
35a8e1175bSopenharmony_ci/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size)
36a8e1175bSopenharmony_ci *
37a8e1175bSopenharmony_ci * Poison a memory area so that any attempt to read or write from it will
38a8e1175bSopenharmony_ci * cause a runtime failure.
39a8e1175bSopenharmony_ci *
40a8e1175bSopenharmony_ci * Depending on the implementation, this may poison a few bytes beyond the
41a8e1175bSopenharmony_ci * indicated region, but will never poison a separate object on the heap
42a8e1175bSopenharmony_ci * or a separate object with more than the alignment of a long long.
43a8e1175bSopenharmony_ci *
44a8e1175bSopenharmony_ci * The behavior is undefined if any part of the memory area is invalid.
45a8e1175bSopenharmony_ci *
46a8e1175bSopenharmony_ci * This is a no-op in builds without a poisoning method.
47a8e1175bSopenharmony_ci * See #MBEDTLS_TEST_MEMORY_CAN_POISON.
48a8e1175bSopenharmony_ci *
49a8e1175bSopenharmony_ci * \param buf   Pointer to the beginning of the memory area to poison.
50a8e1175bSopenharmony_ci * \param size  Size of the memory area in bytes.
51a8e1175bSopenharmony_ci */
52a8e1175bSopenharmony_ci
53a8e1175bSopenharmony_ci/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size)
54a8e1175bSopenharmony_ci *
55a8e1175bSopenharmony_ci * Undo the effect of #MBEDTLS_TEST_MEMORY_POISON.
56a8e1175bSopenharmony_ci *
57a8e1175bSopenharmony_ci * The behavior is undefined if any part of the memory area is invalid,
58a8e1175bSopenharmony_ci * or if the memory area contains a mixture of poisoned and unpoisoned parts.
59a8e1175bSopenharmony_ci *
60a8e1175bSopenharmony_ci * This is a no-op in builds without a poisoning method.
61a8e1175bSopenharmony_ci * See #MBEDTLS_TEST_MEMORY_CAN_POISON.
62a8e1175bSopenharmony_ci *
63a8e1175bSopenharmony_ci * \param buf   Pointer to the beginning of the memory area to unpoison.
64a8e1175bSopenharmony_ci * \param size  Size of the memory area in bytes.
65a8e1175bSopenharmony_ci */
66a8e1175bSopenharmony_ci
67a8e1175bSopenharmony_ci#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
68a8e1175bSopenharmony_ci
69a8e1175bSopenharmony_ci/** Thread-local variable used to enable memory poisoning. This is set and
70a8e1175bSopenharmony_ci *  unset in the test wrappers so that calls to PSA functions from the library
71a8e1175bSopenharmony_ci *  do not poison memory.
72a8e1175bSopenharmony_ci */
73a8e1175bSopenharmony_ciextern _Thread_local unsigned int mbedtls_test_memory_poisoning_count;
74a8e1175bSopenharmony_ci
75a8e1175bSopenharmony_ci/** Poison a memory area so that any attempt to read or write from it will
76a8e1175bSopenharmony_ci * cause a runtime failure.
77a8e1175bSopenharmony_ci *
78a8e1175bSopenharmony_ci * The behavior is undefined if any part of the memory area is invalid.
79a8e1175bSopenharmony_ci */
80a8e1175bSopenharmony_civoid mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
81a8e1175bSopenharmony_ci#define MBEDTLS_TEST_MEMORY_POISON(ptr, size)    \
82a8e1175bSopenharmony_ci    do { \
83a8e1175bSopenharmony_ci        mbedtls_test_memory_poisoning_count++; \
84a8e1175bSopenharmony_ci        mbedtls_test_memory_poison(ptr, size); \
85a8e1175bSopenharmony_ci    } while (0)
86a8e1175bSopenharmony_ci
87a8e1175bSopenharmony_ci/** Undo the effect of mbedtls_test_memory_poison().
88a8e1175bSopenharmony_ci *
89a8e1175bSopenharmony_ci * This is a no-op if the given area is entirely valid, unpoisoned memory.
90a8e1175bSopenharmony_ci *
91a8e1175bSopenharmony_ci * The behavior is undefined if any part of the memory area is invalid,
92a8e1175bSopenharmony_ci * or if the memory area contains a mixture of poisoned and unpoisoned parts.
93a8e1175bSopenharmony_ci */
94a8e1175bSopenharmony_civoid mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
95a8e1175bSopenharmony_ci#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size)    \
96a8e1175bSopenharmony_ci    do { \
97a8e1175bSopenharmony_ci        mbedtls_test_memory_unpoison(ptr, size); \
98a8e1175bSopenharmony_ci        if (mbedtls_test_memory_poisoning_count != 0) { \
99a8e1175bSopenharmony_ci            mbedtls_test_memory_poisoning_count--; \
100a8e1175bSopenharmony_ci        } \
101a8e1175bSopenharmony_ci    } while (0)
102a8e1175bSopenharmony_ci
103a8e1175bSopenharmony_ci#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
104a8e1175bSopenharmony_ci#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size))
105a8e1175bSopenharmony_ci#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) (ptr), (void) (size))
106a8e1175bSopenharmony_ci#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ci#endif /* TEST_MEMORY_H */
109