Merge pull request #157 from gilles-peskine-arm/psa-se_driver-create_key

Secure element key creation foundation
This commit is contained in:
Gilles Peskine 2019-07-26 14:39:55 +02:00 committed by GitHub
commit adb1c52149
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 2194 additions and 360 deletions

View file

@ -193,3 +193,92 @@ The layout of a key file is:
* 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. <br>
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 (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.

View file

@ -1715,12 +1715,15 @@
* Enable secure element support in the Platform Security Architecture
* cryptography API.
*
* \warning This feature is not yet suitable for production. It is provided
* for API evaluation and testing purposes only.
*
* Module: library/psa_crypto_se.c
*
* Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C
*
*/
#define MBEDTLS_PSA_CRYPTO_SE_C
//#define MBEDTLS_PSA_CRYPTO_SE_C
/**
* \def MBEDTLS_PSA_CRYPTO_STORAGE_C

View file

@ -93,117 +93,10 @@ psa_status_t psa_crypto_init(void);
/**@}*/
/** \defgroup attributes Key attributes
/** \addtogroup attributes
* @{
*/
/** The type of a structure containing key attributes.
*
* This is an opaque structure that can represent the metadata of a key
* object. Metadata that can be stored in attributes includes:
* - The location of the key in storage, indicated by its key identifier
* and its lifetime.
* - The key's policy, comprising usage flags and a specification of
* the permitted algorithm(s).
* - Information about the key itself: the key type and its size.
* - Implementations may define additional attributes.
*
* The actual key material is not considered an attribute of a key.
* Key attributes do not contain information that is generally considered
* highly confidential.
*
* An attribute structure can be a simple data structure where each function
* `psa_set_key_xxx` sets a field and the corresponding function
* `psa_get_key_xxx` retrieves the value of the corresponding field.
* However, implementations may report values that are equivalent to the
* original one, but have a different encoding. For example, an
* implementation may use a more compact representation for types where
* many bit-patterns are invalid or not supported, and store all values
* that it does not support as a special marker value. In such an
* implementation, after setting an invalid value, the corresponding
* get function returns an invalid value which may not be the one that
* was originally stored.
*
* An attribute structure may contain references to auxiliary resources,
* for example pointers to allocated memory or indirect references to
* pre-calculated values. In order to free such resources, the application
* must call psa_reset_key_attributes(). As an exception, calling
* psa_reset_key_attributes() on an attribute structure is optional if
* the structure has only been modified by the following functions
* since it was initialized or last reset with psa_reset_key_attributes():
* - psa_set_key_id()
* - psa_set_key_lifetime()
* - psa_set_key_type()
* - psa_set_key_bits()
* - psa_set_key_usage_flags()
* - psa_set_key_algorithm()
*
* Before calling any function on a key attribute structure, the application
* must initialize it by any of the following means:
* - Set the structure to all-bits-zero, for example:
* \code
* psa_key_attributes_t attributes;
* memset(&attributes, 0, sizeof(attributes));
* \endcode
* - Initialize the structure to logical zero values, for example:
* \code
* psa_key_attributes_t attributes = {0};
* \endcode
* - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT,
* for example:
* \code
* psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
* \endcode
* - Assign the result of the function psa_key_attributes_init()
* to the structure, for example:
* \code
* psa_key_attributes_t attributes;
* attributes = psa_key_attributes_init();
* \endcode
*
* A freshly initialized attribute structure contains the following
* values:
*
* - lifetime: #PSA_KEY_LIFETIME_VOLATILE.
* - key identifier: unspecified.
* - type: \c 0.
* - key size: \c 0.
* - usage flags: \c 0.
* - algorithm: \c 0.
*
* A typical sequence to create a key is as follows:
* -# Create and initialize an attribute structure.
* -# If the key is persistent, call psa_set_key_id().
* Also call psa_set_key_lifetime() to place the key in a non-default
* location.
* -# Set the key policy with psa_set_key_usage_flags() and
* psa_set_key_algorithm().
* -# Set the key type with psa_set_key_type().
* Skip this step if copying an existing key with psa_copy_key().
* -# When generating a random key with psa_generate_key() or deriving a key
* with psa_key_derivation_output_key(), set the desired key size with
* psa_set_key_bits().
* -# Call a key creation function: psa_import_key(), psa_generate_key(),
* psa_key_derivation_output_key() or psa_copy_key(). This function reads
* the attribute structure, creates a key with these attributes, and
* outputs a handle to the newly created key.
* -# The attribute structure is now no longer necessary.
* You may call psa_reset_key_attributes(), although this is optional
* with the workflow presented here because the attributes currently
* defined in this specification do not require any additional resources
* beyond the structure itself.
*
* A typical sequence to query a key's attributes is as follows:
* -# Call psa_get_key_attributes().
* -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that
* you are interested in.
* -# Call psa_reset_key_attributes() to free any resources that may be
* used by the attribute structure.
*
* Once a key has been created, it is impossible to change its attributes.
*/
typedef struct psa_key_attributes_s psa_key_attributes_t;
/** \def PSA_KEY_ATTRIBUTES_INIT
*
* This macro returns a suitable initializer for a key attribute structure

View file

@ -40,10 +40,106 @@
extern "C" {
#endif
/** \defgroup se_init Secure element driver initialization
*/
/**@{*/
/** \brief Driver context structure
*
* Driver functions receive a pointer to this structure.
* Each registered driver has one instance of this structure.
*
* Implementations must include the fields specified here and
* may include other fields.
*/
typedef struct {
/** A read-only pointer to the driver's persistent data.
*
* Drivers typically use this persistent data to keep track of
* which slot numbers are available. This is only a guideline:
* drivers may use the persistent data for any purpose, keeping
* in mind the restrictions on when the persistent data is saved
* to storage: the persistent data is only saved after calling
* certain functions that receive a writable pointer to the
* persistent data.
*
* The core allocates a memory buffer for the persistent data.
* The pointer is guaranteed to be suitably aligned for any data type,
* like a pointer returned by `malloc` (but the core can use any
* method to allocate the buffer, not necessarily `malloc`).
*
* The size of this buffer is in the \c persistent_data_size field of
* this structure.
*
* Before the driver is initialized for the first time, the content of
* the persistent data is all-bits-zero. After a driver upgrade, if the
* size of the persistent data has increased, the original data is padded
* on the right with zeros; if the size has decreased, the original data
* is truncated to the new size.
*
* This pointer is to read-only data. Only a few driver functions are
* allowed to modify the persistent data. These functions receive a
* writable pointer. These functions are:
* - psa_drv_se_t::p_init
* - psa_drv_se_key_management_t::p_allocate
* - psa_drv_se_key_management_t::p_destroy
*
* The PSA Cryptography core saves the persistent data from one
* session to the next. It does this before returning from API functions
* that call a driver method that is allowed to modify the persistent
* data, specifically:
* - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call
* psa_drv_se_key_management_t::p_destroy to complete an action
* that was interrupted by a power failure.
* - Key creation functions cause a call to
* psa_drv_se_key_management_t::p_allocate, and may cause a call to
* psa_drv_se_key_management_t::p_destroy in case an error occurs.
* - psa_destroy_key() causes a call to
* psa_drv_se_key_management_t::p_destroy.
*/
const void *const persistent_data;
/** The size of \c persistent_data in bytes.
*
* This is always equal to the value of the `persistent_data_size` field
* of the ::psa_drv_se_t structure when the driver is registered.
*/
const size_t persistent_data_size;
/** Driver transient data.
*
* The core initializes this value to 0 and does not read or modify it
* afterwards. The driver may store whatever it wants in this field.
*/
uintptr_t transient_data;
} psa_drv_se_context_t;
/** \brief A driver initialization function.
*
* \param[in,out] drv_context The driver context structure.
* \param[in,out] persistent_data A pointer to the persistent data
* that allows writing.
* \param lifetime The lifetime value for which this driver
* is registered.
*
* \retval #PSA_SUCCESS
* The driver is operational.
* The core will update the persistent data in storage.
* \return
* Any other return value prevents the driver from being used in
* this session.
* The core will NOT update the persistent data in storage.
*/
typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context,
void *persistent_data,
psa_key_lifetime_t lifetime);
/** An internal designation of a key slot between the core part of the
* PSA Crypto implementation and the driver. The meaning of this value
* is driver-dependent. */
typedef uint32_t psa_key_slot_number_t; // Change this to psa_key_slot_t after psa_key_slot_t is removed from Mbed crypto
typedef uint64_t psa_key_slot_number_t;
/**@}*/
/** \defgroup se_mac Secure Element Message Authentication Codes
* Generation and authentication of Message Authentication Codes (MACs) using
@ -65,7 +161,8 @@ typedef uint32_t psa_key_slot_number_t; // Change this to psa_key_slot_t after p
/** \brief A function that starts a secure element MAC operation for a PSA
* Crypto Driver implementation
*
* \param[in,out] p_context A structure that will contain the
* \param[in,out] drv_context The driver context structure.
* \param[in,out] op_context A structure that will contain the
* hardware-specific MAC context
* \param[in] key_slot The slot of the key to be used for the
* operation
@ -75,28 +172,29 @@ typedef uint32_t psa_key_slot_number_t; // Change this to psa_key_slot_t after p
* \retval PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_mac_setup_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context,
void *op_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm);
/** \brief A function that continues a previously started secure element MAC
* operation
*
* \param[in,out] p_context A hardware-specific structure for the
* \param[in,out] op_context A hardware-specific structure for the
* previously-established MAC operation to be
* updated
* \param[in] p_input A buffer containing the message to be appended
* to the MAC operation
* \param[in] input_length The size in bytes of the input message buffer
* \param[in] input_length The size in bytes of the input message buffer
*/
typedef psa_status_t (*psa_drv_se_mac_update_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context,
const uint8_t *p_input,
size_t input_length);
/** \brief a function that completes a previously started secure element MAC
* operation by returning the resulting MAC.
*
* \param[in,out] p_context A hardware-specific structure for the
* \param[in,out] op_context A hardware-specific structure for the
* previously started MAC operation to be
* finished
* \param[out] p_mac A buffer where the generated MAC will be
@ -109,7 +207,7 @@ typedef psa_status_t (*psa_drv_se_mac_update_t)(void *p_context,
* \retval PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context,
uint8_t *p_mac,
size_t mac_size,
size_t *p_mac_length);
@ -117,11 +215,11 @@ typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *p_context,
/** \brief A function that completes a previously started secure element MAC
* operation by comparing the resulting MAC against a provided value
*
* \param[in,out] p_context A hardware-specific structure for the previously
* started MAC operation to be fiinished
* \param[in] p_mac The MAC value against which the resulting MAC will
* be compared against
* \param[in] mac_length The size in bytes of the value stored in `p_mac`
* \param[in,out] op_context A hardware-specific structure for the previously
* started MAC operation to be fiinished
* \param[in] p_mac The MAC value against which the resulting MAC
* will be compared against
* \param[in] mac_length The size in bytes of the value stored in `p_mac`
*
* \retval PSA_SUCCESS
* The operation completed successfully and the MACs matched each
@ -130,21 +228,22 @@ typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *p_context,
* The operation completed successfully, but the calculated MAC did
* not match the provided MAC
*/
typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context,
const uint8_t *p_mac,
size_t mac_length);
/** \brief A function that aborts a previous started secure element MAC
* operation
*
* \param[in,out] p_context A hardware-specific structure for the previously
* started MAC operation to be aborted
* \param[in,out] op_context A hardware-specific structure for the previously
* started MAC operation to be aborted
*/
typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *p_context);
typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context);
/** \brief A function that performs a secure element MAC operation in one
* command and returns the calculated MAC
*
* \param[in,out] drv_context The driver context structure.
* \param[in] p_input A buffer containing the message to be MACed
* \param[in] input_length The size in bytes of `p_input`
* \param[in] key_slot The slot of the key to be used
@ -159,7 +258,8 @@ typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *p_context);
* \retval PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_mac_generate_t)(const uint8_t *p_input,
typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context,
const uint8_t *p_input,
size_t input_length,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
@ -170,6 +270,7 @@ typedef psa_status_t (*psa_drv_se_mac_generate_t)(const uint8_t *p_input,
/** \brief A function that performs a secure element MAC operation in one
* command and compares the resulting MAC against a provided value
*
* \param[in,out] drv_context The driver context structure.
* \param[in] p_input A buffer containing the message to be MACed
* \param[in] input_length The size in bytes of `input`
* \param[in] key_slot The slot of the key to be used
@ -186,7 +287,8 @@ typedef psa_status_t (*psa_drv_se_mac_generate_t)(const uint8_t *p_input,
* The operation completed successfully, but the calculated MAC did
* not match the provided MAC
*/
typedef psa_status_t (*psa_drv_se_mac_verify_t)(const uint8_t *p_input,
typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context,
const uint8_t *p_input,
size_t input_length,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
@ -263,7 +365,8 @@ typedef struct {
/** \brief A function that provides the cipher setup function for a
* secure element driver
*
* \param[in,out] p_context A structure that will contain the
* \param[in,out] drv_context The driver context structure.
* \param[in,out] op_context A structure that will contain the
* hardware-specific cipher context.
* \param[in] key_slot The slot of the key to be used for the
* operation
@ -275,7 +378,8 @@ typedef struct {
* \retval PSA_SUCCESS
* \retval PSA_ERROR_NOT_SUPPORTED
*/
typedef psa_status_t (*psa_drv_se_cipher_setup_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context,
void *op_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
psa_encrypt_or_decrypt_t direction);
@ -288,21 +392,21 @@ typedef psa_status_t (*psa_drv_se_cipher_setup_t)(void *p_context,
* generate function is not necessary for the drivers to implement as the PSA
* Crypto implementation can do the generation using its RNG features.
*
* \param[in,out] p_context A structure that contains the previously set up
* \param[in,out] op_context A structure that contains the previously set up
* hardware-specific cipher context
* \param[in] p_iv A buffer containing the initialization vector
* \param[in] iv_length The size (in bytes) of the `p_iv` buffer
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context,
const uint8_t *p_iv,
size_t iv_length);
/** \brief A function that continues a previously started secure element cipher
* operation
*
* \param[in,out] p_context A hardware-specific structure for the
* \param[in,out] op_context A hardware-specific structure for the
* previously started cipher operation
* \param[in] p_input A buffer containing the data to be
* encrypted/decrypted
@ -317,7 +421,7 @@ typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *p_context,
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context,
const uint8_t *p_input,
size_t input_size,
uint8_t *p_output,
@ -327,7 +431,7 @@ typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *p_context,
/** \brief A function that completes a previously started secure element cipher
* operation
*
* \param[in,out] p_context A hardware-specific structure for the
* \param[in,out] op_context A hardware-specific structure for the
* previously started cipher operation
* \param[out] p_output The caller-allocated buffer where the output
* will be placed
@ -338,7 +442,7 @@ typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *p_context,
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context,
uint8_t *p_output,
size_t output_size,
size_t *p_output_length);
@ -346,10 +450,10 @@ typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *p_context,
/** \brief A function that aborts a previously started secure element cipher
* operation
*
* \param[in,out] p_context A hardware-specific structure for the
* \param[in,out] op_context A hardware-specific structure for the
* previously started cipher operation
*/
typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *p_context);
typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context);
/** \brief A function that performs the ECB block mode for secure element
* cipher operations
@ -357,23 +461,25 @@ typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *p_context);
* Note: this function should only be used with implementations that do not
* provide a needed higher-level operation.
*
* \param[in] key_slot The slot of the key to be used for the operation
* \param[in] algorithm The algorithm to be used in the cipher operation
* \param[in] direction Indicates whether the operation is an encrypt or
* decrypt
* \param[in] p_input A buffer containing the data to be
* encrypted/decrypted
* \param[in] input_size The size in bytes of the buffer pointed to by
* `p_input`
* \param[out] p_output The caller-allocated buffer where the output will
* be placed
* \param[in] output_size The allocated size in bytes of the `p_output`
* buffer
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot The slot of the key to be used for the operation
* \param[in] algorithm The algorithm to be used in the cipher operation
* \param[in] direction Indicates whether the operation is an encrypt or
* decrypt
* \param[in] p_input A buffer containing the data to be
* encrypted/decrypted
* \param[in] input_size The size in bytes of the buffer pointed to by
* `p_input`
* \param[out] p_output The caller-allocated buffer where the output
* will be placed
* \param[in] output_size The allocated size in bytes of the `p_output`
* buffer
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_NOT_SUPPORTED
*/
typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
psa_encrypt_or_decrypt_t direction,
const uint8_t *p_input,
@ -427,6 +533,7 @@ typedef struct {
* \brief A function that signs a hash or short message with a private key in
* a secure element
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Key slot of an asymmetric key pair
* \param[in] alg A signature algorithm that is compatible
* with the type of `key`
@ -439,7 +546,8 @@ typedef struct {
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_hash,
size_t hash_length,
@ -451,6 +559,7 @@ typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_key_slot_number_t key_s
* \brief A function that verifies the signature a hash or short message using
* an asymmetric public key in a secure element
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Key slot of a public key or an asymmetric key
* pair
* \param[in] alg A signature algorithm that is compatible with
@ -463,7 +572,8 @@ typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_key_slot_number_t key_s
* \retval PSA_SUCCESS
* The signature is valid.
*/
typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_hash,
size_t hash_length,
@ -474,6 +584,7 @@ typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_key_slot_number_t key
* \brief A function that encrypts a short message with an asymmetric public
* key in a secure element
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Key slot of a public key or an asymmetric key
* pair
* \param[in] alg An asymmetric encryption algorithm that is
@ -499,7 +610,8 @@ typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_key_slot_number_t key
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_input,
size_t input_length,
@ -513,6 +625,7 @@ typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_key_slot_number_t ke
* \brief A function that decrypts a short message with an asymmetric private
* key in a secure element.
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Key slot of an asymmetric key pair
* \param[in] alg An asymmetric encryption algorithm that is
* compatible with the type of `key`
@ -537,7 +650,8 @@ typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_key_slot_number_t ke
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_input,
size_t input_length,
@ -581,6 +695,7 @@ typedef struct {
/** \brief A function that performs a secure element authenticated encryption
* operation
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Slot containing the key to use.
* \param[in] algorithm The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
@ -608,7 +723,8 @@ typedef struct {
* \retval #PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
const uint8_t *p_nonce,
size_t nonce_length,
@ -622,6 +738,7 @@ typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_key_slot_number_t key_slot
/** A function that peforms a secure element authenticated decryption operation
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Slot containing the key to use
* \param[in] algorithm The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
@ -648,7 +765,8 @@ typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_key_slot_number_t key_slot
* \retval #PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
const uint8_t *p_nonce,
size_t nonce_length,
@ -685,25 +803,50 @@ typedef struct {
*/
/**@{*/
/** \brief A function that allocates a slot for a key.
*
* \param[in,out] drv_context The driver context structure.
* \param[in,out] persistent_data A pointer to the persistent data
* that allows writing.
* \param[in] attributes Attributes of the key.
* \param[out] key_slot Slot where the key will be stored.
* This must be a valid slot for a key of the
* chosen type. It must be unoccupied.
*
* \retval #PSA_SUCCESS
* Success.
* The core will record \c *key_slot as the key slot where the key
* is stored and will update the persistent data in storage.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
*/
typedef psa_status_t (*psa_drv_se_allocate_key_t)(
psa_drv_se_context_t *drv_context,
void *persistent_data,
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *key_slot);
/** \brief A function that imports a key into a secure element in binary format
*
* This function can support any output from psa_export_key(). Refer to the
* documentation of psa_export_key() for the format for each key type.
*
* \param[in] key_slot Slot where the key will be stored
* This must be a valid slot for a key of the chosen
* type. It must be unoccupied.
* \param[in] lifetime The required lifetime of the key storage
* \param[in] type Key type (a \c PSA_KEY_TYPE_XXX value)
* \param[in] algorithm Key algorithm (a \c PSA_ALG_XXX value)
* \param[in] usage The allowed uses of the key
* \param[in] p_data Buffer containing the key data
* \param[in] data_length Size of the `data` buffer in bytes
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Slot where the key will be stored
* This must be a valid slot for a key of the chosen
* type. It must be unoccupied.
* \param[in] lifetime The required lifetime of the key storage
* \param[in] type Key type (a \c PSA_KEY_TYPE_XXX value)
* \param[in] algorithm Key algorithm (a \c PSA_ALG_XXX value)
* \param[in] usage The allowed uses of the key
* \param[in] p_data Buffer containing the key data
* \param[in] data_length Size of the `data` buffer in bytes
*
* \retval #PSA_SUCCESS
* Success.
*/
typedef psa_status_t (*psa_drv_se_import_key_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_import_key_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_key_lifetime_t lifetime,
psa_key_type_t type,
psa_algorithm_t algorithm,
@ -721,12 +864,18 @@ typedef psa_status_t (*psa_drv_se_import_key_t)(psa_key_slot_number_t key_slot,
*
* This function returns the specified slot to its default state.
*
* \param[in] key_slot The key slot to erase.
* \param[in,out] drv_context The driver context structure.
* \param[in,out] persistent_data A pointer to the persistent data
* that allows writing.
* \param key_slot The key slot to erase.
*
* \retval #PSA_SUCCESS
* The slot's content, if any, has been erased.
*/
typedef psa_status_t (*psa_drv_se_destroy_key_t)(psa_key_slot_number_t key_slot);
typedef psa_status_t (*psa_drv_se_destroy_key_t)(
psa_drv_se_context_t *drv_context,
void *persistent_data,
psa_key_slot_number_t key_slot);
/**
* \brief A function that exports a secure element key in binary format
@ -743,6 +892,7 @@ typedef psa_status_t (*psa_drv_se_destroy_key_t)(psa_key_slot_number_t key_slot)
* `psa_export_key()` does. Refer to the
* documentation of `psa_export_key()` for the format for each key type.
*
* \param[in,out] drv_context The driver context structure.
* \param[in] key Slot whose content is to be exported. This must
* be an occupied key slot.
* \param[out] p_data Buffer where the key data is to be written.
@ -758,7 +908,8 @@ typedef psa_status_t (*psa_drv_se_destroy_key_t)(psa_key_slot_number_t key_slot)
* \retval #PSA_ERROR_HARDWARE_FAILURE
* \retval #PSA_ERROR_CORRUPTION_DETECTED
*/
typedef psa_status_t (*psa_drv_se_export_key_t)(psa_key_slot_number_t key,
typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key,
uint8_t *p_data,
size_t data_size,
size_t *p_data_length);
@ -767,31 +918,34 @@ typedef psa_status_t (*psa_drv_se_export_key_t)(psa_key_slot_number_t key,
* \brief A function that generates a symmetric or asymmetric key on a secure
* element
*
* If \p type is asymmetric (`#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) == 1`),
* If \p type is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) = 1),
* the public component of the generated key will be placed in `p_pubkey_out`.
* The format of the public key information will match the format specified for
* the psa_export_key() function for the key type.
*
* \param[in] key_slot Slot where the generated key will be placed
* \param[in] type The type of the key to be generated
* \param[in] usage The prescribed usage of the generated key
* Note: Not all Secure Elements support the same
* restrictions that PSA Crypto does (and vice versa).
* Driver developers should endeavor to match the
* usages as close as possible.
* \param[in] bits The size in bits of the key to be generated.
* \param[in] extra Extra parameters for key generation. The
* interpretation of this parameter should match the
* interpretation in the `extra` parameter is the
* `psa_generate_key` function
* \param[in] extra_size The size in bytes of the \p extra buffer
* \param[out] p_pubkey_out The buffer where the public key information will
* be placed
* \param[in,out] drv_context The driver context structure.
* \param[in] key_slot Slot where the generated key will be placed
* \param[in] type The type of the key to be generated
* \param[in] usage The prescribed usage of the generated key
* Note: Not all Secure Elements support the same
* restrictions that PSA Crypto does (and vice
* versa).
* Driver developers should endeavor to match the
* usages as close as possible.
* \param[in] bits The size in bits of the key to be generated.
* \param[in] extra Extra parameters for key generation. The
* interpretation of this parameter should match
* the interpretation in the `extra` parameter is
* the `psa_generate_key` function
* \param[in] extra_size The size in bytes of the \p extra buffer
* \param[out] p_pubkey_out The buffer where the public key information will
* be placed
* \param[in] pubkey_out_size The size in bytes of the `p_pubkey_out` buffer
* \param[out] p_pubkey_length Upon successful completion, will contain the
* size of the data placed in `p_pubkey_out`.
*/
typedef psa_status_t (*psa_drv_se_generate_key_t)(psa_key_slot_number_t key_slot,
typedef psa_status_t (*psa_drv_se_generate_key_t)(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_key_type_t type,
psa_key_usage_t usage,
size_t bits,
@ -811,6 +965,8 @@ typedef psa_status_t (*psa_drv_se_generate_key_t)(psa_key_slot_number_t key_slot
* If one of the functions is not implemented, it should be set to NULL.
*/
typedef struct {
/** Function that allocates a slot. */
psa_drv_se_allocate_key_t p_allocate;
/** Function that performs a key import operation */
psa_drv_se_import_key_t p_import;
/** Function that performs a generation */
@ -819,6 +975,8 @@ typedef struct {
psa_drv_se_destroy_key_t p_destroy;
/** Function that performs a key export operation */
psa_drv_se_export_key_t p_export;
/** Function that performs a public key export operation */
psa_drv_se_export_key_t p_export_public;
} psa_drv_se_key_management_t;
/**@}*/
@ -875,15 +1033,17 @@ typedef struct {
/** \brief A function that Sets up a secure element key derivation operation by
* specifying the algorithm and the source key sot
*
* \param[in,out] p_context A hardware-specific structure containing any
* context information for the implementation
* \param[in] kdf_alg The algorithm to be used for the key derivation
* \param[in] source_key The key to be used as the source material for the
* key derivation
* \param[in,out] drv_context The driver context structure.
* \param[in,out] op_context A hardware-specific structure containing any
* context information for the implementation
* \param[in] kdf_alg The algorithm to be used for the key derivation
* \param[in] source_key The key to be used as the source material for
* the key derivation
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context,
void *op_context,
psa_algorithm_t kdf_alg,
psa_key_slot_number_t source_key);
@ -894,7 +1054,7 @@ typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(void *p_context,
* expeced that this function may be called multiple times for the same
* operation, each with a different algorithm-specific `collateral_id`
*
* \param[in,out] p_context A hardware-specific structure containing any
* \param[in,out] op_context A hardware-specific structure containing any
* context information for the implementation
* \param[in] collateral_id An ID for the collateral being provided
* \param[in] p_collateral A buffer containing the collateral data
@ -902,7 +1062,7 @@ typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(void *p_context,
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context,
uint32_t collateral_id,
const uint8_t *p_collateral,
size_t collateral_size);
@ -910,14 +1070,14 @@ typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *p_context,
/** \brief A function that performs the final secure element key derivation
* step and place the generated key material in a slot
*
* \param[in,out] p_context A hardware-specific structure containing any
* \param[in,out] op_context A hardware-specific structure containing any
* context information for the implementation
* \param[in] dest_key The slot where the generated key material
* should be placed
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context,
psa_key_slot_number_t dest_key);
/** \brief A function that performs the final step of a secure element key
@ -931,7 +1091,7 @@ typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *p_context,
*
* \retval PSA_SUCCESS
*/
typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *p_context,
typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context,
uint8_t *p_output,
size_t output_size,
size_t *p_output_length);
@ -978,12 +1138,35 @@ typedef struct {
* Use #PSA_DRV_SE_HAL_VERSION.
*/
uint32_t hal_version;
psa_drv_se_key_management_t key_management;
psa_drv_se_mac_t mac;
psa_drv_se_cipher_t cipher;
psa_drv_se_aead_t aead;
psa_drv_se_asymmetric_t asymmetric;
psa_drv_se_key_derivation_t derivation;
/** The size of the driver's persistent data in bytes.
*
* This can be 0 if the driver does not need persistent data.
*
* See the documentation of psa_drv_se_context_t::persistent_data
* for more information about why and how a driver can use
* persistent data.
*/
size_t persistent_data_size;
/** The driver initialization function.
*
* This function is called once during the initialization of the
* PSA Cryptography subsystem, before any other function of the
* driver is called. If this function returns a failure status,
* the driver will be unusable, at least until the next system reset.
*
* If this field is \c NULL, it is equivalent to a function that does
* nothing and returns #PSA_SUCCESS.
*/
psa_drv_se_init_t p_init;
const psa_drv_se_key_management_t *key_management;
const psa_drv_se_mac_t *mac;
const psa_drv_se_cipher_t *cipher;
const psa_drv_se_aead_t *aead;
const psa_drv_se_asymmetric_t *asymmetric;
const psa_drv_se_key_derivation_t *derivation;
} psa_drv_se_t;
/** The current version of the secure element driver HAL.

View file

@ -133,6 +133,119 @@ typedef uint32_t psa_key_usage_t;
/**@}*/
/** \defgroup attributes Key attributes
* @{
*/
/** The type of a structure containing key attributes.
*
* This is an opaque structure that can represent the metadata of a key
* object. Metadata that can be stored in attributes includes:
* - The location of the key in storage, indicated by its key identifier
* and its lifetime.
* - The key's policy, comprising usage flags and a specification of
* the permitted algorithm(s).
* - Information about the key itself: the key type and its size.
* - Implementations may define additional attributes.
*
* The actual key material is not considered an attribute of a key.
* Key attributes do not contain information that is generally considered
* highly confidential.
*
* An attribute structure can be a simple data structure where each function
* `psa_set_key_xxx` sets a field and the corresponding function
* `psa_get_key_xxx` retrieves the value of the corresponding field.
* However, implementations may report values that are equivalent to the
* original one, but have a different encoding. For example, an
* implementation may use a more compact representation for types where
* many bit-patterns are invalid or not supported, and store all values
* that it does not support as a special marker value. In such an
* implementation, after setting an invalid value, the corresponding
* get function returns an invalid value which may not be the one that
* was originally stored.
*
* An attribute structure may contain references to auxiliary resources,
* for example pointers to allocated memory or indirect references to
* pre-calculated values. In order to free such resources, the application
* must call psa_reset_key_attributes(). As an exception, calling
* psa_reset_key_attributes() on an attribute structure is optional if
* the structure has only been modified by the following functions
* since it was initialized or last reset with psa_reset_key_attributes():
* - psa_set_key_id()
* - psa_set_key_lifetime()
* - psa_set_key_type()
* - psa_set_key_bits()
* - psa_set_key_usage_flags()
* - psa_set_key_algorithm()
*
* Before calling any function on a key attribute structure, the application
* must initialize it by any of the following means:
* - Set the structure to all-bits-zero, for example:
* \code
* psa_key_attributes_t attributes;
* memset(&attributes, 0, sizeof(attributes));
* \endcode
* - Initialize the structure to logical zero values, for example:
* \code
* psa_key_attributes_t attributes = {0};
* \endcode
* - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT,
* for example:
* \code
* psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
* \endcode
* - Assign the result of the function psa_key_attributes_init()
* to the structure, for example:
* \code
* psa_key_attributes_t attributes;
* attributes = psa_key_attributes_init();
* \endcode
*
* A freshly initialized attribute structure contains the following
* values:
*
* - lifetime: #PSA_KEY_LIFETIME_VOLATILE.
* - key identifier: unspecified.
* - type: \c 0.
* - key size: \c 0.
* - usage flags: \c 0.
* - algorithm: \c 0.
*
* A typical sequence to create a key is as follows:
* -# Create and initialize an attribute structure.
* -# If the key is persistent, call psa_set_key_id().
* Also call psa_set_key_lifetime() to place the key in a non-default
* location.
* -# Set the key policy with psa_set_key_usage_flags() and
* psa_set_key_algorithm().
* -# Set the key type with psa_set_key_type().
* Skip this step if copying an existing key with psa_copy_key().
* -# When generating a random key with psa_generate_key() or deriving a key
* with psa_key_derivation_output_key(), set the desired key size with
* psa_set_key_bits().
* -# Call a key creation function: psa_import_key(), psa_generate_key(),
* psa_key_derivation_output_key() or psa_copy_key(). This function reads
* the attribute structure, creates a key with these attributes, and
* outputs a handle to the newly created key.
* -# The attribute structure is now no longer necessary.
* You may call psa_reset_key_attributes(), although this is optional
* with the workflow presented here because the attributes currently
* defined in this specification do not require any additional resources
* beyond the structure itself.
*
* A typical sequence to query a key's attributes is as follows:
* -# Call psa_get_key_attributes().
* -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that
* you are interested in.
* -# Call psa_reset_key_attributes() to free any resources that may be
* used by the attribute structure.
*
* Once a key has been created, it is impossible to change its attributes.
*/
typedef struct psa_key_attributes_s psa_key_attributes_t;
/**@}*/
/** \defgroup derivation Key derivation
* @{
*/

View file

@ -363,6 +363,13 @@ static psa_status_t mbedtls_to_psa_error( int ret )
/* Key management */
/****************************************************************/
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
{
return( psa_key_lifetime_is_external( slot->lifetime ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_ECP_C)
static psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid )
{
@ -864,9 +871,46 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
return( PSA_SUCCESS );
}
/** Retrieve a slot which must contain a transparent key.
*
* A transparent key is a key for which the key material is directly
* available, as opposed to a key in a secure element.
*
* This is a temporary function to use instead of psa_get_key_from_slot()
* until secure element support is fully implemented.
*/
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
static psa_status_t psa_get_transparent_key( psa_key_handle_t handle,
psa_key_slot_t **p_slot,
psa_key_usage_t usage,
psa_algorithm_t alg )
{
psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg );
if( status != PSA_SUCCESS )
return( status );
if( psa_key_slot_is_external( *p_slot ) )
{
*p_slot = NULL;
return( PSA_ERROR_NOT_SUPPORTED );
}
return( PSA_SUCCESS );
}
#else /* MBEDTLS_PSA_CRYPTO_SE_C */
/* With no secure element support, all keys are transparent. */
#define psa_get_transparent_key( handle, p_slot, usage, alg ) \
psa_get_key_from_slot( handle, p_slot, usage, alg )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
/** Wipe key data from a slot. Preserve metadata such as the policy. */
static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
{
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_key_slot_is_external( slot ) )
{
/* No key material to clean. */
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( slot->type == PSA_KEY_TYPE_NONE )
{
/* No key material to clean. */
@ -925,10 +969,39 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle )
psa_key_slot_t *slot;
psa_status_t status = PSA_SUCCESS;
psa_status_t storage_status = PSA_SUCCESS;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
psa_se_drv_table_entry_t *driver;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_get_key_slot( handle, &slot );
if( status != PSA_SUCCESS )
return( status );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
driver = psa_get_se_driver_entry( slot->lifetime );
if( driver != NULL )
{
/* For a key in a secure element, we need to do three things:
* remove the key file in internal storage, destroy the
* key inside the secure element, and update the driver's
* persistent data. Start a transaction that will encompass these
* three actions. */
psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY );
psa_crypto_transaction.key.lifetime = slot->lifetime;
psa_crypto_transaction.key.slot = slot->data.se.slot_number;
psa_crypto_transaction.key.id = slot->persistent_storage_id;
status = psa_crypto_save_transaction( );
if( status != PSA_SUCCESS )
{
(void) psa_crypto_stop_transaction( );
/* TOnogrepDO: destroy what can be destroyed anyway */
return( status );
}
status = psa_destroy_se_key( driver, slot->data.se.slot_number );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
{
@ -936,6 +1009,23 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle )
psa_destroy_persistent_key( slot->persistent_storage_id );
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
psa_status_t status2;
status = psa_save_se_persistent_data( driver );
status2 = psa_crypto_stop_transaction( );
if( status == PSA_SUCCESS )
status = status2;
if( status != PSA_SUCCESS )
{
/* TOnogrepDO: destroy what can be destroyed anyway */
return( status );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_wipe_key_slot( slot );
if( status != PSA_SUCCESS )
return( status );
@ -1050,6 +1140,22 @@ exit:
}
#endif /* MBEDTLS_RSA_C */
/** Retrieve the readily-accessible attributes of a key in a slot.
*
* This function does not compute attributes that are not directly
* stored in the slot, such as the bit size of a transparent key.
*/
static void psa_get_key_slot_attributes( psa_key_slot_t *slot,
psa_key_attributes_t *attributes )
{
attributes->id = slot->persistent_storage_id;
attributes->lifetime = slot->lifetime;
attributes->policy = slot->policy;
attributes->type = slot->type;
}
/** Retrieve all the publicly-accessible attributes of a key.
*/
psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
psa_key_attributes_t *attributes )
{
@ -1058,14 +1164,11 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
psa_reset_key_attributes( attributes );
status = psa_get_key_slot( handle, &slot );
status = psa_get_transparent_key( handle, &slot, 0, 0 );
if( status != PSA_SUCCESS )
return( status );
attributes->id = slot->persistent_storage_id;
attributes->lifetime = slot->lifetime;
attributes->policy = slot->policy;
attributes->type = slot->type;
psa_get_key_slot_attributes( slot, attributes );
attributes->bits = psa_get_key_slot_bits( slot );
switch( slot->type )
@ -1108,11 +1211,33 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot,
size_t *data_length,
int export_public_key )
{
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
const psa_drv_se_t *drv;
psa_drv_se_context_t *drv_context;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
*data_length = 0;
if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->type ) )
return( PSA_ERROR_INVALID_ARGUMENT );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_get_se_driver( slot->lifetime, &drv, &drv_context ) )
{
psa_drv_se_export_key_t method;
if( drv->key_management == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
method = ( export_public_key ?
drv->key_management->p_export_public :
drv->key_management->p_export );
if( method == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
return( method( drv_context,
slot->data.se.slot_number,
data, data_size, data_length ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( key_type_is_raw_bytes( slot->type ) )
{
if( slot->data.raw.bytes > data_size )
@ -1291,9 +1416,11 @@ static psa_status_t psa_set_key_policy_internal(
* In case of failure at any step, stop the sequence and call
* psa_fail_key_creation().
*
* \param attributes Key attributes for the new key.
* \param handle On success, a handle for the allocated slot.
* \param p_slot On success, a pointer to the prepared slot.
* \param[in] attributes Key attributes for the new key.
* \param[out] handle On success, a handle for the allocated slot.
* \param[out] p_slot On success, a pointer to the prepared slot.
* \param[out] p_drv On any return, the driver for the key, if any.
* NULL for a transparent key.
*
* \retval #PSA_SUCCESS
* The key slot is ready to receive key material.
@ -1303,11 +1430,14 @@ static psa_status_t psa_set_key_policy_internal(
static psa_status_t psa_start_key_creation(
const psa_key_attributes_t *attributes,
psa_key_handle_t *handle,
psa_key_slot_t **p_slot )
psa_key_slot_t **p_slot,
psa_se_drv_table_entry_t **p_drv )
{
psa_status_t status;
psa_key_slot_t *slot;
*p_drv = NULL;
status = psa_internal_allocate_key_slot( handle, p_slot );
if( status != PSA_SUCCESS )
return( status );
@ -1317,16 +1447,51 @@ static psa_status_t psa_start_key_creation(
if( status != PSA_SUCCESS )
return( status );
slot->lifetime = attributes->lifetime;
if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE )
{
status = psa_validate_persistent_key_parameters( attributes->lifetime,
attributes->id, 1 );
attributes->id,
p_drv, 1 );
if( status != PSA_SUCCESS )
return( status );
slot->persistent_storage_id = attributes->id;
}
slot->type = attributes->type;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things:
* create the key file in internal storage, create the
* key inside the secure element, and update the driver's
* persistent data. Start a transaction that will encompass these
* three actions. */
/* The first thing to do is to find a slot number for the new key.
* We save the slot number in persistent storage as part of the
* transaction data. It will be needed to recover if the power
* fails during the key creation process, to clean up on the secure
* element side after restarting. Obtaining a slot number from the
* secure element driver updates its persistent state, but we do not yet
* save the driver's persistent state, so that if the power fails,
* we can roll back to a state where the key doesn't exist. */
if( *p_drv != NULL )
{
status = psa_find_se_slot_for_key( attributes, *p_drv,
&slot->data.se.slot_number );
if( status != PSA_SUCCESS )
return( status );
psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY );
psa_crypto_transaction.key.lifetime = slot->lifetime;
psa_crypto_transaction.key.slot = slot->data.se.slot_number;
psa_crypto_transaction.key.id = slot->persistent_storage_id;
status = psa_crypto_save_transaction( );
if( status != PSA_SUCCESS )
{
(void) psa_crypto_stop_transaction( );
return( status );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
return( status );
}
@ -1338,47 +1503,82 @@ static psa_status_t psa_start_key_creation(
* See the documentation of psa_start_key_creation() for the intended use
* of this function.
*
* \param slot Pointer to the slot with key material.
* \param[in,out] slot Pointer to the slot with key material.
* \param[in] driver The secure element driver for the key,
* or NULL for a transparent key.
*
* \retval #PSA_SUCCESS
* The key was successfully created. The handle is now valid.
* \return If this function fails, the key slot is an invalid state.
* You must call psa_fail_key_creation() to wipe and free the slot.
*/
static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot )
static psa_status_t psa_finish_key_creation(
psa_key_slot_t *slot,
psa_se_drv_table_entry_t *driver )
{
psa_status_t status = PSA_SUCCESS;
(void) slot;
(void) driver;
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE )
{
uint8_t *buffer = NULL;
size_t buffer_size = 0;
size_t length;
size_t length = 0;
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
psa_get_key_slot_bits( slot ) );
buffer = mbedtls_calloc( 1, buffer_size );
if( buffer == NULL && buffer_size != 0 )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
status = psa_internal_export_key( slot,
buffer, buffer_size, &length,
0 );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
buffer = (uint8_t*) &slot->data.se.slot_number;
length = sizeof( slot->data.se.slot_number );
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
psa_get_key_slot_bits( slot ) );
buffer = mbedtls_calloc( 1, buffer_size );
if( buffer == NULL && buffer_size != 0 )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
status = psa_internal_export_key( slot,
buffer, buffer_size, &length,
0 );
}
if( status == PSA_SUCCESS )
{
status = psa_save_persistent_key( slot->persistent_storage_id,
slot->type, &slot->policy,
buffer, length );
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_get_key_slot_attributes( slot, &attributes );
status = psa_save_persistent_key( &attributes, buffer, length );
}
if( buffer_size != 0 )
mbedtls_platform_zeroize( buffer, buffer_size );
mbedtls_free( buffer );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver == NULL )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
if( buffer_size != 0 )
mbedtls_platform_zeroize( buffer, buffer_size );
mbedtls_free( buffer );
}
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
status = psa_save_se_persistent_data( driver );
if( status != PSA_SUCCESS )
{
psa_destroy_persistent_key( slot->persistent_storage_id );
return( status );
}
status = psa_crypto_stop_transaction( );
if( status != PSA_SUCCESS )
return( status );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
return( status );
}
@ -1390,12 +1590,30 @@ static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot )
* See the documentation of psa_start_key_creation() for the intended use
* of this function.
*
* \param slot Pointer to the slot with key material.
* \param[in,out] slot Pointer to the slot with key material.
* \param[in] driver The secure element driver for the key,
* or NULL for a transparent key.
*/
static void psa_fail_key_creation( psa_key_slot_t *slot )
static void psa_fail_key_creation( psa_key_slot_t *slot,
psa_se_drv_table_entry_t *driver )
{
(void) driver;
if( slot == NULL )
return;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* TOnogrepDO: If the key has already been created in the secure
* element, and the failure happened later (when saving metadata
* to internal storage), we need to destroy the key in the secure
* element. */
/* Abort the ongoing transaction if any. We already did what it
* takes to undo any partial creation. All that's left is to update
* the transaction data itself. */
(void) psa_crypto_stop_transaction( );
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
psa_wipe_key_slot( slot );
}
@ -1458,23 +1676,45 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes,
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
psa_se_drv_table_entry_t *driver = NULL;
status = psa_start_key_creation( attributes, handle, &slot );
status = psa_start_key_creation( attributes, handle, &slot, &driver );
if( status != PSA_SUCCESS )
goto exit;
status = psa_import_key_into_slot( slot, data, data_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_check_key_slot_attributes( slot, attributes );
if( status != PSA_SUCCESS )
goto exit;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
const psa_drv_se_t *drv = psa_get_se_driver_methods( driver );
if( drv->key_management == NULL ||
drv->key_management->p_import == NULL )
{
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = drv->key_management->p_import(
psa_get_se_driver_context( driver ),
slot->data.se.slot_number,
slot->lifetime, slot->type, slot->policy.alg, slot->policy.usage,
data, data_length );
/* TOnogrepDO: psa_check_key_slot_attributes? */
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
status = psa_import_key_into_slot( slot, data, data_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_check_key_slot_attributes( slot, attributes );
if( status != PSA_SUCCESS )
goto exit;
}
status = psa_finish_key_creation( slot );
status = psa_finish_key_creation( slot, driver );
exit:
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -1514,9 +1754,10 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle,
psa_key_slot_t *source_slot = NULL;
psa_key_slot_t *target_slot = NULL;
psa_key_attributes_t actual_attributes = *specified_attributes;
psa_se_drv_table_entry_t *driver = NULL;
status = psa_get_key_from_slot( source_handle, &source_slot,
PSA_KEY_USAGE_COPY, 0 );
status = psa_get_transparent_key( source_handle, &source_slot,
PSA_KEY_USAGE_COPY, 0 );
if( status != PSA_SUCCESS )
goto exit;
@ -1530,19 +1771,28 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle,
goto exit;
status = psa_start_key_creation( &actual_attributes,
target_handle, &target_slot );
target_handle, &target_slot, &driver );
if( status != PSA_SUCCESS )
goto exit;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Copying to a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_copy_key_material( source_slot, target_slot );
if( status != PSA_SUCCESS )
goto exit;
status = psa_finish_key_creation( target_slot );
status = psa_finish_key_creation( target_slot, driver );
exit:
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( target_slot );
psa_fail_key_creation( target_slot, driver );
*target_handle = 0;
}
return( status );
@ -2296,7 +2546,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
if( is_sign )
operation->is_sign = 1;
status = psa_get_key_from_slot( handle, &slot, usage, alg );
status = psa_get_transparent_key( handle, &slot, usage, alg );
if( status != PSA_SUCCESS )
goto exit;
key_bits = psa_get_key_slot_bits( slot );
@ -2875,7 +3125,7 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle,
*signature_length = signature_size;
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
if( status != PSA_SUCCESS )
goto exit;
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
@ -2948,7 +3198,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle,
psa_key_slot_t *slot;
psa_status_t status;
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
if( status != PSA_SUCCESS )
return( status );
@ -3018,7 +3268,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle,
if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
if( status != PSA_SUCCESS )
return( status );
if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ||
@ -3098,7 +3348,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle,
if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
if( status != PSA_SUCCESS )
return( status );
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
@ -3207,7 +3457,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
if( status != PSA_SUCCESS )
return( status );
status = psa_get_key_from_slot( handle, &slot, usage, alg);
status = psa_get_transparent_key( handle, &slot, usage, alg);
if( status != PSA_SUCCESS )
goto exit;
key_bits = psa_get_key_slot_bits( slot );
@ -3544,7 +3794,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation,
size_t key_bits;
mbedtls_cipher_id_t cipher_id;
status = psa_get_key_from_slot( handle, &operation->slot, usage, alg );
status = psa_get_transparent_key( handle, &operation->slot, usage, alg );
if( status != PSA_SUCCESS )
return( status );
@ -4437,7 +4687,15 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
status = psa_start_key_creation( attributes, handle, &slot );
psa_se_drv_table_entry_t *driver = NULL;
status = psa_start_key_creation( attributes, handle, &slot, &driver );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Deriving a key in a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( status == PSA_SUCCESS )
{
status = psa_generate_derived_key_internal( slot,
@ -4445,10 +4703,10 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
operation );
}
if( status == PSA_SUCCESS )
status = psa_finish_key_creation( slot );
status = psa_finish_key_creation( slot, driver );
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -4718,7 +4976,7 @@ psa_status_t psa_key_derivation( psa_key_derivation_operation_t *operation,
if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DERIVE, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DERIVE, alg );
if( status != PSA_SUCCESS )
return( status );
@ -5092,9 +5350,9 @@ psa_status_t psa_key_derivation_input_key(
{
psa_key_slot_t *slot;
psa_status_t status;
status = psa_get_key_from_slot( handle, &slot,
PSA_KEY_USAGE_DERIVE,
operation->alg );
status = psa_get_transparent_key( handle, &slot,
PSA_KEY_USAGE_DERIVE,
operation->alg );
if( status != PSA_SUCCESS )
return( status );
if( slot->type != PSA_KEY_TYPE_DERIVE )
@ -5241,8 +5499,8 @@ psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *o
psa_status_t status;
if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( private_key, &slot,
PSA_KEY_USAGE_DERIVE, operation->alg );
status = psa_get_transparent_key( private_key, &slot,
PSA_KEY_USAGE_DERIVE, operation->alg );
if( status != PSA_SUCCESS )
return( status );
status = psa_key_agreement_internal( operation, step,
@ -5269,8 +5527,8 @@ psa_status_t psa_raw_key_agreement( psa_algorithm_t alg,
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
status = psa_get_key_from_slot( private_key, &slot,
PSA_KEY_USAGE_DERIVE, alg );
status = psa_get_transparent_key( private_key, &slot,
PSA_KEY_USAGE_DERIVE, alg );
if( status != PSA_SUCCESS )
goto exit;
@ -5467,7 +5725,15 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
status = psa_start_key_creation( attributes, handle, &slot );
psa_se_drv_table_entry_t *driver = NULL;
status = psa_start_key_creation( attributes, handle, &slot, &driver );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Generating a key in a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( status == PSA_SUCCESS )
{
status = psa_generate_key_internal(
@ -5475,10 +5741,10 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
attributes->domain_parameters, attributes->domain_parameters_size );
}
if( status == PSA_SUCCESS )
status = psa_finish_key_creation( slot );
status = psa_finish_key_creation( slot, driver );
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -5520,6 +5786,30 @@ void mbedtls_psa_crypto_free( void )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
}
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
/** Recover a transaction that was interrupted by a power failure.
*
* This function is called during initialization, before psa_crypto_init()
* returns. If this function returns a failure status, the initialization
* fails.
*/
static psa_status_t psa_crypto_recover_transaction(
const psa_crypto_transaction_t *transaction )
{
switch( transaction->unknown.type )
{
case PSA_CRYPTO_TRANSACTION_CREATE_KEY:
case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:
/* TOnogrepDO - fall through to the failure case until this
* is implemented */
default:
/* We found an unsupported transaction in the storage.
* We don't know what state the storage is in. Give up. */
return( PSA_ERROR_STORAGE_FAILURE );
}
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
psa_status_t psa_crypto_init( void )
{
psa_status_t status;
@ -5553,6 +5843,22 @@ psa_status_t psa_crypto_init( void )
if( status != PSA_SUCCESS )
goto exit;
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
status = psa_crypto_load_transaction( );
if( status == PSA_SUCCESS )
{
status = psa_crypto_recover_transaction( &psa_crypto_transaction );
if( status != PSA_SUCCESS )
goto exit;
status = psa_crypto_stop_transaction( );
}
else if( status == PSA_ERROR_DOES_NOT_EXIST )
{
/* There's no transaction to complete. It's all good. */
status = PSA_SUCCESS;
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
/* All done. */
global_data.initialized = 1;

View file

@ -29,6 +29,7 @@
#endif
#include "psa/crypto.h"
#include "psa/crypto_se_driver.h"
#include "mbedtls/ecp.h"
#include "mbedtls/rsa.h"
@ -45,17 +46,25 @@ typedef struct
unsigned allocated : 1;
union
{
/* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */
struct raw_data
{
uint8_t *data;
size_t bytes;
} raw;
#if defined(MBEDTLS_RSA_C)
/* RSA public key or key pair */
mbedtls_rsa_context *rsa;
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C)
/* EC public key or key pair */
mbedtls_ecp_keypair *ecp;
#endif /* MBEDTLS_ECP_C */
/* Any key type in a secure element */
struct se
{
psa_key_slot_number_t slot_number;
} se;
} data;
} psa_key_slot_t;

View file

@ -28,23 +28,232 @@
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include "psa_crypto_its.h"
#else /* Native ITS implementation */
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#endif
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
/****************************************************************/
/* Driver lookup */
/****************************************************************/
/* This structure is identical to psa_drv_se_context_t declared in
* `crypto_se_driver.h`, except that some parts are writable here
* (non-const, or pointer to non-const). */
typedef struct
{
void *persistent_data;
size_t persistent_data_size;
uintptr_t transient_data;
} psa_drv_se_internal_context_t;
typedef struct psa_se_drv_table_entry_s
{
psa_key_lifetime_t lifetime;
const psa_drv_se_t *methods;
} method_table_entry_t;
union
{
psa_drv_se_internal_context_t internal;
psa_drv_se_context_t context;
};
} psa_se_drv_table_entry_t;
static method_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
psa_se_drv_table_entry_t *psa_get_se_driver_entry(
psa_key_lifetime_t lifetime )
{
size_t i;
/* In the driver table, lifetime=0 means an entry that isn't used.
* No driver has a lifetime of 0 because it's a reserved value
* (which designates volatile keys). Make sure we never return
* a driver entry for lifetime 0. */
if( lifetime == 0 )
return( NULL );
for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
{
if( driver_table[i].lifetime == lifetime )
return( &driver_table[i] );
}
return( NULL );
}
const psa_drv_se_t *psa_get_se_driver_methods(
const psa_se_drv_table_entry_t *driver )
{
return( driver->methods );
}
psa_drv_se_context_t *psa_get_se_driver_context(
psa_se_drv_table_entry_t *driver )
{
return( &driver->context );
}
int psa_get_se_driver( psa_key_lifetime_t lifetime,
const psa_drv_se_t **p_methods,
psa_drv_se_context_t **p_drv_context)
{
psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime );
if( p_methods != NULL )
*p_methods = ( driver ? driver->methods : NULL );
if( p_drv_context != NULL )
*p_drv_context = ( driver ? &driver->context : NULL );
return( driver != NULL );
}
/****************************************************************/
/* Persistent data management */
/****************************************************************/
static psa_status_t psa_get_se_driver_its_file_uid(
const psa_se_drv_table_entry_t *driver,
psa_storage_uid_t *uid )
{
if( driver->lifetime > PSA_MAX_SE_LIFETIME )
return( PSA_ERROR_NOT_SUPPORTED );
#if SIZE_MAX > UINT32_MAX
/* ITS file sizes are limited to 32 bits. */
if( driver->internal.persistent_data_size > UINT32_MAX )
return( PSA_ERROR_NOT_SUPPORTED );
#endif
/* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
*uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime;
return( PSA_SUCCESS );
}
psa_status_t psa_load_se_persistent_data(
const psa_se_drv_table_entry_t *driver )
{
psa_status_t status;
psa_storage_uid_t uid;
status = psa_get_se_driver_its_file_uid( driver, &uid );
if( status != PSA_SUCCESS )
return( status );
/* psa_get_se_driver_its_file_uid ensures that the size_t
* persistent_data_size is in range, but compilers don't know that,
* so cast to reassure them. */
return( psa_its_get( uid, 0,
(uint32_t) driver->internal.persistent_data_size,
driver->internal.persistent_data ) );
}
psa_status_t psa_save_se_persistent_data(
const psa_se_drv_table_entry_t *driver )
{
psa_status_t status;
psa_storage_uid_t uid;
status = psa_get_se_driver_its_file_uid( driver, &uid );
if( status != PSA_SUCCESS )
return( status );
/* psa_get_se_driver_its_file_uid ensures that the size_t
* persistent_data_size is in range, but compilers don't know that,
* so cast to reassure them. */
return( psa_its_set( uid,
(uint32_t) driver->internal.persistent_data_size,
driver->internal.persistent_data,
0 ) );
}
psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime )
{
psa_storage_uid_t uid;
if( lifetime > PSA_MAX_SE_LIFETIME )
return( PSA_ERROR_NOT_SUPPORTED );
uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime;
return( psa_its_remove( uid ) );
}
psa_status_t psa_find_se_slot_for_key(
const psa_key_attributes_t *attributes,
psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t *slot_number )
{
psa_status_t status;
psa_drv_se_allocate_key_t p_allocate = NULL;
/* If the lifetime is wrong, it's a bug in the library. */
if( driver->lifetime != attributes->lifetime )
return( PSA_ERROR_CORRUPTION_DETECTED );
/* If the driver doesn't support key creation in any way, give up now. */
if( driver->methods->key_management == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
p_allocate = driver->methods->key_management->p_allocate;
/* If the driver doesn't tell us how to allocate a slot, that's
* not supported for the time being. */
if( p_allocate == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
status = p_allocate( &driver->context,
driver->internal.persistent_data,
attributes,
slot_number );
return( status );
}
psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t slot_number )
{
psa_status_t status;
psa_status_t storage_status;
/* Normally a missing method would mean that the action is not
* supported. But psa_destroy_key() is not supposed to return
* PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should
* be able to destroy it. The only use case for a driver that
* does not have a way to destroy keys at all is if the keys are
* locked in a read-only state: we can use the keys but not
* destroy them. Hence, if the driver doesn't support destroying
* keys, it's really a lack of permission. */
if( driver->methods->key_management == NULL ||
driver->methods->key_management->p_destroy == NULL )
return( PSA_ERROR_NOT_PERMITTED );
status = driver->methods->key_management->p_destroy(
&driver->context,
driver->internal.persistent_data,
slot_number );
storage_status = psa_save_se_persistent_data( driver );
return( status == PSA_SUCCESS ? storage_status : status );
}
/****************************************************************/
/* Driver registration */
/****************************************************************/
psa_status_t psa_register_se_driver(
psa_key_lifetime_t lifetime,
const psa_drv_se_t *methods)
{
size_t i;
psa_status_t status;
if( methods->hal_version != PSA_DRV_SE_HAL_VERSION )
return( PSA_ERROR_NOT_SUPPORTED );
@ -59,6 +268,8 @@ psa_status_t psa_register_se_driver(
{
return( PSA_ERROR_INVALID_ARGUMENT );
}
if( lifetime > PSA_MAX_SE_LIFETIME )
return( PSA_ERROR_NOT_SUPPORTED );
for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
{
@ -75,12 +286,48 @@ psa_status_t psa_register_se_driver(
driver_table[i].lifetime = lifetime;
driver_table[i].methods = methods;
if( methods->persistent_data_size != 0 )
{
driver_table[i].internal.persistent_data =
mbedtls_calloc( 1, methods->persistent_data_size );
if( driver_table[i].internal.persistent_data == NULL )
{
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
/* Load the driver's persistent data. On first use, the persistent
* data does not exist in storage, and is initialized to
* all-bits-zero by the calloc call just above. */
status = psa_load_se_persistent_data( &driver_table[i] );
if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST )
goto error;
}
driver_table[i].internal.persistent_data_size =
methods->persistent_data_size;
return( PSA_SUCCESS );
error:
memset( &driver_table[i], 0, sizeof( driver_table[i] ) );
return( status );
}
void psa_unregister_all_se_drivers( void )
{
size_t i;
for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
{
if( driver_table[i].internal.persistent_data != NULL )
mbedtls_free( driver_table[i].internal.persistent_data );
}
memset( driver_table, 0, sizeof( driver_table ) );
}
/****************************************************************/
/* The end */
/****************************************************************/
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */

View file

@ -31,6 +31,30 @@
#include "psa/crypto.h"
#include "psa/crypto_se_driver.h"
/** The maximum lifetime value that this implementation supports
* for a secure element.
*
* This is not a characteristic that each PSA implementation has, but a
* limitation of the current implementation due to the constraints imposed
* by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE.
*
* The minimum lifetime value for a secure element is 2, like on any
* PSA implementation (0=volatile and 1=internal-storage are taken).
*/
#define PSA_MAX_SE_LIFETIME 255
/** The base of the range of ITS file identifiers for secure element
* driver persistent data.
*
* We use a slice of the implemenation reserved range 0xffff0000..0xffffffff,
* specifically the range 0xfffffe00..0xfffffeff. The length of this range
* drives the value of #PSA_MAX_SE_LIFETIME.
* The identifiers 0xfffffe00 and 0xfffffe01 are actually not used since
* they correspond to #PSA_KEY_LIFETIME_VOLATILE and
* #PSA_KEY_LIFETIME_PERSISTENT which don't have a driver.
*/
#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 )
/** The maximum number of registered secure element driver lifetimes. */
#define PSA_MAX_SE_DRIVERS 4
@ -42,4 +66,109 @@
*/
void psa_unregister_all_se_drivers( void );
/** A structure that describes a registered secure element driver.
*
* A secure element driver table entry contains a pointer to the
* driver's method table as well as the driver context structure.
*/
typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t;
/** Return the secure element driver information for a lifetime value.
*
* \param lifetime The lifetime value to query.
* \param[out] p_methods On output, if there is a driver,
* \c *methods points to its method table.
* Otherwise \c *methods is \c NULL.
* \param[out] p_drv_context On output, if there is a driver,
* \c *drv_context points to its context
* structure.
* Otherwise \c *drv_context is \c NULL.
*
* \retval 1
* \p lifetime corresponds to a registered driver.
* \retval 0
* \p lifetime does not correspond to a registered driver.
*/
int psa_get_se_driver( psa_key_lifetime_t lifetime,
const psa_drv_se_t **p_methods,
psa_drv_se_context_t **p_drv_context);
/** Return the secure element driver table entry for a lifetime value.
*
* \param lifetime The lifetime value to query.
*
* \return The driver table entry for \p lifetime, or
* \p NULL if \p lifetime does not correspond to a registered driver.
*/
psa_se_drv_table_entry_t *psa_get_se_driver_entry(
psa_key_lifetime_t lifetime );
/** Return the method table for a secure element driver.
*
* \param[in] driver The driver table entry to access, or \c NULL.
*
* \return The driver's method table.
* \c NULL if \p driver is \c NULL.
*/
const psa_drv_se_t *psa_get_se_driver_methods(
const psa_se_drv_table_entry_t *driver );
/** Return the context of a secure element driver.
*
* \param[in] driver The driver table entry to access, or \c NULL.
*
* \return A pointer to the driver context.
* \c NULL if \p driver is \c NULL.
*/
psa_drv_se_context_t *psa_get_se_driver_context(
psa_se_drv_table_entry_t *driver );
/** Find a free slot for a key that is to be created.
*
* This function calls the relevant method in the driver to find a suitable
* slot for a key with the given attributes.
*
* \param[in] attributes Metadata about the key that is about to be created.
* \param[in] driver The driver table entry to query.
* \param[out] slot_number On success, a slot number that is free in this
* secure element.
*/
psa_status_t psa_find_se_slot_for_key(
const psa_key_attributes_t *attributes,
psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t *slot_number );
/** Destoy a key in a secure element.
*
* This function calls the relevant driver method to destroy a key
* and updates the driver's persistent data.
*/
psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver,
psa_key_slot_number_t slot_number );
/** Load the persistent data of a secure element driver.
*
* \param driver The driver table entry containing the persistent
* data to load from storage.
*/
psa_status_t psa_load_se_persistent_data(
const psa_se_drv_table_entry_t *driver );
/** Save the persistent data of a secure element driver.
*
* \param[in] driver The driver table entry containing the persistent
* data to save to storage.
*/
psa_status_t psa_save_se_persistent_data(
const psa_se_drv_table_entry_t *driver );
/** Destroy the persistent data of a secure element driver.
*
* This is currently only used for testing.
*
* \param[in] lifetime The driver lifetime whose persistent data should
* be erased.
*/
psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime );
#endif /* PSA_CRYPTO_SE_H */

View file

@ -124,15 +124,35 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot )
psa_status_t status = PSA_SUCCESS;
uint8_t *key_data = NULL;
size_t key_data_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
status = psa_load_persistent_key( p_slot->persistent_storage_id,
&( p_slot )->type,
&( p_slot )->policy, &key_data,
&key_data_length );
psa_set_key_id( &attributes, p_slot->persistent_storage_id );
status = psa_load_persistent_key( &attributes,
&key_data, &key_data_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_import_key_into_slot( p_slot,
key_data, key_data_length );
p_slot->lifetime = psa_get_key_lifetime( &attributes );
p_slot->type = psa_get_key_type( &attributes );
p_slot->policy = attributes.policy;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_key_lifetime_is_external( p_slot->lifetime ) )
{
if( key_data_length != sizeof( p_slot->data.se.slot_number ) )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
memcpy( &p_slot->data.se.slot_number, key_data,
sizeof( p_slot->data.se.slot_number ) );
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
status = psa_import_key_into_slot( p_slot,
key_data, key_data_length );
}
exit:
psa_free_persistent_key_data( key_data, key_data_length );
return( status );
@ -168,8 +188,20 @@ static int psa_is_key_id_valid( psa_key_file_id_t file_id,
psa_status_t psa_validate_persistent_key_parameters(
psa_key_lifetime_t lifetime,
psa_key_file_id_t id,
psa_se_drv_table_entry_t **p_drv,
int creating )
{
if( p_drv != NULL )
*p_drv = NULL;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_key_lifetime_is_external( lifetime ) )
{
*p_drv = psa_get_se_driver_entry( lifetime );
if( *p_drv == NULL )
return( PSA_ERROR_INVALID_ARGUMENT );
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( lifetime != PSA_KEY_LIFETIME_PERSISTENT )
return( PSA_ERROR_INVALID_ARGUMENT );
@ -194,7 +226,7 @@ psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle )
*handle = 0;
status = psa_validate_persistent_key_parameters(
PSA_KEY_LIFETIME_PERSISTENT, id, 0 );
PSA_KEY_LIFETIME_PERSISTENT, id, NULL, 0 );
if( status != PSA_SUCCESS )
return( status );

View file

@ -22,6 +22,9 @@
#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H
#define PSA_CRYPTO_SLOT_MANAGEMENT_H
#include "psa/crypto.h"
#include "psa_crypto_se.h"
/* Number of key slots (plus one because 0 is not used).
* The value is a compile-time constant for now, for simplicity. */
#define PSA_KEY_SLOT_COUNT 32
@ -71,6 +74,24 @@ void psa_wipe_all_key_slots( void );
psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle,
psa_key_slot_t **p_slot );
/** Test whether a lifetime designates a key in an external cryptoprocessor.
*
* \param lifetime The lifetime to test.
*
* \retval 1
* The lifetime designates an external key. There should be a
* registered driver for this lifetime, otherwise the key cannot
* be created or manipulated.
* \retval 0
* The lifetime designates a key that is volatile or in internal
* storage.
*/
static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime )
{
return( lifetime != PSA_KEY_LIFETIME_VOLATILE &&
lifetime != PSA_KEY_LIFETIME_PERSISTENT );
}
/** Test whether the given parameters are acceptable for a persistent key.
*
* This function does not access the storage in any way. It only tests
@ -78,8 +99,16 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle,
* It does not test whether the a file by the given id exists or could be
* created.
*
* If the key is in external storage, this function returns the corresponding
* driver.
*
* \param lifetime The lifetime to test.
* \param id The key id to test.
* \param[out] p_drv On output, if \p lifetime designates a key
* in an external processor, \c *p_drv is a pointer
* to the driver table entry fot this lifetime.
* If \p lifetime designates a transparent key,
* \c *p_drv is \c NULL.
* \param creating 0 if attempting to open an existing key.
* Nonzero if attempting to create a key.
*
@ -93,6 +122,7 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle,
psa_status_t psa_validate_persistent_key_parameters(
psa_key_lifetime_t lifetime,
psa_key_file_id_t id,
psa_se_drv_table_entry_t **p_drv,
int creating );

View file

@ -50,6 +50,12 @@
#define mbedtls_free free
#endif
/****************************************************************/
/* Key storage */
/****************************************************************/
/* Determine a file name (ITS file identifier) for the given key file
* identifier. The file name must be distinct from any file that is used
* for a purpose other than storing a key. Currently, the only such file
@ -221,7 +227,7 @@ static psa_status_t psa_crypto_storage_get_data_length(
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
#define GET_UINT32_LE( n, b, i ) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
@ -231,7 +237,7 @@ static psa_status_t psa_crypto_storage_get_data_length(
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
#define PUT_UINT32_LE( n, b, i ) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
@ -249,6 +255,7 @@ static psa_status_t psa_crypto_storage_get_data_length(
typedef struct {
uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
uint8_t version[4];
uint8_t lifetime[sizeof( psa_key_lifetime_t )];
uint8_t type[sizeof( psa_key_type_t )];
uint8_t policy[sizeof( psa_key_policy_t )];
uint8_t data_len[4];
@ -257,20 +264,20 @@ typedef struct {
void psa_format_key_data_for_storage( const uint8_t *data,
const size_t data_length,
const psa_key_type_t type,
const psa_key_policy_t *policy,
const psa_key_attributes_t *attributes,
uint8_t *storage_data )
{
psa_persistent_key_storage_format *storage_format =
(psa_persistent_key_storage_format *) storage_data;
memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
PUT_UINT32_LE(0, storage_format->version, 0);
PUT_UINT32_LE(type, storage_format->type, 0);
PUT_UINT32_LE(policy->usage, storage_format->policy, 0);
PUT_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
PUT_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
PUT_UINT32_LE(data_length, storage_format->data_len, 0);
PUT_UINT32_LE( 0, storage_format->version, 0 );
PUT_UINT32_LE( psa_get_key_lifetime( attributes ), storage_format->lifetime, 0 );
PUT_UINT32_LE( psa_get_key_type( attributes ), storage_format->type, 0 );
PUT_UINT32_LE( psa_get_key_usage_flags( attributes ), storage_format->policy, 0 );
PUT_UINT32_LE( psa_get_key_algorithm( attributes ), storage_format->policy, sizeof( uint32_t ) );
PUT_UINT32_LE( psa_get_key_enrollment_algorithm( attributes ), storage_format->policy, 2 * sizeof( uint32_t ) );
PUT_UINT32_LE( data_length, storage_format->data_len, 0 );
memcpy( storage_format->key_data, data, data_length );
}
@ -286,8 +293,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
psa_key_type_t *type,
psa_key_policy_t *policy )
psa_key_attributes_t *attributes )
{
psa_status_t status;
const psa_persistent_key_storage_format *storage_format =
@ -301,11 +307,11 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
if( status != PSA_SUCCESS )
return( status );
GET_UINT32_LE(version, storage_format->version, 0);
GET_UINT32_LE( version, storage_format->version, 0 );
if( version != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
GET_UINT32_LE(*key_data_length, storage_format->data_len, 0);
GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 );
if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) ||
*key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
return( PSA_ERROR_STORAGE_FAILURE );
@ -322,17 +328,16 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
memcpy( *key_data, storage_format->key_data, *key_data_length );
}
GET_UINT32_LE(*type, storage_format->type, 0);
GET_UINT32_LE(policy->usage, storage_format->policy, 0);
GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
GET_UINT32_LE(policy->alg2, storage_format->policy, 2 * sizeof( uint32_t ));
GET_UINT32_LE( attributes->lifetime, storage_format->lifetime, 0 );
GET_UINT32_LE( attributes->type, storage_format->type, 0 );
GET_UINT32_LE( attributes->policy.usage, storage_format->policy, 0 );
GET_UINT32_LE( attributes->policy.alg, storage_format->policy, sizeof( uint32_t ) );
GET_UINT32_LE( attributes->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
return( PSA_SUCCESS );
}
psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
const psa_key_type_t type,
const psa_key_policy_t *policy,
psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes,
const uint8_t *data,
const size_t data_length )
{
@ -348,10 +353,10 @@ psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
if( storage_data == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
psa_format_key_data_for_storage( data, data_length, type, policy,
psa_format_key_data_for_storage( data, data_length, attributes,
storage_data );
status = psa_crypto_storage_store( key,
status = psa_crypto_storage_store( psa_get_key_id( attributes ),
storage_data, storage_data_length );
mbedtls_free( storage_data );
@ -368,15 +373,14 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length )
mbedtls_free( key_data );
}
psa_status_t psa_load_persistent_key( psa_key_file_id_t key,
psa_key_type_t *type,
psa_key_policy_t *policy,
psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes,
uint8_t **data,
size_t *data_length )
{
psa_status_t status = PSA_SUCCESS;
uint8_t *loaded_data;
size_t storage_data_length = 0;
psa_key_id_t key = psa_get_key_id( attributes );
status = psa_crypto_storage_get_data_length( key, &storage_data_length );
if( status != PSA_SUCCESS )
@ -392,13 +396,67 @@ psa_status_t psa_load_persistent_key( psa_key_file_id_t key,
goto exit;
status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
data, data_length, type, policy );
data, data_length, attributes );
exit:
mbedtls_free( loaded_data );
return( status );
}
/****************************************************************/
/* Transactions */
/****************************************************************/
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
psa_crypto_transaction_t psa_crypto_transaction;
psa_status_t psa_crypto_save_transaction( void )
{
struct psa_storage_info_t p_info;
psa_status_t status;
status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
if( status == PSA_SUCCESS )
{
/* This shouldn't happen: we're trying to start a transaction while
* there is still a transaction that hasn't been replayed. */
return( PSA_ERROR_CORRUPTION_DETECTED );
}
else if( status != PSA_ERROR_DOES_NOT_EXIST )
return( status );
return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID,
sizeof( psa_crypto_transaction ),
&psa_crypto_transaction,
0 ) );
}
psa_status_t psa_crypto_load_transaction( void )
{
return( psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0,
sizeof( psa_crypto_transaction ),
&psa_crypto_transaction ) );
}
psa_status_t psa_crypto_stop_transaction( void )
{
psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID );
/* Whether or not updating the storage succeeded, the transaction is
* finished now. It's too late to go back, so zero out the in-memory
* data. */
memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) );
return( status );
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
/****************************************************************/
/* Random generator state */
/****************************************************************/
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed,
size_t seed_size )
@ -421,4 +479,10 @@ psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed,
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
/****************************************************************/
/* The end */
/****************************************************************/
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */

View file

@ -29,16 +29,11 @@
extern "C" {
#endif
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#include "psa/crypto.h"
#include "psa/crypto_se_driver.h"
#include <stdint.h>
#include <string.h>
/* Limit the maximum key size to 30kB (just in case someone tries to
* inadvertently store an obscene amount of data) */
@ -88,12 +83,11 @@ int psa_is_key_present_in_storage( const psa_key_file_id_t key );
* already occupied non-persistent key, as well as validating the key data.
*
*
* \param key Persistent identifier of the key to be stored. This
* should be an unoccupied storage location.
* \param type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param[in] policy The key policy to save.
* \param[in] data Buffer containing the key data.
* \param data_length The number of bytes that make up the key data.
* \param[in] attributes The attributes of the key to save.
* The key identifier field in the attributes
* determines the key's location.
* \param[in] data Buffer containing the key data.
* \param data_length The number of bytes that make up the key data.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
@ -101,9 +95,7 @@ int psa_is_key_present_in_storage( const psa_key_file_id_t key );
* \retval PSA_ERROR_STORAGE_FAILURE
* \retval PSA_ERROR_ALREADY_EXISTS
*/
psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
const psa_key_type_t type,
const psa_key_policy_t *policy,
psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes,
const uint8_t *data,
const size_t data_length );
@ -119,11 +111,11 @@ psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
* this function to zeroize and free this buffer, regardless of whether this
* function succeeds or fails.
*
* \param key Persistent identifier of the key to be loaded. This
* should be an occupied storage location.
* \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX
* value).
* \param[out] policy On success, the key's policy.
* \param[in,out] attributes
* On input, the key identifier field identifies
* the key to load. Other fields are ignored.
* On success, the attribute structure contains
* the key metadata that was loaded from storage.
* \param[out] data Pointer to an allocated key data buffer on return.
* \param[out] data_length The number of bytes that make up the key data.
*
@ -132,9 +124,7 @@ psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
* \retval PSA_ERROR_STORAGE_FAILURE
* \retval PSA_ERROR_DOES_NOT_EXIST
*/
psa_status_t psa_load_persistent_key( psa_key_file_id_t key,
psa_key_type_t *type,
psa_key_policy_t *policy,
psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes,
uint8_t **data,
size_t *data_length );
@ -166,17 +156,15 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length );
/**
* \brief Formats key data and metadata for persistent storage
*
* \param[in] data Buffer for the key data.
* \param[in] data Buffer containing the key data.
* \param data_length Length of the key data buffer.
* \param type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param policy The key policy.
* \param[in] attributes The attributes of the key.
* \param[out] storage_data Output buffer for the formatted data.
*
*/
void psa_format_key_data_for_storage( const uint8_t *data,
const size_t data_length,
const psa_key_type_t type,
const psa_key_policy_t *policy,
const psa_key_attributes_t *attributes,
uint8_t *storage_data );
/**
@ -188,8 +176,8 @@ void psa_format_key_data_for_storage( const uint8_t *data,
* containing the key data. This must be freed
* using psa_free_persistent_key_data()
* \param[out] key_data_length Length of the key data buffer
* \param[out] type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param[out] policy The key policy.
* \param[out] attributes On success, the attribute structure is filled
* with the loaded key metadata.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_STORAGE
@ -200,8 +188,180 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
psa_key_type_t *type,
psa_key_policy_t *policy );
psa_key_attributes_t *attributes );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/** This symbol is defined if transaction support is required. */
#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS
#endif
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
/** The type of transaction that is in progress.
*/
/* This is an integer type rather than an enum for two reasons: to support
* unknown values when loading a transaction file, and to ensure that the
* type has a known size.
*/
typedef uint16_t psa_crypto_transaction_type_t;
/** No transaction is in progress.
*
* This has the value 0, so zero-initialization sets a transaction's type to
* this value.
*/
#define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 )
/** A key creation transaction.
*
* This is only used for keys in an external cryptoprocessor (secure element).
* Keys in RAM or in internal storage are created atomically in storage
* (simple file creation), so they do not need a transaction mechanism.
*/
#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 )
/** A key destruction transaction.
*
* This is only used for keys in an external cryptoprocessor (secure element).
* Keys in RAM or in internal storage are destroyed atomically in storage
* (simple file deletion), so they do not need a transaction mechanism.
*/
#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 )
/** Transaction data.
*
* This type is designed to be serialized by writing the memory representation
* and reading it back on the same device.
*
* \note The transaction mechanism is designed for a single active transaction
* at a time. The transaction object is #psa_crypto_transaction.
*
* \note If an API call starts a transaction, it must complete this transaction
* before returning to the application.
*
* The lifetime of a transaction is the following (note that only one
* transaction may be active at a time):
*
* -# Call psa_crypto_prepare_transaction() to initialize the transaction
* object in memory and declare the type of transaction that is starting.
* -# Fill in the type-specific fields of #psa_crypto_transaction.
* -# Call psa_crypto_save_transaction() to start the transaction. This
* saves the transaction data to internal storage.
* -# Perform the work of the transaction by modifying files, contacting
* external entities, or whatever needs doing. Note that the transaction
* may be interrupted by a power failure, so you need to have a way
* recover from interruptions either by undoing what has been done
* so far or by resuming where you left off.
* -# If there are intermediate stages in the transaction, update
* the fields of #psa_crypto_transaction and call
* psa_crypto_save_transaction() again when each stage is reached.
* -# When the transaction is over, call psa_crypto_stop_transaction() to
* remove the transaction data in storage and in memory.
*
* If the system crashes while a transaction is in progress, psa_crypto_init()
* calls psa_crypto_load_transaction() and takes care of completing or
* rewinding the transaction. This is done in psa_crypto_recover_transaction()
* in psa_crypto.c. If you add a new type of transaction, be
* sure to add code for it in psa_crypto_recover_transaction().
*/
typedef union
{
/* Each element of this union must have the following properties
* to facilitate serialization and deserialization:
*
* - The element is a struct.
* - The first field of the struct is `psa_crypto_transaction_type_t type`.
* - Elements of the struct are arranged such a way that there is
* no padding.
*/
struct psa_crypto_transaction_unknown_s
{
psa_crypto_transaction_type_t type;
uint16_t unused1;
uint32_t unused2;
uint64_t unused3;
uint64_t unused4;
} unknown;
/* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or
* #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */
struct psa_crypto_transaction_key_s
{
psa_crypto_transaction_type_t type;
uint16_t unused1;
psa_key_lifetime_t lifetime;
psa_key_slot_number_t slot;
psa_key_id_t id;
} key;
} psa_crypto_transaction_t;
/** The single active transaction.
*/
extern psa_crypto_transaction_t psa_crypto_transaction;
/** Prepare for a transaction.
*
* There must not be an ongoing transaction.
*
* \param type The type of transaction to start.
*/
static inline void psa_crypto_prepare_transaction(
psa_crypto_transaction_type_t type )
{
psa_crypto_transaction.unknown.type = type;
}
/** Save the transaction data to storage.
*
* You may call this function multiple times during a transaction to
* atomically update the transaction state.
*
* \retval #PSA_SUCCESS
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_crypto_save_transaction( void );
/** Load the transaction data from storage, if any.
*
* This function is meant to be called from psa_crypto_init() to recover
* in case a transaction was interrupted by a system crash.
*
* \retval #PSA_SUCCESS
* The data about the ongoing transaction has been loaded to
* #psa_crypto_transaction.
* \retval #PSA_ERROR_DOES_NOT_EXIST
* There is no ongoing transaction.
* \retval #PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_crypto_load_transaction( void );
/** Indicate that the current transaction is finished.
*
* Call this function at the very end of transaction processing.
* This function does not "commit" or "abort" the transaction: the storage
* subsystem has no concept of "commit" and "abort", just saving and
* removing the transaction information in storage.
*
* This function erases the transaction data in storage (if any) and
* resets the transaction data in memory.
*
* \retval #PSA_SUCCESS
* There was transaction data in storage.
* \retval #PSA_ERROR_DOES_NOT_EXIST
* There was no transaction data in storage.
* \retval #PSA_ERROR_STORAGE_FAILURE
* It was impossible to determine whether there was transaction data
* in storage, or the transaction data could not be erased.
*/
psa_status_t psa_crypto_stop_transaction( void );
/** The ITS file identifier for the transaction data.
*
* 0xffffffNN = special file; 0x74 = 't' for transaction.
*/
#define PSA_CRYPTO_ITS_TRANSACTION_UID ( (psa_key_id_t) 0xffffff74 )
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
/** Backend side of mbedtls_psa_inject_entropy().

View file

@ -85,6 +85,7 @@ MBEDTLS_NO_PLATFORM_ENTROPY
MBEDTLS_RSA_NO_CRT
MBEDTLS_NO_UDBL_DIVISION
MBEDTLS_NO_64BIT_MULTIPLICATION
MBEDTLS_PSA_CRYPTO_SE_C
MBEDTLS_PSA_CRYPTO_SPM
MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
MBEDTLS_PSA_INJECT_ENTROPY

View file

@ -783,6 +783,24 @@ component_test_aes_fewer_tables_and_rom_tables () {
make test
}
component_test_se_default () {
msg "build: default config + MBEDTLS_PSA_CRYPTO_SE_C"
scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
make CC=clang CFLAGS='-Werror -Wall -Wextra -Wno-unused-function -Os -fsanitize=address' LDFLAGS='-fsanitize=address'
msg "test: default config + MBEDTLS_PSA_CRYPTO_SE_C"
make test
}
component_test_se_full () {
msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C"
scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
make CC=gcc CFLAGS='-Werror -Wall -Wextra -O2 -fsanitize=address' LDFLAGS='-fsanitize=address'
msg "test: full config + MBEDTLS_PSA_CRYPTO_SE_C"
make test
}
component_test_make_shared () {
msg "build/test: make shared" # ~ 40s
make SHARED=1 all check

View file

@ -41,7 +41,7 @@ rm -f identifiers
grep '^[^ /#{]' $HEADERS | \
sed -e 's/^[^:]*://' | \
egrep -v '^(extern "C"|(typedef )?(struct|enum)( {)?$|};?$)' \
egrep -v '^(extern "C"|(typedef )?(struct|union|enum)( {)?$|};?$)' \
> _decls
if true; then

View file

@ -1,20 +1,20 @@
PSA Storage format data for storage
format_storage_data_check:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b4559000000000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN
format_storage_data_check:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN
PSA Storage parse stored data
parse_storage_data_check:"505341004b4559000000000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_SUCCESS
parse_storage_data_check:"505341004b455900000000000100000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_SUCCESS
PSA Storage parse stored data wrong version, should fail
parse_storage_data_check:"505341004b455900ffffffff00000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
parse_storage_data_check:"505341004b455900ffffffff0100000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
PSA Storage parse too big data, should fail
parse_storage_data_check:"505341004b4559000000000000000170010000000000001200000010ffffffff3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
parse_storage_data_check:"505341004b455900000000000100000000000170010000000000001200000010ffffffff3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
PSA Storage parse bad magic, should fail
parse_storage_data_check:"645341004b4559000000000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
parse_storage_data_check:"645341004b455900000000000100000000000170010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
PSA Storage parse not enough magic, should fail
parse_storage_data_check:"505341004b4559":"":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
parse_storage_data_check:"505341004b4559":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
# Not specific to files, but only run this test in an environment where the maximum size could be reached.
Save maximum size persistent raw key

View file

@ -12,6 +12,7 @@
typedef struct {
uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
uint8_t version[4];
uint8_t lifetime[sizeof( psa_key_lifetime_t )];
uint8_t type[sizeof( psa_key_type_t )];
uint8_t policy[sizeof( psa_key_policy_t )];
uint8_t data_len[4];
@ -28,21 +29,23 @@ typedef struct {
/* BEGIN_CASE */
void format_storage_data_check( data_t *key_data,
data_t *expected_file_data,
int key_type,
int key_lifetime, int key_type,
int key_usage, int key_alg, int key_alg2 )
{
uint8_t *file_data;
size_t file_data_length;
psa_key_policy_t key_policy;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
key_policy.usage = (psa_key_usage_t) key_usage;
key_policy.alg = (psa_algorithm_t) key_alg;
key_policy.alg2 = (psa_algorithm_t) key_alg2;
psa_set_key_lifetime( &attributes, key_lifetime );
psa_set_key_type( &attributes, key_type );
psa_set_key_usage_flags( &attributes, key_usage );
psa_set_key_algorithm( &attributes, key_alg );
psa_set_key_enrollment_algorithm( &attributes, key_alg2 );
file_data_length = key_data->len + sizeof( psa_persistent_key_storage_format );
file_data = mbedtls_calloc( 1, file_data_length );
psa_format_key_data_for_storage( key_data->x, key_data->len,
(psa_key_type_t) key_type, &key_policy,
&attributes,
file_data );
ASSERT_COMPARE( expected_file_data->x, expected_file_data->len,
@ -54,6 +57,7 @@ void format_storage_data_check( data_t *key_data,
/* BEGIN_CASE */
void parse_storage_data_check( data_t *file_data,
data_t *expected_key_data,
int expected_key_lifetime,
int expected_key_type,
int expected_key_usage,
int expected_key_alg,
@ -62,22 +66,27 @@ void parse_storage_data_check( data_t *file_data,
{
uint8_t *key_data = NULL;
size_t key_data_length = 0;
psa_key_type_t key_type = 0;
psa_key_policy_t key_policy;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
status = psa_parse_key_data_from_storage( file_data->x, file_data->len,
&key_data, &key_data_length,
&key_type, &key_policy );
&attributes );
TEST_EQUAL( status, expected_status );
if( status != PSA_SUCCESS )
goto exit;
TEST_EQUAL( key_type, (psa_key_type_t) expected_key_type );
TEST_EQUAL( key_policy.usage, (uint32_t) expected_key_usage );
TEST_EQUAL( key_policy.alg, (uint32_t) expected_key_alg );
TEST_EQUAL( key_policy.alg2, (uint32_t) expected_key_alg2 );
TEST_EQUAL( psa_get_key_lifetime( &attributes ),
(psa_key_type_t) expected_key_lifetime );
TEST_EQUAL( psa_get_key_type( &attributes ),
(psa_key_type_t) expected_key_type );
TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
(uint32_t) expected_key_usage );
TEST_EQUAL( psa_get_key_algorithm( &attributes ),
(uint32_t) expected_key_alg );
TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ),
(uint32_t) expected_key_alg2 );
ASSERT_COMPARE( expected_key_data->x, expected_key_data->len,
key_data, key_data_length );

View file

@ -26,3 +26,72 @@ register_twice:3
Register SE driver: maximum number of drivers
register_max:
SE key import-export (p_allocate allows all slots)
key_creation_import_export:0:0
SE key import-export (p_allocate allows 1 slot)
key_creation_import_export:ARRAY_LENGTH( ram_slots ) - 1:0
SE key import-export, check after restart (slot 0)
key_creation_import_export:0:1
SE key import-export, check after restart (slot 3)
key_creation_import_export:3:1
Key creation smoke test: AES-CTR
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: AES-CBC
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: AES-CMAC
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: AES-CCM
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: AES-GCM
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: CAMELLIA-CTR
key_creation_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: CAMELLIA-CBC
key_creation_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_CBC_NO_PADDING:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: CAMELLIA-CMAC
key_creation_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_CMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: CAMELLIA-CCM
key_creation_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: CAMELLIA-CCM
key_creation_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: HMAC-SHA-256
key_creation_smoke:PSA_KEY_TYPE_HMAC:PSA_ALG_HMAC( PSA_ALG_SHA_256 ):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: HKDF-SHA-256
key_creation_smoke:PSA_KEY_TYPE_DERIVE:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Key creation smoke test: RSA PKCS#1v1.5 signature
key_creation_smoke:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
Key creation smoke test: RSA PKCS#1v1.5 encryption
key_creation_smoke:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_CRYPT:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
Key creation smoke test: RSA OAEP encryption
key_creation_smoke:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_OAEP( PSA_ALG_SHA_256 ):"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
Key creation smoke test: ECDSA secp256r1
key_creation_smoke:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_ECDSA_ANY:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
Key creation smoke test: ECDH secp256r1
key_creation_smoke:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_ECDH:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
Key creation smoke test: ECDH secp256r1 with HKDF
key_creation_smoke:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
Generate key: not supported
generate_key_not_supported:PSA_KEY_TYPE_AES:128

View file

@ -3,10 +3,328 @@
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
#include "psa_crypto_storage.h"
/* The minimum valid lifetime value for a secure element driver. */
/****************************************************************/
/* Test driver helpers */
/****************************************************************/
/** The minimum valid lifetime value for a secure element driver. */
#define MIN_DRIVER_LIFETIME 2
/** The driver detected a condition that shouldn't happen.
* This is probably a bug in the library. */
#define PSA_ERROR_DETECTED_BY_DRIVER ((psa_status_t)( -500 ))
/** Like #TEST_ASSERT for use in a driver method.
*
* Use this macro to assert on guarantees provided by the core.
*/
#define DRIVER_ASSERT( TEST ) \
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
return( PSA_ERROR_DETECTED_BY_DRIVER ); \
} \
} while( 0 )
/****************************************************************/
/* Miscellaneous driver methods */
/****************************************************************/
/* Allocate slot numbers with a monotonic counter. */
static psa_status_t counter_allocate( psa_drv_se_context_t *context,
void *persistent_data,
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number )
{
psa_key_slot_number_t *p_counter = persistent_data;
(void) attributes;
if( context->persistent_data_size != sizeof( psa_key_slot_number_t ) )
return( PSA_ERROR_DETECTED_BY_DRIVER );
++*p_counter;
if( *p_counter == 0 )
return( PSA_ERROR_INSUFFICIENT_STORAGE );
*slot_number = *p_counter;
return( PSA_SUCCESS );
}
/* Null import: do nothing, but pretend it worked. */
static psa_status_t null_import( psa_drv_se_context_t *context,
psa_key_slot_number_t slot_number,
psa_key_lifetime_t lifetime,
psa_key_type_t type,
psa_algorithm_t algorithm,
psa_key_usage_t usage,
const uint8_t *p_data,
size_t data_length )
{
(void) context;
(void) slot_number;
(void) lifetime;
(void) type;
(void) algorithm;
(void) usage;
(void) p_data;
(void) data_length;
return( PSA_SUCCESS );
}
/****************************************************************/
/* RAM-based test driver */
/****************************************************************/
#define RAM_MAX_KEY_SIZE 64
typedef struct
{
psa_key_lifetime_t lifetime;
psa_key_type_t type;
size_t bits;
uint8_t content[RAM_MAX_KEY_SIZE];
} ram_slot_t;
static ram_slot_t ram_slots[16];
/* A type with at least ARRAY_LENGTH(ram_slots) bits, containing a
* bit vector indicating which slots are in use. */
typedef uint16_t ram_slot_usage_t;
static uint8_t ram_min_slot = 0;
static void ram_slots_reset( void )
{
memset( ram_slots, 0, sizeof( ram_slots ) );
ram_min_slot = 0;
}
static psa_status_t ram_import( psa_drv_se_context_t *context,
psa_key_slot_number_t slot_number,
psa_key_lifetime_t lifetime,
psa_key_type_t type,
psa_algorithm_t algorithm,
psa_key_usage_t usage,
const uint8_t *p_data,
size_t data_length )
{
(void) context;
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
if( data_length > sizeof( ram_slots[slot_number].content ) )
return( PSA_ERROR_INSUFFICIENT_STORAGE );
ram_slots[slot_number].lifetime = lifetime;
ram_slots[slot_number].type = type;
ram_slots[slot_number].bits = PSA_BYTES_TO_BITS( data_length );
(void) algorithm;
(void) usage;
memcpy( ram_slots[slot_number].content, p_data, data_length );
return( PSA_SUCCESS );
}
static psa_status_t ram_export( psa_drv_se_context_t *context,
psa_key_slot_number_t slot_number,
uint8_t *p_data,
size_t data_size,
size_t *p_data_length )
{
size_t actual_size;
(void) context;
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
actual_size = PSA_BITS_TO_BYTES( ram_slots[slot_number].bits );
if( actual_size > data_size )
return( PSA_ERROR_BUFFER_TOO_SMALL );
*p_data_length = actual_size;
memcpy( p_data, ram_slots[slot_number].content, actual_size );
return( PSA_SUCCESS );
}
static psa_status_t ram_destroy( psa_drv_se_context_t *context,
void *persistent_data,
psa_key_slot_number_t slot_number )
{
ram_slot_usage_t *slot_usage = persistent_data;
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
memset( &ram_slots[slot_number], 0, sizeof( ram_slots[slot_number] ) );
*slot_usage &= ~(ram_slot_usage_t)( 1 << slot_number );
return( PSA_SUCCESS );
}
static psa_status_t ram_allocate( psa_drv_se_context_t *context,
void *persistent_data,
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number )
{
ram_slot_usage_t *slot_usage = persistent_data;
(void) attributes;
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
for( *slot_number = ram_min_slot;
*slot_number < ARRAY_LENGTH( ram_slots );
++( *slot_number ) )
{
if( ! ( *slot_usage & 1 << *slot_number ) )
return( PSA_SUCCESS );
}
return( PSA_ERROR_INSUFFICIENT_STORAGE );
}
/****************************************************************/
/* Other test helper functions */
/****************************************************************/
/* Check that a function's return status is "smoke-free", i.e. that
* it's an acceptable error code when calling an API function that operates
* on a key with potentially bogus parameters. */
static int is_status_smoke_free( psa_status_t status )
{
switch( status )
{
case PSA_SUCCESS:
case PSA_ERROR_NOT_SUPPORTED:
case PSA_ERROR_NOT_PERMITTED:
case PSA_ERROR_BUFFER_TOO_SMALL:
case PSA_ERROR_INVALID_ARGUMENT:
case PSA_ERROR_INVALID_SIGNATURE:
case PSA_ERROR_INVALID_PADDING:
return( 1 );
default:
return( 0 );
}
}
#define SMOKE_ASSERT( expr ) \
TEST_ASSERT( is_status_smoke_free( expr ) )
/* Smoke test a key. There are mostly no wrong answers here since we pass
* mostly bogus parameters: the goal is to ensure that there is no memory
* corruption or crash. This test function is most useful when run under
* an environment with sanity checks such as ASan or MSan. */
static int smoke_test_key( psa_key_handle_t handle )
{
int ok = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT;
psa_cipher_operation_t cipher_operation = PSA_CIPHER_OPERATION_INIT;
psa_key_derivation_operation_t derivation_operation =
PSA_KEY_DERIVATION_OPERATION_INIT;
uint8_t buffer[80]; /* large enough for a public key for ECDH */
size_t length;
psa_key_handle_t handle2 = 0;
SMOKE_ASSERT( psa_get_key_attributes( handle, &attributes ) );
SMOKE_ASSERT( psa_export_key( handle,
buffer, sizeof( buffer ), &length ) );
SMOKE_ASSERT( psa_export_public_key( handle,
buffer, sizeof( buffer ), &length ) );
SMOKE_ASSERT( psa_copy_key( handle, &attributes, &handle2 ) );
if( handle2 != 0 )
PSA_ASSERT( psa_close_key( handle2 ) );
SMOKE_ASSERT( psa_mac_sign_setup( &mac_operation, handle, PSA_ALG_CMAC ) );
PSA_ASSERT( psa_mac_abort( &mac_operation ) );
SMOKE_ASSERT( psa_mac_verify_setup( &mac_operation, handle,
PSA_ALG_HMAC( PSA_ALG_SHA_256 ) ) );
PSA_ASSERT( psa_mac_abort( &mac_operation ) );
SMOKE_ASSERT( psa_cipher_encrypt_setup( &cipher_operation, handle,
PSA_ALG_CTR ) );
PSA_ASSERT( psa_cipher_abort( &cipher_operation ) );
SMOKE_ASSERT( psa_cipher_decrypt_setup( &cipher_operation, handle,
PSA_ALG_CTR ) );
PSA_ASSERT( psa_cipher_abort( &cipher_operation ) );
SMOKE_ASSERT( psa_aead_encrypt( handle, PSA_ALG_CCM,
buffer, sizeof( buffer ),
NULL, 0,
buffer, sizeof( buffer),
buffer, sizeof( buffer), &length ) );
SMOKE_ASSERT( psa_aead_decrypt( handle, PSA_ALG_CCM,
buffer, sizeof( buffer ),
NULL, 0,
buffer, sizeof( buffer),
buffer, sizeof( buffer), &length ) );
SMOKE_ASSERT( psa_asymmetric_sign( handle, PSA_ALG_ECDSA_ANY,
buffer, 32,
buffer, sizeof( buffer ), &length ) );
SMOKE_ASSERT( psa_asymmetric_verify( handle, PSA_ALG_ECDSA_ANY,
buffer, 32,
buffer, sizeof( buffer ) ) );
SMOKE_ASSERT( psa_asymmetric_encrypt( handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
buffer, 10, NULL, 0,
buffer, sizeof( buffer ), &length ) );
SMOKE_ASSERT( psa_asymmetric_decrypt( handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
buffer, sizeof( buffer ), NULL, 0,
buffer, sizeof( buffer ), &length ) );
#if defined(MBEDTLS_SHA256_C)
/* Try the key in a plain key derivation. */
PSA_ASSERT( psa_key_derivation_setup( &derivation_operation,
PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ) );
PSA_ASSERT( psa_key_derivation_input_bytes( &derivation_operation,
PSA_KEY_DERIVATION_INPUT_SALT,
NULL, 0 ) );
SMOKE_ASSERT( psa_key_derivation_input_key( &derivation_operation,
PSA_KEY_DERIVATION_INPUT_SECRET,
handle ) );
PSA_ASSERT( psa_key_derivation_abort( &derivation_operation ) );
/* If the key is asymmetric, try it in a key agreement, both as
* part of a derivation operation and standalone. */
if( psa_export_public_key( handle, buffer, sizeof( buffer ), &length ) ==
PSA_SUCCESS )
{
psa_algorithm_t alg =
PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH,
PSA_ALG_HKDF( PSA_ALG_SHA_256 ) );
PSA_ASSERT( psa_key_derivation_setup( &derivation_operation, alg ) );
PSA_ASSERT( psa_key_derivation_input_bytes(
&derivation_operation, PSA_KEY_DERIVATION_INPUT_SALT,
NULL, 0 ) );
SMOKE_ASSERT( psa_key_derivation_key_agreement(
&derivation_operation,
PSA_KEY_DERIVATION_INPUT_SECRET,
handle, buffer, length ) );
PSA_ASSERT( psa_key_derivation_abort( &derivation_operation ) );
SMOKE_ASSERT( psa_raw_key_agreement(
alg, handle, buffer, length,
buffer, sizeof( buffer ), &length ) );
}
#endif /* MBEDTLS_SHA256_C */
ok = 1;
exit:
psa_reset_key_attributes( &attributes );
return( ok );
}
#define MAX_KEY_ID_FOR_TEST 10
static void psa_purge_storage( void )
{
psa_key_id_t id;
psa_key_lifetime_t lifetime;
/* The tests may have potentially created key ids from 1 to
* MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
* 0, which file-based storage uses as a temporary file. */
for( id = 0; id <= MAX_KEY_ID_FOR_TEST; id++ )
psa_destroy_persistent_key( id );
/* Purge the transaction file. */
psa_crypto_stop_transaction( );
/* Purge driver persistent data. */
for( lifetime = 0; lifetime < PSA_MAX_SE_LIFETIME; lifetime++ )
psa_destroy_se_persistent_data( lifetime );
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@ -78,3 +396,164 @@ exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void key_creation_import_export( int min_slot, int restart )
{
psa_drv_se_t driver;
psa_drv_se_key_management_t key_management;
psa_key_lifetime_t lifetime = 2;
psa_key_id_t id = 1;
psa_key_handle_t handle = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
uint8_t exported[sizeof( key_material )];
size_t exported_length;
memset( &driver, 0, sizeof( driver ) );
memset( &key_management, 0, sizeof( key_management ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
driver.key_management = &key_management;
driver.persistent_data_size = sizeof( ram_slot_usage_t );
key_management.p_allocate = ram_allocate;
key_management.p_import = ram_import;
key_management.p_destroy = ram_destroy;
key_management.p_export = ram_export;
ram_min_slot = min_slot;
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
/* Create a key. */
psa_set_key_id( &attributes, id );
psa_set_key_lifetime( &attributes, lifetime );
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
PSA_ASSERT( psa_import_key( &attributes,
key_material, sizeof( key_material ),
&handle ) );
/* Maybe restart, to check that the information is saved correctly. */
if( restart )
{
mbedtls_psa_crypto_free( );
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
PSA_ASSERT( psa_open_key( id, &handle ) );
}
/* Test that the key was created in the expected slot. */
TEST_ASSERT( ram_slots[min_slot].type == PSA_KEY_TYPE_RAW_DATA );
PSA_ASSERT( psa_export_key( handle,
exported, sizeof( exported ),
&exported_length ) );
ASSERT_COMPARE( key_material, sizeof( key_material ),
exported, exported_length );
PSA_ASSERT( psa_destroy_key( handle ) );
/* Test that the key has been erased from the designated slot. */
TEST_ASSERT( ram_slots[min_slot].type == 0 );
exit:
PSA_DONE( );
ram_slots_reset( );
psa_purge_storage( );
}
/* END_CASE */
/* BEGIN_CASE */
void key_creation_smoke( int type_arg, int alg_arg,
data_t *key_material )
{
psa_key_type_t type = type_arg;
psa_algorithm_t alg = alg_arg;
psa_drv_se_t driver;
psa_drv_se_key_management_t key_management;
psa_key_lifetime_t lifetime = 2;
psa_key_id_t id = 1;
psa_key_handle_t handle = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
memset( &driver, 0, sizeof( driver ) );
memset( &key_management, 0, sizeof( key_management ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
driver.key_management = &key_management;
driver.persistent_data_size = sizeof( psa_key_slot_number_t );
key_management.p_allocate = counter_allocate;
key_management.p_import = null_import;
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
/* Create a key. */
psa_set_key_id( &attributes, id );
psa_set_key_lifetime( &attributes, lifetime );
psa_set_key_usage_flags( &attributes,
PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY |
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT |
PSA_KEY_USAGE_EXPORT );
psa_set_key_algorithm( &attributes, alg );
psa_set_key_type( &attributes, type );
PSA_ASSERT( psa_import_key( &attributes,
key_material->x, key_material->len,
&handle ) );
/* Do stuff with the key. */
if( ! smoke_test_key( handle ) )
goto exit;
/* Restart and try again. */
mbedtls_psa_crypto_free( );
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
PSA_ASSERT( psa_open_key( id, &handle ) );
if( ! smoke_test_key( handle ) )
goto exit;
/* We're done. */
PSA_ASSERT( psa_destroy_key( handle ) );
exit:
PSA_DONE( );
ram_slots_reset( );
psa_purge_storage( );
}
/* END_CASE */
/* BEGIN_CASE */
void generate_key_not_supported( int type_arg, int bits_arg )
{
psa_key_type_t type = type_arg;
size_t bits = bits_arg;
psa_drv_se_t driver;
psa_drv_se_key_management_t key_management;
psa_key_lifetime_t lifetime = 2;
psa_key_id_t id = 1;
psa_key_handle_t handle = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
memset( &driver, 0, sizeof( driver ) );
memset( &key_management, 0, sizeof( key_management ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
driver.key_management = &key_management;
driver.persistent_data_size = sizeof( psa_key_slot_number_t );
key_management.p_allocate = counter_allocate;
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
psa_set_key_id( &attributes, id );
psa_set_key_lifetime( &attributes, lifetime );
psa_set_key_type( &attributes, type );
psa_set_key_bits( &attributes, bits );
TEST_EQUAL( psa_generate_key( &attributes, &handle ),
PSA_ERROR_NOT_SUPPORTED );
exit:
PSA_DONE( );
ram_slots_reset( );
psa_purge_storage( );
}
/* END_CASE */