-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incremental/partial initialization of a Crypto implementation #16
Comments
Working through the proposal to construct a draft PR, I notice a handful of issues that are worth resolving:
|
Almost all function calls can return
With the addition of
My current thinking is to do (2). |
I think there are two plausible choices here. One is to make it entirely implementation-defined. The other is what I made a guarantee in Mbed TLS, which is that you can verify a signature before randomness is available. The second choice removes doubt that in a bootloader, you can verify the signature of the next bit (which may include drivers for other mechanisms).
These are storage-related failures. They can happen if a driver stores persistent data which it reads during initialization, or if there is a secure element with key storage that requires transaction recovery during startup. I think they should be added to
My thinking was: if you're requesting a specific feature, you really need the implementation to support it. But that's in terms of what's available to the application, not in terms of what the implementation does internally. For example, To avoid requesting features that are not supported by the implementation, you can request one feature at a time and ignore failures (a failure of partial initialization leaves the previously-initialized subsystems available). Also, we could standardize (TL,DR: leaning towards b.)
We need to describe somewhere what you can do with various subsystems initialized. I don't have a strong opinion as to where. To some extent, this will be implementation-defined: for example only algorithms that require randomness are guaranteed to fail if RANDOM isn't initialized (and even then, an implementation may initialize RANDOM implicitly, for example a client in a client-server implementation will typically have everything available as soon as COMMUNICATION is established). |
I see that, and this is already reflected in the existing specification text in the 'Note' here regarding initialization of an RNG. I think this use case is important enough to keep a specification-level requirement for hashes and signature verification not requiring the RANDOM subsystem.
Do we want applications that want to use this facility to need to write code like this:
... just in case they are compiled against a client-server implementation, and a non-client-server implementation is permitted to report any of SUCCESS, INVALID_ARGUMENT, or NOT_SUPPORTED in this situation? I think I am leaning toward an in-between approach:
I have been reworking the text that is currently in the description of |
Yes, that was my intent. For example COMMUNICATION is effectively always enabled in a non-client-server implementation, and init(COMMUNICATION) should always succeed. |
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 beforepsa_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 withoutpsa_crypto_init()
. And even hash drivers may need some initialization. And client-server implementations may needpsa_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.
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.
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.
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 requirePSA_CRYPTO_SUBSYSTEM_SECURE_ELEMENTS
.PSA_CRYPTO_SUBSYSTEM_STORAGE
(macro)Crypto subsystem identifier for access to keys in storage.
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.
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.
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 notPSA_KEY_LOCATION_LOCAL_STORAGE
).PSA_CRYPTO_SUBSYSTEM_RANDOM
(macro)Crypto subsystem identifier for the random generator.
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:PSA_CRYPTO_SUBSYSTEM_BUILTIN_KEYS
(macro)Crypto subsystem identifier for access to built-in keys.
Initializing this subsystem as well as
PSA_CRYPTO_SUBSYSTEM_KEYS
allows access to built-in keys.psa_crypto_init_subsystem
(function)Partial library initialization.
subsystem
PSA_CRYPTO_SUBSYSTEM_xxx
values, or a bitwise-or of them.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 initializesPSA_CRYPTO_SUBSYSTEM_COMMUNICATION
.Calling
psa_crypto_init()
is equivalent to callingpsa_crypto_init_subsystem()
on all the available subsystems.PSA_CRYPTO_SUBSYSTEM_xxx
values. If the initialization of one subsystem fails, it is unspecified whether other requested subsystems are initialized or not.The text was updated successfully, but these errors were encountered: