blob: 707b6a64a3011c9907c77261b89d1870a1f6d35d [file] [log] [blame] [view]
Fredrik Hessecc207bc2021-09-28 21:06:08 +02001# Mbed TLS driver interface test strategy
Gilles Peskineb26c8d82019-09-04 19:26:17 +02002
Fredrik Hessecc207bc2021-09-28 21:06:08 +02003This document describes the test strategy for the driver interfaces in Mbed TLS. Mbed TLS has interfaces for secure element drivers, accelerator drivers and entropy drivers. This document is about testing Mbed TLS itself; testing drivers is out of scope.
Gilles Peskineb26c8d82019-09-04 19:26:17 +02004
5The driver interfaces are standardized through PSA Cryptography functional specifications.
6
Gilles Peskinef0e28532020-11-30 17:51:14 +01007## Secure element driver interface testing
Gilles Peskineb26c8d82019-09-04 19:26:17 +02008
Gilles Peskinef0e28532020-11-30 17:51:14 +01009### Secure element driver interfaces
10
11#### Opaque driver interface
12
13The [unified driver interface](../../proposed/psa-driver-interface.md) supports both transparent drivers (for accelerators) and opaque drivers (for secure elements).
14
15Drivers exposing this interface need to be registered at compile time by declaring their JSON description file.
16
17#### Dynamic secure element driver interface
18
Fredrik Hessecc207bc2021-09-28 21:06:08 +020019The dynamic secure element driver interface (SE interface for short) is defined by [`psa/crypto_se_driver.h`](../../../include/psa/crypto_se_driver.h). This is an interface between Mbed TLS and one or more third-party drivers.
Gilles Peskineb26c8d82019-09-04 19:26:17 +020020
Fredrik Hessecc207bc2021-09-28 21:06:08 +020021The SE interface consists of one function provided by Mbed TLS (`psa_register_se_driver`) and many functions that drivers must implement. To make a driver usable by Mbed TLS, the initialization code must call `psa_register_se_driver` with a structure that describes the driver. The structure mostly contains function pointers, pointing to the driver's methods. All calls to a driver function are triggered by a call to a PSA crypto API function.
Gilles Peskineb26c8d82019-09-04 19:26:17 +020022
Gilles Peskine92bcfdb2019-09-04 19:26:50 +020023### SE driver interface unit tests
24
25This section describes unit tests that must be implemented to validate the secure element driver interface. Note that a test case may cover multiple requirements; for example a “good case” test can validate that the proper function is called, that it receives the expected inputs and that it produces the expected outputs.
26
27Many SE driver interface unit tests could be covered by running the existing API tests with a key in a secure element.
28
29#### SE driver registration
30
Gilles Peskinef0e28532020-11-30 17:51:14 +010031This applies to dynamic drivers only.
32
Gilles Peskine92bcfdb2019-09-04 19:26:50 +020033* Test `psa_register_se_driver` with valid and with invalid arguments.
34* Make at least one failing call to `psa_register_se_driver` followed by a successful call.
35* Make at least one test that successfully registers the maximum number of drivers and fails to register one more.
36
37#### Dispatch to SE driver
38
39For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent):
40
41* Make at least one test with a key in a secure element that checks that the driver method is called. A few API functions involve multiple driver methods; these should validate that all the expected driver methods are called.
42* Make at least one test with a key that is not in a secure element that checks that the driver method is not called.
43* Make at least one test with a key in a secure element with a driver that does not have the requisite method (i.e. the method pointer is `NULL`) but has the substructure containing that method, and check that the return value is `PSA_ERROR_NOT_SUPPORTED`.
44* Make at least one test with a key in a secure element with a driver that does not have the substructure containing that method (i.e. the pointer to the substructure is `NULL`), and check that the return value is `PSA_ERROR_NOT_SUPPORTED`.
45* At least one test should register multiple drivers with a key in each driver and check that the expected driver is called. This does not need to be done for all operations (use a white-box approach to determine if operations may use different code paths to choose the driver).
46* At least one test should register the same driver structure with multiple lifetime values and check that the driver receives the expected lifetime value.
47
48Some methods only make sense as a group (for example a driver that provides the MAC methods must provide all or none). In those cases, test with all of them null and none of them null.
49
50#### SE driver inputs
51
52For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent):
53
54* Wherever the specification guarantees parameters that satisfy certain preconditions, check these preconditions whenever practical.
55* If the API function can take parameters that are invalid and must not reach the driver, call the API function with such parameters and verify that the driver method is not called.
Gilles Peskine8b193c12019-09-05 17:58:13 +020056* Check that the expected inputs reach the driver. This may be implicit in a test that checks the outputs if the only realistic way to obtain the correct outputs is to start from the expected inputs (as is often the case for cryptographic material, but not for metadata).
Gilles Peskine92bcfdb2019-09-04 19:26:50 +020057
58#### SE driver outputs
59
Fredrik Hessecc207bc2021-09-28 21:06:08 +020060For each API function that leads to a driver call, call it with parameters that cause a driver to be invoked and check how Mbed TLS handles the outputs.
Gilles Peskine92bcfdb2019-09-04 19:26:50 +020061
62* Correct outputs.
63* Incorrect outputs such as an invalid output length.
64* Expected errors (e.g. `PSA_ERROR_INVALID_SIGNATURE` from a signature verification method).
65* Unexpected errors. At least test that if the driver returns `PSA_ERROR_GENERIC_ERROR`, this is propagated correctly.
66
67Key creation functions invoke multiple methods and need more complex error handling:
68
69* Check the consequence of errors detected at each stage (slot number allocation or validation, key creation method, storage accesses).
70* Check that the storage ends up in the expected state. At least make sure that no intermediate file remains after a failure.
71
72#### Persistence of SE keys
73
74The following tests must be performed at least one for each key creation method (import, generate, ...).
75
76* Test that keys in a secure element survive `psa_close_key(); psa_open_key()`.
77* Test that keys in a secure element survive `mbedtls_psa_crypto_free(); psa_crypto_init()`.
78* Test that the driver's persistent data survives `mbedtls_psa_crypto_free(); psa_crypto_init()`.
79* Test that `psa_destroy_key()` does not leave any trace of the key.
80
81#### Resilience for SE drivers
82
83Creating or removing a key in a secure element involves multiple storage modifications (M<sub>1</sub>, ..., M<sub>n</sub>). If the operation is interrupted by a reset at any point, it must be either rolled back or completed.
84
85* For each potential interruption point (before M<sub>1</sub>, between M<sub>1</sub> and M<sub>2</sub>, ..., after M<sub>n</sub>), call `mbedtls_psa_crypto_free(); psa_crypto_init()` at that point and check that this either rolls back or completes the operation that was started.
86* This must be done for each key creation method and for key destruction.
87* This must be done for each possible flow, including error cases (e.g. a key creation that fails midway due to `OUT_OF_MEMORY`).
88* The recovery during `psa_crypto_init` can itself be interrupted. Test those interruptions too.
89* Two things need to be tested: the key that is being created or destroyed, and the driver's persistent storage.
bootstrap-prime6dbbf442022-05-17 19:30:44 -040090* Check both that the storage has the expected content (this can be done by e.g. using a key that is supposed to be present) and does not have any unexpected content (for keys, this can be done by checking that `psa_open_key` fails with `PSA_ERROR_DOES_NOT_EXIST`).
Gilles Peskine92bcfdb2019-09-04 19:26:50 +020091
92This requires instrumenting the storage implementation, either to force it to fail at each point or to record successive storage states and replay each of them. Each `psa_its_xxx` function call is assumed to be atomic.
93
94### SE driver system tests
95
96#### Real-world use case
97
98We must have at least one driver that is close to real-world conditions:
99
100* With its own source tree.
101* Running on actual hardware.
102* Run the full driver validation test suite (which does not yet exist).
103* Run at least one test application (e.g. the Mbed OS TLS example).
104
Gilles Peskine545c28b2019-09-04 19:41:16 +0200105This requirement shall be fulfilled by the [Microchip ATECC508A driver](https://github.com/ARMmbed/mbed-os-atecc608a/).
Gilles Peskine92bcfdb2019-09-04 19:26:50 +0200106
107#### Complete driver
108
109We should have at least one driver that covers the whole interface:
110
111* With its own source tree.
112* Implementing all the methods.
113* Run the full driver validation test suite (which does not yet exist).
114
115A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering.
Gilles Peskine24cebf62020-11-30 17:51:53 +0100116
Manuel Pégourié-Gonnard1a827a32023-11-13 10:01:21 +0100117## Unified driver interface testing
Gilles Peskine24cebf62020-11-30 17:51:53 +0100118
119The [unified driver interface](../../proposed/psa-driver-interface.md) defines interfaces for accelerators.
120
121### Test requirements
122
123#### Requirements for transparent driver testing
124
125Every cryptographic mechanism for which a transparent driver interface exists (key creation, cryptographic operations, …) must be exercised in at least one build. The test must verify that the driver code is called.
126
127#### Requirements for fallback
128
129The driver interface includes a fallback mechanism so that a driver can reject a request at runtime and let another driver handle the request. For each entry point, there must be at least three test runs with two or more drivers available with driver A configured to fall back to driver B, with one run where A returns `PSA_SUCCESS`, one where A returns `PSA_ERROR_NOT_SUPPORTED` and B is invoked, and one where A returns a different error and B is not invoked.
130
Manuel Pégourié-Gonnard1a827a32023-11-13 10:01:21 +0100131### Test framework
132
133We have test drivers that are enabled by `PSA_CRYPTO_DRIVER_TEST` (not present
134in the usual config files, must be defined on the command line or in a custom
135config file). Those test drivers are implemented in `tests/src/drivers/*.c`
136and their API is declared in `tests/include/test/drivers/*.h`.
137
138We have two test driver registered: `mbedtls_test_opaque_driver` and
139`mbedtls_test_transparent_driver`. These are described in
140`scripts/data_files/driver_jsons/mbedtls_test_xxx_driver.json` (as much as our
141JSON support currently allows). Each of the drivers can potentially implement
142support for several mechanism; conversely, each of the file mentioned in the
143previous paragraph can potentially contribute to both the opaque and the
144transparent test driver.
145
146Each entry point is instrumented to record the number of hits for each part of
147the driver (same division as the files) and the status of the last call. It is
148also possible to force the next call to return a specified status. See the
149various `mbedtls_test_driver_XXX_hooks_t` structures declared by each driver.
150
151The drivers can use one of two back-ends:
152- internal: this requires the built-in implementation to be present.
153- libtestdriver1: this allows the built-in implementation to be omitted from
154 the build.
155
156Historical note: internal was initially the only back-end; then support for
157libtestdriver1 was added gradually.
158
159Question: if/when we have complete libtestdriver1 support, do we still need
160internal? Thoughts:
161- It's useful to have builds with both a driver and the built-in, in
162order to test fallback to built-in, but this could be achieved with
163libtestdriver1 too.
164 - Performance might be better with internal though?
165- The instrumentation works the same with both back-ends.
166
167Our implementation of PSA Crypto is structured in a way that the built-in
168implementation of each operation follows the driver API, see
169[`../architecture/psa-crypto-implementation-structure.md`](../architecture/psa-crypto-implementation-structure.html).
170This makes implementing the test drivers very easy: each entry point has a
171corresponding `mbedtls_psa_xxx()` function that it can call as its
172implementation - with the `libtestdriver1` back-end the function is called
173`libtestdriver1_mbedtls_psa_xxx()` instead.
174
175The renaming process for `libtestdriver1` is implemented as a few Perl regexes
176applied to a copy of the library code, see the `libtestdriver1.a` target in
177`tests/Makefile`. Another modification that's done to this copy is appending
178`tests/include/test/drivers/crypto_config_test_driver_extension.h` to
179`psa/crypto_config.h`. This file reverses the `ACCEL`/`BUILTIN` macros so that
180`libtestdriver1` includes as built-in what the main `libmbedcrypto.a` will
181have accelerated; see that file's initial comment for details. See also
182`helper_libtestdriver1_` functions and the preceding comment in `all.sh` for
183how libtestdriver is used in practice.
184
185This general framework needs specific code for each family of operations. At a
186given point in time, not all operations have the same level of support. The
187following sub-sections describe the status of the test driver support, mostly
188following the structure and order of sections 9.6 and 10.2 to 10.10 of the
189[PSA Crypto standard](https://arm-software.github.io/psa-api/crypto/1.1/) as
190that is also a natural division for implementing test drivers (that's how the
191code is divided into files). It should be noted that the implementation
192strategy ensures that when and entry point has test-driver support, it
193automatically works for all algorithms and key types supported by the library,
194thanks to the implementation strategy mentioned above.
195
196#### Key management
197
198TODO
199
200#### Message digests (Hashes)
201
202TODO
203
204#### Message authentication codes (MAC)
205
206TODO
207
208#### Unauthenticated ciphers
209
210TODO
211
212#### Authenticated encryption with associated data (AEAD)
213
214TODO
215
216#### Key derivation
217
218TODO
219
220#### Asymmetric signature
221
222TODO
223
224#### Asymmetric encryption
225
226TODO
227
228#### Key agreement
229
230TODO
231
232#### Other cryptographic services (Random number generation)
Gilles Peskine24cebf62020-11-30 17:51:53 +0100233
234TODO