From fc0c4ed9a3103e0e6534311923668879fc8e0875 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Sat, 26 Nov 2022 16:20:59 -0500 Subject: Removed openssl, and curl, and added mbedded tls. Almost fully removed curl, needs more testing. Fixed most issues, now trying to cross compile. Fix? Sigh. --- lib/mbedtls-2.27.0/docs/architecture/Makefile | 26 ++ .../mbed-crypto-storage-specification.md | 316 ++++++++++++++++++ .../psa-crypto-implementation-structure.md | 73 ++++ .../testing/driver-interface-test-strategy.md | 133 ++++++++ .../docs/architecture/testing/invasive-testing.md | 367 +++++++++++++++++++++ .../testing/psa-storage-format-testing.md | 103 ++++++ .../docs/architecture/testing/test-framework.md | 58 ++++ .../docs/architecture/tls13-experimental.md | 68 ++++ 8 files changed, 1144 insertions(+) create mode 100644 lib/mbedtls-2.27.0/docs/architecture/Makefile create mode 100644 lib/mbedtls-2.27.0/docs/architecture/mbed-crypto-storage-specification.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/psa-crypto-implementation-structure.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/testing/driver-interface-test-strategy.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/testing/invasive-testing.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/testing/psa-storage-format-testing.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/testing/test-framework.md create mode 100644 lib/mbedtls-2.27.0/docs/architecture/tls13-experimental.md (limited to 'lib/mbedtls-2.27.0/docs/architecture') diff --git a/lib/mbedtls-2.27.0/docs/architecture/Makefile b/lib/mbedtls-2.27.0/docs/architecture/Makefile new file mode 100644 index 0000000..d8db2e0 --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/Makefile @@ -0,0 +1,26 @@ +PANDOC = pandoc + +default: all + +all_markdown = \ + mbed-crypto-storage-specification.md \ + testing/driver-interface-test-strategy.md \ + testing/invasive-testing.md \ + testing/test-framework.md \ + # This line is intentionally left blank + +html: $(all_markdown:.md=.html) +pdf: $(all_markdown:.md=.pdf) +all: html pdf + +.SUFFIXES: +.SUFFIXES: .md .html .pdf + +.md.html: + $(PANDOC) -o $@ $< +.md.pdf: + $(PANDOC) -o $@ $< + +clean: + rm -f *.html *.pdf + rm -f testing/*.html testing/*.pdf diff --git a/lib/mbedtls-2.27.0/docs/architecture/mbed-crypto-storage-specification.md b/lib/mbedtls-2.27.0/docs/architecture/mbed-crypto-storage-specification.md new file mode 100644 index 0000000..914bca3 --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/mbed-crypto-storage-specification.md @@ -0,0 +1,316 @@ +Mbed Crypto storage specification +================================= + +This document specifies how Mbed Crypto uses storage. + +Mbed Crypto may be upgraded on an existing device with the storage preserved. Therefore: + +1. Any change may break existing installations and may require an upgrade path. +1. This document retains historical information about all past released versions. Do not remove information from this document unless it has always been incorrect or it is about a version that you are sure was never released. + +Mbed Crypto 0.1.0 +----------------- + +Tags: mbedcrypto-0.1.0b, mbedcrypto-0.1.0b2 + +Released in November 2018.
+Integrated in Mbed OS 5.11. + +Supported backends: + +* [PSA ITS](#file-namespace-on-its-for-0.1.0) +* [C stdio](#file-namespace-on-stdio-for-0.1.0) + +Supported features: + +* [Persistent transparent keys](#key-file-format-for-0.1.0) designated by a [slot number](#key-names-for-0.1.0). +* [Nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0) on ITS only. + +This is a beta release, and we do not promise backward compatibility, with one exception: + +> On Mbed OS, if a device has a nonvolatile random seed file produced with Mbed OS 5.11.x and is upgraded to a later version of Mbed OS, the nonvolatile random seed file is preserved or upgraded. + +We do not make any promises regarding key storage, or regarding the nonvolatile random seed file on other platforms. + +### Key names for 0.1.0 + +Information about each key is stored in a dedicated file whose name is constructed from the key identifier. The way in which the file name is constructed depends on the storage backend. The content of the file is described [below](#key-file-format-for-0.1.0). + +The valid values for a key identifier are the range from 1 to 0xfffeffff. This limitation on the range is not documented in user-facing documentation: according to the user-facing documentation, arbitrary 32-bit values are valid. + +The code uses the following constant in an internal header (note that despite the name, this value is actually one plus the maximum permitted value): + + #define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xffff0000 + +There is a shared namespace for all callers. + +### Key file format for 0.1.0 + +All integers are encoded in little-endian order in 8-bit bytes. + +The layout of a key file is: + +* magic (8 bytes): `"PSA\0KEY\0"` +* version (4 bytes): 0 +* type (4 bytes): `psa_key_type_t` value +* policy usage flags (4 bytes): `psa_key_usage_t` value +* policy usage algorithm (4 bytes): `psa_algorithm_t` value +* key material length (4 bytes) +* key material: output of `psa_export_key` +* Any trailing data is rejected on load. + +### Nonvolatile random seed file format for 0.1.0 + +The nonvolatile random seed file contains a seed for the random generator. If present, it is rewritten at each boot as part of the random generator initialization. + +The file format is just the seed as a byte string with no metadata or encoding of any kind. + +### File namespace on ITS for 0.1.0 + +Assumption: ITS provides a 32-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. + +* File 0: unused. +* Files 1 through 0xfffeffff: [content](#key-file-format-for-0.1.0) of the [key whose identifier is the file identifier](#key-names-for-0.1.0). +* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0). +* Files 0xffff0000 through 0xffffff51, 0xffffff53 through 0xffffffff: unused. + +### File namespace on stdio for 0.1.0 + +Assumption: C stdio, allowing names containing lowercase letters, digits and underscores, of length up to 23. + +An undocumented build-time configuration value `CRYPTO_STORAGE_FILE_LOCATION` allows storing the key files in a directory other than the current directory. This value is simply prepended to the file name (so it must end with a directory separator to put the keys in a different directory). + +* `CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0"`: used as a temporary file. Must be writable. May be overwritten or deleted if present. +* `sprintf(CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu", key_id)` [content](#key-file-format-for-0.1.0) of the [key whose identifier](#key-names-for-0.1.0) is `key_id`. +* Other files: unused. + +Mbed Crypto 1.0.0 +----------------- + +Tags: mbedcrypto-1.0.0d4, mbedcrypto-1.0.0 + +Released in February 2019.
+Integrated in Mbed OS 5.12. + +Supported integrations: + +* [PSA platform](#file-namespace-on-a-psa-platform-for-1.0.0) +* [library using PSA ITS](#file-namespace-on-its-as-a-library-for-1.0.0) +* [library using C stdio](#file-namespace-on-stdio-for-1.0.0) + +Supported features: + +* [Persistent transparent keys](#key-file-format-for-1.0.0) designated by a [key identifier and owner](#key-names-for-1.0.0). +* [Nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0) on ITS only. + +Backward compatibility commitments: TBD + +### Key names for 1.0.0 + +Information about each key is stored in a dedicated file designated by the key identifier. In integrations where there is no concept of key owner (in particular, in library integrations), the key identifier is exactly the key identifier as defined in the PSA Cryptography API specification (`psa_key_id_t`). In integrations where there is a concept of key owner (integration into a service for example), the key identifier is made of an owner identifier (its semantics and type are integration specific) and of the key identifier (`psa_key_id_t`) from the key owner point of view. + +The way in which the file name is constructed from the key identifier depends on the storage backend. The content of the file is described [below](#key-file-format-for-1.0.0). + +* Library integration: the key file name is just the key identifier as defined in the PSA crypto specification. This is a 32-bit value. +* PSA service integration: the key file name is `(uint32_t)owner_uid << 32 | key_id` where `key_id` is the key identifier from the owner point of view and `owner_uid` (of type `int32_t`) is the calling partition identifier provided to the server by the partition manager. This is a 64-bit value. + +### Key file format for 1.0.0 + +The layout is identical to [0.1.0](#key-file-format-for-0.1.0) so far. However note that the encoding of key types, algorithms and key material has changed, therefore the storage format is not compatible (despite using the same value in the version field so far). + +### Nonvolatile random seed file format for 1.0.0 + +[Identical to 0.1.0](#nonvolatile-random-seed-file-format-for-0.1.0). + +### File namespace on a PSA platform for 1.0.0 + +Assumption: ITS provides a 64-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. + +Assumption: the owner identifier is a nonzero value of type `int32_t`. + +* Files 0 through 0xffffff51, 0xffffff53 through 0xffffffff: unused, reserved for internal use of the crypto library or crypto service. +* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-0.1.0). +* Files 0x100000000 through 0xffffffffffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). The upper 32 bits determine the owner. + +### File namespace on ITS as a library for 1.0.0 + +Assumption: ITS provides a 64-bit file identifier namespace. The entity using the crypto library can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. + +This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. + +* File 0: unused. +* Files 1 through 0xfffeffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). +* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0). +* Files 0xffff0000 through 0xffffff51, 0xffffff53 through 0xffffffff, 0x100000000 through 0xffffffffffffffff: unused. + +### File namespace on stdio for 1.0.0 + +This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. + +[Identical to 0.1.0](#file-namespace-on-stdio-for-0.1.0). + +### Upgrade from 0.1.0 to 1.0.0. + +* Delete files 1 through 0xfffeffff, which contain keys in a format that is no longer supported. + +### Suggested changes to make before 1.0.0 + +The library integration and the PSA platform integration use different sets of file names. This is annoyingly non-uniform. For example, if we want to store non-key files, we have room in different ranges (0 through 0xffffffff on a PSA platform, 0xffff0000 through 0xffffffffffffffff in a library integration). + +It would simplify things to always have a 32-bit owner, with a nonzero value, and thus reserve the range 0–0xffffffff for internal library use. + +Mbed Crypto 1.1.0 +----------------- + +Tags: mbedcrypto-1.1.0 + +Released in early June 2019.
+Integrated in Mbed OS 5.13. + +Identical to [1.0.0](#mbed-crypto-1.0.0) except for some changes in the key file format. + +### Key file format for 1.1.0 + +The key file format is identical to [1.0.0](#key-file-format-for-1.0.0), except for the following changes: + +* A new policy field, marked as [NEW:1.1.0] below. +* The encoding of key types, algorithms and key material has changed, therefore the storage format is not compatible (despite using the same value in the version field so far). + +A self-contained description of the file layout follows. + +All integers are encoded in little-endian order in 8-bit bytes. + +The layout of a key file is: + +* magic (8 bytes): `"PSA\0KEY\0"` +* version (4 bytes): 0 +* type (4 bytes): `psa_key_type_t` value +* policy usage flags (4 bytes): `psa_key_usage_t` value +* policy usage algorithm (4 bytes): `psa_algorithm_t` value +* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value [NEW:1.1.0] +* key material length (4 bytes) +* key material: output of `psa_export_key` +* Any trailing data is rejected on load. + +Mbed Crypto TBD +--------------- + +Tags: TBD + +Released in TBD 2019.
+Integrated in Mbed OS TBD. + +### Changes introduced in TBD + +* The layout of a key file now has a lifetime field before the type field. +* Key files can store references to keys in a secure element. In such key files, the key material contains the slot number. + +### File namespace on a PSA platform on TBD + +Assumption: ITS provides a 64-bit file identifier namespace. The Crypto service can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. + +Assumption: the owner identifier is a nonzero value of type `int32_t`. + +* Files 0 through 0xfffeffff: unused. +* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-tbd). +* Files 0x100000000 through 0xffffffffffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). The upper 32 bits determine the owner. + +### File namespace on ITS as a library on TBD + +Assumption: ITS provides a 64-bit file identifier namespace. The entity using the crypto library can use arbitrary file identifiers and no other part of the system accesses the same file identifier namespace. + +This is a library integration, so there is no owner. The key file identifier is identical to the key identifier. + +* File 0: unused. +* Files 1 through 0xfffeffff: [content](#key-file-format-for-1.0.0) of the [key whose identifier is the file identifier](#key-names-for-1.0.0). +* Files 0xffff0000 through 0xffffffff: reserved for internal use of the crypto library or crypto service. See [non-key files](#non-key-files-on-tbd). +* Files 0x100000000 through 0xffffffffffffffff: unused. + +### Non-key files on TBD + +File identifiers in the range 0xffff0000 through 0xffffffff are reserved for internal use in Mbed Crypto. + +* Files 0xfffffe02 through 0xfffffeff (`PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime`): secure element driver storage. The content of the file is the secure element driver's persistent data. +* File 0xffffff52 (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`): [nonvolatile random seed](#nonvolatile-random-seed-file-format-for-1.0.0). +* File 0xffffff54 (`PSA_CRYPTO_ITS_TRANSACTION_UID`): [transaction file](#transaction-file-format-for-tbd). +* Other files are unused and reserved for future use. + +### Key file format for TBD + +All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated. + +The layout of a key file is: + +* magic (8 bytes): `"PSA\0KEY\0"`. +* version (4 bytes): 0. +* lifetime (4 bytes): `psa_key_lifetime_t` value. +* type (4 bytes): `psa_key_type_t` value. +* policy usage flags (4 bytes): `psa_key_usage_t` value. +* policy usage algorithm (4 bytes): `psa_algorithm_t` value. +* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value. +* key material length (4 bytes). +* key material: + * For a transparent key: output of `psa_export_key`. + * For an opaque key (unified driver interface): driver-specific opaque key blob. + * For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness. +* Any trailing data is rejected on load. + +### Transaction file format for TBD + +The transaction file contains data about an ongoing action that cannot be completed atomically. It exists only if there is an ongoing transaction. + +All integers are encoded in platform endianness. + +All currently existing transactions concern a key in a secure element. + +The layout of a transaction file is: + +* type (2 bytes): the [transaction type](#transaction-types-on-tbd). +* unused (2 bytes) +* lifetime (4 bytes): `psa_key_lifetime_t` value that corresponds to a key in a secure element. +* slot number (8 bytes): `psa_key_slot_number_t` value. This is the unique designation of the key for the secure element driver. +* key identifier (4 bytes in a library integration, 8 bytes on a PSA platform): the internal representation of the key identifier. On a PSA platform, this encodes the key owner in the same way as [in file identifiers for key files](#file-namespace-on-a-psa-platform-on-tbd)). + +#### Transaction types on TBD + +* 0x0001: key creation. The following locations may or may not contain data about the key that is being created: + * The slot in the secure element designated by the slot number. + * The file containing the key metadata designated by the key identifier. + * The driver persistent data. +* 0x0002: key destruction. The following locations may or may not still contain data about the key that is being destroyed: + * The slot in the secure element designated by the slot number. + * The file containing the key metadata designated by the key identifier. + * The driver persistent data. + +Mbed Crypto TBD +--------------- + +Tags: TBD + +Released in TBD 2020.
+Integrated in Mbed OS TBD. + +### Changes introduced in TBD + +* The type field has been split into a type and a bits field of 2 bytes each. + +### Key file format for TBD + +All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated. + +The layout of a key file is: + +* magic (8 bytes): `"PSA\0KEY\0"`. +* version (4 bytes): 0. +* lifetime (4 bytes): `psa_key_lifetime_t` value. +* type (2 bytes): `psa_key_type_t` value. +* bits (2 bytes): `psa_key_bits_t` value. +* policy usage flags (4 bytes): `psa_key_usage_t` value. +* policy usage algorithm (4 bytes): `psa_algorithm_t` value. +* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value. +* key material length (4 bytes). +* key material: + * For a transparent key: output of `psa_export_key`. + * For an opaque key (unified driver interface): driver-specific opaque key blob. + * For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness. +* Any trailing data is rejected on load. diff --git a/lib/mbedtls-2.27.0/docs/architecture/psa-crypto-implementation-structure.md b/lib/mbedtls-2.27.0/docs/architecture/psa-crypto-implementation-structure.md new file mode 100644 index 0000000..cd4d427 --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/psa-crypto-implementation-structure.md @@ -0,0 +1,73 @@ +PSA Cryptograpy API implementation and PSA driver interface +=========================================================== + +## Introduction + +The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations for which the Mbed TLS library provides a reference implementation. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers. + +This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tightly related to the PSA driver interface. + +## High level organization of the Mbed TLS PSA Cryptography API implementation +In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a core and PSA drivers as defined in the PSA driver interface. The key point is that software cryptographic operations are organized as PSA drivers: they interact with the core through the PSA driver interface. + +### Rationale + +* Addressing software and hardware cryptographic implementations through the same C interface reduces the core code size and its call graph complexity. The core and its dispatching to software and hardware implementations are consequently easier to test and validate. +* The organization of the software cryptographic implementations in drivers promotes modularization of those implementations. +* As hardware capabilities, software cryptographic functionalities can be described by a JSON driver description file as defined in the PSA driver interface. +* Along with JSON driver description files, the PSA driver specification defines the deliverables for a driver to be included into the Mbed TLS PSA Cryptography implementation. This provides a natural framework to integrate third party or alternative software implementations of cryptographic operations. + +## The Mbed TLS PSA Cryptography API implementation core + +The core implements all the APIs as defined in the PSA Cryptography API specification but does not perform on its own any cryptographic operation. The core relies on PSA drivers to actually +perform the cryptographic operations. The core is responsible for: + +* the key store. +* checking PSA API arguments and translating them into valid arguments for the necessary calls to the PSA driver interface. +* dispatching the cryptographic operations to the appropriate PSA drivers. + +The sketch of an Mbed TLS PSA cryptographic API implementation is thus: +```C +psa_status_t psa_api( ... ) +{ + psa_status_t status; + + /* Pre driver interface call processing: validation of arguments, building + * of arguments for the call to the driver interface, ... */ + + ... + + /* Call to the driver interface */ + status = psa_driver_wrapper_( ... ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Post driver interface call processing: validation of the values returned + * by the driver, finalization of the values to return to the caller, + * clean-up in case of error ... */ +} +``` +The code of most PSA APIs is expected to match precisely the above layout. However, it is likely that the code structure of some APIs will be more complicated with several calls to the driver interface, mainly to encompass a larger variety of hardware designs. For example, to encompass hardware accelerators that are capable of verifying a MAC and those that are only capable of computing a MAC, the psa_mac_verify() API could call first psa_driver_wrapper_mac_verify() and then fallback to psa_driver_wrapper_mac_compute(). + +The implementations of `psa_driver_wrapper_` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are generated in a psa_crypto_driver_wrappers.c C file and the function prototypes declared in a psa_crypto_driver_wrappers.h header file. + +The psa_driver_wrapper_() functions dispatch cryptographic operations to accelerator drivers, secure element drivers as well as to the software implementations of cryptographic operations. + +Note that the implementation allows to build the library with only a C compiler by shipping a generated file corresponding to a pure software implementation. The driver entry points and their code in this generated file are guarded by pre-processor directives based on PSA_WANT_xyz macros (see [Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS](psa-conditional-inclusion-c.html). That way, it is possible to compile and include in the library only the desired cryptographic operations. + +### Key creation + +Key creation implementation in Mbed TLS PSA core is articulated around three internal functions: psa_start_key_creation(), psa_finish_key_creation() and psa_fail_key_creation(). Implementations of key creation PSA APIs, namely psa_import_key(), psa_generate_key(), psa_key_derivation_output_key() and psa_copy_key() go by the following sequence: + 1. Check the input parameters. + 2. Call psa_start_key_creation() that allocates a key slot, prepares it with the specified key attributes, and in case of a volatile key assign it a volatile key identifier. + 3. Generate or copy the key material into the key slot. This entails the allocation of the buffer to store the key material. + 4. Call psa_finish_key_creation() that mostly saves persistent keys into persistent storage. + +In case of any error occurring at step 3 or 4, psa_fail_key_creation() is called. It wipes and cleans the slot especially the key material: reset to zero of the RAM memory that contained the key material, free the allocated buffer. + + +## Mbed TLS PSA Cryptography API implementation drivers + +A driver of the Mbed TLS PSA Cryptography API implementation (Mbed TLS PSA driver in the following) is a driver in the sense that it is compliant with the PSA driver interface specification. But it is not an actual driver that drives some hardware. It implements cryptographic operations purely in software. + +An Mbed TLS PSA driver C file is named psa_crypto_.c and its associated header file psa_crypto_.h. The functions implementing a driver entry point as defined in the PSA driver interface specification are named as mbedtls_psa__(). As an example, the psa_crypto_rsa.c and psa_crypto_rsa.h are the files containing the Mbed TLS PSA driver implementing RSA cryptographic operations. This RSA driver implements among other entry points the "import_key" entry point. The function implementing this entry point is named mbedtls_psa_rsa_import_key(). diff --git a/lib/mbedtls-2.27.0/docs/architecture/testing/driver-interface-test-strategy.md b/lib/mbedtls-2.27.0/docs/architecture/testing/driver-interface-test-strategy.md new file mode 100644 index 0000000..086fc1a --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/testing/driver-interface-test-strategy.md @@ -0,0 +1,133 @@ +# Mbed Crypto driver interface test strategy + +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. + +## Secure element driver interface testing + +### Secure element driver interfaces + +#### Opaque driver interface + +The [unified driver interface](../../proposed/psa-driver-interface.md) 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. + +#### Dynamic secure element driver interface + +The 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 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. + +### SE driver interface unit tests + +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. + +#### SE driver registration + +This applies to dynamic drivers only. + +* Test `psa_register_se_driver` with valid and with invalid arguments. +* Make at least one failing call to `psa_register_se_driver` followed by a successful call. +* Make at least one test that successfully registers the maximum number of drivers and fails to register one more. + +#### Dispatch to SE driver + +For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent): + +* 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. +* Make at least one test with a key that is not in a secure element that checks that the driver method is not called. +* 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`. +* 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`. +* 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). +* At least one test should register the same driver structure with multiple lifetime values and check that the driver receives the expected lifetime value. + +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. + +#### SE driver inputs + +For each API function that can lead to a driver call (more precisely, for each driver method call site, but this is practically equivalent): + +* Wherever the specification guarantees parameters that satisfy certain preconditions, check these preconditions whenever practical. +* 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. +* 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). + +#### SE driver outputs + +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. + +* Correct outputs. +* Incorrect outputs such as an invalid output length. +* Expected errors (e.g. `PSA_ERROR_INVALID_SIGNATURE` from a signature verification method). +* Unexpected errors. At least test that if the driver returns `PSA_ERROR_GENERIC_ERROR`, this is propagated correctly. + +Key creation functions invoke multiple methods and need more complex error handling: + +* Check the consequence of errors detected at each stage (slot number allocation or validation, key creation method, storage accesses). +* Check that the storage ends up in the expected state. At least make sure that no intermediate file remains after a failure. + +#### Persistence of SE keys + +The following tests must be performed at least one for each key creation method (import, generate, ...). + +* Test that keys in a secure element survive `psa_close_key(); psa_open_key()`. +* Test that keys in a secure element survive `mbedtls_psa_crypto_free(); psa_crypto_init()`. +* Test that the driver's persistent data survives `mbedtls_psa_crypto_free(); psa_crypto_init()`. +* Test that `psa_destroy_key()` does not leave any trace of the key. + +#### Resilience for SE drivers + +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. + +* For each potential interruption point (before M1, between M1 and M2, ..., after Mn), 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. +* This must be done for each key creation method and for key destruction. +* This must be done for each possible flow, including error cases (e.g. a key creation that fails midway due to `OUT_OF_MEMORY`). +* The recovery during `psa_crypto_init` can itself be interrupted. Test those interruptions too. +* Two things need to be tested: the key that is being created or destroyed, and the driver's persistent storage. +* 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_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. + +### SE driver system tests + +#### Real-world use case + +We must have at least one driver that is close to real-world conditions: + +* With its own source tree. +* Running on actual hardware. +* Run the full driver validation test suite (which does not yet exist). +* Run at least one test application (e.g. the Mbed OS TLS example). + +This requirement shall be fulfilled by the [Microchip ATECC508A driver](https://github.com/ARMmbed/mbed-os-atecc608a/). + +#### Complete driver + +We should have at least one driver that covers the whole interface: + +* With its own source tree. +* Implementing all the methods. +* Run the full driver validation test suite (which does not yet exist). + +A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering. + +## Transparent driver interface testing + +The [unified driver interface](../../proposed/psa-driver-interface.md) defines interfaces for accelerators. + +### Test requirements + +#### Requirements for transparent driver testing + +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. + +#### Requirements for fallback + +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. + +## Entropy and randomness interface testing + +TODO diff --git a/lib/mbedtls-2.27.0/docs/architecture/testing/invasive-testing.md b/lib/mbedtls-2.27.0/docs/architecture/testing/invasive-testing.md new file mode 100644 index 0000000..de611a5 --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/testing/invasive-testing.md @@ -0,0 +1,367 @@ +# Mbed TLS invasive testing strategy + +## Introduction + +In 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. + +The goal of this document is to identify areas where black-box testing is insufficient and to propose solutions. + +This is a test strategy document, not a test plan. A description of exactly what is tested is out of scope. + +This document is structured as follows: + +* [“Rules”](#rules) gives general rules and is written for brevity. +* [“Requirements”](#requirements) explores the reasons why invasive testing is needed and how it should be done. +* [“Possible approaches”](#possible-approaches) discusses some general methods for non-black-box testing. +* [“Solutions”](#solutions) explains how we currently solve, or intend to solve, specific problems. + +### TLS + +This 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. + +## Rules + +Always follow these rules unless you have a good reason not to. If you deviate, document the rationale somewhere. + +See the section [“Possible approaches”](#possible-approaches) for a rationale. + +### Interface design for testing + +Do 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. + +### Reliance on internal details + +In unit tests and in test programs, it's ok to include header files from `library/`. Do not define non-public interfaces in public headers (`include/mbedtls` has `*_internal.h` headers for legacy reasons, but this approach is deprecated). In contrast, sample programs must not include header files from `library/`. + +Sometimes 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)). + +If 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: + +> ``` +> /* This test file is specific to the ITS implementation in PSA Crypto +> * on top of stdio. It expects to know what the stdio name of a file is +> * based on its keystore name. +> */ +> ``` + +> ``` +> # This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes +> # and not expected to be raised any time soon) is less than the maximum +> # output from HKDF-SHA512 (255*64 = 16320 bytes). +> ``` + +### Rules for compile-time options + +If 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). + +* **Only use test-specific code when necessary.** Anything that can be tested through the documented API must be tested through the documented API. +* **Test-specific code must be guarded by `#if defined(MBEDTLS_TEST_HOOKS)`**. Do not create fine-grained guards for test-specific code. +* **Do not use `MBEDTLS_TEST_HOOKS` for security checks or assertions.** Security checks belong in the product. +* **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. +* **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. + +#### Rules for function substitution + +This 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. + +Often `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. + +Sometimes 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. + +With `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`. + +In unit test code that needs to modify the internal behavior: + +* The test function (or the whole test file) must depend on `MBEDTLS_TEST_HOOKS`. +* At the beginning of the test function, set the global function pointers to the desired value. +* In the test function's cleanup code, restore the global function pointers to their default value. + +## Requirements + +### General goals + +We need to balance the following goals, which are sometimes contradictory. + +* 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. +* 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. +* Effacement: the product should not include features that are solely present for test purposes, since these increase the attack surface and the code size. +* Portability: tests should work on every platform. Skipping tests on certain platforms may hide errors that are only apparent on such platforms. +* 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. + +Where those goals conflict, we should at least mitigate the goals that cannot be fulfilled, and document the architectural choices and their rationale. + +### Problem areas + +#### Allocation + +Resource allocation can fail, but rarely does so in a typical test environment. How does the product cope if some allocations fail? + +Resources include: + +* Memory. +* Files in storage (PSA API only — in the Mbed TLS API, black-box unit tests are sufficient). +* Key slots (PSA API only). +* Key slots in a secure element (PSA SE HAL). +* Communication handles (PSA crypto service only). + +#### Storage + +Storage can fail, either due to hardware errors or to active attacks on trusted storage. How does the code cope if some storage accesses fail? + +We also need to test resilience: if the system is reset during an operation, does it restart in a correct state? + +#### Cleanup + +When code should clean up resources, how do we know that they have truly been cleaned up? + +* Zeroization of confidential data after use. +* Freeing memory. +* Freeing key slots. +* Freeing key slots in a secure element. +* Deleting files in storage (PSA API only). + +#### Internal data + +Sometimes it is useful to peek or poke internal data. + +* Check consistency of internal data (e.g. output of key generation). +* Check the format of files (which matters so that the product can still read old files after an upgrade). +* Inject faults and test corruption checks inside the product. + +## Possible approaches + +Key to requirement tables: + +* ++ requirement is fully met +* \+ requirement is mostly met +* ~ requirement is partially met but there are limitations +* ! requirement is somewhat problematic +* !! requirement is very problematic + +### Fine-grained public interfaces + +We 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). + +As 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. + +Mbed 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. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ~ Many useful tests are not reasonably achievable | +| Correctness | ++ Ideal | +| Effacement | !! Requires adding many otherwise-useless interfaces | +| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | +| Maintainability | !! Combinatorial explosion on the testing burden | +| | ! Public interfaces must remain for backward compatibility even if the test architecture changes | + +### Fine-grained undocumented interfaces + +We 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. + +Mbed 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). + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ~ Many useful tests are not reasonably achievable | +| Correctness | ++ Ideal | +| Effacement | !! Requires adding many otherwise-useless interfaces | +| Portability | ++ Ideal; the additional interfaces may be useful for portability beyond testing | +| Maintainability | ! Combinatorial explosion on the testing burden | + +### Internal interfaces + +We 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. + +A 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. + +Another 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. + +This 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. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ~ Many useful tests require additional internal interfaces | +| Correctness | + Does not require a product change | +| | ~ The tests may call internal functions in a way that does not reflect actual usage inside the product | +| Effacement | ++ Fine as long as the internal interfaces aren't added solely for test purposes | +| Portability | + Fine as long as we control how the tests are linked | +| | ~ Doesn't work if the users rewrite an internal module | +| Maintainability | + Tests interfaces that are documented; dependencies in the tests are easily noticed when changing these interfaces | + +### Static analysis + +If we guarantee certain properties through static analysis, we don't need to test them. This puts some constraints on the properties: + +* We need to have confidence in the specification (but we can gain this confidence by evaluating the specification on test data). +* This does not work for platform-dependent properties unless we have a formal model of the platform. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ~ Good for platform-independent properties, if we can guarantee them statically | +| Correctness | + Good as long as we have confidence in the specification | +| Effacement | ++ Zero impact on the code | +| Portability | ++ Zero runtime burden | +| Maintainability | ~ Static analysis is hard, but it's also helpful | + +### Compile-time options + +If 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. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ++ Most things can be tested that way | +| Correctness | ! Difficult to ensure that what we test is what we run | +| Effacement | ++ No impact on the product when built normally or on the documentation, if done right | +| | ! Risk of getting “no impact” wrong | +| Portability | ++ It's just C code so it works everywhere | +| | ~ Doesn't work if the users rewrite an internal module | +| Maintainability | + Test interfaces impact the product source code, but at least they're clearly marked as such in the code | + +#### Guidelines for compile-time options + +* **Minimize the number of compile-time options.**
+ Either we're testing or we're not. Fine-grained options for testing would require more test builds, especially if combinatorics enters the play. +* **Merely enabling the compile-time option should not change the behavior.**
+ 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). +* **Minimize the impact on code**.
+ We should not have test-specific conditional compilation littered through the code, as that makes the code hard to read. + +### Runtime instrumentation + +Some properties can be tested through runtime instrumentation: have the compiler or a similar tool inject something into the binary. + +* Sanitizers check for certain bad usage patterns (ASan, MSan, UBSan, Valgrind). +* We can inject external libraries at link time. This can be a way to make system functions fail. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ! Limited scope | +| Correctness | + Instrumentation generally does not affect the program's functional behavior | +| Effacement | ++ Zero impact on the code | +| Portability | ~ Depends on the method | +| Maintainability | ~ Depending on the instrumentation, this may require additional builds and scripts | +| | + 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) | + +### Debugger-based testing + +If 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. + +This is a very powerful approach, but it comes with limitations: + +* 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. +* Due to compiler optimizations, the memory may not have the layout that we expect. +* 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. +* Debugger scripts are very much non-portable. + +| Requirement | Analysis | +| ----------- | -------- | +| Coverage | ++ The sky is the limit | +| Correctness | ++ The code is unmodified, and tested as compiled (so we even detect compiler-induced bugs) | +| | ! Compiler optimizations may hinder | +| | ~ Modifying the execution may introduce divergence | +| Effacement | ++ Zero impact on the code | +| Portability | !! Not all environments have a debugger, and even if they do, we'd need completely different scripts for every debugger | +| Maintainability | ! Writing reliable debugger scripts is hard | +| | !! Very tight coupling with the details of the source code and even with the compiler | + +## Solutions + +This section lists some strategies that are currently used for invasive testing, or planned to be used. This list is not intended to be exhaustive. + +### Memory management + +#### Zeroization testing + +Goal: test that `mbedtls_platform_zeroize` does wipe the memory buffer. + +Solution ([debugger](#debugger-based-testing)): implemented in `tests/scripts/test_zeroize.gdb`. + +Rationale: 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. + +#### Memory cleanup + +Goal: test the absence of memory leaks. + +Solution ([instrumentation](#runtime-instrumentation)): run tests with ASan. (We also use Valgrind, but it's slower than ASan, so we favor ASan.) + +Since 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. + +#### Robustness against memory allocation failure + +Solution: TODO. We don't test this at all at this point. + +#### PSA key store memory cleanup + +Goal: test the absence of resource leaks in the PSA key store code, in particular that `psa_close_key` and `psa_destroy_key` work correctly. + +Solution ([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. + +Note there must also be tests that call `mbedtls_psa_crypto_free` with keys still open, to verify that it does close all keys. + +`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`. + +### PSA storage + +#### PSA storage cleanup on success + +Goal: test that no stray files are left over in the key store after a test that succeeded. + +Solution: TODO. Currently the various test suites do it differently. + +#### PSA storage cleanup on failure + +Goal: 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). + +Solution: TODO. Currently the various test suites do it differently. + +#### PSA storage resilience + +Goal: test the resilience of PSA storage against power failures. + +Solution: TODO. + +See the [secure element driver interface test strategy](driver-interface-test-strategy.html) for more information. + +#### Corrupted storage + +Goal: test the robustness against corrupted storage. + +Solution ([internal interface](#internal-interfaces)): call `psa_its` functions to modify the storage. + +#### Storage read failure + +Goal: test the robustness against read errors. + +Solution: TODO + +#### Storage write failure + +Goal: test the robustness against write errors (`STORAGE_FAILURE` or `INSUFFICIENT_STORAGE`). + +Solution: TODO + +#### Storage format stability + +Goal: test that the storage format does not change between versions (or if it does, an upgrade path must be provided). + +Solution ([internal interface](#internal-interfaces)): call internal functions to inspect the content of the file. + +Note 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 + +### Other fault injection + +#### PSA crypto init failure + +Goal: test the failure of `psa_crypto_init`. + +Solution ([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. + +When we implement the PSA entropy driver interface, this should be reworked to use the entropy driver interface. + +#### PSA crypto data corruption + +The PSA crypto subsystem has a few checks to detect corrupted data in memory. We currently don't have a way to exercise those checks. + +Solution: 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. + diff --git a/lib/mbedtls-2.27.0/docs/architecture/testing/psa-storage-format-testing.md b/lib/mbedtls-2.27.0/docs/architecture/testing/psa-storage-format-testing.md new file mode 100644 index 0000000..71bf968 --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/testing/psa-storage-format-testing.md @@ -0,0 +1,103 @@ +# Mbed TLS PSA keystore format stability testing strategy + +## Introduction + +The PSA crypto subsystem includes a persistent key store. It is possible to create a persistent key and read it back later. This must work even if Mbed TLS has been upgraded in the meantime (except for deliberate breaks in the backward compatibility of the storage). + +The goal of this document is to define a test strategy for the key store that not only validates that it's possible to load a key that was saved with the version of Mbed TLS under test, but also that it's possible to load a key that was saved with previous versions of Mbed TLS. + +Interoperability is not a goal: PSA crypto implementations are not intended to have compatible storage formats. Downgrading is not required to work. + +## General approach + +### Limitations of a direct approach + +The goal of storage format stability testing is: as a user of Mbed TLS, I want to store a key under version V and read it back under version W, with W ≥ V. + +Doing the testing this way would be difficult because we'd need to have version V of Mbed TLS available when testing version W. + +An alternative, semi-direct approach consists of generating test data under version V, and reading it back under version W. Done naively, this would require keeping a large amount of test data (full test coverage multiplied by the number of versions that we want to preserve backward compatibility with). + +### Save-and-compare approach + +Importing and saving a key is deterministic. Therefore we can ensure the stability of the storage format by creating test cases under a version V of Mbed TLS, where the test case parameters include both the parameters to pass to key creation and the expected state of the storage after the key is created. The test case creates a key as indicated by the parameters, then compares the actual state of the storage with the expected state. In addition, the test case also loads the key and checks that it has the expected data and metadata. + +If the test passes with version V, this means that the test data is consistent with what the implementation does. When the test later runs under version W ≥ V, it creates and reads back a storage state which is known to be identical to the state that V would have produced. Thus, this approach validates that W can read storage states created by V. + +Use a similar approach for files other than keys where possible and relevant. + +### Keeping up with storage format evolution + +Test cases should normally not be removed from the code base: if something has worked before, it should keep working in future versions, so we should keep testing it. + +If the way certain keys are stored changes, and we don't deliberately decide to stop supporting old keys (which should only be done by retiring a version of the storage format), then we should keep the corresponding test cases in load-only mode: create a file with the expected content, load it and check the data that it contains. + +## Storage architecture overview + +The PSA subsystem provides storage on top of the PSA trusted storage interface. The state of the storage is a mapping from file identifer (a 64-bit number) to file content (a byte array). These files include: + +* [Key files](#key-storage) (files containing one key's metadata and, except for some secure element keys, key material). +* The [random generator injected seed or state file](#random-generator-state) (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`). +* [Storage transaction file](#storage-transaction-resumption). +* [Driver state files](#driver-state-files). + +For a more detailed description, refer to the [Mbed Crypto storage specification](../mbed-crypto-storage-specification.md). + +In addition, Mbed TLS includes an implementation of the PSA trusted storage interface on top of C stdio. This document addresses the test strategy for [PSA ITS over file](#psa-its-over-file) in a separate section below. + +## Key storage testing + +This section describes the desired test cases for keys created with the current storage format version. When the storage format changes, if backward compatibility is desired, old test data should be kept as described under [“Keeping up with storage format evolution”](#keeping-up-with-storage-format-evolution). + +### Keystore layout + +Objective: test that the key file name corresponds to the key identifier. + +Method: Create a key with a given identifier (using `psa_import_key`) and verify that a file with the expected name is created, and no other. Repeat for different identifiers. + +### General key format + +Objective: test the format of the key file: which field goes where and how big it is. + +Method: Create a key with certain metadata with `psa_import_key`. Read the file content and validate that it has the expected layout, deduced from the storage specification. Repeat with different metadata. Ensure that there are test cases covering all fields. + +### Enumeration of test cases for keys + +Objective: ensure that the coverage is sufficient to have assurance that all keys are stored correctly. This requires a sufficient selection of key types, sizes, policies, etc. + +In particular, the tests must validate that each `PSA_xxx` constant that is stored in a key is covered by at least once test case: + +* Usage flags: `PSA_KEY_USAGE_xxx`. +* Algorithms in policies: `PSA_ALG_xxx`. +* Key types: `PSA_KEY_TYPE_xxx`, `PSA_ECC_FAMILY_xxx`, `PSA_DH_FAMILY_xxx`. + +Method: Each test case creates a key with `psa_import_key`, purges it from memory, then reads it back and exercises it. Generate test cases automatically based on an enumeration of available constants and some knowledge of what attributes (sizes, algorithms, …) and content to use for keys of a certain type. Note that the generated test cases will be checked into the repository (generating test cases at runtime would not allow us to test the stability of the format, only that a given version is internally consistent). + +### Testing with alternative lifetime values + +Objective: have test coverage for lifetimes other than the default persistent lifetime (`PSA_KEY_LIFETIME_PERSISTENT`). + +Method: + +* For alternative locations: have tests conditional on the presence of a driver for that location. +* For alternative persistence levels: TODO + +## Random generator state + +TODO + +## Driver state files + +Not yet implemented. + +TODO + +## Storage transaction resumption + +Only relevant for secure element support. Not yet fully implemented. + +TODO + +## PSA ITS over file + +TODO diff --git a/lib/mbedtls-2.27.0/docs/architecture/testing/test-framework.md b/lib/mbedtls-2.27.0/docs/architecture/testing/test-framework.md new file mode 100644 index 0000000..c4178fa --- /dev/null +++ b/lib/mbedtls-2.27.0/docs/architecture/testing/test-framework.md @@ -0,0 +1,58 @@ +# Mbed TLS test framework + +This document is an overview of the Mbed TLS test framework and test tools. + +This document is incomplete. You can help by expanding it. + +## Unit tests + +See + +### Unit test descriptions + +Each test case has a description which succinctly describes for a human audience what the test does. The first non-comment line of each paragraph in a `.data` file is the test description. The following rules and guidelines apply: + +* Test descriptions may not contain semicolons, line breaks and other control characters, or non-ASCII characters.
+ Rationale: keep the tools that process test descriptions (`generate_test_code.py`, [outcome file](#outcome-file) tools) simple. +* Test descriptions must be unique within a `.data` file. If you can't think of a better description, the convention is to append `#1`, `#2`, etc.
+ Rationale: make it easy to relate a failure log to the test data. Avoid confusion between cases in the [outcome file](#outcome-file). +* Test descriptions should be a maximum of **66 characters**.
+ Rationale: 66 characters is what our various tools assume (leaving room for 14 more characters on an 80-column line). Longer descriptions may be truncated or may break a visual alignment.
+ We have a lot of test cases with longer descriptions, but they should be avoided. At least please make sure that the first 66 characters describe the test uniquely. +* Make the description descriptive. “foo: x=2, y=4” is more descriptive than “foo #2”. “foo: 0