From 27d5b2ca25dae161effee583b976dabf63ed57c6 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 15 Sep 2023 16:25:43 +0100 Subject: [PATCH 01/12] crypto: Add new key agreement function Add psa_key_agreement() as a standalone function that outputs to a new derivation key. --- doc/crypto/api/ops/ka.rst | 121 ++++++++++++++++++++++++-- doc/crypto/appendix/history.rst | 2 + doc/crypto/overview/functionality.rst | 2 +- 3 files changed, 116 insertions(+), 9 deletions(-) diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 635faa7f..6e7e7b44 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -9,11 +9,19 @@ Key agreement ============= -Two functions are provided for a Diffie-Hellman-style key agreement where each party combines its own private key with the peer’s public key. +Three functions are provided for a Diffie-Hellman-style key agreement where each party combines its own private key with the peer’s public key: -* The recommended approach is to use a :ref:`key derivation operation ` with the `psa_key_derivation_key_agreement()` input function, which calculates a shared secret for the key derivation function. +* A call to `psa_key_agreement()` will compute the shared secret and store the result in a new derivation key. -* Where an application needs direct access to the shared secret, it can call `psa_raw_key_agreement()` instead. Note that in general the shared secret is not directly suitable for use as a key because it is biased. +* If the resulting shared secret will be used for a single key derivation, a :ref:`key derivation operation ` can be used with the `psa_key_derivation_key_agreement()` input function. This calculates the shared secret and inputs it directly to the key derivation operation. + +* Where an application needs direct access to the shared secret, it can call `psa_raw_key_agreement()` instead. + +Using `psa_key_agreement()` or `psa_key_derivation_key_agreement()` is recommended, as these do not expose the shared secret to the application. + +.. note:: + + In general the shared secret is not directly suitable for use as a key because it is biased. .. _key-agreement-algorithms: @@ -26,11 +34,11 @@ Key agreement algorithms .. summary:: The finite-field Diffie-Hellman (DH) key agreement algorithm. - This algorithm can be used directly in a call to `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. + This algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. When used as a key's permitted-algorithm policy, the following uses are permitted: - * In a call to `psa_raw_key_agreement()`, with algorithm `PSA_ALG_FFDH`. + * In a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, with algorithm `PSA_ALG_FFDH`. * In a call to `psa_key_derivation_key_agreement()`, with any combined key agreement and key derivation algorithm constructed with `PSA_ALG_FFDH`. When used as part of a multi-part key derivation operation, this implements a Diffie-Hellman key agreement scheme using a single Diffie-Hellman key-pair for each participant. This includes the *dhEphem*, *dhOneFlow*, and *dhStatic* schemes. The input step `PSA_KEY_DERIVATION_INPUT_SECRET` is used when providing the secret and peer keys to the operation. @@ -49,11 +57,11 @@ Key agreement algorithms .. summary:: The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - This algorithm can be used directly in a call to `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. + This algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. When used as a key's permitted-algorithm policy, the following uses are permitted: - * In a call to `psa_raw_key_agreement()`, with algorithm `PSA_ALG_ECDH`. + * In a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, with algorithm `PSA_ALG_ECDH`. * In a call to `psa_key_derivation_key_agreement()`, with any combined key agreement and key derivation algorithm constructed with `PSA_ALG_ECDH`. When used as part of a multi-part key derivation operation, this implements a Diffie-Hellman key agreement scheme using a single elliptic curve key-pair for each participant. This includes the *Ephemeral unified model*, the *Static unified model*, and the *One-pass Diffie-Hellman* schemes. The input step `PSA_KEY_DERIVATION_INPUT_SECRET` is used when providing the secret and peer keys to the operation. @@ -114,6 +122,90 @@ Key agreement algorithms Standalone key agreement ------------------------ +.. function:: psa_key_agreement + + .. summary:: + Perform a key agreement and return the shared secret as a derivation key. + + .. param:: psa_algorithm_t alg + The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. + .. param:: psa_key_id_t private_key + Identifier of the private key to use. + It must permit the usage `PSA_KEY_USAGE_DERIVE`. + .. param:: const uint8_t * peer_key + Public key of the peer. The peer key must be in the same format that `psa_import_key()` accepts for the public key type corresponding to the type of ``private_key``. That is, this function performs the equivalent of :code:`psa_import_key(..., peer_key, peer_key_length)`, with key attributes indicating the public key type corresponding to the type of ``private_key``. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation of `psa_export_public_key()`. + .. param:: size_t peer_key_length + Size of ``peer_key`` in bytes. + + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + This function uses the attributes as follows: + + * The key type must either be `PSA_KEY_TYPE_NONE` (``0``), or `PSA_KEY_TYPE_DERIVE`. :issue:`(Is this ok, or should we allow other unstructured (or just raw?) key types to be returned? Or should we mandate exactly one of those options, because the function always returns KEY_TYPE DERIVE?)` + * The key size must either be ``0``, or the size of the key agreement output, in bits. :issue:`(Is this ok, or should we mandate leaving as default zero? Or should we permit the secret to be truncated into the output key?)` + + The output size, in bits, of the key agreement is :code:`8 * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` is the type of ``private_key`` and ``bits`` is the bit-size of either ``private_key`` or the ``peer_key``. + + * The key permitted-algorithm policy is required for keys that will be used for a cryptographic operation, see :secref:`permitted-algorithms`. + * The key usage flags define what operations are permitted with the key, see :secref:`key-usage-flags`. + * The key lifetime and identifier are required for a persistent key. + + .. note:: + This is an input parameter: it is not updated with the final key attributes. The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. + + .. param:: psa_key_id_t * key + On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The new key contains the share secret. + If the key is persistent, the key material and the key's metadata have been saved to persistent storage. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``private_key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * ``private_key`` does not have the `PSA_KEY_USAGE_DERIVE` flag, or it does not permit the requested algorithm. + * The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key agreement algorithm. + * ``private_key`` is not compatible with ``alg``. + * ``peer_key`` is not a valid public key corresponding to ``private_key``. + * The output key attribuets in ``attributes`` are not valid : + + - The key type is neither `PSA_KEY_TYPE_NONE`, nor a valid type fo. + - The key size is neither ``0``, nor the correct output size for the algorithm. + - The key lifetime is invalid. + - The key identifier is not valid for the key lifetime. + - The key usage flags include invalid values. + - The key's permitted-usage algorithm is invalid. + - The key attributes, as a whole, are invalid. + + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key agreement algorithm. + * ``private_key`` is not supported for use with ``alg``. + * The output key attributes, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is returned as a derivation key, for use in a key derivation operation. + + .. warning:: + The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. + + The output of this function can be input to a key derivation operation using `psa_key_derivation_input_key()`. + .. function:: psa_raw_key_agreement .. summary:: @@ -146,6 +238,8 @@ Standalone key agreement The first ``(*output_length)`` bytes of ``output`` contain the raw shared secret. .. retval:: PSA_ERROR_INVALID_HANDLE ``private_key`` is not a valid key identifier. + .. retval:: PSA_ERROR_ALREADY_EXISTS + This is an attempt to create a persistent key, and there is already a persistent key with the given identifier. .. retval:: PSA_ERROR_NOT_PERMITTED ``private_key`` does not have the `PSA_KEY_USAGE_DERIVE` flag, or it does not permit the requested algorithm. .. retval:: PSA_ERROR_INVALID_ARGUMENT @@ -168,11 +262,16 @@ Standalone key agreement .. retval:: PSA_ERROR_STORAGE_FAILURE .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is returned in the ``output`` buffer. + .. warning:: - The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for use as key material. Instead it is recommended that the result is used as input to a key derivation algorithm. To chain a key agreement with a key derivation, use `psa_key_derivation_key_agreement()` and other functions from the key derivation interface. + The result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. + + To chain a key agreement with a key derivation, either use `psa_key_agreement()` to obtain the result of the key agreement as a derivation key, or use `psa_key_derivation_key_agreement()` and other functions from the key derivation interface. Combining key agreement and key derivation ------------------------------------------ @@ -228,6 +327,12 @@ Combining key agreement and key derivation If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_key_derivation_abort()`. + .. note:: + + This function cannot be used when the resulting shared secret is required for multiple key derivations. + + Instead, the application can call `psa_key_agreement()` to obtain the shared secret as a derivation key. This key can be used as input to as many key derivation operations as required. + Support macros -------------- diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 2eec8c15..6bf37408 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -21,6 +21,8 @@ Changes to the API * Changed the policy for `psa_key_derivation_verify_bytes()` and `psa_key_derivation_verify_key()`, so that these functions are also permitted when an input key has the `PSA_KEY_USAGE_DERIVE` usage flag. * Removed the special treatment of :code:`PSA_ERROR_INVALID_SIGNATURE` for key derivation operations. A verification failure in `psa_key_derivation_verify_bytes()` and `psa_key_derivation_verify_key()` now puts the operation into an error state. +* Added `psa_key_agreement()` for standalone key agreement that outputs to a new key object. + Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/crypto/overview/functionality.rst b/doc/crypto/overview/functionality.rst index ec4fa0f2..e6ea7974 100644 --- a/doc/crypto/overview/functionality.rst +++ b/doc/crypto/overview/functionality.rst @@ -339,7 +339,7 @@ This specification defines interfaces for the following types of asymmetric cryp * Asymmetric signature. See :secref:`sign`. * Two-way key agreement (also known as key establishment). See :secref:`key-agreement`. -For asymmetric encryption and signature, the API provides *single-part* functions. For key agreement, the API provides a single-part function and an additional input method for a key derivation operation. +For asymmetric encryption and signature, the API provides *single-part* functions. For key agreement, the API provides single-part functions and an additional input method for a key derivation operation. Randomness and key generation From 5c48afe702061b077754cf60156b4b1972713742 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 25 Sep 2023 14:19:40 +0100 Subject: [PATCH 02/12] Finalise psa_key_agreement attribute requirements Specify the key type and size constraints for the output. --- doc/crypto/api.db/psa/crypto.h | 6 ++++++ doc/crypto/api/ops/ka.rst | 19 ++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 58de38d9..0cea447a 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -485,6 +485,12 @@ psa_status_t psa_import_key(const psa_key_attributes_t * attributes, const uint8_t * data, size_t data_length, psa_key_id_t * key); +psa_status_t psa_key_agreement(psa_algorithm_t alg, + psa_key_id_t private_key, + const uint8_t * peer_key, + size_t peer_key_length, + const psa_key_attributes_t * attributes, + psa_key_id_t * key); psa_key_attributes_t psa_key_attributes_init(void); psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t * operation); psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t * operation, diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 6e7e7b44..22cfa1aa 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -141,8 +141,11 @@ Standalone key agreement The attributes for the new key. This function uses the attributes as follows: - * The key type must either be `PSA_KEY_TYPE_NONE` (``0``), or `PSA_KEY_TYPE_DERIVE`. :issue:`(Is this ok, or should we allow other unstructured (or just raw?) key types to be returned? Or should we mandate exactly one of those options, because the function always returns KEY_TYPE DERIVE?)` - * The key size must either be ``0``, or the size of the key agreement output, in bits. :issue:`(Is this ok, or should we mandate leaving as default zero? Or should we permit the secret to be truncated into the output key?)` + * The key type must be one of `PSA_KEY_TYPE_DERIVE`, `PSA_KEY_TYPE_RAW_DATA`, `PSA_KEY_TYPE_HMAC`, or `PSA_KEY_TYPE_PASSWORD`. + + Implementations must support the `PSA_KEY_TYPE_DERIVE` and `PSA_KEY_TYPE_RAW_DATA` key types. Support for output as `PSA_KEY_TYPE_HMAC` or `PSA_KEY_TYPE_PASSWORD` is :scterm:`implementation defined` . + + * The key size is always determined from the key agreement's shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. The output size, in bits, of the key agreement is :code:`8 * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` is the type of ``private_key`` and ``bits`` is the bit-size of either ``private_key`` or the ``peer_key``. @@ -176,8 +179,8 @@ Standalone key agreement * ``peer_key`` is not a valid public key corresponding to ``private_key``. * The output key attribuets in ``attributes`` are not valid : - - The key type is neither `PSA_KEY_TYPE_NONE`, nor a valid type fo. - - The key size is neither ``0``, nor the correct output size for the algorithm. + - The key type is not valid for key agreement output. + - The key size is nonzero, and is not the size of the shared secret. - The key lifetime is invalid. - The key identifier is not valid for the key lifetime. - The key usage flags include invalid values. @@ -199,13 +202,11 @@ Standalone key agreement .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. - A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is returned as a derivation key, for use in a key derivation operation. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, returned as a derivation key. The output of this function can be input to a key derivation operation using `psa_key_derivation_input_key()`. .. warning:: The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. - The output of this function can be input to a key derivation operation using `psa_key_derivation_input_key()`. - .. function:: psa_raw_key_agreement .. summary:: @@ -266,7 +267,7 @@ Standalone key agreement .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. - A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is returned in the ``output`` buffer. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, returned in the ``output`` buffer. .. warning:: The result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. @@ -323,7 +324,7 @@ Combining key agreement and key derivation .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID - A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is passed as input to the key derivation operation. The output of this key derivation can be extracted by reading from the resulting operation to produce keys and other cryptographic material. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, which is directly input to the key derivation operation. The output of the key derivation can be extracted by reading from the resulting operation to produce keys and other cryptographic material. If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_key_derivation_abort()`. From ee3a0370f28aa5ba52e301c2f77f5696d9ebca78 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 31 Oct 2023 13:08:33 +0000 Subject: [PATCH 03/12] Fix typo Signed-off-by: Andrew Thoelke --- doc/crypto/api/ops/ka.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 22cfa1aa..34124511 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -177,7 +177,7 @@ Standalone key agreement * ``alg`` is not a key agreement algorithm. * ``private_key`` is not compatible with ``alg``. * ``peer_key`` is not a valid public key corresponding to ``private_key``. - * The output key attribuets in ``attributes`` are not valid : + * The output key attributes in ``attributes`` are not valid : - The key type is not valid for key agreement output. - The key size is nonzero, and is not the size of the shared secret. From c9f71a2d2e25c2ed6256dbde7a76d7c10d1c11f0 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Thu, 2 Nov 2023 11:26:23 +0000 Subject: [PATCH 04/12] Reorder parameters for psa_key_agreement() --- doc/crypto/api.db/psa/crypto.h | 4 ++-- doc/crypto/api/ops/ka.rst | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 0cea447a..be039837 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -485,10 +485,10 @@ psa_status_t psa_import_key(const psa_key_attributes_t * attributes, const uint8_t * data, size_t data_length, psa_key_id_t * key); -psa_status_t psa_key_agreement(psa_algorithm_t alg, - psa_key_id_t private_key, +psa_status_t psa_key_agreement(psa_key_id_t private_key, const uint8_t * peer_key, size_t peer_key_length, + psa_algorithm_t alg, const psa_key_attributes_t * attributes, psa_key_id_t * key); psa_key_attributes_t psa_key_attributes_init(void); diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 34124511..9303afd8 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -127,8 +127,6 @@ Standalone key agreement .. summary:: Perform a key agreement and return the shared secret as a derivation key. - .. param:: psa_algorithm_t alg - The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. .. param:: psa_key_id_t private_key Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. @@ -136,7 +134,8 @@ Standalone key agreement Public key of the peer. The peer key must be in the same format that `psa_import_key()` accepts for the public key type corresponding to the type of ``private_key``. That is, this function performs the equivalent of :code:`psa_import_key(..., peer_key, peer_key_length)`, with key attributes indicating the public key type corresponding to the type of ``private_key``. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation of `psa_export_public_key()`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. - + .. param:: psa_algorithm_t alg + The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. .. param:: const psa_key_attributes_t * attributes The attributes for the new key. This function uses the attributes as follows: @@ -155,7 +154,6 @@ Standalone key agreement .. note:: This is an input parameter: it is not updated with the final key attributes. The final attributes of the new key can be queried by calling `psa_get_key_attributes()` with the key's identifier. - .. param:: psa_key_id_t * key On success, an identifier for the newly created key. `PSA_KEY_ID_NULL` on failure. From 5fcf37e77acf96c8f5df7b94884594800e5214e7 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 7 Nov 2023 21:31:15 +0000 Subject: [PATCH 05/12] Fix misplaced error returns --- doc/crypto/api/ops/ka.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 9303afd8..a9e94187 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -169,6 +169,8 @@ Standalone key agreement * ``private_key`` does not have the `PSA_KEY_USAGE_DERIVE` flag, or it does not permit the requested algorithm. * The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. + .. retval:: PSA_ERROR_ALREADY_EXISTS + This is an attempt to create a persistent key, and there is already a persistent key with the given identifier. .. retval:: PSA_ERROR_INVALID_ARGUMENT The following conditions can result in this error: @@ -197,6 +199,7 @@ Standalone key agreement .. retval:: PSA_ERROR_STORAGE_FAILURE .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. @@ -237,8 +240,6 @@ Standalone key agreement The first ``(*output_length)`` bytes of ``output`` contain the raw shared secret. .. retval:: PSA_ERROR_INVALID_HANDLE ``private_key`` is not a valid key identifier. - .. retval:: PSA_ERROR_ALREADY_EXISTS - This is an attempt to create a persistent key, and there is already a persistent key with the given identifier. .. retval:: PSA_ERROR_NOT_PERMITTED ``private_key`` does not have the `PSA_KEY_USAGE_DERIVE` flag, or it does not permit the requested algorithm. .. retval:: PSA_ERROR_INVALID_ARGUMENT @@ -261,7 +262,6 @@ Standalone key agreement .. retval:: PSA_ERROR_STORAGE_FAILURE .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID - .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. From 8b9df71050b59894517cd074a760ffcf7f49dbaf Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 7 Nov 2023 21:33:40 +0000 Subject: [PATCH 06/12] Add missing cross references --- doc/crypto/api/keys/policy.rst | 1 + doc/crypto/appendix/encodings.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/crypto/api/keys/policy.rst b/doc/crypto/api/keys/policy.rst index 456db482..626f7698 100644 --- a/doc/crypto/api/keys/policy.rst +++ b/doc/crypto/api/keys/policy.rst @@ -231,6 +231,7 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. This flag must be present on keys used with the following APIs: + * `psa_key_agreement()` * `psa_key_derivation_key_agreement()` * `psa_raw_key_agreement()` diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index 692673ce..b08c868e 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -348,7 +348,7 @@ a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash_alg``, used to constr Key agreement algorithm encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A key agreement algorithm identifier can either be for the raw key agreement algorithm, or for a combined key agreement with key derivation algorithm. The former can only be used with `psa_raw_key_agreement()`, while the latter are used with `psa_key_derivation_key_agreement()` and the shared secret is not exposed to the client. +A key agreement algorithm identifier can either be for the raw key agreement algorithm, or for a combined key agreement with key derivation algorithm. The former can only be used with `psa_key_agreement()` and `psa_raw_key_agreement()`, while the latter are used with `psa_key_derivation_key_agreement()` and the shared secret is not exposed to the client. The algorithm identifier for raw key agreement algorithms defined in this specification are encoded as shown in :numref:`fig-ka-raw-fields`. From 484aac943b92a86bc3612769b781bfef112e1f64 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 7 Nov 2023 22:25:11 +0000 Subject: [PATCH 07/12] Clarifications in parameter and result descriptions --- doc/crypto/api/keys/management.rst | 2 +- doc/crypto/api/ops/ka.rst | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/crypto/api/keys/management.rst b/doc/crypto/api/keys/management.rst index 5568098a..9d1b758d 100644 --- a/doc/crypto/api/keys/management.rst +++ b/doc/crypto/api/keys/management.rst @@ -523,7 +523,7 @@ Key export Key formats ----------- -This section defines the format of the key data that an implementation is required to support when importing and exporting keys. Keys can be imported using `psa_import_key()`, and exported using `psa_export_key()` or `psa_export_public_key()`. +This section defines the format of the key data that an implementation is required to support when importing and exporting keys. Keys can be imported using `psa_import_key()`, and exported using `psa_export_key()` or `psa_export_public_key()`. The public key formats are also used for the key agreement functions, see :secref:`key-agreement`. .. list-table:: Standard key formats :name: std-key-formats diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index a9e94187..b8c20b4d 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -131,7 +131,7 @@ Standalone key agreement Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key must be in the same format that `psa_import_key()` accepts for the public key type corresponding to the type of ``private_key``. That is, this function performs the equivalent of :code:`psa_import_key(..., peer_key, peer_key_length)`, with key attributes indicating the public key type corresponding to the type of ``private_key``. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation of `psa_export_public_key()`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. .. param:: psa_algorithm_t alg @@ -142,11 +142,11 @@ Standalone key agreement * The key type must be one of `PSA_KEY_TYPE_DERIVE`, `PSA_KEY_TYPE_RAW_DATA`, `PSA_KEY_TYPE_HMAC`, or `PSA_KEY_TYPE_PASSWORD`. - Implementations must support the `PSA_KEY_TYPE_DERIVE` and `PSA_KEY_TYPE_RAW_DATA` key types. Support for output as `PSA_KEY_TYPE_HMAC` or `PSA_KEY_TYPE_PASSWORD` is :scterm:`implementation defined` . + Implementations must support the `PSA_KEY_TYPE_DERIVE` and `PSA_KEY_TYPE_RAW_DATA` key types. - * The key size is always determined from the key agreement's shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. + * The key size is always determined from the key agreement's shared secret. If the key size in ``attributes`` is zero, the key is the size of the shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. - The output size, in bits, of the key agreement is :code:`8 * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` is the type of ``private_key`` and ``bits`` is the bit-size of either ``private_key`` or the ``peer_key``. + The output size, in bits, of the key agreement is :code:`8 * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` and ``bits`` are the type and bit-size of ``private_key``. * The key permitted-algorithm policy is required for keys that will be used for a cryptographic operation, see :secref:`permitted-algorithms`. * The key usage flags define what operations are permitted with the key, see :secref:`key-usage-flags`. @@ -203,7 +203,7 @@ Standalone key agreement .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. - A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, returned as a derivation key. The output of this function can be input to a key derivation operation using `psa_key_derivation_input_key()`. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, returned as a derivation key. This key can be input to a key derivation operation using `psa_key_derivation_input_key()`. .. warning:: The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. @@ -219,7 +219,7 @@ Standalone key agreement Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key must be in the same format that `psa_import_key()` accepts for the public key type corresponding to the type of ``private_key``. That is, this function performs the equivalent of :code:`psa_import_key(..., peer_key, peer_key_length)`, with key attributes indicating the public key type corresponding to the type of ``private_key``. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation of `psa_export_public_key()`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. .. param:: uint8_t * output @@ -228,7 +228,7 @@ Standalone key agreement Size of the ``output`` buffer in bytes. This must be appropriate for the keys: - * The required output size is :code:`PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)` where ``type`` is the type of ``private_key`` and ``bits`` is the bit-size of either ``private_key`` or the ``peer_key``. + * The required output size is :code:`PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` and ``bits`` are the type and bit-size of ``private_key``. * `PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported raw key agreement algorithm. .. param:: size_t * output_length @@ -290,7 +290,7 @@ Combining key agreement and key derivation Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key must be in the same format that `psa_import_key()` accepts for the public key type corresponding to the type of ``private_key``. That is, this function performs the equivalent of :code:`psa_import_key(..., peer_key, peer_key_length)`, with key attributes indicating the public key type corresponding to the type of ``private_key``. For example, for ECC keys, this means that peer_key is interpreted as a point on the curve that the private key is on. The standard formats for public keys are documented in the documentation of `psa_export_public_key()`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. @@ -322,7 +322,7 @@ Combining key agreement and key derivation .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID - A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, which is directly input to the key derivation operation. The output of the key derivation can be extracted by reading from the resulting operation to produce keys and other cryptographic material. + A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, which is directly input to the key derivation operation. Output from the key derivation operation can then be used as keys and other cryptographic material. If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_key_derivation_abort()`. From 1959504fb86162f1a3fe22ec74044f28a4b604a3 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 7 Nov 2023 22:58:59 +0000 Subject: [PATCH 08/12] Terminology improvement for key agreement * 'raw key agreement' -> 'standalone key agreement' * 'full key agreement' -> 'combined key agreement' --- doc/crypto/api/keys/policy.rst | 2 +- doc/crypto/api/ops/ka.rst | 42 +++++++++++++++---------------- doc/crypto/appendix/encodings.rst | 10 ++++---- doc/crypto/appendix/history.rst | 4 ++- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/doc/crypto/api/keys/policy.rst b/doc/crypto/api/keys/policy.rst index 626f7698..0a1f4d17 100644 --- a/doc/crypto/api/keys/policy.rst +++ b/doc/crypto/api/keys/policy.rst @@ -33,7 +33,7 @@ The following algorithm policies are supported: * `PSA_ALG_NONE` does not permit any cryptographic operation with the key. The key can still be used for non-cryptographic actions such as exporting, if permitted by the usage flags. * A specific algorithm value permits exactly that particular algorithm. * A signature algorithm constructed with `PSA_ALG_ANY_HASH` permits the specified signature scheme with any hash algorithm. In addition, :code:`PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)` also permits the `PSA_ALG_RSA_PKCS1V15_SIGN_RAW` signature algorithm. -* A raw key agreement algorithm also permits the specified key agreement scheme to be combined with any key derivation algorithm. +* A standalone key agreement algorithm also permits the specified key agreement scheme to be combined with any key derivation algorithm. * An algorithm built from `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC()` permits any MAC algorithm from the same base class (for example, CMAC) which computes or verifies a MAC length greater than or equal to the length encoded in the wildcard algorithm. * An algorithm built from `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG()` permits any AEAD algorithm from the same base class (for example, CCM) which computes or verifies a tag length greater than or equal to the length encoded in the wildcard algorithm. diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index b8c20b4d..21fae47b 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -9,7 +9,7 @@ Key agreement ============= -Three functions are provided for a Diffie-Hellman-style key agreement where each party combines its own private key with the peer’s public key: +Three functions are provided for a Diffie-Hellman-style key agreement where each party combines its own private key with the peer’s public key, to produce a shared secret value: * A call to `psa_key_agreement()` will compute the shared secret and store the result in a new derivation key. @@ -34,7 +34,7 @@ Key agreement algorithms .. summary:: The finite-field Diffie-Hellman (DH) key agreement algorithm. - This algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. + This standalone key agreement algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. When used as a key's permitted-algorithm policy, the following uses are permitted: @@ -57,7 +57,7 @@ Key agreement algorithms .. summary:: The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - This algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. + This standalone key agreement algorithm can be used directly in a call to `psa_key_agreement()` or `psa_raw_key_agreement()`, or combined with a key derivation operation using `PSA_ALG_KEY_AGREEMENT()` for use with `psa_key_derivation_key_agreement()`. When used as a key's permitted-algorithm policy, the following uses are permitted: @@ -116,7 +116,7 @@ Key agreement algorithms .. subsection:: Compatible key types - The resulting combined key agreement algorithm is compatible with the same key types as the raw key agreement algorithm used to construct it. + The resulting combined key agreement algorithm is compatible with the same key types as the standalone key agreement algorithm used to construct it. Standalone key agreement @@ -131,7 +131,7 @@ Standalone key agreement Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key_formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. .. param:: psa_algorithm_t alg @@ -206,12 +206,12 @@ Standalone key agreement A key agreement algorithm takes two inputs: a private key ``private_key``, and a public key ``peer_key``. The result of this function is a shared secret, returned as a derivation key. This key can be input to a key derivation operation using `psa_key_derivation_input_key()`. .. warning:: - The raw result of a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases, and is not suitable for direct use as key material, for example, as an AES key. Instead it is recommended that the result is used as input to a key derivation algorithm. + The shared secret resulting from a key agreement algorithm such as finite-field Diffie-Hellman or elliptic curve Diffie-Hellman has biases. This makes it unsuitable for use as key material, for example, as an AES key. Instead, it is recommended that a key derivation algorithm is applied to the result, to derive unbiased cryptographic keys. .. function:: psa_raw_key_agreement .. summary:: - Perform a key agreement and return the raw shared secret. + Perform a key agreement and return the shared secret. .. param:: psa_algorithm_t alg The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. @@ -219,17 +219,17 @@ Standalone key agreement Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key_formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. .. param:: uint8_t * output - Buffer where the raw shared secret is to be written. + Buffer where the shared secret is to be written. .. param:: size_t output_size Size of the ``output`` buffer in bytes. This must be appropriate for the keys: * The required output size is :code:`PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` and ``bits`` are the type and bit-size of ``private_key``. - * `PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported raw key agreement algorithm. + * `PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE` evaluates to the maximum output size of any supported standalone key agreement algorithm. .. param:: size_t * output_length On success, the number of bytes that make up the returned output. @@ -237,7 +237,7 @@ Standalone key agreement .. return:: psa_status_t .. retval:: PSA_SUCCESS Success. - The first ``(*output_length)`` bytes of ``output`` contain the raw shared secret. + The first ``(*output_length)`` bytes of ``output`` contain the shared secret. .. retval:: PSA_ERROR_INVALID_HANDLE ``private_key`` is not a valid key identifier. .. retval:: PSA_ERROR_NOT_PERMITTED @@ -290,7 +290,7 @@ Combining key agreement and key derivation Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. .. param:: const uint8_t * peer_key - Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key-formats`. + Public key of the peer. The peer key data is parsed with the type :code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)` where ``type`` is the type of ``private_key``, and with the same bit-size as ``private_key``. The peer key must be in the format that `psa_import_key()` accepts for this public key type. These formats are described in :secref:`key_formats`. .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. @@ -339,13 +339,13 @@ Support macros :definition: /* specification-defined value */ .. summary:: - Get the raw key agreement algorithm from a full key agreement algorithm. + Get the standalone key agreement algorithm from a combined key agreement and key derivation algorithm. .. param:: alg A key agreement algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_AGREEMENT(alg)` is true. .. return:: - The underlying raw key agreement algorithm if ``alg`` is a key agreement algorithm. + The underlying standalone key agreement algorithm if ``alg`` is a key agreement algorithm. Unspecified if ``alg`` is not a key agreement algorithm or if it is not supported by the implementation. @@ -355,7 +355,7 @@ Support macros :definition: /* specification-defined value */ .. summary:: - Get the key derivation algorithm used in a full key agreement algorithm. + Get the key derivation algorithm used in a combined key agreement and key derivation algorithm. .. param:: alg A key agreement algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_AGREEMENT(alg)` is true. @@ -371,17 +371,17 @@ Support macros :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is a raw key agreement algorithm. + Whether the specified algorithm is a standalone key agreement algorithm. .. param:: alg An algorithm identifier: a value of type `psa_algorithm_t`. .. return:: - ``1`` if ``alg`` is a raw key agreement algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + ``1`` if ``alg`` is a standalone key agreement algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. - A raw key agreement algorithm is one that does not specify a key derivation function. Usually, raw key agreement algorithms are constructed directly with a ``PSA_ALG_xxx`` macro while non-raw key agreement algorithms are constructed with `PSA_ALG_KEY_AGREEMENT()`. + A standalone key agreement algorithm is one that does not specify a key derivation function. Usually, standalone key agreement algorithms are constructed directly with a ``PSA_ALG_xxx`` macro while combined key agreement algorithms are constructed with `PSA_ALG_KEY_AGREEMENT()`. - The raw key agreement algorithm can be extracted from a full key agreement algorithm identifier using `PSA_ALG_KEY_AGREEMENT_GET_BASE()`. + The standalone key agreement algorithm can be extracted from a combined key agreement algorithm identifier using `PSA_ALG_KEY_AGREEMENT_GET_BASE()`. .. macro:: PSA_ALG_IS_FFDH :definition: /* specification-defined value */ @@ -395,7 +395,7 @@ Support macros .. return:: ``1`` if ``alg`` is a finite field Diffie-Hellman algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported key agreement algorithm identifier. - This includes the raw finite field Diffie-Hellman algorithm as well as finite-field Diffie-Hellman followed by any supported key derivation algorithm. + This includes the standalone finite field Diffie-Hellman algorithm, as well as finite-field Diffie-Hellman combined with any supported key derivation algorithm. .. macro:: PSA_ALG_IS_ECDH :definition: /* specification-defined value */ @@ -409,7 +409,7 @@ Support macros .. return:: ``1`` if ``alg`` is an elliptic curve Diffie-Hellman algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported key agreement algorithm identifier. - This includes the raw elliptic curve Diffie-Hellman algorithm as well as elliptic curve Diffie-Hellman followed by any supporter key derivation algorithm. + This includes the standalone elliptic curve Diffie-Hellman algorithm, as well as elliptic curve Diffie-Hellman combined with any supported key derivation algorithm. .. macro:: PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE :definition: /* implementation-defined value */ diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index b08c868e..dd1ed94f 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -348,14 +348,14 @@ a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash_alg``, used to constr Key agreement algorithm encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A key agreement algorithm identifier can either be for the raw key agreement algorithm, or for a combined key agreement with key derivation algorithm. The former can only be used with `psa_key_agreement()` and `psa_raw_key_agreement()`, while the latter are used with `psa_key_derivation_key_agreement()` and the shared secret is not exposed to the client. +A key agreement algorithm identifier can either be for the standalone key agreement algorithm, or for a combined key agreement with key derivation algorithm. The former can only be used with `psa_key_agreement()` and `psa_raw_key_agreement()`, while the latter are used with `psa_key_derivation_key_agreement()`. -The algorithm identifier for raw key agreement algorithms defined in this specification are encoded as shown in :numref:`fig-ka-raw-fields`. +The algorithm identifier for standalone key agreement algorithms defined in this specification are encoded as shown in :numref:`fig-ka-raw-fields`. .. figure:: ../figure/encoding/ka_raw.* :name: fig-ka-raw-fields - Raw key agreement algorithm encoding + Standalone key agreement algorithm encoding The defined values for KA-TYPE are shown in :numref:`table-ka-type`. @@ -369,13 +369,13 @@ The defined values for KA-TYPE are shown in :numref:`table-ka-type`. FFDH, ``0x01``, `PSA_ALG_FFDH`, ``0x09010000`` ECDH, ``0x02``, `PSA_ALG_ECDH`, ``0x09020000`` -A combined key agreement is constructed by a bitwise OR of the raw key agreement algorithm identifier and the key derivation algorithm identifier. This operation is provided by the `PSA_ALG_KEY_AGREEMENT()` macro. +A combined key agreement is constructed by a bitwise OR of the standalone key agreement algorithm identifier and the key derivation algorithm identifier. This operation is provided by the `PSA_ALG_KEY_AGREEMENT()` macro. .. figure:: ../figure/encoding/ka_combined.* Combined key agreement algorithm encoding -The underlying raw key agreement algorithm can be extracted from the KA-TYPE field, and the key derivation algorithm from the KDF-TYPE and HASH-TYPE fields. +The underlying standalone key agreement algorithm can be extracted from the KA-TYPE field, and the key derivation algorithm from the KDF-TYPE and HASH-TYPE fields. .. _key-type-encoding: diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 6bf37408..91537fe6 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -29,6 +29,8 @@ Clarifications and fixes * Clarified the behavior of a key derivation operation when there is insufficient capacity for a call to `psa_key_derivation_output_bytes()`, `psa_key_derivation_output_key()`, `psa_key_derivation_verify_bytes()`, or `psa_key_derivation_verify_key()`. * Reserved the value ``0`` for most enum-like integral types. +* Changed terminology for clarification: a 'raw key agreement' algorithm is now a 'standalone key agreement', and a 'full key agreement' is a 'combined key agreement'. + Other changes ~~~~~~~~~~~~~ @@ -71,7 +73,7 @@ Changes between *1.0.1* and *1.1.0* Changes to the API ~~~~~~~~~~~~~~~~~~ -* Relaxation when a raw key agreement is used as a key's permitted-algorithm policy. This now also permits the key agreement to be combined with any key derivation algorithm. See `PSA_ALG_FFDH` and `PSA_ALG_ECDH`. +* Relaxation when a standalone key agreement is used as a key's permitted-algorithm policy. This now also permits the key agreement to be combined with any key derivation algorithm. See `PSA_ALG_FFDH` and `PSA_ALG_ECDH`. * Provide wildcard permitted-algorithm polices for MAC and AEAD that can specify a minimum MAC or tag length. The following elements are added to the API: From d8946cd83d5b7ec69adb09d7f8c53f0b6c72c9c8 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 13 Nov 2023 14:58:59 +0000 Subject: [PATCH 09/12] Update xref to key agreement from key derivation --- doc/crypto/api/ops/kdf.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index fd742011..8355080f 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -218,7 +218,7 @@ Key derivation algorithms * The other secret depends on the key exchange specified in the cipher suite: - For a plain PSK cipher suite (:RFC:`4279#2`), omit `PSA_KEY_DERIVATION_INPUT_OTHER_SECRET`. - - For a DHE-PSK (:RFC:`4279#3`) or ECDHE-PSK cipher suite (:RFC-title:`5489#2`), the other secret should be the output of the `PSA_ALG_FFDH` or `PSA_ALG_ECDH` key agreement performed with the peer. The recommended way to pass this input is to use a key derivation algorithm constructed as :code:`PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg))` and to call `psa_key_derivation_key_agreement()`. Alternatively, this input may be an output of `psa_raw_key_agreement()` passed with `psa_key_derivation_input_bytes()`, or an equivalent input passed with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`. + - For a DHE-PSK (:RFC:`4279#3`) or ECDHE-PSK cipher suite (:RFC-title:`5489#2`), the other secret should be the output of the `PSA_ALG_FFDH` or `PSA_ALG_ECDH` key agreement performed with the peer. The recommended way to pass this input is to use a key derivation algorithm constructed as :code:`PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg))` and to call `psa_key_derivation_key_agreement()`. Alternatively, this input may be an output of `psa_key_agreement()` passed with `psa_key_derivation_input_key()`, or an equivalent input passed with `psa_key_derivation_input_bytes()` or `psa_key_derivation_input_key()`. - For a RSA-PSK cipher suite (:RFC:`4279#4`), the other secret should be the 48-byte client challenge (the ``PreMasterSecret`` of :RFC:`5246#7.4.7.1`) concatenation of the TLS version and a 46-byte random string chosen by the client. On the server, this is typically an output of `psa_asymmetric_decrypt()` using `PSA_ALG_RSA_PKCS1V15_CRYPT`, passed to the key derivation operation with `psa_key_derivation_input_bytes()`. * The label is ``"master secret"`` or ``"extended master secret"``. From 35a6e65fb70dc8763e59f87f51a2c48f98dc2a05 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 14 Nov 2023 15:15:22 +0000 Subject: [PATCH 10/12] Add PSA_ALG_IS_STANDALONE_KEY_AGREEMENT() Synonym for PSA_ALG_IS_RAW_KEY_AGREEMENT(). --- doc/crypto/api.db/psa/crypto.h | 5 ++++- doc/crypto/api/ops/ka.rst | 19 +++++++++++++++---- doc/crypto/appendix/history.rst | 2 +- doc/crypto/appendix/specdef_values.rst | 6 +++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index be039837..8d74b591 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -96,7 +96,8 @@ typedef /* implementation-defined type */ psa_mac_operation_t; #define PSA_ALG_IS_MAC(alg) /* specification-defined value */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) /* specification-defined value */ #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) /* specification-defined value */ -#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) /* specification-defined value */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) #define PSA_ALG_IS_RSA_OAEP(alg) /* specification-defined value */ #define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) /* specification-defined value */ #define PSA_ALG_IS_RSA_PSS(alg) /* specification-defined value */ @@ -105,6 +106,8 @@ typedef /* implementation-defined type */ psa_mac_operation_t; #define PSA_ALG_IS_SIGN(alg) /* specification-defined value */ #define PSA_ALG_IS_SIGN_HASH(alg) /* specification-defined value */ #define PSA_ALG_IS_SIGN_MESSAGE(alg) /* specification-defined value */ +#define PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) \ + /* specification-defined value */ #define PSA_ALG_IS_STREAM_CIPHER(alg) /* specification-defined value */ #define PSA_ALG_IS_TLS12_PRF(alg) /* specification-defined value */ #define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) /* specification-defined value */ diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 21fae47b..4c669d4c 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -135,7 +135,7 @@ Standalone key agreement .. param:: size_t peer_key_length Size of ``peer_key`` in bytes. .. param:: psa_algorithm_t alg - The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. + The standalone key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg)` is true. .. param:: const psa_key_attributes_t * attributes The attributes for the new key. This function uses the attributes as follows: @@ -214,7 +214,7 @@ Standalone key agreement Perform a key agreement and return the shared secret. .. param:: psa_algorithm_t alg - The key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is true. + The standalone key agreement algorithm to compute: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg)` is true. .. param:: psa_key_id_t private_key Identifier of the private key to use. It must permit the usage `PSA_KEY_USAGE_DERIVE`. @@ -281,7 +281,7 @@ Combining key agreement and key derivation Perform a key agreement and use the shared secret as input to a key derivation. .. param:: psa_key_derivation_operation_t * operation - The key derivation operation object to use. It must have been set up with `psa_key_derivation_setup()` with a key agreement and derivation algorithm ``alg``: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_AGREEMENT(alg)` is true and :code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)` is false. + The key derivation operation object to use. It must have been set up with `psa_key_derivation_setup()` with a combined key agreement and derivation algorithm ``alg``: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_AGREEMENT(alg)` is true and :code:`PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg)` is false. The operation must be ready for an input of the type given by ``step``. .. param:: psa_key_derivation_step_t step @@ -367,7 +367,7 @@ Support macros See also `PSA_ALG_KEY_AGREEMENT()` and `PSA_ALG_KEY_AGREEMENT_GET_BASE()`. -.. macro:: PSA_ALG_IS_RAW_KEY_AGREEMENT +.. macro:: PSA_ALG_IS_STANDALONE_KEY_AGREEMENT :definition: /* specification-defined value */ .. summary:: @@ -383,6 +383,17 @@ Support macros The standalone key agreement algorithm can be extracted from a combined key agreement algorithm identifier using `PSA_ALG_KEY_AGREEMENT_GET_BASE()`. +.. macro:: PSA_ALG_IS_RAW_KEY_AGREEMENT + :definition: PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) + + .. summary:: + Whether the specified algorithm is a standalone key agreement algorithm. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + This is the original API name for `PSA_ALG_IS_STANDALONE_KEY_AGREEMENT()`. + .. macro:: PSA_ALG_IS_FFDH :definition: /* specification-defined value */ diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 91537fe6..b967a83c 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -21,7 +21,7 @@ Changes to the API * Changed the policy for `psa_key_derivation_verify_bytes()` and `psa_key_derivation_verify_key()`, so that these functions are also permitted when an input key has the `PSA_KEY_USAGE_DERIVE` usage flag. * Removed the special treatment of :code:`PSA_ERROR_INVALID_SIGNATURE` for key derivation operations. A verification failure in `psa_key_derivation_verify_bytes()` and `psa_key_derivation_verify_key()` now puts the operation into an error state. -* Added `psa_key_agreement()` for standalone key agreement that outputs to a new key object. +* Added `psa_key_agreement()` for standalone key agreement that outputs to a new key object. Also added `PSA_ALG_IS_STANDALONE_KEY_AGREEMENT()` as a synonym for `PSA_ALG_IS_RAW_KEY_AGREEMENT()`. Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 71b863a2..29092a29 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -127,9 +127,6 @@ Algorithm macros #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000600) - #define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ - (((alg) & 0x7f00ffff) == 0x09000000) - #define PSA_ALG_IS_RSA_OAEP(alg) \ (((alg) & ~0x000000ff) == 0x07000300) @@ -155,6 +152,9 @@ Algorithm macros (PSA_ALG_IS_SIGN(alg) && \ (alg) != PSA_ALG_ECDSA_ANY && (alg) != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) + #define PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) \ + (((alg) & 0x7f00ffff) == 0x09000000) + #define PSA_ALG_IS_STREAM_CIPHER(alg) \ (((alg) & 0x7f800000) == 0x04800000) From 5f5a8e6d282d6a72f7698603eb1f49455f884174 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 17:21:38 +0000 Subject: [PATCH 11/12] Revert mistaken update in change history --- doc/crypto/appendix/history.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index b967a83c..80072b7c 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -73,7 +73,7 @@ Changes between *1.0.1* and *1.1.0* Changes to the API ~~~~~~~~~~~~~~~~~~ -* Relaxation when a standalone key agreement is used as a key's permitted-algorithm policy. This now also permits the key agreement to be combined with any key derivation algorithm. See `PSA_ALG_FFDH` and `PSA_ALG_ECDH`. +* Relaxation when a raw key agreement is used as a key's permitted-algorithm policy. This now also permits the key agreement to be combined with any key derivation algorithm. See `PSA_ALG_FFDH` and `PSA_ALG_ECDH`. * Provide wildcard permitted-algorithm polices for MAC and AEAD that can specify a minimum MAC or tag length. The following elements are added to the API: From a719ef3cb9e69193e6068f0ea3a1722cbe236d9d Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 17:36:26 +0000 Subject: [PATCH 12/12] Correct the key size returned by psa_key_agreement() --- doc/crypto/api/ops/ka.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/api/ops/ka.rst b/doc/crypto/api/ops/ka.rst index 4c669d4c..883fb94f 100644 --- a/doc/crypto/api/ops/ka.rst +++ b/doc/crypto/api/ops/ka.rst @@ -144,7 +144,7 @@ Standalone key agreement Implementations must support the `PSA_KEY_TYPE_DERIVE` and `PSA_KEY_TYPE_RAW_DATA` key types. - * The key size is always determined from the key agreement's shared secret. If the key size in ``attributes`` is zero, the key is the size of the shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. + * The size of the returned key is always the bit-size of the shared secret, rounded up to a whole number of bytes. The key size in ``attributes`` can be zero; if it is nonzero, it must be equal to the output size of the key agreement, in bits. The output size, in bits, of the key agreement is :code:`8 * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits)`, where ``type`` and ``bits`` are the type and bit-size of ``private_key``.