From a2b41598d67b3e318bf5e678dfeb99611c88ed59 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 24 Jan 2022 14:52:59 +0100 Subject: [PATCH 01/24] Draft specification for key derivation Pass all the initial inputs in a single structure. It's impossible to pass the inputs as soon as the application makes them available because the core cannot know which driver to call until it receives the SECRET input. Do support hiding the key material inside a secure element if the relevant driver has all the requisite entry points. Do cooked key derivation (i.e. derivation of non-raw keys) and key agreement separately. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 267 ++++++++++++++++++++++++-- 1 file changed, 250 insertions(+), 17 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 125a415f4..c12e01065 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -297,25 +297,251 @@ TODO TODO -#### Operation family `"key_derivation"` +### Driver entry points for key derivation -This family requires the following type and entry points: +Key derivation is more complex than other multipart operations due to the multiplicity of inputs and outputs, to the fact that multiple drivers can be involved (key agreement and subsequent key derivation accelerator, opaque driver for the secret key and for derived keys), and because the involvement of an opaque driver cannot be determined as soon as the operation is set up (since `psa_key_derivation_setup()` does not determine the key input). -* Type `"key_derivation_operation_t"`: the type of a key derivation operation context. -* `"key_derivation_setup"`: called by `psa_key_derivation_setup()`. -* `"key_derivation_set_capacity"`: called by `psa_key_derivation_set_capacity()`. The core will always enforce the capacity, therefore this function does not need to do anything for algorithms where the output stream only depends on the effective generated length and not on the capacity. -* `"key_derivation_input_bytes"`: called by `psa_key_derivation_input_bytes()` and `psa_key_derivation_input_key()`. For transparent drivers, when processing a call to `psa_key_derivation_input_key()`, the core always calls the applicable driver's `"key_derivation_input_bytes"` entry point. -* `"key_derivation_input_integer"`: called by `psa_key_derivation_input_integer()`. -* `"key_derivation_input_key"` (opaque drivers only) -* `"key_derivation_output_bytes"`: called by `psa_key_derivation_output_bytes()`; also by `psa_key_derivation_output_key()` for transparent drivers. -* `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()` for transparent drivers when deriving an asymmetric key pair, and also for opaque drivers. -* `"key_derivation_verify_bytes"` (opaque drivers only). -* `"key_derivation_verify_key"` (opaque drivers only). -* `"key_derivation_abort"`: called by all key derivation functions of the PSA Cryptography API. +#### Key derivation driver dispatch logic -TODO: key input and output for opaque drivers; deterministic key generation for transparent drivers +The core decides whether to dispatch a key derivation operation to a driver based on the location of the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. -TODO +1. If this step is passed via `psa_key_derivation_input_key()` for a key in a secure element: + * If the driver for this secure element implements the `"key_derivation"` family for the specified key type and algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. + * Otherwise the core calls the secure element driver's [`"export_key"`](#key-management-with-opaque-drivers) entry point. +2. Otherwise ([or on fallback?](#fallback-for-key-derivation-in-opaque-drivers)), if there is a transparent driver for the specified key type and algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. +3. Otherwise, or on fallback, the core uses its built-in implementation. + +#### Summary of entry points for the operation family `"key_derivation"` + +A key derivation driver has the following entry points: + +* `"key_derivation_setup"` (mandatory): always the first entry point to be called. This entry point provides the [initial inputs](#key-derivation-driver-initial-inputs). See [“Key derivation driver setup”](#key-derivation-driver-setup). +* `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver extra inputs”](#key-derivation-driver-inputs). +* `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). +* `"key_derivation_derive_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). +* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). +* `"key_derivation_abort"` (mandatory): always the last entry point to be called. + +For naming purposes, here and in the following subsection, this specification takes the example of a driver with the prefix `"acme"` that implements the `"key_derivation"` entry point family with a capability that does not use the `"names"` property to declare different type and entry point names. Such a driver must implement the following type and functions, as well as the entry points listed above and described in the following subsections: +``` +typedef ... acme_key_derivation_operation_t; +psa_status_t acme_hash_abort(acme_key_derivation_operation_t *operation); +``` + +#### Key derivation driver initial inputs + +The core conveys the initial inputs for a key derivation via an opaque data structure of type `psa_crypto_driver_key_derivation_inputs_t`. + +``` +typedef ... psa_crypto_driver_key_derivation_inputs_t; // implementation-specific type +``` + +A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its content using the following functions. + +``` +psa_status_t psa_crypto_driver_key_derivation_get_input_size( + const psa_crypto_driver_key_derivation_inputs_t *inputs, + psa_key_derivation_step_t step, + size_t *size); +psa_status_t psa_crypto_driver_key_derivation_get_input_bytes( + const psa_crypto_driver_key_derivation_inputs_t *inputs, + psa_key_derivation_step_t step, + uint8_t *output, size_t output_size, size_t *output_length); +psa_status_t psa_crypto_driver_key_derivation_get_input_key( + const psa_crypto_driver_key_derivation_inputs_t *inputs, + psa_key_derivation_step_t step, + uint8_t** p_key_buffer, size_t *key_buffer_size); +psa_status_t psa_crypto_driver_key_derivation_get_input_integer( + const psa_crypto_driver_key_derivation_inputs_t *inputs, + psa_key_derivation_step_t step, + uint64_t *value); +``` + +These functions take the following parameters: + +* The first parameter `inputs` must be a pointer passed by the core to a key derivation driver setup entry points which has not returned yet. +* The `step` parameter indicates the input step whose content the driver wants to retrieve. The type of the input step must be compatible with the function: + * `psa_crypto_driver_key_derivation_get_input_integer` for integer inputs (steps that the application passes with `psa_key_derivation_input_integer()`). + * `psa_crypto_driver_key_derivation_get_input_size` and `psa_crypto_driver_key_derivation_get_input_bytes` for data inputs (steps that the application passes with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`, excluding key inputs from the same secure element). + * `psa_crypto_driver_key_derivation_get_input_key` for key inputs (steps that the application passes with `psa_key_derivation_input_key()`, only for secure element drivers receiving a key from the same secure element). +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_size`, the core sets `*size` to the size of the desired input in bytes. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `output` with the desired input and sets `*output_length` to *N*, where *N* is the length of the input in bytes. The value of `output_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_key`, the core sets `*key_buffer` to a pointer to a buffer containing the key context and `*key_buffer_size` to the size of the key context in bytes. The key context buffer remains valid for the duration of the driver entry point. If the driver needs to access the key context after the current entry point returns, it must make a copy of the key context. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_integer`, the core sets `*value` to the value of the desired input. + +These functions can return the following statuses: + +* `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter. +* `PSA_ERROR_INSUFFICIENT_DATA`: the driver called `psa_crypto_driver_key_derivation_get_input_key` on a data input step which is available as a bytes input, or the driver called ``psa_crypto_driver_key_derivation_get_input_size` or `psa_crypto_driver_key_derivation_get_input_bytes` on a data input step which is available as a key input. This is not a fatal error and the driver is expected to call the appropriate function(s) instead. +* `PSA_ERROR_DOES_NOT_EXIST`: the input step, is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-extra-inputs). +* `PSA_ERROR_INVALID_ARGUMENT`: the input step is not valid for this particular algorithm, or the type of the input step is not suitable for this function. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. +* `PSA_ERROR_BUFFER_TOO_SMALL` (`psa_crypto_driver_key_derivation_get_input_bytes` only): the output buffer is too small. This is not a fatal error and the driver can, for example, subsequently call the same function again with a larger buffer. Call `psa_crypto_driver_key_derivation_get_input_size` to obtain the required size. +* The core may return other errors such as `PSA_ERROR_CORRUPTION_DETECTED` or `PSA_ERROR_COMMUNICATION_FAILURE` to convey implementation-specific error conditions. Portable drivers should treat such conditions as fatal errors. + +#### Key derivation driver setup + +A key derivation driver must implement the following entry point: +``` +psa_status_t acme_key_derivation_setup( + acme_key_derivation_operation_t *operation, + psa_algorithm_t alg, + const psa_crypto_driver_key_derivation_inputs_t *inputs); +``` + +* `operation` is a zero-initialized operation object. +* `alg` is the algorithm for the key derivation operation. It does not include a key agreement component. +* `inputs` is an opaque pointer to the [initial inputs](#key-derivation-driver-initial-inputs) for the key derivation. + +The following process describes how a driver is expected to retrieve the inputs of the key derivation. For each input step that is valid for the algorithm `alg` and is not a [long input](#key-derivation-driver-long-inputs): + +* If the step is a data step and the driver is an opaque driver, call `psa_crypto_driver_key_derivation_get_input_key`. This may either succeed or fail with `PSA_ERROR_INSUFFICIENT_DATA` depending on whether the input comes from the same secure element or not. Note that the driver obtains a pointer key context which only remains valid until the end of the call to the setup entry point. If the driver needs the context in subsequent steps of the operation, it must make a copy. +* If the step is a data step and the driver is a transparent driver, or if `psa_crypto_driver_key_derivation_get_input_key` returned `PSA_ERROR_INSUFFICIENT_DATA`, call `psa_crypto_driver_key_derivation_get_input_size` to retrieve the size of the input, then call `psa_crypto_driver_key_derivation_get_input_bytes` with a large enough buffer to retrieve the input data. +* If the step is an integer, call `psa_crypto_driver_key_derivation_get_input_integer`. + +#### Key derivation driver long inputs + +Some key derivation algorithms take long inputs which it would not be practical to pass in the [initial inputs](#key-derivation-driver-initial-inputs). A driver that implements a key derivation algorithm that takes such inputs must provide a `"key_derivation_input_step"` entry point. The core calls this input step for all the long inputs, in an unspecified order. Long input steps may be fragmented into multiple calls of `psa_key_derivation_input_bytes()`, and the core may reassemble or refragment those fragments before passing them to the driver. + +``` +psa_status_t acme_key_derivation_input_step( + acme_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *input, size_t input_length); +``` + +At the time of writing, no standard key derivation algorithm has long inputs. It is likely that such algorithms will be added in the future. + +#### Key derivation driver operation capacity + +The core keeps track of an operation's capacity and enforces it. The core guarantees that it will not request output beyond the capacity of the operation, with one exception: opaque drivers that support `"key_derivation_derive_key"` for key types where the derived key material is not a direct copy of the key derivation's output stream. + +Such drivers must enforce the capacity limitation and must return `PSA_ERROR_INSUFFICIENT_CAPACITY` from any output request that exceeds the operation's capacity. Such drivers must provide the following entry point: +``` +psa_status_t acme_key_derivation_set_capacity( + acme_key_derivation_operation_t *operation, + size_t capacity); +``` +`capacity` is guaranteed to be less or equal to any value previously set through this entry point, and is guaraneed not to be `PSA_KEY_DERIVATION_UNLIMITED_CAPACITY`. + +If this entry point has not been called, the operation has an unlimited capacity. + +#### Key derivation driver outputs + +A key derivation driver must provide the following entry point: +``` +psa_status_t acme_key_derivation_output_bytes( + acme_key_derivation_operation_t *operation, + uint8_t *output, size_t length); +``` + +An opaque key derivation driver may provide the following entry points: +``` +psa_status_t acme_key_derivation_output_key( + const psa_key_attributes_t *attributes, + acme_key_derivation_operation_t *operation, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); +psa_status_t acme_key_derivation_verify_bytes( + acme_key_derivation_operation_t *operation, + const uint8_t *expected output, size_t length); +psa_status_t acme_key_derivation_verify_key( + acme_key_derivation_operation_t *operation, + uint8_t *key_buffer, size_t key_buffer_size); +``` + +The core calls a key derivation driver's output entry point when the application calls `psa_key_derivation_output_bytes()`, `psa_key_derivation_output_key()`, `psa_key_derivation_verify_bytes()` or `psa_key_derivation_verify_key()`. + +If the key derivation's `PSA_KEY_DERIVATION_INPUT_SECRET` input is in a secure element and the derivation operation is handled by that secure element, the core performs the following steps: + +1. For a call to `psa_key_derivation_output_key()` where the derived key is in the same secure element, if the driver has an `"key_derivation_output_key"` entry point, call that entry point. If the driver has no such entry point, or if that entry point returns `PSA_ERROR_NOT_SUPPORTED`, continue with the following steps, otherwise stop. +1. For a call to `psa_key_derivation_output_key()`, if the driver's capabilities indicate that its `"import_key"` entry point does not support the derived key, stop and return `PSA_ERROR_NOT_SUPPORTED`. +1. For a call to `psa_key_derivation_verify_key()`, if the driver has a `"key_derivation_verify_key"` entry point, call it and stop. +1. For a call to `psa_key_derivation_verify_key()` or `psa_key_derivation_verify_bytes()`, if the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's `"export_key"` entry point on the key object that contains the expected value, call the `"key_derivation_verify_bytes"` entry point on the exported material, and stop. +1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a non-raw key or if the output size exceeds some implementation limit. + +If the key derivation operation is not handled by an opaque driver as described above, the core calls the `"key_derivation_output_bytes"` from the applicable transparent driver (or multiple drivers in succession if fallback applies). In some cases, the driver then calls additional entry points in the same or another driver: + +* For a call to `psa_key_derivation_output_key()` for some key types, the core calls a transparent driver's `"derive_key"` entry point. See [“Transparent cooked key derivation”](#transparent-cooked-key-derivation). +* For a call to `psa_key_derivation_output_key()` where the derived key is in a secure element, call that secure element driver's `"import_key"` entry point. + +#### Transparent cooked key derivation + +Key derivation is said to be *raw* for some key types, where the key material of a derived (8×*n*)-bit key consists of the next *n* bytes of output from the key derivation, and *cooked* otherwise. When deriving a raw key, the core only calls the driver's `"output_bytes"` entry point, except when deriving a key entirely inside a secure element as described in [“Key derivation driver outputs”](#key-derivation-driver-outputs). When deriving a cooked key, the core calls a transparent driver's `"derive_key"` entry point if available. + +A capability for cooked key derivation contains the following properties (this is not a subset of [the usual entry point properties](#capability-syntax)): + +* `"entry_points"` (mandatory, list of strings). Must be `["derive_key"]`. +* `"derived_types"` (mandatory, list of strings). Each element is a [key type specification](#key-type-specifications). This capability only applies when deriving a key of the specified type. +* `"derived_sizes"` (optional, list of integers). Each element is a [key type specification](#key-type-specifications). This capability only applies when deriving a key of the specified sizes, in bits. If absent, this capability applies to all sizes for the specified types. +* `"memory"` (optional, boolean). If present and true, the driver must define a type `"derive_key_memory_t"` and the core will allocate an object of that type as specified below. +* `"names"` (optional, object). A mapping from entry point names to C function and type names, as usual. +* `"fallback"` (optional, boolean). If present and true, the driver may return `PSA_ERROR_NOT_SUPPORTED` if it only partially supports the specified mechanism, as usual. + +A transparent driver with the prefix `"acme"` that implements cooked key derivation must provide the following type and function: + +``` +typedef ... acme_derive_key_memory_t; // only if the "memory" property is true +psa_status_t acme_derive_key( + const psa_key_attributes_t *attributes, + const uint8_t *input, size_t input_length, + acme_derive_key_memory_t *memory, // if the "memory" property is false: void* + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); +``` + +* `attributes` contains the attributes of the desired key. Note that only the key type and the bit-size are guaranteed to be set. +* `input` is a buffer of `input_length` bytes which contains the raw key stream, i.e. the data that `psa_key_derivation_output_bytes()` would return. +* If `"memory"` property in the driver capability is true, `memory` is a data structure that the driver may use to store data between successive calls of the `"derive_key"` entry point to derive the same key. If the `"memory"` property is false or absent, the `memory` parameter is a null pointer. +* `key_buffer` is a buffer for the output material. Its size is `key_buffer_size` bytes. +* On success, `*key_buffer_length` must contain the number of bytes written to `key_buffer`. + +This entry point may return the following statuses: + +* `PSA_SUCCESS`: a key was derived successfully. The driver has placed representation of the key is in `key_buffer`. +* `PSA_ERROR_NOT_SUPPORTED` (for the first call only) (only if fallback is enabled): the driver cannot fulfill this request, but a fallback driver might. +* `PSA_ERROR_INSUFFICIENT_DATA`: the core must call the `"derive_key"` entry point again with the same `memory` object and with subsequent data from the key stream. +* Any other error is a fatal error. + +The core calls the `"derive_key"` entry point in a loop until it returns a status other than `PSA_ERROR_INSUFFICIENT_DATA`. Each call has a successive fragment of the key stream. The `memory` object is guaranteed to be the same for successive calls, but note that its address may change between calls. Before the first call, `*memory` is initialized to all-bits-zero. + +For standard key types, the `"derive_key"` entry point is called with a certain input length as follows: + +* `PSA_KEY_TYPE_DES`: the length of the key. +* `PSA_KEY_TYPE_ECC_KEY_PAIR(…)`, `PSA_KEY_TYPE_DH_KEY_PAIR(…)`: *m* bytes, where the bit-size of the key *n* satisfies *m*-1 < 8×*n* ≤ *m*. +* `PSA_KEY_TYPE_RSA_KEY_PAIR`: an implementation-defined length. A future version of this specification may specify a length. +* Other key types: not applicable. + +#### Key agreement + +The core always decouples key agreement from symmetric key derivation. + +To implement a call to `psa_key_derivation_key_agreement()` where the private key is in a secure element that has a `"key_agreement_to_key"` entry point which is applicable for the given key type and algorithm, the core calls the secure element driver as follows: + +1. Call the `"key_agreement_to_key"` entry point to create a key object containing the shared secret. The key object is volatile and has the type `PSA_KEY_TYPE_DERIVE`. +2. Call the `"key_derivation_setup"` entry point, passing the resulting key object . +3. Perform the rest of the key derivation, up to and including the call to the `"key_derivation_abort"` entry point. +4. Call the `"destroy_key"` entry point to destroy the key containing the key object. + +In other cases, the core treats `psa_key_derivation_key_agreement()` as if it was a call to `psa_raw_key_agreement()` followed by a call to `psa_key_derivation_input_bytes()` on the shared secret. + +The entry points related to key agreement have the following prototypes for a driver with the prefix `"acme"`: +``` +psa_status_t acme_key_agreement(psa_algorithm_t alg, + const uint8_t *our_key_buffer, + size_t our_key_buffer_length, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); +psa_status_t acme_key_agreement_to_key(psa_algorithm_t alg, + const psa_key_attributes_t *attributes, + const uint8_t *our_key_buffer, + size_t our_key_buffer_length, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret_key_buffer, + size_t shared_secret_key_buffer_size, + size_t *shared_secret_key_buffer_length); +``` ### Driver entry points for key management @@ -336,8 +562,9 @@ psa_status_t acme_generate_key(const psa_key_attributes_t *attributes, size_t key_buffer_size, size_t *key_buffer_length); ``` +Additionally, opaque drivers can create keys through their [`"key_derivation_output_key"`](#key-derivation-driver-outputs) and [`"key_agreement_key"`](#key-agreement) entry points. Transparent drivers can create key material through their [`"derive_key"`](#transparent-cooked-key-derivation) entry point. -TODO: derivation, copy +TODO: copy * The key attributes (`attributes`) have the same semantics as in the PSA Cryptography application interface. * For the `"import_key"` entry point, the input in the `data` buffer is either the export format or an implementation-specific format that the core documents as an acceptable input format for `psa_import_key()`. @@ -660,7 +887,7 @@ If the key is stored in wrapped form outside the secure element, and the wrapped Opaque drivers may provide the following key management entry points: -* `"export_key"`: called by `psa_export_key()`, or by `psa_copy_key()` when copying a key from or to a different [location](#lifetimes-and-locations). +* `"export_key"`: called by `psa_export_key()`, or by `psa_copy_key()` when copying a key from or to a different [location](#lifetimes-and-locations), or [as a fallback for key derivation](#key-derivation-driver-dispatch-logic). * `"export_public_key"`: called by the core to obtain the public key of a key pair. The core may call this entry point at any time to obtain the public key, which can be for `psa_export_public_key()` but also at other times, including during a cryptographic operation that requires the public key such as a call to `psa_verify_message()` on a key pair object. * `"import_key"`: called by `psa_import_key()`, or by `psa_copy_key()` when copying a key from another location. * `"generate_key"`: called by `psa_generate_key()`. @@ -974,6 +1201,12 @@ An example use case for updating the persistent state at arbitrary times is to r `psa_crypto_driver_get_persistent_state` does not identify the calling driver, so the driver needs to remember which driver it's calling. This may require a thread-local variable in a multithreaded core. Is this ok? +#### Fallback for key derivation in opaque drivers + +Should [dispatch to an opaque driver](#key-derivation-driver-dispatch-logic) allow fallback, so that if `"key_derivation_setup"` returns `PSA_ERROR_NOT_SUPPORTED` then the core exports the key from the secure element instead? + +Should the ["`key_derivation_output_key`"](#key-derivation-driver-outputs) capability indicate which key types the driver can derive? How should fallback work? For example, consider a secure element that implements HMAC, HKDF and ECDSA, and that can derive an HMAC key from HKDF without exporting intermediate material but can only import or randomly generate ECC keys. How does this driver convey that it can't derive an ECC key with HKDF, but it can let the core do this and import the resulting key? + ### Randomness #### Input to `"add_entropy"` From 220bda7f76f04311aff19d5f066cbeb3590147b7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 25 Jan 2022 12:03:34 +0100 Subject: [PATCH 02/24] Rename a function parameter to avoid confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't use “output” for an input of the KDF. It's correct in context (it's the output of a function that copies the input of the KDF from core-owned memory to driver-owned memory) but confusing. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index c12e01065..e3ec0b19d 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -346,7 +346,7 @@ psa_status_t psa_crypto_driver_key_derivation_get_input_size( psa_status_t psa_crypto_driver_key_derivation_get_input_bytes( const psa_crypto_driver_key_derivation_inputs_t *inputs, psa_key_derivation_step_t step, - uint8_t *output, size_t output_size, size_t *output_length); + uint8_t *buffer, size_t buffer_size, size_t *buffer_length); psa_status_t psa_crypto_driver_key_derivation_get_input_key( const psa_crypto_driver_key_derivation_inputs_t *inputs, psa_key_derivation_step_t step, @@ -365,13 +365,13 @@ These functions take the following parameters: * `psa_crypto_driver_key_derivation_get_input_size` and `psa_crypto_driver_key_derivation_get_input_bytes` for data inputs (steps that the application passes with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`, excluding key inputs from the same secure element). * `psa_crypto_driver_key_derivation_get_input_key` for key inputs (steps that the application passes with `psa_key_derivation_input_key()`, only for secure element drivers receiving a key from the same secure element). * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_size`, the core sets `*size` to the size of the desired input in bytes. -* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `output` with the desired input and sets `*output_length` to *N*, where *N* is the length of the input in bytes. The value of `output_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `buffer` with the desired input and sets `*buffer_length` to *N*, where *N* is the length of the input in bytes. The value of `buffer_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_key`, the core sets `*key_buffer` to a pointer to a buffer containing the key context and `*key_buffer_size` to the size of the key context in bytes. The key context buffer remains valid for the duration of the driver entry point. If the driver needs to access the key context after the current entry point returns, it must make a copy of the key context. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_integer`, the core sets `*value` to the value of the desired input. These functions can return the following statuses: -* `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter. +* `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been writen to the applicable parameter (`buffer_length`, `key_buffer_size`). * `PSA_ERROR_INSUFFICIENT_DATA`: the driver called `psa_crypto_driver_key_derivation_get_input_key` on a data input step which is available as a bytes input, or the driver called ``psa_crypto_driver_key_derivation_get_input_size` or `psa_crypto_driver_key_derivation_get_input_bytes` on a data input step which is available as a key input. This is not a fatal error and the driver is expected to call the appropriate function(s) instead. * `PSA_ERROR_DOES_NOT_EXIST`: the input step, is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-extra-inputs). * `PSA_ERROR_INVALID_ARGUMENT`: the input step is not valid for this particular algorithm, or the type of the input step is not suitable for this function. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. From c2e29108f00550687694618e3ea9fe7177251fcb Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 3 Jun 2022 17:07:19 +0200 Subject: [PATCH 03/24] Fix internal links Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index e3ec0b19d..43586f397 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -316,7 +316,7 @@ The core decides whether to dispatch a key derivation operation to a driver base A key derivation driver has the following entry points: * `"key_derivation_setup"` (mandatory): always the first entry point to be called. This entry point provides the [initial inputs](#key-derivation-driver-initial-inputs). See [“Key derivation driver setup”](#key-derivation-driver-setup). -* `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver extra inputs”](#key-derivation-driver-inputs). +* `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). * `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_derive_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). @@ -373,7 +373,7 @@ These functions can return the following statuses: * `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been writen to the applicable parameter (`buffer_length`, `key_buffer_size`). * `PSA_ERROR_INSUFFICIENT_DATA`: the driver called `psa_crypto_driver_key_derivation_get_input_key` on a data input step which is available as a bytes input, or the driver called ``psa_crypto_driver_key_derivation_get_input_size` or `psa_crypto_driver_key_derivation_get_input_bytes` on a data input step which is available as a key input. This is not a fatal error and the driver is expected to call the appropriate function(s) instead. -* `PSA_ERROR_DOES_NOT_EXIST`: the input step, is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-extra-inputs). +* `PSA_ERROR_DOES_NOT_EXIST`: the input step, is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-long-inputs). * `PSA_ERROR_INVALID_ARGUMENT`: the input step is not valid for this particular algorithm, or the type of the input step is not suitable for this function. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. * `PSA_ERROR_BUFFER_TOO_SMALL` (`psa_crypto_driver_key_derivation_get_input_bytes` only): the output buffer is too small. This is not a fatal error and the driver can, for example, subsequently call the same function again with a larger buffer. Call `psa_crypto_driver_key_derivation_get_input_size` to obtain the required size. * The core may return other errors such as `PSA_ERROR_CORRUPTION_DETECTED` or `PSA_ERROR_COMMUNICATION_FAILURE` to convey implementation-specific error conditions. Portable drivers should treat such conditions as fatal errors. @@ -697,7 +697,7 @@ psa_status_t acme_import_key(const psa_key_attributes_t *attributes, This entry point has several roles: 1. Parse the key data in the input buffer `data`. The driver must support the export format for the key types that the entry point is declared for. It may support additional formats as specified in the description of [`psa_import_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_key) in the PSA Cryptography API specification. -2. Validate the key data. The necessary validation is described in the section [“Key validation with transparent drivers”](#key-validation-with-transparent-drivers) above. +2. Validate the key data. The necessary validation is described in the section [“Key validation”](#key-validation) above. 3. [Determine the key size](#key-size-determination-on-import) and output it through `*bits`. 4. Copy the validated key data from `data` to `key_buffer`. The output must be in the canonical format documented for [`psa_export_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_key) or [`psa_export_public_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_public_key), so if the input is not in this format, the entry point must convert it. From 1a5b83007c4c1dc6950941f7764c3adb18d208aa Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 3 Jun 2022 17:47:40 +0200 Subject: [PATCH 04/24] Fix typos and copypasta Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 43586f397..a0e995c76 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -325,7 +325,7 @@ A key derivation driver has the following entry points: For naming purposes, here and in the following subsection, this specification takes the example of a driver with the prefix `"acme"` that implements the `"key_derivation"` entry point family with a capability that does not use the `"names"` property to declare different type and entry point names. Such a driver must implement the following type and functions, as well as the entry points listed above and described in the following subsections: ``` typedef ... acme_key_derivation_operation_t; -psa_status_t acme_hash_abort(acme_key_derivation_operation_t *operation); +psa_status_t acme_key_derivation_abort(acme_key_derivation_operation_t *operation); ``` #### Key derivation driver initial inputs @@ -336,7 +336,7 @@ The core conveys the initial inputs for a key derivation via an opaque data stru typedef ... psa_crypto_driver_key_derivation_inputs_t; // implementation-specific type ``` -A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its content using the following functions. +A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents using the following functions. ``` psa_status_t psa_crypto_driver_key_derivation_get_input_size( @@ -359,7 +359,7 @@ psa_status_t psa_crypto_driver_key_derivation_get_input_integer( These functions take the following parameters: -* The first parameter `inputs` must be a pointer passed by the core to a key derivation driver setup entry points which has not returned yet. +* The first parameter `inputs` must be a pointer passed by the core to a key derivation driver setup entry point which has not returned yet. * The `step` parameter indicates the input step whose content the driver wants to retrieve. The type of the input step must be compatible with the function: * `psa_crypto_driver_key_derivation_get_input_integer` for integer inputs (steps that the application passes with `psa_key_derivation_input_integer()`). * `psa_crypto_driver_key_derivation_get_input_size` and `psa_crypto_driver_key_derivation_get_input_bytes` for data inputs (steps that the application passes with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`, excluding key inputs from the same secure element). @@ -373,7 +373,7 @@ These functions can return the following statuses: * `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been writen to the applicable parameter (`buffer_length`, `key_buffer_size`). * `PSA_ERROR_INSUFFICIENT_DATA`: the driver called `psa_crypto_driver_key_derivation_get_input_key` on a data input step which is available as a bytes input, or the driver called ``psa_crypto_driver_key_derivation_get_input_size` or `psa_crypto_driver_key_derivation_get_input_bytes` on a data input step which is available as a key input. This is not a fatal error and the driver is expected to call the appropriate function(s) instead. -* `PSA_ERROR_DOES_NOT_EXIST`: the input step, is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-long-inputs). +* `PSA_ERROR_DOES_NOT_EXIST`: the input step is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-long-inputs). * `PSA_ERROR_INVALID_ARGUMENT`: the input step is not valid for this particular algorithm, or the type of the input step is not suitable for this function. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. * `PSA_ERROR_BUFFER_TOO_SMALL` (`psa_crypto_driver_key_derivation_get_input_bytes` only): the output buffer is too small. This is not a fatal error and the driver can, for example, subsequently call the same function again with a larger buffer. Call `psa_crypto_driver_key_derivation_get_input_size` to obtain the required size. * The core may return other errors such as `PSA_ERROR_CORRUPTION_DETECTED` or `PSA_ERROR_COMMUNICATION_FAILURE` to convey implementation-specific error conditions. Portable drivers should treat such conditions as fatal errors. @@ -394,7 +394,7 @@ psa_status_t acme_key_derivation_setup( The following process describes how a driver is expected to retrieve the inputs of the key derivation. For each input step that is valid for the algorithm `alg` and is not a [long input](#key-derivation-driver-long-inputs): -* If the step is a data step and the driver is an opaque driver, call `psa_crypto_driver_key_derivation_get_input_key`. This may either succeed or fail with `PSA_ERROR_INSUFFICIENT_DATA` depending on whether the input comes from the same secure element or not. Note that the driver obtains a pointer key context which only remains valid until the end of the call to the setup entry point. If the driver needs the context in subsequent steps of the operation, it must make a copy. +* If the step is a data step and the driver is an opaque driver, call `psa_crypto_driver_key_derivation_get_input_key`. This may either succeed or fail with `PSA_ERROR_INSUFFICIENT_DATA` depending on whether the input comes from the same secure element or not. Note that the driver obtains a pointer to the [key context](#overview-of-driver-entry-points) which only remains valid until the end of the call to the setup entry point. If the driver needs the context in subsequent steps of the operation, it must make a copy. * If the step is a data step and the driver is a transparent driver, or if `psa_crypto_driver_key_derivation_get_input_key` returned `PSA_ERROR_INSUFFICIENT_DATA`, call `psa_crypto_driver_key_derivation_get_input_size` to retrieve the size of the input, then call `psa_crypto_driver_key_derivation_get_input_bytes` with a large enough buffer to retrieve the input data. * If the step is an integer, call `psa_crypto_driver_key_derivation_get_input_integer`. From 3fc9e04bc489b3fcaa8677a1d7add640c1b1e789 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 3 Jun 2022 17:48:46 +0200 Subject: [PATCH 05/24] Be more consistent with raw/cooked key derivation terminology Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index a0e995c76..d737b0d80 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -319,7 +319,7 @@ A key derivation driver has the following entry points: * `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). * `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_derive_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). -* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). +* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for “cooked”, i.e. non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). * `"key_derivation_abort"` (mandatory): always the last entry point to be called. For naming purposes, here and in the following subsection, this specification takes the example of a driver with the prefix `"acme"` that implements the `"key_derivation"` entry point family with a capability that does not use the `"names"` property to declare different type and entry point names. Such a driver must implement the following type and functions, as well as the entry points listed above and described in the following subsections: @@ -413,7 +413,7 @@ At the time of writing, no standard key derivation algorithm has long inputs. It #### Key derivation driver operation capacity -The core keeps track of an operation's capacity and enforces it. The core guarantees that it will not request output beyond the capacity of the operation, with one exception: opaque drivers that support `"key_derivation_derive_key"` for key types where the derived key material is not a direct copy of the key derivation's output stream. +The core keeps track of an operation's capacity and enforces it. The core guarantees that it will not request output beyond the capacity of the operation, with one exception: opaque drivers that support `"key_derivation_derive_key"` [cooked key types](#transparent-cooked-key-derivation), i.e. for key types where the derived key material is not a direct copy of the key derivation's output stream. Such drivers must enforce the capacity limitation and must return `PSA_ERROR_INSUFFICIENT_CAPACITY` from any output request that exceeds the operation's capacity. Such drivers must provide the following entry point: ``` @@ -456,7 +456,7 @@ If the key derivation's `PSA_KEY_DERIVATION_INPUT_SECRET` input is in a secure e 1. For a call to `psa_key_derivation_output_key()`, if the driver's capabilities indicate that its `"import_key"` entry point does not support the derived key, stop and return `PSA_ERROR_NOT_SUPPORTED`. 1. For a call to `psa_key_derivation_verify_key()`, if the driver has a `"key_derivation_verify_key"` entry point, call it and stop. 1. For a call to `psa_key_derivation_verify_key()` or `psa_key_derivation_verify_bytes()`, if the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's `"export_key"` entry point on the key object that contains the expected value, call the `"key_derivation_verify_bytes"` entry point on the exported material, and stop. -1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a non-raw key or if the output size exceeds some implementation limit. +1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a cooked (non-raw) key as described below, or if the output size exceeds some implementation limit. If the key derivation operation is not handled by an opaque driver as described above, the core calls the `"key_derivation_output_bytes"` from the applicable transparent driver (or multiple drivers in succession if fallback applies). In some cases, the driver then calls additional entry points in the same or another driver: From 54eb0686b3aae1310ea084a3663098653eb9b047 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 30 Jun 2022 18:09:27 +0200 Subject: [PATCH 06/24] New function psa_crypto_driver_key_derivation_get_input_type The new function psa_crypto_driver_key_derivation_get_input_type() allows drivers to retrieve the effective type of each input step, and thus to call the correct get-data function. This is simpler than the previous scheme which required a somewhat contrived dance with get_key() and get_bytes() for inputs that can be passed either as a key or as a byte buffer at the application's choice. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 42 ++++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index d737b0d80..fa3f1d169 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -336,7 +336,31 @@ The core conveys the initial inputs for a key derivation via an opaque data stru typedef ... psa_crypto_driver_key_derivation_inputs_t; // implementation-specific type ``` -A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents using the following functions. +A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents by calling one of type-specific the functions below. To determine the correct function, the driver can call `psa_crypto_driver_key_derivation_get_input_type()`. + +``` +enum psa_crypto_driver_key_derivation_input_type_t { + PSA_KEY_DERIVATION_INPUT_TYPE_INVALID = 0, + PSA_KEY_DERIVATION_INPUT_TYPE_OMITTED, + PSA_KEY_DERIVATION_INPUT_TYPE_BYTES, + PSA_KEY_DERIVATION_INPUT_TYPE_KEY, + PSA_KEY_DERIVATION_INPUT_TYPE_INTEGER, + // Implementations may add other values, and may freely choose the + // numerical values for each identifer except as explicitly specified + // above. +}; +psa_crypto_driver_key_derivation_input_type_t psa_crypto_driver_key_derivation_get_input_type( + const psa_crypto_driver_key_derivation_inputs_t *inputs, + psa_key_derivation_step_t step); +``` + +The function `psa_crypto_driver_key_derivation_get_input_type()` determines whether a given step is present and how to access its value: + +* `PSA_KEY_DERIVATION_INPUT_TYPE_INVALID`: the step is invalid for the algorithm of the operation that the inputs are for. +* `PSA_KEY_DERIVATION_INPUT_TYPE_OMITTED`: the step is optional for the algorithm of the operation that the inputs are for, and has been omitted. +* `PSA_KEY_DERIVATION_INPUT_TYPE_BYTES`: the step is valid and present and is a transparent byte string. Call `psa_crypto_driver_key_derivation_get_input_size()` to obtain the size of the input data. Call `psa_crypto_driver_key_derivation_get_input_bytes()` make a copy of the input data. +* `PSA_KEY_DERIVATION_INPUT_TYPE_KEY`: the step is valid and present and is a byte string passed via a key object. Call `psa_crypto_driver_key_derivation_get_input_key()` to obtain a pointer to the key data. +* `PSA_KEY_DERIVATION_INPUT_TYPE_INTEGER`: the step is valid and present and is an integer. Call `psa_crypto_driver_key_derivation_get_input_integer()` to retrieve the integer value. ``` psa_status_t psa_crypto_driver_key_derivation_get_input_size( @@ -357,13 +381,10 @@ psa_status_t psa_crypto_driver_key_derivation_get_input_integer( uint64_t *value); ``` -These functions take the following parameters: +The get-data functions take the following parameters: * The first parameter `inputs` must be a pointer passed by the core to a key derivation driver setup entry point which has not returned yet. -* The `step` parameter indicates the input step whose content the driver wants to retrieve. The type of the input step must be compatible with the function: - * `psa_crypto_driver_key_derivation_get_input_integer` for integer inputs (steps that the application passes with `psa_key_derivation_input_integer()`). - * `psa_crypto_driver_key_derivation_get_input_size` and `psa_crypto_driver_key_derivation_get_input_bytes` for data inputs (steps that the application passes with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`, excluding key inputs from the same secure element). - * `psa_crypto_driver_key_derivation_get_input_key` for key inputs (steps that the application passes with `psa_key_derivation_input_key()`, only for secure element drivers receiving a key from the same secure element). +* The `step` parameter indicates the input step whose content the driver wants to retrieve. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_size`, the core sets `*size` to the size of the desired input in bytes. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `buffer` with the desired input and sets `*buffer_length` to *N*, where *N* is the length of the input in bytes. The value of `buffer_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_key`, the core sets `*key_buffer` to a pointer to a buffer containing the key context and `*key_buffer_size` to the size of the key context in bytes. The key context buffer remains valid for the duration of the driver entry point. If the driver needs to access the key context after the current entry point returns, it must make a copy of the key context. @@ -372,9 +393,8 @@ These functions take the following parameters: These functions can return the following statuses: * `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been writen to the applicable parameter (`buffer_length`, `key_buffer_size`). -* `PSA_ERROR_INSUFFICIENT_DATA`: the driver called `psa_crypto_driver_key_derivation_get_input_key` on a data input step which is available as a bytes input, or the driver called ``psa_crypto_driver_key_derivation_get_input_size` or `psa_crypto_driver_key_derivation_get_input_bytes` on a data input step which is available as a key input. This is not a fatal error and the driver is expected to call the appropriate function(s) instead. * `PSA_ERROR_DOES_NOT_EXIST`: the input step is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-long-inputs). -* `PSA_ERROR_INVALID_ARGUMENT`: the input step is not valid for this particular algorithm, or the type of the input step is not suitable for this function. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. +* `PSA_ERROR_INVALID_ARGUMENT`: the input type is not compatible with this function or was omitted. Call `psa_crypto_driver_key_derivation_get_input_type()` to find out the actual type of this input step. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. * `PSA_ERROR_BUFFER_TOO_SMALL` (`psa_crypto_driver_key_derivation_get_input_bytes` only): the output buffer is too small. This is not a fatal error and the driver can, for example, subsequently call the same function again with a larger buffer. Call `psa_crypto_driver_key_derivation_get_input_size` to obtain the required size. * The core may return other errors such as `PSA_ERROR_CORRUPTION_DETECTED` or `PSA_ERROR_COMMUNICATION_FAILURE` to convey implementation-specific error conditions. Portable drivers should treat such conditions as fatal errors. @@ -392,12 +412,6 @@ psa_status_t acme_key_derivation_setup( * `alg` is the algorithm for the key derivation operation. It does not include a key agreement component. * `inputs` is an opaque pointer to the [initial inputs](#key-derivation-driver-initial-inputs) for the key derivation. -The following process describes how a driver is expected to retrieve the inputs of the key derivation. For each input step that is valid for the algorithm `alg` and is not a [long input](#key-derivation-driver-long-inputs): - -* If the step is a data step and the driver is an opaque driver, call `psa_crypto_driver_key_derivation_get_input_key`. This may either succeed or fail with `PSA_ERROR_INSUFFICIENT_DATA` depending on whether the input comes from the same secure element or not. Note that the driver obtains a pointer to the [key context](#overview-of-driver-entry-points) which only remains valid until the end of the call to the setup entry point. If the driver needs the context in subsequent steps of the operation, it must make a copy. -* If the step is a data step and the driver is a transparent driver, or if `psa_crypto_driver_key_derivation_get_input_key` returned `PSA_ERROR_INSUFFICIENT_DATA`, call `psa_crypto_driver_key_derivation_get_input_size` to retrieve the size of the input, then call `psa_crypto_driver_key_derivation_get_input_bytes` with a large enough buffer to retrieve the input data. -* If the step is an integer, call `psa_crypto_driver_key_derivation_get_input_integer`. - #### Key derivation driver long inputs Some key derivation algorithms take long inputs which it would not be practical to pass in the [initial inputs](#key-derivation-driver-initial-inputs). A driver that implements a key derivation algorithm that takes such inputs must provide a `"key_derivation_input_step"` entry point. The core calls this input step for all the long inputs, in an unspecified order. Long input steps may be fragmented into multiple calls of `psa_key_derivation_input_bytes()`, and the core may reassemble or refragment those fragments before passing them to the driver. From d9645c847e90f73cca0afad97d70a02631a4cc8e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 30 Jun 2022 18:19:51 +0200 Subject: [PATCH 07/24] Fix naming confusion with opaque key derivation "key_derivation_derive_key" should have been "key_derivation_output_key". Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index fa3f1d169..ae84987de 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -318,7 +318,7 @@ A key derivation driver has the following entry points: * `"key_derivation_setup"` (mandatory): always the first entry point to be called. This entry point provides the [initial inputs](#key-derivation-driver-initial-inputs). See [“Key derivation driver setup”](#key-derivation-driver-setup). * `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). * `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). -* `"key_derivation_derive_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). +* `"key_derivation_output_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for “cooked”, i.e. non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). * `"key_derivation_abort"` (mandatory): always the last entry point to be called. @@ -427,7 +427,7 @@ At the time of writing, no standard key derivation algorithm has long inputs. It #### Key derivation driver operation capacity -The core keeps track of an operation's capacity and enforces it. The core guarantees that it will not request output beyond the capacity of the operation, with one exception: opaque drivers that support `"key_derivation_derive_key"` [cooked key types](#transparent-cooked-key-derivation), i.e. for key types where the derived key material is not a direct copy of the key derivation's output stream. +The core keeps track of an operation's capacity and enforces it. The core guarantees that it will not request output beyond the capacity of the operation, with one exception: opaque drivers that support [`"key_derivation_output_key"`](#key-derivation-driver-outputs), i.e. for key types where the derived key material is not a direct copy of the key derivation's output stream. Such drivers must enforce the capacity limitation and must return `PSA_ERROR_INSUFFICIENT_CAPACITY` from any output request that exceeds the operation's capacity. Such drivers must provide the following entry point: ``` From eda71ce5356c67beeb03e06bd898323fdead19cc Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 12 Jan 2023 14:32:56 +0100 Subject: [PATCH 08/24] Key derivation: improve overview of the problem space Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index ae84987de..be09f0d16 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -299,7 +299,12 @@ TODO ### Driver entry points for key derivation -Key derivation is more complex than other multipart operations due to the multiplicity of inputs and outputs, to the fact that multiple drivers can be involved (key agreement and subsequent key derivation accelerator, opaque driver for the secret key and for derived keys), and because the involvement of an opaque driver cannot be determined as soon as the operation is set up (since `psa_key_derivation_setup()` does not determine the key input). +Key derivation is more complex than other multipart operations for several reasons: + +* There are multiple of inputs and outputs. +* Multiple drivers can be involved. This happens when an operation combines a key agreement and a subsequent symmetric key derivation, each of which can have independent drivers. This also happens when deriving an asymmetric key, where processing the secret input and generating the key output might involve different drivers. +* When multiple drivers are involved, they are not always independent: if the secret input is managed by an opaque driver, it might not allow the core to retrieve the intermediate output and pass it to another driver. +* The involvement of an opaque driver cannot be determined as soon as the operation is set up (since `psa_key_derivation_setup()` does not determine the key input). #### Key derivation driver dispatch logic From 4e346bd569308481bbf56136e300a7f7381bf3b6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 12 Jan 2023 14:33:22 +0100 Subject: [PATCH 09/24] Fix entry point name Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index be09f0d16..bc7e57a39 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -324,7 +324,7 @@ A key derivation driver has the following entry points: * `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). * `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_output_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). -* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_bytes"` for “cooked”, i.e. non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). +* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_key"` for “cooked”, i.e. non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). * `"key_derivation_abort"` (mandatory): always the last entry point to be called. For naming purposes, here and in the following subsection, this specification takes the example of a driver with the prefix `"acme"` that implements the `"key_derivation"` entry point family with a capability that does not use the `"names"` property to declare different type and entry point names. Such a driver must implement the following type and functions, as well as the entry points listed above and described in the following subsections: From 635b779cfd238c4300c4f7d5d6d5636d54cb0dfd Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 12 Jan 2023 14:33:44 +0100 Subject: [PATCH 10/24] Fix math character used in text mode Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index bc7e57a39..d4b5542c4 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -524,7 +524,7 @@ The core calls the `"derive_key"` entry point in a loop until it returns a statu For standard key types, the `"derive_key"` entry point is called with a certain input length as follows: * `PSA_KEY_TYPE_DES`: the length of the key. -* `PSA_KEY_TYPE_ECC_KEY_PAIR(…)`, `PSA_KEY_TYPE_DH_KEY_PAIR(…)`: *m* bytes, where the bit-size of the key *n* satisfies *m*-1 < 8×*n* ≤ *m*. +* `PSA_KEY_TYPE_ECC_KEY_PAIR(…)`, `PSA_KEY_TYPE_DH_KEY_PAIR(…)`: $m$ bytes, where the bit-size of the key $n$ satisfies $m-1 < 8 n \le m$. * `PSA_KEY_TYPE_RSA_KEY_PAIR`: an implementation-defined length. A future version of this specification may specify a length. * Other key types: not applicable. From fd094081e1fe702dbfdbe84cc8a63c0bd27f72a8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 20 Jan 2023 20:24:17 +0100 Subject: [PATCH 11/24] Pass attributes alongside key buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the generic way of going adapting a psa_key_id_t argument in the application interface to the driver interface. Thanks Hannes Lindström. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index d4b5542c4..faa0ec369 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -379,6 +379,7 @@ psa_status_t psa_crypto_driver_key_derivation_get_input_bytes( psa_status_t psa_crypto_driver_key_derivation_get_input_key( const psa_crypto_driver_key_derivation_inputs_t *inputs, psa_key_derivation_step_t step, + const psa_key_attributes_t *attributes, uint8_t** p_key_buffer, size_t *key_buffer_size); psa_status_t psa_crypto_driver_key_derivation_get_input_integer( const psa_crypto_driver_key_derivation_inputs_t *inputs, From 66b96e2d877d84a1ee13ba185895d3963b9fb85a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:39:58 +0200 Subject: [PATCH 12/24] Copyediting Fix some typos and copypasta. Some very minor wording improvements. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index faa0ec369..5cae1ff29 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -301,14 +301,14 @@ TODO Key derivation is more complex than other multipart operations for several reasons: -* There are multiple of inputs and outputs. +* There are multiple inputs and outputs. * Multiple drivers can be involved. This happens when an operation combines a key agreement and a subsequent symmetric key derivation, each of which can have independent drivers. This also happens when deriving an asymmetric key, where processing the secret input and generating the key output might involve different drivers. * When multiple drivers are involved, they are not always independent: if the secret input is managed by an opaque driver, it might not allow the core to retrieve the intermediate output and pass it to another driver. * The involvement of an opaque driver cannot be determined as soon as the operation is set up (since `psa_key_derivation_setup()` does not determine the key input). #### Key derivation driver dispatch logic -The core decides whether to dispatch a key derivation operation to a driver based on the location of the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. +The core decides whether to dispatch a key derivation operation to a driver based on the location associated with of the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. 1. If this step is passed via `psa_key_derivation_input_key()` for a key in a secure element: * If the driver for this secure element implements the `"key_derivation"` family for the specified key type and algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. @@ -341,7 +341,7 @@ The core conveys the initial inputs for a key derivation via an opaque data stru typedef ... psa_crypto_driver_key_derivation_inputs_t; // implementation-specific type ``` -A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents by calling one of type-specific the functions below. To determine the correct function, the driver can call `psa_crypto_driver_key_derivation_get_input_type()`. +A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents by calling one of the type-specific the functions below. To determine the correct function, the driver can call `psa_crypto_driver_key_derivation_get_input_type()`. ``` enum psa_crypto_driver_key_derivation_input_type_t { @@ -364,7 +364,7 @@ The function `psa_crypto_driver_key_derivation_get_input_type()` determines whet * `PSA_KEY_DERIVATION_INPUT_TYPE_INVALID`: the step is invalid for the algorithm of the operation that the inputs are for. * `PSA_KEY_DERIVATION_INPUT_TYPE_OMITTED`: the step is optional for the algorithm of the operation that the inputs are for, and has been omitted. * `PSA_KEY_DERIVATION_INPUT_TYPE_BYTES`: the step is valid and present and is a transparent byte string. Call `psa_crypto_driver_key_derivation_get_input_size()` to obtain the size of the input data. Call `psa_crypto_driver_key_derivation_get_input_bytes()` make a copy of the input data. -* `PSA_KEY_DERIVATION_INPUT_TYPE_KEY`: the step is valid and present and is a byte string passed via a key object. Call `psa_crypto_driver_key_derivation_get_input_key()` to obtain a pointer to the key data. +* `PSA_KEY_DERIVATION_INPUT_TYPE_KEY`: the step is valid and present and is a byte string passed via a key object. Call `psa_crypto_driver_key_derivation_get_input_key()` to obtain a pointer to the key context. * `PSA_KEY_DERIVATION_INPUT_TYPE_INTEGER`: the step is valid and present and is an integer. Call `psa_crypto_driver_key_derivation_get_input_integer()` to retrieve the integer value. ``` @@ -391,14 +391,14 @@ The get-data functions take the following parameters: * The first parameter `inputs` must be a pointer passed by the core to a key derivation driver setup entry point which has not returned yet. * The `step` parameter indicates the input step whose content the driver wants to retrieve. -* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_size`, the core sets `*size` to the size of the desired input in bytes. -* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `buffer` with the desired input and sets `*buffer_length` to *N*, where *N* is the length of the input in bytes. The value of `buffer_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_size`, the core sets `*size` to the size of the specified input in bytes. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_bytes`, the core fills the first *N* bytes of `buffer` with the specified input and sets `*buffer_length` to *N*, where *N* is the length of the input in bytes. The value of `buffer_size` must be at least *N*, otherwise this function fails with the status `PSA_ERROR_BUFFER_TOO_SMALL`. * On a successful invocation of `psa_crypto_driver_key_derivation_get_input_key`, the core sets `*key_buffer` to a pointer to a buffer containing the key context and `*key_buffer_size` to the size of the key context in bytes. The key context buffer remains valid for the duration of the driver entry point. If the driver needs to access the key context after the current entry point returns, it must make a copy of the key context. -* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_integer`, the core sets `*value` to the value of the desired input. +* On a successful invocation of `psa_crypto_driver_key_derivation_get_input_integer`, the core sets `*value` to the value of the specified input. These functions can return the following statuses: -* `PSA_SUCCESS`: the call succeeded and the desired value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been writen to the applicable parameter (`buffer_length`, `key_buffer_size`). +* `PSA_SUCCESS`: the call succeeded and the requested value has been copied to the output parameter (`size`, `buffer`, `value` or `p_key_buffer`) and if applicable the size of the value has been written to the applicable parameter (`buffer_length`, `key_buffer_size`). * `PSA_ERROR_DOES_NOT_EXIST`: the input step is valid for this particular algorithm, but it is not part of the initial inputs. This is not a fatal error. The driver will receive the input later as a [long input](#key-derivation-driver-long-inputs). * `PSA_ERROR_INVALID_ARGUMENT`: the input type is not compatible with this function or was omitted. Call `psa_crypto_driver_key_derivation_get_input_type()` to find out the actual type of this input step. This is not a fatal error and the driver can, for example, subsequently call the appropriate function on the same step. * `PSA_ERROR_BUFFER_TOO_SMALL` (`psa_crypto_driver_key_derivation_get_input_bytes` only): the output buffer is too small. This is not a fatal error and the driver can, for example, subsequently call the same function again with a larger buffer. Call `psa_crypto_driver_key_derivation_get_input_size` to obtain the required size. @@ -441,7 +441,7 @@ psa_status_t acme_key_derivation_set_capacity( acme_key_derivation_operation_t *operation, size_t capacity); ``` -`capacity` is guaranteed to be less or equal to any value previously set through this entry point, and is guaraneed not to be `PSA_KEY_DERIVATION_UNLIMITED_CAPACITY`. +`capacity` is guaranteed to be less or equal to any value previously set through this entry point, and is guaranteed not to be `PSA_KEY_DERIVATION_UNLIMITED_CAPACITY`. If this entry point has not been called, the operation has an unlimited capacity. @@ -478,7 +478,7 @@ If the key derivation's `PSA_KEY_DERIVATION_INPUT_SECRET` input is in a secure e 1. For a call to `psa_key_derivation_verify_key()` or `psa_key_derivation_verify_bytes()`, if the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's `"export_key"` entry point on the key object that contains the expected value, call the `"key_derivation_verify_bytes"` entry point on the exported material, and stop. 1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a cooked (non-raw) key as described below, or if the output size exceeds some implementation limit. -If the key derivation operation is not handled by an opaque driver as described above, the core calls the `"key_derivation_output_bytes"` from the applicable transparent driver (or multiple drivers in succession if fallback applies). In some cases, the driver then calls additional entry points in the same or another driver: +If the key derivation operation is not handled by an opaque driver as described above, the core calls the `"key_derivation_output_bytes"` from the applicable transparent driver (or multiple drivers in succession if fallback applies). In some cases, the core then calls additional entry points in the same or another driver: * For a call to `psa_key_derivation_output_key()` for some key types, the core calls a transparent driver's `"derive_key"` entry point. See [“Transparent cooked key derivation”](#transparent-cooked-key-derivation). * For a call to `psa_key_derivation_output_key()` where the derived key is in a secure element, call that secure element driver's `"import_key"` entry point. @@ -491,7 +491,7 @@ A capability for cooked key derivation contains the following properties (this i * `"entry_points"` (mandatory, list of strings). Must be `["derive_key"]`. * `"derived_types"` (mandatory, list of strings). Each element is a [key type specification](#key-type-specifications). This capability only applies when deriving a key of the specified type. -* `"derived_sizes"` (optional, list of integers). Each element is a [key type specification](#key-type-specifications). This capability only applies when deriving a key of the specified sizes, in bits. If absent, this capability applies to all sizes for the specified types. +* `"derived_sizes"` (optional, list of integers). Each element is a size for the derived key, in bits. This capability only applies when deriving a key of the specified sizes. If absent, this capability applies to all sizes for the specified types. * `"memory"` (optional, boolean). If present and true, the driver must define a type `"derive_key_memory_t"` and the core will allocate an object of that type as specified below. * `"names"` (optional, object). A mapping from entry point names to C function and type names, as usual. * `"fallback"` (optional, boolean). If present and true, the driver may return `PSA_ERROR_NOT_SUPPORTED` if it only partially supports the specified mechanism, as usual. @@ -507,7 +507,7 @@ psa_status_t acme_derive_key( uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); ``` -* `attributes` contains the attributes of the desired key. Note that only the key type and the bit-size are guaranteed to be set. +* `attributes` contains the attributes of the specified key. Note that only the key type and the bit-size are guaranteed to be set. * `input` is a buffer of `input_length` bytes which contains the raw key stream, i.e. the data that `psa_key_derivation_output_bytes()` would return. * If `"memory"` property in the driver capability is true, `memory` is a data structure that the driver may use to store data between successive calls of the `"derive_key"` entry point to derive the same key. If the `"memory"` property is false or absent, the `memory` parameter is a null pointer. * `key_buffer` is a buffer for the output material. Its size is `key_buffer_size` bytes. @@ -515,7 +515,7 @@ psa_status_t acme_derive_key( This entry point may return the following statuses: -* `PSA_SUCCESS`: a key was derived successfully. The driver has placed representation of the key is in `key_buffer`. +* `PSA_SUCCESS`: a key was derived successfully. The driver has placed the representation of the key in `key_buffer`. * `PSA_ERROR_NOT_SUPPORTED` (for the first call only) (only if fallback is enabled): the driver cannot fulfill this request, but a fallback driver might. * `PSA_ERROR_INSUFFICIENT_DATA`: the core must call the `"derive_key"` entry point again with the same `memory` object and with subsequent data from the key stream. * Any other error is a fatal error. @@ -525,7 +525,7 @@ The core calls the `"derive_key"` entry point in a loop until it returns a statu For standard key types, the `"derive_key"` entry point is called with a certain input length as follows: * `PSA_KEY_TYPE_DES`: the length of the key. -* `PSA_KEY_TYPE_ECC_KEY_PAIR(…)`, `PSA_KEY_TYPE_DH_KEY_PAIR(…)`: $m$ bytes, where the bit-size of the key $n$ satisfies $m-1 < 8 n \le m$. +* `PSA_KEY_TYPE_ECC_KEY_PAIR(…)`, `PSA_KEY_TYPE_DH_KEY_PAIR(…)`: $m$ bytes, where the bit-size of the key $n$ satisfies $8 (m-1) < n \le 8 m$. * `PSA_KEY_TYPE_RSA_KEY_PAIR`: an implementation-defined length. A future version of this specification may specify a length. * Other key types: not applicable. From 4e94fead864467901039d5cb27af490eccad2220 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:40:56 +0200 Subject: [PATCH 13/24] Key derivation dispatch doesn't depend on the key type At least for all currently specified algorithms. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 5cae1ff29..dd35ed226 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -311,9 +311,10 @@ Key derivation is more complex than other multipart operations for several reaso The core decides whether to dispatch a key derivation operation to a driver based on the location associated with of the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. 1. If this step is passed via `psa_key_derivation_input_key()` for a key in a secure element: - * If the driver for this secure element implements the `"key_derivation"` family for the specified key type and algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. + * If the driver for this secure element implements the `"key_derivation"` family for the specified algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. + Note that for all currently specified algorithms, the key type for the secret input does not matter. * Otherwise the core calls the secure element driver's [`"export_key"`](#key-management-with-opaque-drivers) entry point. -2. Otherwise ([or on fallback?](#fallback-for-key-derivation-in-opaque-drivers)), if there is a transparent driver for the specified key type and algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. +2. Otherwise ([or on fallback?](#fallback-for-key-derivation-in-opaque-drivers)), if there is a transparent driver for the specified algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. 3. Otherwise, or on fallback, the core uses its built-in implementation. #### Summary of entry points for the operation family `"key_derivation"` From d2fe1d5498ca48e4a31ef4db88dcfd1c8e896ddb Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:41:57 +0200 Subject: [PATCH 14/24] Rationale on key derivation inputs and buffer ownership Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index dd35ed226..cca709d43 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -364,7 +364,7 @@ The function `psa_crypto_driver_key_derivation_get_input_type()` determines whet * `PSA_KEY_DERIVATION_INPUT_TYPE_INVALID`: the step is invalid for the algorithm of the operation that the inputs are for. * `PSA_KEY_DERIVATION_INPUT_TYPE_OMITTED`: the step is optional for the algorithm of the operation that the inputs are for, and has been omitted. -* `PSA_KEY_DERIVATION_INPUT_TYPE_BYTES`: the step is valid and present and is a transparent byte string. Call `psa_crypto_driver_key_derivation_get_input_size()` to obtain the size of the input data. Call `psa_crypto_driver_key_derivation_get_input_bytes()` make a copy of the input data. +* `PSA_KEY_DERIVATION_INPUT_TYPE_BYTES`: the step is valid and present and is a transparent byte string. Call `psa_crypto_driver_key_derivation_get_input_size()` to obtain the size of the input data. Call `psa_crypto_driver_key_derivation_get_input_bytes()` to make a copy of the input data (design note: [why a copy?](#key-derivation-inputs-and-buffer-ownership)). * `PSA_KEY_DERIVATION_INPUT_TYPE_KEY`: the step is valid and present and is a byte string passed via a key object. Call `psa_crypto_driver_key_derivation_get_input_key()` to obtain a pointer to the key context. * `PSA_KEY_DERIVATION_INPUT_TYPE_INTEGER`: the step is valid and present and is an integer. Call `psa_crypto_driver_key_derivation_get_input_integer()` to retrieve the integer value. @@ -1179,6 +1179,12 @@ Should drivers really have to cope with overlap? Should the core guarantee that the output buffer size has the size indicated by the applicable buffer size macro (which may be an overestimation)? +#### Key derivation inputs and buffer ownership + +Why is `psa_crypto_driver_key_derivation_get_input_bytes` a copy, rather than giving a pointer? + +The main reason is to avoid complex buffer ownership. A driver entry point does not own memory after the entry point return. This is generally necessary because an API function does not own memory after the entry point returns. In the case of key derivation inputs, this could be relaxed because the driver entry point is making callbacks to the core: these functions could return a pointer that is valid until the driver entry point, which would allow the driver to process the data immediately (e.g. hash it rather than copy it). + ### Partial computations in drivers #### Substitution points From f787879a140e933614cc68686613bbb21339c21e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:42:29 +0200 Subject: [PATCH 15/24] Clarify sequencing of long inputs Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index cca709d43..8cdc35942 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -421,7 +421,7 @@ psa_status_t acme_key_derivation_setup( #### Key derivation driver long inputs -Some key derivation algorithms take long inputs which it would not be practical to pass in the [initial inputs](#key-derivation-driver-initial-inputs). A driver that implements a key derivation algorithm that takes such inputs must provide a `"key_derivation_input_step"` entry point. The core calls this input step for all the long inputs, in an unspecified order. Long input steps may be fragmented into multiple calls of `psa_key_derivation_input_bytes()`, and the core may reassemble or refragment those fragments before passing them to the driver. +Some key derivation algorithms take long inputs which it would not be practical to pass in the [initial inputs](#key-derivation-driver-initial-inputs). A driver that implements a key derivation algorithm that takes such inputs must provide a `"key_derivation_input_step"` entry point. The core calls this entry point for all the long inputs after calling `"acme_key_derivation_setup"`. A long input step may be fragmented into multiple calls of `psa_key_derivation_input_bytes()`, and the core may reassemble or refragment those fragments before passing them to the driver. Calls to this entry point for different step values occur in an unspecified order and may be interspersed. ``` psa_status_t acme_key_derivation_input_step( From b319ed69c4a358ab1a056f3842a1bc7b377e0750 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:42:45 +0200 Subject: [PATCH 16/24] State explicitly that cooked key derivation uses the export format This is the case for all key creation in a secure element, but state it explicitly where relevant. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 8cdc35942..3aaa58bf5 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -511,7 +511,7 @@ psa_status_t acme_derive_key( * `attributes` contains the attributes of the specified key. Note that only the key type and the bit-size are guaranteed to be set. * `input` is a buffer of `input_length` bytes which contains the raw key stream, i.e. the data that `psa_key_derivation_output_bytes()` would return. * If `"memory"` property in the driver capability is true, `memory` is a data structure that the driver may use to store data between successive calls of the `"derive_key"` entry point to derive the same key. If the `"memory"` property is false or absent, the `memory` parameter is a null pointer. -* `key_buffer` is a buffer for the output material. Its size is `key_buffer_size` bytes. +* `key_buffer` is a buffer for the output material, in the appropriate [export format](#key-format-for-transparent-drivers) for the key type. Its size is `key_buffer_size` bytes. * On success, `*key_buffer_length` must contain the number of bytes written to `key_buffer`. This entry point may return the following statuses: From e52bff994cbfe1f253a3842663cb2f9d66a646f4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:43:29 +0200 Subject: [PATCH 17/24] Note possible issue with derive_key: who should choose the input length? Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 3aaa58bf5..da251465e 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -510,6 +510,7 @@ psa_status_t acme_derive_key( * `attributes` contains the attributes of the specified key. Note that only the key type and the bit-size are guaranteed to be set. * `input` is a buffer of `input_length` bytes which contains the raw key stream, i.e. the data that `psa_key_derivation_output_bytes()` would return. + TODO: how does the core choose `input_length`? Doesn't the driver know better? Should there be a driver entry point to determine the length, or should there be a callback that allows the driver to retrieve the input? (Note that for some algorithms, it's impossible to predict the amount of input in advance, because it depends on some complex calculation or even on random data, e.g. if doing a randomized pseudo-primality test.) * If `"memory"` property in the driver capability is true, `memory` is a data structure that the driver may use to store data between successive calls of the `"derive_key"` entry point to derive the same key. If the `"memory"` property is false or absent, the `memory` parameter is a null pointer. * `key_buffer` is a buffer for the output material, in the appropriate [export format](#key-format-for-transparent-drivers) for the key type. Its size is `key_buffer_size` bytes. * On success, `*key_buffer_length` must contain the number of bytes written to `key_buffer`. From 24f52296f1e785712f4eb968c19a49e86f507325 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 May 2023 00:44:04 +0200 Subject: [PATCH 18/24] Key agreement needs an attribute structure for our key Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index da251465e..075b386b1 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -547,6 +547,7 @@ In other cases, the core treats `psa_key_derivation_key_agreement()` as if it wa The entry points related to key agreement have the following prototypes for a driver with the prefix `"acme"`: ``` psa_status_t acme_key_agreement(psa_algorithm_t alg, + const psa_key_attributes_t *our_attributes, const uint8_t *our_key_buffer, size_t our_key_buffer_length, const uint8_t *peer_key, @@ -555,16 +556,19 @@ psa_status_t acme_key_agreement(psa_algorithm_t alg, size_t output_size, size_t *output_length); psa_status_t acme_key_agreement_to_key(psa_algorithm_t alg, - const psa_key_attributes_t *attributes, + const psa_key_attributes_t *our_attributes, const uint8_t *our_key_buffer, size_t our_key_buffer_length, const uint8_t *peer_key, size_t peer_key_length, + const psa_key_attributes_t *shared_secret_attributes, uint8_t *shared_secret_key_buffer, size_t shared_secret_key_buffer_size, size_t *shared_secret_key_buffer_length); ``` +Note that unlike most other key creation entry points, in `"acme_key_agreement_to_key"`, the parameters for the shared secret are not placed near the beginning, but rather grouped with the other parameters at the end, to avoid confusion with the keys passed as inputs. + ### Driver entry points for key management The driver entry points for key management differ significantly between [transparent drivers](#key-management-with-transparent-drivers) and [opaque drivers](#key-management-with-opaque-drivers). This section describes common elements. Refer to the applicable section for each driver type for more information. From 1414bc34b9cd91e6ebe4a0161c17ed2d125cf96e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 2 Jun 2023 17:54:21 +0200 Subject: [PATCH 19/24] Minor copyediting Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 075b386b1..551e59265 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -308,7 +308,7 @@ Key derivation is more complex than other multipart operations for several reaso #### Key derivation driver dispatch logic -The core decides whether to dispatch a key derivation operation to a driver based on the location associated with of the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. +The core decides whether to dispatch a key derivation operation to a driver based on the location associated with the input step `PSA_KEY_DERIVATION_INPUT_SECRET`. 1. If this step is passed via `psa_key_derivation_input_key()` for a key in a secure element: * If the driver for this secure element implements the `"key_derivation"` family for the specified algorithm, the core calls that driver's `"key_derivation_setup"` and subsequent entry points. @@ -342,7 +342,7 @@ The core conveys the initial inputs for a key derivation via an opaque data stru typedef ... psa_crypto_driver_key_derivation_inputs_t; // implementation-specific type ``` -A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents by calling one of the type-specific the functions below. To determine the correct function, the driver can call `psa_crypto_driver_key_derivation_get_input_type()`. +A driver receiving an argument that points to a `psa_crypto_driver_key_derivation_inputs_t` can retrieve its contents by calling one of the type-specific functions below. To determine the correct function, the driver can call `psa_crypto_driver_key_derivation_get_input_type()`. ``` enum psa_crypto_driver_key_derivation_input_type_t { @@ -567,7 +567,7 @@ psa_status_t acme_key_agreement_to_key(psa_algorithm_t alg, size_t *shared_secret_key_buffer_length); ``` -Note that unlike most other key creation entry points, in `"acme_key_agreement_to_key"`, the parameters for the shared secret are not placed near the beginning, but rather grouped with the other parameters at the end, to avoid confusion with the keys passed as inputs. +Note that unlike most other key creation entry points, in `"acme_key_agreement_to_key"`, the attributes for the shared secret are not placed near the beginning, but rather grouped with the other parameters related to the shared secret at the end of the parameter list. This is to avoid potential confusion with the attributes of the private key that is passed as an input. ### Driver entry points for key management @@ -1188,7 +1188,7 @@ Should the core guarantee that the output buffer size has the size indicated by Why is `psa_crypto_driver_key_derivation_get_input_bytes` a copy, rather than giving a pointer? -The main reason is to avoid complex buffer ownership. A driver entry point does not own memory after the entry point return. This is generally necessary because an API function does not own memory after the entry point returns. In the case of key derivation inputs, this could be relaxed because the driver entry point is making callbacks to the core: these functions could return a pointer that is valid until the driver entry point, which would allow the driver to process the data immediately (e.g. hash it rather than copy it). +The main reason is to avoid complex buffer ownership. A driver entry point does not own memory after the entry point return. This is generally necessary because an API function does not own memory after the entry point returns. In the case of key derivation inputs, this could be relaxed because the driver entry point is making callbacks to the core: these functions could return a pointer that is valid until the driver entry point returns, which would allow the driver to process the data immediately (e.g. hash it rather than copy it). ### Partial computations in drivers From f96a18edc7b7d1a21bf3c322521d48e3a1a467e7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 2 Jun 2023 18:02:15 +0200 Subject: [PATCH 20/24] Probably resolve concern about the input size for derive_key Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index 551e59265..f04f8e976 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -510,7 +510,6 @@ psa_status_t acme_derive_key( * `attributes` contains the attributes of the specified key. Note that only the key type and the bit-size are guaranteed to be set. * `input` is a buffer of `input_length` bytes which contains the raw key stream, i.e. the data that `psa_key_derivation_output_bytes()` would return. - TODO: how does the core choose `input_length`? Doesn't the driver know better? Should there be a driver entry point to determine the length, or should there be a callback that allows the driver to retrieve the input? (Note that for some algorithms, it's impossible to predict the amount of input in advance, because it depends on some complex calculation or even on random data, e.g. if doing a randomized pseudo-primality test.) * If `"memory"` property in the driver capability is true, `memory` is a data structure that the driver may use to store data between successive calls of the `"derive_key"` entry point to derive the same key. If the `"memory"` property is false or absent, the `memory` parameter is a null pointer. * `key_buffer` is a buffer for the output material, in the appropriate [export format](#key-format-for-transparent-drivers) for the key type. Its size is `key_buffer_size` bytes. * On success, `*key_buffer_length` must contain the number of bytes written to `key_buffer`. @@ -531,6 +530,8 @@ For standard key types, the `"derive_key"` entry point is called with a certain * `PSA_KEY_TYPE_RSA_KEY_PAIR`: an implementation-defined length. A future version of this specification may specify a length. * Other key types: not applicable. +See [“Open questions around cooked key derivation”](#open-questions-around-cooked-key-derivation) for some points that may not be fully settled. + #### Key agreement The core always decouples key agreement from symmetric key derivation. @@ -1233,6 +1234,10 @@ An example use case for updating the persistent state at arbitrary times is to r `psa_crypto_driver_get_persistent_state` does not identify the calling driver, so the driver needs to remember which driver it's calling. This may require a thread-local variable in a multithreaded core. Is this ok? +#### Open questions around cooked key derivation + +For the `"derive_key"` entry point, how does the core choose `input_length`? Doesn't the driver know better? Should there be a driver entry point to determine the length, or should there be a callback that allows the driver to retrieve the input? Note that for some key types, it's impossible to predict the amount of input in advance, because it depends on some complex calculation or even on random data, e.g. if doing a randomized pseudo-primality test. However, for all key types except RSA, the specification mandates how the key is derived, which practically dictates how the pseudorandom key stream is consumed. So it's probably ok. + #### Fallback for key derivation in opaque drivers Should [dispatch to an opaque driver](#key-derivation-driver-dispatch-logic) allow fallback, so that if `"key_derivation_setup"` returns `PSA_ERROR_NOT_SUPPORTED` then the core exports the key from the secure element instead? From dcaf104eefbcd524410da7b1413a1b8ac8018d26 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 2 Jun 2023 18:02:41 +0200 Subject: [PATCH 21/24] Note that we may want to rename derive_key ... if we think of a better name Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index f04f8e976..b5e657c62 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -1236,6 +1236,8 @@ An example use case for updating the persistent state at arbitrary times is to r #### Open questions around cooked key derivation +`"derive_key"` is not a clear name. Can we use a better one? + For the `"derive_key"` entry point, how does the core choose `input_length`? Doesn't the driver know better? Should there be a driver entry point to determine the length, or should there be a callback that allows the driver to retrieve the input? Note that for some key types, it's impossible to predict the amount of input in advance, because it depends on some complex calculation or even on random data, e.g. if doing a randomized pseudo-primality test. However, for all key types except RSA, the specification mandates how the key is derived, which practically dictates how the pseudorandom key stream is consumed. So it's probably ok. #### Fallback for key derivation in opaque drivers From 7df8ba6a103bebf747d523ad77440c1c09f5cef0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 2 Jun 2023 18:16:02 +0200 Subject: [PATCH 22/24] Rework the description of key derivation output/verify key Some of the fallback mechanisms between the entry points were not described corrrectly. Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index b5e657c62..c96452e5f 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -473,11 +473,22 @@ The core calls a key derivation driver's output entry point when the application If the key derivation's `PSA_KEY_DERIVATION_INPUT_SECRET` input is in a secure element and the derivation operation is handled by that secure element, the core performs the following steps: -1. For a call to `psa_key_derivation_output_key()` where the derived key is in the same secure element, if the driver has an `"key_derivation_output_key"` entry point, call that entry point. If the driver has no such entry point, or if that entry point returns `PSA_ERROR_NOT_SUPPORTED`, continue with the following steps, otherwise stop. -1. For a call to `psa_key_derivation_output_key()`, if the driver's capabilities indicate that its `"import_key"` entry point does not support the derived key, stop and return `PSA_ERROR_NOT_SUPPORTED`. -1. For a call to `psa_key_derivation_verify_key()`, if the driver has a `"key_derivation_verify_key"` entry point, call it and stop. -1. For a call to `psa_key_derivation_verify_key()` or `psa_key_derivation_verify_bytes()`, if the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's `"export_key"` entry point on the key object that contains the expected value, call the `"key_derivation_verify_bytes"` entry point on the exported material, and stop. -1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a cooked (non-raw) key as described below, or if the output size exceeds some implementation limit. +* For a call to `psa_key_derivation_output_key()`: + + 1. If the derived key is in the same secure element, if the driver has an `"key_derivation_output_key"` entry point, call that entry point. If the driver has no such entry point, or if that entry point returns `PSA_ERROR_NOT_SUPPORTED`, continue with the following steps, otherwise stop. + 1. If the driver's capabilities indicate that its `"import_key"` entry point does not support the derived key, stop and return `PSA_ERROR_NOT_SUPPORTED`. + 1. Otherwise proceed as for `psa_key_derivation_output_bytes()`, then import the resulting key material. + +* For a call to `psa_key_derivation_verify_key()`: + 1. For ``psa_key_derivation_verify_key()` only: if the driver has a `"key_derivation_verify_key"` entry point, call it and stop. + 1. Call the driver's `"export_key"` entry point on the key object that contains the expected value, then proceed as for `psa_key_derivation_verify_bytes()`. + +* For a call to `psa_key_derivation_verify_bytes()`: + 1. If the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's , call the `"key_derivation_verify_bytes"` entry point on the expected output, then stop. + 1. Otherwise, proceed as for `psa_key_derivation_output_bytes()`, and compare the resulting output to the expected output inside the core.. + +* For a call to `psa_key_derivation_output_bytes()`: + 1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a cooked (non-raw) key as described below, or if the output size exceeds some implementation limit. If the key derivation operation is not handled by an opaque driver as described above, the core calls the `"key_derivation_output_bytes"` from the applicable transparent driver (or multiple drivers in succession if fallback applies). In some cases, the core then calls additional entry points in the same or another driver: From 8dd1e623e1774688377c79293086b5bea2bf99f2 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 5 Jun 2023 14:14:41 +0200 Subject: [PATCH 23/24] Copyediting Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index c96452e5f..bbd1f5887 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -480,12 +480,12 @@ If the key derivation's `PSA_KEY_DERIVATION_INPUT_SECRET` input is in a secure e 1. Otherwise proceed as for `psa_key_derivation_output_bytes()`, then import the resulting key material. * For a call to `psa_key_derivation_verify_key()`: - 1. For ``psa_key_derivation_verify_key()` only: if the driver has a `"key_derivation_verify_key"` entry point, call it and stop. + 1. If the driver has a `"key_derivation_verify_key"` entry point, call it and stop. 1. Call the driver's `"export_key"` entry point on the key object that contains the expected value, then proceed as for `psa_key_derivation_verify_bytes()`. * For a call to `psa_key_derivation_verify_bytes()`: - 1. If the driver has a `"key_derivation_verify_bytes"` entry point, call the driver's , call the `"key_derivation_verify_bytes"` entry point on the expected output, then stop. - 1. Otherwise, proceed as for `psa_key_derivation_output_bytes()`, and compare the resulting output to the expected output inside the core.. + 1. If the driver has a `"key_derivation_verify_bytes"` entry point, call that entry point on the expected output, then stop. + 1. Otherwise, proceed as for `psa_key_derivation_output_bytes()`, and compare the resulting output to the expected output inside the core. * For a call to `psa_key_derivation_output_bytes()`: 1. Call the `"key_derivation_output_bytes"` entry point. The core may call this entry point multiple times to implement a single call from the application when deriving a cooked (non-raw) key as described below, or if the output size exceeds some implementation limit. From f4ba0013e2361088fa42a90719e57d5017495c01 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 5 Jun 2023 14:23:58 +0200 Subject: [PATCH 24/24] Clarify when key derivation entry points are mandatory/permitted Signed-off-by: Gilles Peskine --- docs/proposed/psa-driver-interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md index bbd1f5887..b6a650888 100644 --- a/docs/proposed/psa-driver-interface.md +++ b/docs/proposed/psa-driver-interface.md @@ -322,10 +322,10 @@ The core decides whether to dispatch a key derivation operation to a driver base A key derivation driver has the following entry points: * `"key_derivation_setup"` (mandatory): always the first entry point to be called. This entry point provides the [initial inputs](#key-derivation-driver-initial-inputs). See [“Key derivation driver setup”](#key-derivation-driver-setup). -* `"key_derivation_input_step"` (optional): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). +* `"key_derivation_input_step"` (mandatory if the driver supports a key derivation algorithm with long inputs, otherwise ignored): provide an extra input for the key derivation. This entry point is only mandatory in drivers that support algorithms that have extra inputs. See [“Key derivation driver long inputs”](#key-derivation-driver-long-inputs). * `"key_derivation_output_bytes"` (mandatory): derive cryptographic material and output it. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). * `"key_derivation_output_key"`, `"key_derivation_verify_bytes"`, `"key_derivation_verify_key"` (optional, opaque drivers only): derive key material which remains inside the same secure element. See [“Key derivation driver outputs”](#key-derivation-driver-outputs). -* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_key"` for “cooked”, i.e. non-raw-data key types): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). +* `"key_derivation_set_capacity"` (mandatory for opaque drivers that implement `"key_derivation_output_key"` for “cooked”, i.e. non-raw-data key types; ignored for other opaque drivers; not permitted for transparent drivers): update the capacity policy on the operation. See [“Key derivation driver operation capacity”](#key-derivation-driver-operation-capacity). * `"key_derivation_abort"` (mandatory): always the last entry point to be called. For naming purposes, here and in the following subsection, this specification takes the example of a driver with the prefix `"acme"` that implements the `"key_derivation"` entry point family with a capability that does not use the `"names"` property to declare different type and entry point names. Such a driver must implement the following type and functions, as well as the entry points listed above and described in the following subsections: