1a8e1175bSopenharmony_ci# Mbed TLS invasive testing strategy 2a8e1175bSopenharmony_ci 3a8e1175bSopenharmony_ci## Introduction 4a8e1175bSopenharmony_ci 5a8e1175bSopenharmony_ciIn Mbed TLS, we use black-box testing as much as possible: test the documented behavior of the product, in a realistic environment. However this is not always sufficient. 6a8e1175bSopenharmony_ci 7a8e1175bSopenharmony_ciThe goal of this document is to identify areas where black-box testing is insufficient and to propose solutions. 8a8e1175bSopenharmony_ci 9a8e1175bSopenharmony_ciThis is a test strategy document, not a test plan. A description of exactly what is tested is out of scope. 10a8e1175bSopenharmony_ci 11a8e1175bSopenharmony_ciThis document is structured as follows: 12a8e1175bSopenharmony_ci 13a8e1175bSopenharmony_ci* [“Rules”](#rules) gives general rules and is written for brevity. 14a8e1175bSopenharmony_ci* [“Requirements”](#requirements) explores the reasons why invasive testing is needed and how it should be done. 15a8e1175bSopenharmony_ci* [“Possible approaches”](#possible-approaches) discusses some general methods for non-black-box testing. 16a8e1175bSopenharmony_ci* [“Solutions”](#solutions) explains how we currently solve, or intend to solve, specific problems. 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci### TLS 19a8e1175bSopenharmony_ci 20a8e1175bSopenharmony_ciThis document currently focuses on data structure manipulation and storage, which is what the crypto/keystore and X.509 parts of the library are about. More work is needed to fully take TLS into account. 21a8e1175bSopenharmony_ci 22a8e1175bSopenharmony_ci## Rules 23a8e1175bSopenharmony_ci 24a8e1175bSopenharmony_ciAlways follow these rules unless you have a good reason not to. If you deviate, document the rationale somewhere. 25a8e1175bSopenharmony_ci 26a8e1175bSopenharmony_ciSee the section [“Possible approaches”](#possible-approaches) for a rationale. 27a8e1175bSopenharmony_ci 28a8e1175bSopenharmony_ci### Interface design for testing 29a8e1175bSopenharmony_ci 30a8e1175bSopenharmony_ciDo not add test-specific interfaces if there's a practical way of doing it another way. All public interfaces should be useful in at least some configurations. Features with a significant impact on the code size or attack surface should have a compile-time guard. 31a8e1175bSopenharmony_ci 32a8e1175bSopenharmony_ci### Reliance on internal details 33a8e1175bSopenharmony_ci 34a8e1175bSopenharmony_ciIn unit tests and in test programs, it's ok to include internal header files from `library/`. Do not define non-public interfaces in public headers. In contrast, sample programs must not include header files from `library/`. 35a8e1175bSopenharmony_ci 36a8e1175bSopenharmony_ciSometimes it makes sense to have unit tests on functions that aren't part of the public API. Declare such functions in `library/*.h` and include the corresponding header in the test code. If the function should be `static` for optimization but can't be `static` for testing, declare it as `MBEDTLS_STATIC_TESTABLE`, and make the tests that use it depend on `MBEDTLS_TEST_HOOKS` (see [“rules for compile-time options”](#rules-for-compile-time-options)). 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ciIf test code or test data depends on internal details of the library and not just on its documented behavior, add a comment in the code that explains the dependency. For example: 39a8e1175bSopenharmony_ci 40a8e1175bSopenharmony_ci> ``` 41a8e1175bSopenharmony_ci> /* This test file is specific to the ITS implementation in PSA Crypto 42a8e1175bSopenharmony_ci> * on top of stdio. It expects to know what the stdio name of a file is 43a8e1175bSopenharmony_ci> * based on its keystore name. 44a8e1175bSopenharmony_ci> */ 45a8e1175bSopenharmony_ci> ``` 46a8e1175bSopenharmony_ci 47a8e1175bSopenharmony_ci> ``` 48a8e1175bSopenharmony_ci> # This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes 49a8e1175bSopenharmony_ci> # and not expected to be raised any time soon) is less than the maximum 50a8e1175bSopenharmony_ci> # output from HKDF-SHA512 (255*64 = 16320 bytes). 51a8e1175bSopenharmony_ci> ``` 52a8e1175bSopenharmony_ci 53a8e1175bSopenharmony_ci### Rules for compile-time options 54a8e1175bSopenharmony_ci 55a8e1175bSopenharmony_ciIf the most practical way to test something is to add code to the product that is only useful for testing, do so, but obey the following rules. For more information, see the [rationale](#guidelines-for-compile-time-options). 56a8e1175bSopenharmony_ci 57a8e1175bSopenharmony_ci* **Only use test-specific code when necessary.** Anything that can be tested through the documented API must be tested through the documented API. 58a8e1175bSopenharmony_ci* **Test-specific code must be guarded by `#if defined(MBEDTLS_TEST_HOOKS)`**. Do not create fine-grained guards for test-specific code. 59a8e1175bSopenharmony_ci* **Do not use `MBEDTLS_TEST_HOOKS` for security checks or assertions.** Security checks belong in the product. 60a8e1175bSopenharmony_ci* **Merely defining `MBEDTLS_TEST_HOOKS` must not change the behavior**. It may define extra functions. It may add fields to structures, but if so, make it very clear that these fields have no impact on non-test-specific fields. 61a8e1175bSopenharmony_ci* **Where tests must be able to change the behavior, do it by function substitution.** See [“rules for function substitution”](#rules-for-function-substitution) for more details. 62a8e1175bSopenharmony_ci 63a8e1175bSopenharmony_ci#### Rules for function substitution 64a8e1175bSopenharmony_ci 65a8e1175bSopenharmony_ciThis section explains how to replace a library function `mbedtls_foo()` by alternative code for test purposes. That is, library code calls `mbedtls_foo()`, and there is a mechanism to arrange for these calls to invoke different code. 66a8e1175bSopenharmony_ci 67a8e1175bSopenharmony_ciOften `mbedtls_foo` is a macro which is defined to be a system function (like `mbedtls_calloc` or `mbedtls_fopen`), which we replace to mock or wrap the system function. This is useful to simulate I/O failure, for example. Note that if the macro can be replaced at compile time to support alternative platforms, the test code should be compatible with this compile-time configuration so that it works on these alternative platforms as well. 68a8e1175bSopenharmony_ci 69a8e1175bSopenharmony_ciSometimes the substitutable function is a `static inline` function that does nothing (not a macro, to avoid accidentally skipping side effects in its parameters), to provide a hook for test code; such functions should have a name that starts with the prefix `mbedtls_test_hook_`. In such cases, the function should generally not modify its parameters, so any pointer argument should be const. The function should return void. 70a8e1175bSopenharmony_ci 71a8e1175bSopenharmony_ciWith `MBEDTLS_TEST_HOOKS` set, `mbedtls_foo` is a global variable of function pointer type. This global variable is initialized to the system function, or to a function that does nothing. The global variable is defined in a header in the `library` directory such as `psa_crypto_invasive.h`. This is similar to the platform function configuration mechanism with `MBEDTLS_PLATFORM_xxx_ALT`. 72a8e1175bSopenharmony_ci 73a8e1175bSopenharmony_ciIn unit test code that needs to modify the internal behavior: 74a8e1175bSopenharmony_ci 75a8e1175bSopenharmony_ci* The test function (or the whole test file) must depend on `MBEDTLS_TEST_HOOKS`. 76a8e1175bSopenharmony_ci* At the beginning of the test function, set the global function pointers to the desired value. 77a8e1175bSopenharmony_ci* In the test function's cleanup code, restore the global function pointers to their default value. 78a8e1175bSopenharmony_ci 79a8e1175bSopenharmony_ci## Requirements 80a8e1175bSopenharmony_ci 81a8e1175bSopenharmony_ci### General goals 82a8e1175bSopenharmony_ci 83a8e1175bSopenharmony_ciWe need to balance the following goals, which are sometimes contradictory. 84a8e1175bSopenharmony_ci 85a8e1175bSopenharmony_ci* Coverage: we need to test behaviors which are not easy to trigger by using the API or which cannot be triggered deterministically, for example I/O failures. 86a8e1175bSopenharmony_ci* Correctness: we want to test the actual product, not a modified version, since conclusions drawn from a test of a modified product may not apply to the real product. 87a8e1175bSopenharmony_ci* Effacement: the product should not include features that are solely present for test purposes, since these increase the attack surface and the code size. 88a8e1175bSopenharmony_ci* Portability: tests should work on every platform. Skipping tests on certain platforms may hide errors that are only apparent on such platforms. 89a8e1175bSopenharmony_ci* Maintainability: tests should only enforce the documented behavior of the product, to avoid extra work when the product's internal or implementation-specific behavior changes. We should also not give the impression that whatever the tests check is guaranteed behavior of the product which cannot change in future versions. 90a8e1175bSopenharmony_ci 91a8e1175bSopenharmony_ciWhere those goals conflict, we should at least mitigate the goals that cannot be fulfilled, and document the architectural choices and their rationale. 92a8e1175bSopenharmony_ci 93a8e1175bSopenharmony_ci### Problem areas 94a8e1175bSopenharmony_ci 95a8e1175bSopenharmony_ci#### Allocation 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ciResource allocation can fail, but rarely does so in a typical test environment. How does the product cope if some allocations fail? 98a8e1175bSopenharmony_ci 99a8e1175bSopenharmony_ciResources include: 100a8e1175bSopenharmony_ci 101a8e1175bSopenharmony_ci* Memory. 102a8e1175bSopenharmony_ci* Files in storage (PSA API only — in the Mbed TLS API, black-box unit tests are sufficient). 103a8e1175bSopenharmony_ci* Key slots (PSA API only). 104a8e1175bSopenharmony_ci* Key slots in a secure element (PSA SE HAL). 105a8e1175bSopenharmony_ci* Communication handles (PSA crypto service only). 106a8e1175bSopenharmony_ci 107a8e1175bSopenharmony_ci#### Storage 108a8e1175bSopenharmony_ci 109a8e1175bSopenharmony_ciStorage can fail, either due to hardware errors or to active attacks on trusted storage. How does the code cope if some storage accesses fail? 110a8e1175bSopenharmony_ci 111a8e1175bSopenharmony_ciWe also need to test resilience: if the system is reset during an operation, does it restart in a correct state? 112a8e1175bSopenharmony_ci 113a8e1175bSopenharmony_ci#### Cleanup 114a8e1175bSopenharmony_ci 115a8e1175bSopenharmony_ciWhen code should clean up resources, how do we know that they have truly been cleaned up? 116a8e1175bSopenharmony_ci 117a8e1175bSopenharmony_ci* Zeroization of confidential data after use. 118a8e1175bSopenharmony_ci* Freeing memory. 119a8e1175bSopenharmony_ci* Freeing key slots. 120a8e1175bSopenharmony_ci* Freeing key slots in a secure element. 121a8e1175bSopenharmony_ci* Deleting files in storage (PSA API only). 122a8e1175bSopenharmony_ci 123a8e1175bSopenharmony_ci#### Internal data 124a8e1175bSopenharmony_ci 125a8e1175bSopenharmony_ciSometimes it is useful to peek or poke internal data. 126a8e1175bSopenharmony_ci 127a8e1175bSopenharmony_ci* Check consistency of internal data (e.g. output of key generation). 128a8e1175bSopenharmony_ci* Check the format of files (which matters so that the product can still read old files after an upgrade). 129a8e1175bSopenharmony_ci* Inject faults and test corruption checks inside the product. 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci## Possible approaches 132a8e1175bSopenharmony_ci 133a8e1175bSopenharmony_ciKey to requirement tables: 134a8e1175bSopenharmony_ci 135a8e1175bSopenharmony_ci* ++ requirement is fully met 136a8e1175bSopenharmony_ci* \+ requirement is mostly met 137a8e1175bSopenharmony_ci* ~ requirement is partially met but there are limitations 138a8e1175bSopenharmony_ci* ! requirement is somewhat problematic 139a8e1175bSopenharmony_ci* !! requirement is very problematic 140a8e1175bSopenharmony_ci 141a8e1175bSopenharmony_ci### Fine-grained public interfaces 142a8e1175bSopenharmony_ci 143a8e1175bSopenharmony_ciWe can include all the features we want to test in the public interface. Then the tests can be truly black-box. The limitation of this approach is that this requires adding a lot of interfaces that are not useful in production. These interfaces have costs: they increase the code size, the attack surface, and the testing burden (exponentially, because we need to test all these interfaces in combination). 144a8e1175bSopenharmony_ci 145a8e1175bSopenharmony_ciAs a rule, we do not add public interfaces solely for testing purposes. We only add public interfaces if they are also useful in production, at least sometimes. For example, the main purpose of `mbedtls_psa_crypto_free` is to clean up all resources in tests, but this is also useful in production in some applications that only want to use PSA Crypto during part of their lifetime. 146a8e1175bSopenharmony_ci 147a8e1175bSopenharmony_ciMbed TLS traditionally has very fine-grained public interfaces, with many platform functions that can be substituted (`MBEDTLS_PLATFORM_xxx` macros). PSA Crypto has more opacity and less platform substitution macros. 148a8e1175bSopenharmony_ci 149a8e1175bSopenharmony_ci| Requirement | Analysis | 150a8e1175bSopenharmony_ci| ----------- | -------- | 151a8e1175bSopenharmony_ci| Coverage | ~ Many useful tests are not reasonably achievable | 152a8e1175bSopenharmony_ci| Correctness | ++ Ideal | 153a8e1175bSopenharmony_ci| Effacement | !! Requires adding many otherwise-useless interfaces | 154a8e1175bSopenharmony_ci| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | 155a8e1175bSopenharmony_ci| Maintainability | !! Combinatorial explosion on the testing burden | 156a8e1175bSopenharmony_ci| | ! Public interfaces must remain for backward compatibility even if the test architecture changes | 157a8e1175bSopenharmony_ci 158a8e1175bSopenharmony_ci### Fine-grained undocumented interfaces 159a8e1175bSopenharmony_ci 160a8e1175bSopenharmony_ciWe can include all the features we want to test in undocumented interfaces. Undocumented interfaces are described in public headers for the sake of the C compiler, but are described as “do not use” in comments (or not described at all) and are not included in Doxygen-rendered documentation. This mitigates some of the downsides of [fine-grained public interfaces](#fine-grained-public-interfaces), but not all. In particular, the extra interfaces do increase the code size, the attack surface and the test surface. 161a8e1175bSopenharmony_ci 162a8e1175bSopenharmony_ciMbed TLS traditionally has a few internal interfaces, mostly intended for cross-module abstraction leakage rather than for testing. For the PSA API, we favor [internal interfaces](#internal-interfaces). 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci| Requirement | Analysis | 165a8e1175bSopenharmony_ci| ----------- | -------- | 166a8e1175bSopenharmony_ci| Coverage | ~ Many useful tests are not reasonably achievable | 167a8e1175bSopenharmony_ci| Correctness | ++ Ideal | 168a8e1175bSopenharmony_ci| Effacement | !! Requires adding many otherwise-useless interfaces | 169a8e1175bSopenharmony_ci| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | 170a8e1175bSopenharmony_ci| Maintainability | ! Combinatorial explosion on the testing burden | 171a8e1175bSopenharmony_ci 172a8e1175bSopenharmony_ci### Internal interfaces 173a8e1175bSopenharmony_ci 174a8e1175bSopenharmony_ciWe can write tests that call internal functions that are not exposed in the public interfaces. This is nice when it works, because it lets us test the unchanged product without compromising the design of the public interface. 175a8e1175bSopenharmony_ci 176a8e1175bSopenharmony_ciA limitation is that these interfaces must exist in the first place. If they don't, this has mostly the same downside as public interfaces: the extra interfaces increase the code size and the attack surface for no direct benefit to the product. 177a8e1175bSopenharmony_ci 178a8e1175bSopenharmony_ciAnother limitation is that internal interfaces need to be used correctly. We may accidentally rely on internal details in the tests that are not necessarily always true (for example that are platform-specific). We may accidentally use these internal interfaces in ways that don't correspond to the actual product. 179a8e1175bSopenharmony_ci 180a8e1175bSopenharmony_ciThis approach is mostly portable since it only relies on C interfaces. A limitation is that the test-only interfaces must not be hidden at link time (but link-time hiding is not something we currently do). Another limitation is that this approach does not work for users who patch the library by replacing some modules; this is a secondary concern since we do not officially offer this as a feature. 181a8e1175bSopenharmony_ci 182a8e1175bSopenharmony_ci| Requirement | Analysis | 183a8e1175bSopenharmony_ci| ----------- | -------- | 184a8e1175bSopenharmony_ci| Coverage | ~ Many useful tests require additional internal interfaces | 185a8e1175bSopenharmony_ci| Correctness | + Does not require a product change | 186a8e1175bSopenharmony_ci| | ~ The tests may call internal functions in a way that does not reflect actual usage inside the product | 187a8e1175bSopenharmony_ci| Effacement | ++ Fine as long as the internal interfaces aren't added solely for test purposes | 188a8e1175bSopenharmony_ci| Portability | + Fine as long as we control how the tests are linked | 189a8e1175bSopenharmony_ci| | ~ Doesn't work if the users rewrite an internal module | 190a8e1175bSopenharmony_ci| Maintainability | + Tests interfaces that are documented; dependencies in the tests are easily noticed when changing these interfaces | 191a8e1175bSopenharmony_ci 192a8e1175bSopenharmony_ci### Static analysis 193a8e1175bSopenharmony_ci 194a8e1175bSopenharmony_ciIf we guarantee certain properties through static analysis, we don't need to test them. This puts some constraints on the properties: 195a8e1175bSopenharmony_ci 196a8e1175bSopenharmony_ci* We need to have confidence in the specification (but we can gain this confidence by evaluating the specification on test data). 197a8e1175bSopenharmony_ci* This does not work for platform-dependent properties unless we have a formal model of the platform. 198a8e1175bSopenharmony_ci 199a8e1175bSopenharmony_ci| Requirement | Analysis | 200a8e1175bSopenharmony_ci| ----------- | -------- | 201a8e1175bSopenharmony_ci| Coverage | ~ Good for platform-independent properties, if we can guarantee them statically | 202a8e1175bSopenharmony_ci| Correctness | + Good as long as we have confidence in the specification | 203a8e1175bSopenharmony_ci| Effacement | ++ Zero impact on the code | 204a8e1175bSopenharmony_ci| Portability | ++ Zero runtime burden | 205a8e1175bSopenharmony_ci| Maintainability | ~ Static analysis is hard, but it's also helpful | 206a8e1175bSopenharmony_ci 207a8e1175bSopenharmony_ci### Compile-time options 208a8e1175bSopenharmony_ci 209a8e1175bSopenharmony_ciIf there's code that we want to have in the product for testing, but not in production, we can add a compile-time option to enable it. This is very powerful and usually easy to use, but comes with a major downside: we aren't testing the same code anymore. 210a8e1175bSopenharmony_ci 211a8e1175bSopenharmony_ci| Requirement | Analysis | 212a8e1175bSopenharmony_ci| ----------- | -------- | 213a8e1175bSopenharmony_ci| Coverage | ++ Most things can be tested that way | 214a8e1175bSopenharmony_ci| Correctness | ! Difficult to ensure that what we test is what we run | 215a8e1175bSopenharmony_ci| Effacement | ++ No impact on the product when built normally or on the documentation, if done right | 216a8e1175bSopenharmony_ci| | ! Risk of getting “no impact” wrong | 217a8e1175bSopenharmony_ci| Portability | ++ It's just C code so it works everywhere | 218a8e1175bSopenharmony_ci| | ~ Doesn't work if the users rewrite an internal module | 219a8e1175bSopenharmony_ci| Maintainability | + Test interfaces impact the product source code, but at least they're clearly marked as such in the code | 220a8e1175bSopenharmony_ci 221a8e1175bSopenharmony_ci#### Guidelines for compile-time options 222a8e1175bSopenharmony_ci 223a8e1175bSopenharmony_ci* **Minimize the number of compile-time options.**<br> 224a8e1175bSopenharmony_ci Either we're testing or we're not. Fine-grained options for testing would require more test builds, especially if combinatorics enters the play. 225a8e1175bSopenharmony_ci* **Merely enabling the compile-time option should not change the behavior.**<br> 226a8e1175bSopenharmony_ci When building in test mode, the code should have exactly the same behavior. Changing the behavior should require some action at runtime (calling a function or changing a variable). 227a8e1175bSopenharmony_ci* **Minimize the impact on code**.<br> 228a8e1175bSopenharmony_ci We should not have test-specific conditional compilation littered through the code, as that makes the code hard to read. 229a8e1175bSopenharmony_ci 230a8e1175bSopenharmony_ci### Runtime instrumentation 231a8e1175bSopenharmony_ci 232a8e1175bSopenharmony_ciSome properties can be tested through runtime instrumentation: have the compiler or a similar tool inject something into the binary. 233a8e1175bSopenharmony_ci 234a8e1175bSopenharmony_ci* Sanitizers check for certain bad usage patterns (ASan, MSan, UBSan, Valgrind). 235a8e1175bSopenharmony_ci* We can inject external libraries at link time. This can be a way to make system functions fail. 236a8e1175bSopenharmony_ci 237a8e1175bSopenharmony_ci| Requirement | Analysis | 238a8e1175bSopenharmony_ci| ----------- | -------- | 239a8e1175bSopenharmony_ci| Coverage | ! Limited scope | 240a8e1175bSopenharmony_ci| Correctness | + Instrumentation generally does not affect the program's functional behavior | 241a8e1175bSopenharmony_ci| Effacement | ++ Zero impact on the code | 242a8e1175bSopenharmony_ci| Portability | ~ Depends on the method | 243a8e1175bSopenharmony_ci| Maintainability | ~ Depending on the instrumentation, this may require additional builds and scripts | 244a8e1175bSopenharmony_ci| | + Many properties come for free, but some require effort (e.g. the test code itself must be leak-free to avoid false positives in a leak detector) | 245a8e1175bSopenharmony_ci 246a8e1175bSopenharmony_ci### Debugger-based testing 247a8e1175bSopenharmony_ci 248a8e1175bSopenharmony_ciIf we want to do something in a test that the product isn't capable of doing, we can use a debugger to read or modify the memory, or hook into the code at arbitrary points. 249a8e1175bSopenharmony_ci 250a8e1175bSopenharmony_ciThis is a very powerful approach, but it comes with limitations: 251a8e1175bSopenharmony_ci 252a8e1175bSopenharmony_ci* The debugger may introduce behavior changes (e.g. timing). If we modify data structures in memory, we may do so in a way that the code doesn't expect. 253a8e1175bSopenharmony_ci* Due to compiler optimizations, the memory may not have the layout that we expect. 254a8e1175bSopenharmony_ci* Writing reliable debugger scripts is hard. We need to have confidence that we're testing what we mean to test, even in the face of compiler optimizations. Languages such as gdb make it hard to automate even relatively simple things such as finding the place(s) in the binary corresponding to some place in the source code. 255a8e1175bSopenharmony_ci* Debugger scripts are very much non-portable. 256a8e1175bSopenharmony_ci 257a8e1175bSopenharmony_ci| Requirement | Analysis | 258a8e1175bSopenharmony_ci| ----------- | -------- | 259a8e1175bSopenharmony_ci| Coverage | ++ The sky is the limit | 260a8e1175bSopenharmony_ci| Correctness | ++ The code is unmodified, and tested as compiled (so we even detect compiler-induced bugs) | 261a8e1175bSopenharmony_ci| | ! Compiler optimizations may hinder | 262a8e1175bSopenharmony_ci| | ~ Modifying the execution may introduce divergence | 263a8e1175bSopenharmony_ci| Effacement | ++ Zero impact on the code | 264a8e1175bSopenharmony_ci| Portability | !! Not all environments have a debugger, and even if they do, we'd need completely different scripts for every debugger | 265a8e1175bSopenharmony_ci| Maintainability | ! Writing reliable debugger scripts is hard | 266a8e1175bSopenharmony_ci| | !! Very tight coupling with the details of the source code and even with the compiler | 267a8e1175bSopenharmony_ci 268a8e1175bSopenharmony_ci## Solutions 269a8e1175bSopenharmony_ci 270a8e1175bSopenharmony_ciThis section lists some strategies that are currently used for invasive testing, or planned to be used. This list is not intended to be exhaustive. 271a8e1175bSopenharmony_ci 272a8e1175bSopenharmony_ci### Memory management 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci#### Zeroization testing 275a8e1175bSopenharmony_ci 276a8e1175bSopenharmony_ciGoal: test that `mbedtls_platform_zeroize` does wipe the memory buffer. 277a8e1175bSopenharmony_ci 278a8e1175bSopenharmony_ciSolution ([debugger](#debugger-based-testing)): implemented in `tests/scripts/test_zeroize.gdb`. 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ciRationale: 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. 281a8e1175bSopenharmony_ci 282a8e1175bSopenharmony_ci#### Memory cleanup 283a8e1175bSopenharmony_ci 284a8e1175bSopenharmony_ciGoal: test the absence of memory leaks. 285a8e1175bSopenharmony_ci 286a8e1175bSopenharmony_ciSolution ([instrumentation](#runtime-instrumentation)): run tests with ASan. (We also use Valgrind, but it's slower than ASan, so we favor ASan.) 287a8e1175bSopenharmony_ci 288a8e1175bSopenharmony_ciSince we run many test jobs with a memory leak detector, each test function or test program must clean up after itself. Use the cleanup code (after the `exit` label in test functions) to free any memory that the function may have allocated. 289a8e1175bSopenharmony_ci 290a8e1175bSopenharmony_ci#### Robustness against memory allocation failure 291a8e1175bSopenharmony_ci 292a8e1175bSopenharmony_ciSolution: TODO. We don't test this at all at this point. 293a8e1175bSopenharmony_ci 294a8e1175bSopenharmony_ci#### PSA key store memory cleanup 295a8e1175bSopenharmony_ci 296a8e1175bSopenharmony_ciGoal: test the absence of resource leaks in the PSA key store code, in particular that `psa_close_key` and `psa_destroy_key` work correctly. 297a8e1175bSopenharmony_ci 298a8e1175bSopenharmony_ciSolution ([internal interface](#internal-interfaces)): in most tests involving PSA functions, the cleanup code explicitly calls `PSA_DONE()` instead of `mbedtls_psa_crypto_free()`. `PSA_DONE` fails the test if the key store in memory is not empty. 299a8e1175bSopenharmony_ci 300a8e1175bSopenharmony_ciNote there must also be tests that call `mbedtls_psa_crypto_free` with keys still open, to verify that it does close all keys. 301a8e1175bSopenharmony_ci 302a8e1175bSopenharmony_ci`PSA_DONE` is a macro defined in `psa_crypto_helpers.h` which uses `mbedtls_psa_get_stats()` to get information about the keystore content before calling `mbedtls_psa_crypto_free()`. This feature is mostly but not exclusively useful for testing, and may be moved under `MBEDTLS_TEST_HOOKS`. 303a8e1175bSopenharmony_ci 304a8e1175bSopenharmony_ci### PSA storage 305a8e1175bSopenharmony_ci 306a8e1175bSopenharmony_ci#### PSA storage cleanup on success 307a8e1175bSopenharmony_ci 308a8e1175bSopenharmony_ciGoal: test that no stray files are left over in the key store after a test that succeeded. 309a8e1175bSopenharmony_ci 310a8e1175bSopenharmony_ciSolution: TODO. Currently the various test suites do it differently. 311a8e1175bSopenharmony_ci 312a8e1175bSopenharmony_ci#### PSA storage cleanup on failure 313a8e1175bSopenharmony_ci 314a8e1175bSopenharmony_ciGoal: ensure that no stray files are left over in the key store even if a test has failed (as that could cause other tests to fail). 315a8e1175bSopenharmony_ci 316a8e1175bSopenharmony_ciSolution: TODO. Currently the various test suites do it differently. 317a8e1175bSopenharmony_ci 318a8e1175bSopenharmony_ci#### PSA storage resilience 319a8e1175bSopenharmony_ci 320a8e1175bSopenharmony_ciGoal: test the resilience of PSA storage against power failures. 321a8e1175bSopenharmony_ci 322a8e1175bSopenharmony_ciSolution: TODO. 323a8e1175bSopenharmony_ci 324a8e1175bSopenharmony_ciSee the [secure element driver interface test strategy](driver-interface-test-strategy.html) for more information. 325a8e1175bSopenharmony_ci 326a8e1175bSopenharmony_ci#### Corrupted storage 327a8e1175bSopenharmony_ci 328a8e1175bSopenharmony_ciGoal: test the robustness against corrupted storage. 329a8e1175bSopenharmony_ci 330a8e1175bSopenharmony_ciSolution ([internal interface](#internal-interfaces)): call `psa_its` functions to modify the storage. 331a8e1175bSopenharmony_ci 332a8e1175bSopenharmony_ci#### Storage read failure 333a8e1175bSopenharmony_ci 334a8e1175bSopenharmony_ciGoal: test the robustness against read errors. 335a8e1175bSopenharmony_ci 336a8e1175bSopenharmony_ciSolution: TODO 337a8e1175bSopenharmony_ci 338a8e1175bSopenharmony_ci#### Storage write failure 339a8e1175bSopenharmony_ci 340a8e1175bSopenharmony_ciGoal: test the robustness against write errors (`STORAGE_FAILURE` or `INSUFFICIENT_STORAGE`). 341a8e1175bSopenharmony_ci 342a8e1175bSopenharmony_ciSolution: TODO 343a8e1175bSopenharmony_ci 344a8e1175bSopenharmony_ci#### Storage format stability 345a8e1175bSopenharmony_ci 346a8e1175bSopenharmony_ciGoal: test that the storage format does not change between versions (or if it does, an upgrade path must be provided). 347a8e1175bSopenharmony_ci 348a8e1175bSopenharmony_ciSolution ([internal interface](#internal-interfaces)): call internal functions to inspect the content of the file. 349a8e1175bSopenharmony_ci 350a8e1175bSopenharmony_ciNote that the storage format is defined not only by the general layout, but also by the numerical values of encodings for key types and other metadata. For numerical values, there is a risk that we would accidentally modify a single value or a few values, so the tests should be exhaustive. This probably requires some compile-time analysis (perhaps the automation for `psa_constant_names` can be used here). TODO 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci### Other fault injection 353a8e1175bSopenharmony_ci 354a8e1175bSopenharmony_ci#### PSA crypto init failure 355a8e1175bSopenharmony_ci 356a8e1175bSopenharmony_ciGoal: test the failure of `psa_crypto_init`. 357a8e1175bSopenharmony_ci 358a8e1175bSopenharmony_ciSolution ([compile-time option](#compile-time-options)): replace entropy initialization functions by functions that can fail. This is the only failure point for `psa_crypto_init` that is present in all builds. 359a8e1175bSopenharmony_ci 360a8e1175bSopenharmony_ciWhen we implement the PSA entropy driver interface, this should be reworked to use the entropy driver interface. 361a8e1175bSopenharmony_ci 362a8e1175bSopenharmony_ci#### PSA crypto data corruption 363a8e1175bSopenharmony_ci 364a8e1175bSopenharmony_ciThe PSA crypto subsystem has a few checks to detect corrupted data in memory. We currently don't have a way to exercise those checks. 365a8e1175bSopenharmony_ci 366a8e1175bSopenharmony_ciSolution: TODO. To corrupt a multipart operation structure, we can do it by looking inside the structure content, but only when running without isolation. To corrupt the key store, we would need to add a function to the library or to use a debugger. 367a8e1175bSopenharmony_ci 368