Incremental/partial initialization of a Crypto implementation
athoelke opened this issue · comments
psa_crypto_init()
is allowed to, and even encouraged to, initialize the RNG. This allows many implementations to provide a RNG that will never fail. (Implementations that comply to some security standards will still need to fail RNG calls if the entropy source fails, but a CSPRNG that has been seeded once can be good forever under reasonable security requirements.)
This is a problem on systems that don't have an entropy source available, or where the entropy source is not yet available at the time the application wants to call psa_crypto_init()
. The typical scenario would be a device or an application that only wants to calculate hashes and verify signatures, for example a bootloader.
An application that only wants to calculate hashes might get away with insisting that the implementation accepts psa_hash_xxx()
calls before psa_crypto_init()
, although this is strict non-portable. An application that wants to verify signatures needs the keystore to be available, and it's less reasonable to require this to happen without psa_crypto_init()
. And even hash drivers may need some initialization. And client-server implementations may need psa_crypto_init()
to establish the communication between the client and the server.
There are use cases for doing a partial initialization of the PSA crypto subsystem: initialize basic functionality, initialize drivers, maybe initialize the key store, but do not initialize the RNG. This behavior is currently implementation-specific, but it makes sense to standardize it.
The following API definition is based on the current PR proposal for Mbed-TLS: Mbed-TLS/mbedtls#6636.
Proposed API
psa_crypto_init
(function)
Amend the description to also refer to the fine-grained initialization control provided by psa_crypto_init_subsystem()
.
psa_crypto_subsystem_t
(type)
The designation of a subsystem of the PSA Crypto implementation.
typedef uint32_t psa_crypto_subsystem_t;
Value of this type are masks of PSA_CRYPTO_SUBSYSTEM_xxx
constants.
PSA_CRYPTO_SUBSYSTEM_COMMUNICATION
(macro)
Crypto subsystem identifier for the communication with the server, if this is a client that communicates with a server where the key store is located.
#define PSA_CRYPTO_SUBSYSTEM_COMMUNICATION /* implementation-defined value */
In a client-server implementation, this subsystem is necessary before any API function other than library initialization, deinitialization and functions accessing local data structures such as key attributes.
In a library implementation, initializing this subsystem does nothing and succeeds.
PSA_CRYPTO_SUBSYSTEM_KEYS
(macro)
Crypto subsystem identifier for the key store in memory.
#define PSA_CRYPTO_SUBSYSTEM_KEYS /* implementation-defined value */
Initializing this subsystem allows creating, accessing and destroying volatile keys in the default location, i.e. keys with the lifetime PSA_KEY_LIFETIME_VOLATILE
.
Persistent keys also require PSA_CRYPTO_SUBSYSTEM_STORAGE
. Keys in other locations also require PSA_CRYPTO_SUBSYSTEM_SECURE_ELEMENTS
.
PSA_CRYPTO_SUBSYSTEM_STORAGE
(macro)
Crypto subsystem identifier for access to keys in storage.
#define PSA_CRYPTO_SUBSYSTEM_STORAGE /* implementation-defined value */
Initializing this subsystem as well as PSA_CRYPTO_SUBSYSTEM_KEYS
allows creating, accessing and destroying persistent keys.
Persistent keys in secure elements also require PSA_CRYPTO_SUBSYSTEM_SECURE_ELEMENTS
.
PSA_CRYPTO_SUBSYSTEM_ACCELERATORS
(macro)
Crypto subsystem identifier for accelerator drivers.
#define PSA_CRYPTO_SUBSYSTEM_ACCELERATORS /* implementation-defined value */
Initializing this subsystem calls the initialization entry points of all registered accelerator drivers.
Initializing this subsystem allows cryptographic operations that are implemented via an accelerator driver.
PSA_CRYPTO_SUBSYSTEM_SECURE_ELEMENTS
(macro)
Crypto subsystem identifier for secure element drivers.
#define PSA_CRYPTO_SUBSYSTEM_SECURE_ELEMENTS /* implementation-defined value */
Initializing this subsystem calls the initialization entry points of all registered secure element drivers.
Initializing this subsystem as well as PSA_CRYPTO_SUBSYSTEM_KEYS
allows creating, accessing and destroying keys in a secure element (i.e. keys whose location is not PSA_KEY_LOCATION_LOCAL_STORAGE
).
PSA_CRYPTO_SUBSYSTEM_RANDOM
(macro)
Crypto subsystem identifier for the random generator.
#define PSA_CRYPTO_SUBSYSTEM_RANDOM /* implementation-defined value */
Initializing this subsystem initializes all registered entropy drivers and accesses the registered entropy sources.
Initializing this subsystem is necessary for psa_generate_random()
, psa_generate_key()
, as well as some operations using private or secret keys. Only the following operations are guaranteed not to require this subsystem:
- hash operations;
- signature verification operations.
Note |
---|
Currently, symmetric decryption (authenticated or not) and MAC operations do not require the random generator. This may change in future versions of the library or when the operations are performed by a driver. |
PSA_CRYPTO_SUBSYSTEM_BUILTIN_KEYS
(macro)
Crypto subsystem identifier for access to built-in keys.
#define PSA_CRYPTO_SUBSYSTEM_BUILTIN_KEYS /* implementation-defined value */
Initializing this subsystem as well as PSA_CRYPTO_SUBSYSTEM_KEYS
allows access to built-in keys.
psa_crypto_init_subsystem
(function)
Partial library initialization.
psa_status_t psa_crypto_init_subsystem(psa_crypto_subsystem_t subsystem);
Parameters | |
---|---|
subsystem |
The subsystem, or set of subsystems, to initialize. This must be one of the PSA_CRYPTO_SUBSYSTEM_xxx values, or a bitwise-or of them. |
Returns: psa_status_t |
---|
PSA_SUCCESS |
PSA_ERROR_INSUFFICIENT_MEMORY |
PSA_ERROR_INSUFFICIENT_STORAGE |
PSA_ERROR_COMMUNICATION_FAILURE |
PSA_ERROR_HARDWARE_FAILURE |
PSA_ERROR_CORRUPTION_DETECTED |
PSA_ERROR_INSUFFICIENT_ENTROPY |
PSA_ERROR_STORAGE_FAILURE |
PSA_ERROR_DATA_INVALID |
PSA_ERROR_DATA_CORRUPT |
Description
Applications may call this function on the same subsystem more than once. Once a call succeeds, subsequent calls with the same subsystem are guaranteed to succeed.
Initializing a subsystem may initialize other subsystems if the implementations needs them internally. For example, in a typical client-server implementation, PSA_CRYPTO_SUBSYSTEM_COMMUNICATION
is required for all other subsystems, and therefore initializing any other subsystem also initializes PSA_CRYPTO_SUBSYSTEM_COMMUNICATION
.
Calling psa_crypto_init()
is equivalent to calling psa_crypto_init_subsystem()
on all the available subsystems.
Note |
---|
You can initialize multiple subsystems in the same call by passing a bitwise-or of PSA_CRYPTO_SUBSYSTEM_xxx values. If the initialization of one subsystem fails, it is unspecified whether other requested subsystems are initialized or not. |