From 5d5e6402f6500439dee2ebabd14de763e1779e0a Mon Sep 17 00:00:00 2001 From: Aditya Deshpande Date: Tue, 24 Jan 2023 17:02:56 +0000 Subject: [PATCH] Add example for integrating a driver alongside Mbed TLS for entrypoints where auto-generation of driver wrappers is not implemented yet. Using p256-m as the example driver/software accelerator. Signed-off-by: Aditya Deshpande --- docs/psa-driver-example-and-guide.md | 37 ++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/psa-driver-example-and-guide.md b/docs/psa-driver-example-and-guide.md index 699826a5d59..f824410ce6e 100644 --- a/docs/psa-driver-example-and-guide.md +++ b/docs/psa-driver-example-and-guide.md @@ -56,6 +56,7 @@ If one has not been provided then write one. Its name should begin with the driv *Return Codes:* * `PSA_SUCCESS`: Successful Execution * `PSA_ERROR_NOT_SUPPORTED`: Input arguments are correct, but the driver does not support the operation. If a transparent driver returns this +* `PSA_ERROR_XXX`: Any other PSA error code, see API documentation **4. Include the following in one of the driver header files:** ``` @@ -110,7 +111,6 @@ psa_driver_wrapper_xxx() └── return psa_xxx_builtin() // fall back to built in implementation ``` - All code related to driver calls within each `case` must be contained between `#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)` and a corresponding `#endif`. Within this block, each individual driver's compatibility checks and call to the entry point must be contained between `#if defined(DRIVER_PREFIX_ENABLED)` and a corresponding `#endif`. Checks that involve accessing key material using PSA macros, such as determining the key type or number of bits, must be done in the driver wrapper. **7. Build Mbed TLS with the driver** @@ -123,4 +123,37 @@ This guide assumes you are building Mbed TLS from source alongside your project. [p256-m](https://github.com/mpg/p256-m) is a minimalistic implementation of ECDH and ECDSA on NIST P-256 curves, specifically optimized for use in constrained 32-bit environments. As such, it serves as a software accelerator. This section demonstrates the integration of `p256-m` as a transparent driver alongside Mbed TLS, serving as a guide for implementation. The code for p256-m can be found in `3rdparty/p256-m/p256m`. In this demonstration, p256-m is built from source alongside Mbed TLS. -**1. Driver Prefix/Macro** \ \ No newline at end of file + +**NOTE:** p256-m also implements key generation. However, it's RNG is based on `stdlib`, making this feature **unsuitable for production builds**. It is included with Mbed TLS purely to be used as an example. + +The driver prefix for p256-m is `P256`/`p256`. The driver macro is `MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED`. To build with and use p256-m, set this macro by running the following command from the root of the `mbedtls/` directory: + + python3 scripts/config.py set MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED + +p256-m implements four entry points: `generate_key`, `key_agreement`, `sign_hash`, `verify_hash`. The `sign/verify_hash` entry points are used instead of `sign/verify_message` as messages must be hashed prior to any operation, and p256-m does not implement this. The driver entry point functions can be found in `p256m_driver_entrypoints.[hc]`. These functions act as an interface between Mbed TLS and p256-m; converting between PSA and p256-m argument formats and performing sanity checks. If the driver's status codes are different to the PSA status codes, it is also recommended that a status code translation function be implemented. For example, the function `p256_to_psa_error()` converts error codes returned by p256-m into PSA error codes. + +The driver wrapper functions in `psa_crypto_driver_wrappers.c.jinja` for all four entry points have also been modified. The code block below shows the additions made to `psa_driver_wrapper_sign_hash()`. In adherence to the defined process, all code related to the driver call is placed within a check for `MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED`. p256-m only supports non-deterministic ECDSA using keys based on NIST P256; these constraints are enforced through checks (see the `if` statement). Checks that involve accessing key material, (e.g. checking key type or bits) **must** be performed in the driver wrapper. This is because this information is marked private and may not be accessed outside the library. Other checks can be performed here or in the entry point function. The status returned by the driver is propagated up the call hierarchy **unless** the driver does not support the operation (i.e. return `PSA_ERROR_NOT_SUPPORTED`). In that case the next available driver/built-in implementation is called. + +``` +#if defined (MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED) + if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) && + PSA_ALG_IS_ECDSA(alg) && + !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && + PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) == PSA_ECC_FAMILY_SECP_R1 && + attributes->core.bits == 256 ) + { + status = p256_transparent_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + } +#endif /* MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED */ +``` +Following this, p256-m is now ready to use alongside Mbed TLS as a software accelerator. If `MBEDTLS_P256M_EXAMPLE_DRIVER_ENABLED` is set in the config, p256-m's implementations of key generation, ECDH, and ECDSA will be used where applicable. \ No newline at end of file