Skip to content

Commit

Permalink
Add example for integrating a driver alongside Mbed TLS for entrypoin…
Browse files Browse the repository at this point in the history
…ts where auto-generation of driver wrappers is not implemented yet.

Using p256-m as the example driver/software accelerator.

Signed-off-by: Aditya Deshpande <aditya.deshpande@arm.com>
  • Loading branch information
aditya-deshpande-arm committed Jan 25, 2023
1 parent 1f786aa commit 5d5e640
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions docs/psa-driver-example-and-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:**
```
Expand Down Expand Up @@ -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**
Expand All @@ -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** \

**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.

0 comments on commit 5d5e640

Please sign in to comment.