This document describes the test strategy for the driver interfaces in Mbed Crypto. Mbed Crypto has interfaces for secure element drivers, accelerator drivers and entropy drivers. This document is about testing Mbed Crypto itself; testing drivers is out of scope.
The driver interfaces are standardized through PSA Cryptography functional specifications.
The unified driver interface supports both transparent drivers (for accelerators) and opaque drivers (for secure elements).
Drivers exposing this interface need to be registered at compile time by declaring their JSON description file.
The dynamic secure element driver interface (SE interface for short) is defined by psa/crypto_se_driver.h
. This is an interface between Mbed Crypto and one or more third-party drivers.
The SE interface consists of one function provided by Mbed Crypto (psa_register_se_driver
) and many functions that drivers must implement. To make a driver usable by Mbed Crypto, 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.
This 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.
Many SE driver interface unit tests could be covered by running the existing API tests with a key in a secure element.
This applies to dynamic drivers only.
psa_register_se_driver
with valid and with invalid arguments.psa_register_se_driver
followed by a successful call.For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent):
NULL
) but has the substructure containing that method, and check that the return value is PSA_ERROR_NOT_SUPPORTED
.NULL
), and check that the return value is PSA_ERROR_NOT_SUPPORTED
.Some 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.
For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent):
For each API function that leads to a driver call, call it with parameters that cause a driver to be invoked and check how Mbed Crypto handles the outputs.
PSA_ERROR_INVALID_SIGNATURE
from a signature verification method).PSA_ERROR_GENERIC_ERROR
, this is propagated correctly.Key creation functions invoke multiple methods and need more complex error handling:
The following tests must be performed at least one for each key creation method (import, generate, ...).
psa_close_key(); psa_open_key()
.mbedtls_psa_crypto_free(); psa_crypto_init()
.mbedtls_psa_crypto_free(); psa_crypto_init()
.psa_destroy_key()
does not leave any trace of the key.Creating or removing a key in a secure element involves multiple storage modifications (M1, ..., Mn). If the operation is interrupted by a reset at any point, it must be either rolled back or completed.
mbedtls_psa_crypto_free(); psa_crypto_init()
at that point and check that this either rolls back or completes the operation that was started.OUT_OF_MEMORY
).psa_crypto_init
can itself be interrupted. Test those interruptions too.psa_open_key
fails with PSA_ERRROR_DOES_NOT_EXIST
).This 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.
We must have at least one driver that is close to real-world conditions:
This requirement shall be fulfilled by the Microchip ATECC508A driver.
We should have at least one driver that covers the whole interface:
A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering.
The unified driver interface defines interfaces for accelerators.
Every 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.
The 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.
TODO