diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 8cc8cf5c..bd6ba5e5 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -76,6 +76,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_ECDH ((psa_algorithm_t)0x09020000) #define PSA_ALG_ECDSA(hash_alg) /* specification-defined value */ #define PSA_ALG_ECDSA_ANY ((psa_algorithm_t) 0x06000600) +#define PSA_ALG_ECIES_SEC1 ((psa_algorithm_t)0x0c000100) #define PSA_ALG_ED25519PH ((psa_algorithm_t) 0x0600090B) #define PSA_ALG_ED448PH ((psa_algorithm_t) 0x06000915) #define PSA_ALG_FFDH ((psa_algorithm_t)0x09010000) @@ -107,6 +108,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_KEY_DERIVATION(alg) /* specification-defined value */ #define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ /* specification-defined value */ +#define PSA_ALG_IS_KEY_ENCAPSULATION(alg) /* specification-defined value */ #define PSA_ALG_IS_MAC(alg) /* specification-defined value */ #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) /* specification-defined value */ @@ -221,6 +223,9 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) #define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) #define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) +#define PSA_ENCAPSULATE_CIPHERTEXT_MAX_SIZE /* implementation-defined value */ +#define PSA_ENCAPSULATE_CIPHERTEXT_SIZE(key_type, key_bits, alg) \ + /* implementation-defined value */ #define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) #define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) #define PSA_EXPORT_ASYMMETRIC_KEY_MAX_SIZE /* implementation-defined value */ @@ -498,7 +503,20 @@ psa_status_t psa_copy_key(psa_key_id_t source_key, const psa_key_attributes_t * attributes, psa_key_id_t * target_key); psa_status_t psa_crypto_init(void); +psa_status_t psa_decapsulate(psa_key_id_t key, + psa_algorithm_t alg, + const uint8_t * ciphertext, + size_t ciphertext_length, + const psa_key_attributes_t * attributes, + psa_key_id_t * output_key); psa_status_t psa_destroy_key(psa_key_id_t key); +psa_status_t psa_encapsulate(psa_key_id_t key, + psa_algorithm_t alg, + const psa_key_attributes_t * attributes, + psa_key_id_t * output_key, + uint8_t * ciphertext, + size_t ciphertext_size, + size_t * ciphertext_length); psa_status_t psa_export_key(psa_key_id_t key, uint8_t * data, size_t data_size, diff --git a/doc/crypto/api/keys/attributes.rst b/doc/crypto/api/keys/attributes.rst index 71a00fc8..63691dc5 100644 --- a/doc/crypto/api/keys/attributes.rst +++ b/doc/crypto/api/keys/attributes.rst @@ -112,7 +112,7 @@ Managing key attributes #. Set the key policy with `psa_set_key_usage_flags()` and `psa_set_key_algorithm()`. #. Set the key type with `psa_set_key_type()`. Skip this step if copying an existing key with `psa_copy_key()`. #. When generating a random key with `psa_generate_key()` or `psa_generate_key_custom()`, or deriving a key with `psa_key_derivation_output_key()` or `psa_key_derivation_output_key_custom()`, set the desired key size with `psa_set_key_bits()`. - #. Call a key creation function: `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. This function reads the attribute object, creates a key with these attributes, and outputs an identifier for the newly created key. + #. Call a key creation function: `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_encapsulate()`, `psa_decapsulate()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. This function reads the attribute object, creates a key with these attributes, and outputs an identifier for the newly created key. #. Optionally call `psa_reset_key_attributes()`, now that the attribute object is no longer needed. Currently this call is not required as the attributes defined in this specification do not require additional resources beyond the object itself. A typical sequence to query a key's attributes is as follows: diff --git a/doc/crypto/api/keys/ids.rst b/doc/crypto/api/keys/ids.rst index ed537b90..e5a586fa 100644 --- a/doc/crypto/api/keys/ids.rst +++ b/doc/crypto/api/keys/ids.rst @@ -92,7 +92,7 @@ Attribute accessors If the attribute object currently declares the key as volatile, which is the default lifetime of an attribute object, this function sets the lifetime attribute to `PSA_KEY_LIFETIME_PERSISTENT`. - This function does not access storage, it merely stores the given value in the attribute object. The persistent key will be written to storage when the attribute object is passed to a key creation function such as `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. + This function does not access storage, it merely stores the given value in the attribute object. The persistent key will be written to storage when the attribute object is passed to a key creation function such as `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_encapsulate()`, `psa_decapsulate()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. .. admonition:: Implementation note diff --git a/doc/crypto/api/keys/lifetimes.rst b/doc/crypto/api/keys/lifetimes.rst index 300a5cb3..21bc7656 100644 --- a/doc/crypto/api/keys/lifetimes.rst +++ b/doc/crypto/api/keys/lifetimes.rst @@ -273,7 +273,7 @@ Attribute accessors To make a key persistent, give it a persistent key identifier by using `psa_set_key_id()`. By default, a key that has a persistent identifier is stored in the default storage area identifier by `PSA_KEY_LIFETIME_PERSISTENT`. Call this function to choose a storage area, or to explicitly declare the key as volatile. - This function does not access storage, it merely stores the given value in the attribute object. The persistent key will be written to storage when the attribute object is passed to a key creation function such as `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. + This function does not access storage, it merely stores the given value in the attribute object. The persistent key will be written to storage when the attribute object is passed to a key creation function such as `psa_import_key()`, `psa_generate_key()`, `psa_generate_key_custom()`, `psa_key_derivation_output_key()`, `psa_key_derivation_output_key_custom()`, `psa_key_agreement()`, `psa_encapsulate()`, `psa_decapsulate()`, `psa_pake_get_shared_key()`, or `psa_copy_key()`. .. admonition:: Implementation note diff --git a/doc/crypto/api/keys/management.rst b/doc/crypto/api/keys/management.rst index b6a7391c..7b72ef67 100644 --- a/doc/crypto/api/keys/management.rst +++ b/doc/crypto/api/keys/management.rst @@ -18,6 +18,7 @@ New keys can be created in the following ways: * `psa_generate_key()` and `psa_generate_key_custom()` create a key from randomly generated data. * `psa_key_derivation_output_key()` and `psa_key_derivation_output_key_custom()` create a key from data generated by a pseudorandom derivation process. See :secref:`kdf`. * `psa_key_agreement()` creates a key from the shared secret result of a key agreement process. See :secref:`key-agreement`. +* `psa_encapsulate()` and `psa_decapsulate()` create a shared secret key using a key-encapsulation mechanism. * `psa_pake_get_shared_key()` creates a key from the shared secret result of a password-authenticated key exchange. See :secref:`pake`. * `psa_copy_key()` duplicates an existing key with a different lifetime or with a more restrictive usage policy. diff --git a/doc/crypto/api/keys/policy.rst b/doc/crypto/api/keys/policy.rst index 40b56db2..45b83ea6 100644 --- a/doc/crypto/api/keys/policy.rst +++ b/doc/crypto/api/keys/policy.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2018-2023 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2018-2024 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. header:: psa/crypto @@ -86,7 +86,16 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. * The extractable flag `PSA_KEY_USAGE_EXPORT` determines whether the key material can be extracted from the cryptoprocessor, or copied outside of its current security boundary. * The copyable flag `PSA_KEY_USAGE_COPY` determines whether the key material can be copied into a new key, which can have a different lifetime or a more restrictive policy. * The cacheable flag `PSA_KEY_USAGE_CACHE` determines whether the implementation is permitted to retain non-essential copies of the key material in RAM. This policy only applies to persistent keys. See also :secref:`key-material`. -* The other usage flags, for example, `PSA_KEY_USAGE_ENCRYPT` and `PSA_KEY_USAGE_SIGN_MESSAGE`, determine whether the corresponding operation is permitted on the key. +* The following usage flags determine whether the corresponding operations are permitted with the key: + + - `PSA_KEY_USAGE_ENCRYPT` + - `PSA_KEY_USAGE_DECRYPT` + - `PSA_KEY_USAGE_SIGN_MESSAGE` + - `PSA_KEY_USAGE_VERIFY_MESSAGE` + - `PSA_KEY_USAGE_SIGN_HASH` + - `PSA_KEY_USAGE_VERIFY_HASH` + - `PSA_KEY_USAGE_DERIVE` + - `PSA_KEY_USAGE_VERIFY_DERIVATION` .. typedef:: uint32_t psa_key_usage_t @@ -142,15 +151,16 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. :definition: ((psa_key_usage_t)0x00000100) .. summary:: - Permission to encrypt a message with the key. + Permission to encrypt a message, or perform key encapsulation, with the key. - This flag is required to use the key in a symmetric encryption operation, in an AEAD encryption-and-authentication operation, or in an asymmetric encryption operation. The flag must be present on keys used with the following APIs: + This flag is required to use the key in a symmetric encryption operation, in an AEAD encryption-and-authentication operation, in an asymmetric encryption operation, or in a key-encapsulation operation. The flag must be present on keys used with the following APIs: * `psa_cipher_encrypt()` * `psa_cipher_encrypt_setup()` * `psa_aead_encrypt()` * `psa_aead_encrypt_setup()` * `psa_asymmetric_encrypt()` + * `psa_encapsulate()` For a key pair, this concerns the public key. @@ -158,15 +168,16 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. :definition: ((psa_key_usage_t)0x00000200) .. summary:: - Permission to decrypt a message with the key. + Permission to decrypt a message, or perform key decapsulation, with the key. - This flag is required to use the key in a symmetric decryption operation, in an AEAD decryption-and-verification operation, or in an asymmetric decryption operation. The flag must be present on keys used with the following APIs: + This flag is required to use the key in a symmetric decryption operation, in an AEAD decryption-and-verification operation, in an asymmetric decryption operation, or in a key-decapsulation operation. The flag must be present on keys used with the following APIs: * `psa_cipher_decrypt()` * `psa_cipher_decrypt_setup()` * `psa_aead_decrypt()` * `psa_aead_decrypt_setup()` * `psa_asymmetric_decrypt()` + * `psa_decapsulate()` For a key pair, this concerns the private key. diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index ea18391c..7f1c7f83 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -797,7 +797,7 @@ The curve type affects the key format, the key derivation procedure, and the alg * - Curve type - Compatible algorithms * - Weierstrass - - Weierstrass curve key-pairs can be used in asymmetric signature and key agreement algorithms. + - Weierstrass curve key-pairs can be used in asymmetric signature, key agreement, and key-encapsulation algorithms. `PSA_ALG_DETERMINISTIC_ECDSA` @@ -806,10 +806,16 @@ The curve type affects the key format, the key derivation procedure, and the alg `PSA_ALG_ECDSA_ANY` `PSA_ALG_ECDH` + + `PSA_ALG_ECIES_SEC1` + * - Montgomery - - Montgomery curve key-pairs can only be used in key agreement algorithms. + - Montgomery curve key-pairs can be used in key agreement and key-encapsulation algorithms. `PSA_ALG_ECDH` + + `PSA_ALG_ECIES_SEC1` + * - Twisted Edwards - Twisted Edwards curve key-pairs can only be used in asymmetric signature algorithms. @@ -920,7 +926,7 @@ The curve type affects the key format, the key derivation procedure, and the alg * - Curve type - Compatible algorithms * - Weierstrass - - Weierstrass curve public keys can be used in asymmetric signature algorithms. + - Weierstrass curve public keys can be used in asymmetric signature and key-encapsulation algorithms. `PSA_ALG_DETERMINISTIC_ECDSA` @@ -928,8 +934,15 @@ The curve type affects the key format, the key derivation procedure, and the alg `PSA_ALG_ECDSA_ANY` + `PSA_ALG_ECIES_SEC1` + + * - Montgomery + - Montgomery curve public keys can only be used in key-encapsulation algorithms. + + `PSA_ALG_ECIES_SEC1` + * - Twisted Edwards - - Twisted Edwards curve public key can only be used in asymmetric signature algorithms. + - Twisted Edwards curve public keys can only be used in asymmetric signature algorithms. `PSA_ALG_PURE_EDDSA` diff --git a/doc/crypto/api/ops/algorithms.rst b/doc/crypto/api/ops/algorithms.rst index 8a5cd299..4897255e 100644 --- a/doc/crypto/api/ops/algorithms.rst +++ b/doc/crypto/api/ops/algorithms.rst @@ -23,6 +23,7 @@ The specific algorithm identifiers are described alongside the cryptographic ope * :secref:`sign` * :secref:`asymmetric-encryption-algorithms` * :secref:`key-agreement-algorithms` +* :secref:`key-encapsulation-algorithms` * :secref:`pake` @@ -193,6 +194,20 @@ Algorithm categories ``1`` if ``alg`` is a password-authenticated key exchange (PAKE) algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. +.. macro:: PSA_ALG_IS_KEY_ENCAPSULATION + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a key-encapsulation algorithm. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a key-encapsulation algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + + See :secref:`key-encapsulation-algorithms` for a list of defined key-encapsulation algorithms. + Support macros -------------- diff --git a/doc/crypto/api/ops/index.rst b/doc/crypto/api/ops/index.rst index 903c79cf..d7f1b458 100644 --- a/doc/crypto/api/ops/index.rst +++ b/doc/crypto/api/ops/index.rst @@ -18,5 +18,6 @@ Cryptographic operation reference signature pk-encryption key-agreement + key-encapsulation pake rng diff --git a/doc/crypto/api/ops/key-encapsulation.rst b/doc/crypto/api/ops/key-encapsulation.rst new file mode 100644 index 00000000..8fd3af80 --- /dev/null +++ b/doc/crypto/api/ops/key-encapsulation.rst @@ -0,0 +1,384 @@ +.. SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +.. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license + +.. header:: psa/crypto + :seq: 29 + +.. _key-encapsulation: + +Key encapsulation +================= + +A key-encapsulation algorithm can be used by two participants to establish a shared secret key over a public channel. +The shared secret key can then be used with symmetric-key cryptographic algorithms. +Key-encapsulation algorithms are often referred to as 'key-encapsulation mechanisms' or KEMs. + +In a key-encapsulation algorithm, participants A and B establish a shared secret as follows: + +1. Participant A generates a key-pair: a private decapsulation key, and a public encapsulation key. +#. The public encapsulation key is made available to participant B. +#. Participant B uses the encapsulation key to generate one copy of a shared secret, and some ciphertext. +#. The ciphertext is transferred to participant A. +#. Participant A uses the private decapsulation key to compute another copy of the shared secret. + +Typically, the shared secret is used as input to a key-derivation function, to create keys for secure communication between participants A and B. +However, some key-encapsulation algorithms result in a uniformly pseudorandom shared secret, which is suitable to be used directly as a cryptographic key. + +Applications can use the resulting keys for different use cases. +For example: + +* Encrypting and authenticating a single non-interactive message from participant B to participant A. +* Securing an interactive communication channel between participants A and B. + +.. _key-encapsulation-algorithms: + +Elliptic Curve Integrated Encryption Scheme +------------------------------------------- + +The Elliptic Curve Integrated Encryption Scheme (ECIES) was first proposed by Shoup, then improved by Ballare and Rogaway. + +The original specification permitted a number of variants. +The |API| uses the version specified in :cite-title:`SEC1`. + +The full ECIES scheme uses an elliptic-curve key agreement between the recipient's static public key and an ephemeral private key, to establish encryption and authentication keys for secure transmission of arbitrary-length messages to the recipient. + +An application using ECIES must select all of the following parameters: + +* The elliptic curve for the initial key agreement. +* The KDF to derive the symmetric keys, and any label used in that derivation. +* The encryption and MAC algorithms. +* The additional data to include when computing the authentication. + +The |API| presents the key-agreement step of ECIES as a key-encapsulation algorithm. +The key derivation, encryption, and authentication steps are left to the application. + +.. rationale:: + + Although it is possible to implement this in an application using key generation and key agreement, using the key-encapsulation functions enables an easy migration to other key-encapsulation algorithms, such as ML-KEM. + +.. admonition:: Implementation note + + It is possible that some applications may need to use alternative versions of ECIES to interoperate with legacy systems. + + While the application can implement this using key agreement functions, an implementation can choose to add these as a convenience with an :scterm:`implementation defined` key-encapsulation algorithm identifier. + +.. macro:: PSA_ALG_ECIES_SEC1 + :definition: ((psa_algorithm_t)0x0c000100) + + .. summary:: + The Elliptic Curve Integrated Encryption Scheme (ECIES). + + This key-encapsulation algorithm is defined by :cite-title:`SEC1` §5.1 under the name Elliptic Curve Integrated Encryption Scheme. + + A call to `psa_encapsulate()` carries out steps 1 to 4 of the ECIES encryption process described in `[SEC1]` §5.1.3: + + * The elliptic curve to use is determined by the key. + * The public key part of the input key is used as :math:`Q_V`. + * Cofactor ECDH is used to perform the key agreement. + * The octet string :math:`Z` is output as the shared secret key. + * The ephemeral public key :math:`\overline{R}` is output as the ciphertext. + + A call to `psa_decapsulate()` carries out steps 2 to 5 of the ECIES decryption process described in `[SEC1]` §5.1.4: + + * The elliptic curve to use is determined by the key. + * The ciphertext is decoded as :math:`\overline{R}`. + * The private key of the input key is used as :math:`d_V`. + * Cofactor ECDH is used to perform the key agreement. + * The octet string :math:`Z` is output as the shared secret key. + + The ciphertext produced by `PSA_ALG_ECIES_SEC1` is not authenticated. + In the full ECIES scheme, the authentication of the encrypted message using a key derived from the shared secret provides assurance that the message has not been manipulated. + + The shared secret key that is produced by `PSA_ALG_ECIES_SEC1` is not suitable for use as an encryption key. + It must be used as an input to a key derivation operation to produce additional cryptographic keys. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_ECC_KEY_PAIR(family)` + | :code:`PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)` (encapsulaton only) + + where ``family`` is a Weierstrass or Montgomery Elliptic curve family. + That is, one of the following values: + + * ``PSA_ECC_FAMILY_SECT_XX`` + * ``PSA_ECC_FAMILY_SECP_XX`` + * `PSA_ECC_FAMILY_FRP` + * `PSA_ECC_FAMILY_BRAINPOOL_P_R1` + * `PSA_ECC_FAMILY_MONTGOMERY` + +Key-encapsulation functions +--------------------------- + +.. function:: psa_encapsulate + + .. summary:: + Use a public key to generate a new shared secret key and associated ciphertext. + + .. param:: psa_key_id_t key + Identifier of the key to use for the encapsulation. + It must be a public key or an asymmetric key pair. + It must permit the usage `PSA_KEY_USAGE_ENCRYPT`. + .. param:: psa_algorithm_t alg + The key-encapsulation algorithm to use: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_ENCAPSULATION(alg)` is true. + .. param:: const psa_key_attributes_t * attributes + The attributes for the output key. + This function uses the attributes as follows: + + * The key type. + All key-encapsulation algorithms can output a key of type :code:`PSA_KEY_TYPE_DERIVE` or :code:`PSA_KEY_TYPE_HMAC`. + Key-encapsulation algorithms that produce a uniformly pseudorandom shared secret, can also output block-cipher key types, for example :code:`PSA_KEY_TYPE_AES`. + Refer to the documentation of individual key-encapsulation algorithms for more information. + + The following attributes must be set for keys used in cryptographic operations: + + * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. + * The key usage flags, see :secref:`key-usage-flags`. + + The following attributes must be set for keys that do not use the default volatile lifetime: + + * The key lifetime, see :secref:`key-lifetimes`. + * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. + + The following attributes are optional: + + * If the key size is nonzero, it must be equal to the size, in bits, of the shared secret. + + .. 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 * output_key + On success, an identifier for the newly created shared secret key. + `PSA_KEY_ID_NULL` on failure. + .. param:: uint8_t * ciphertext + Buffer where the ciphertext output is to be written. + .. param:: size_t ciphertext_size + Size of the ``ciphertext`` buffer in bytes. + This must be appropriate for the selected algorithm and key: + + * A sufficient ciphertext size is :code:`PSA_ENCAPSULATE_CIPHERTEXT_SIZE(type, bits, alg)`, where ``type`` and ``bits`` are the type and bit-size of ``key``. + * `PSA_ENCAPSULATE_CIPHERTEXT_MAX_SIZE` evaluates to the maximum ciphertext size of any supported key-encapsulation algorithm. + .. param:: size_t * ciphertext_length + On success, the number of bytes that make up the ciphertext value. + + .. return:: psa_status_t + + .. retval:: PSA_SUCCESS + Success. + The bytes of ``ciphertext`` contain the data to be sent to the other participant, and ``output_key`` contains the identifier for the shared secret key. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * ``key`` does not have the `PSA_KEY_USAGE_ENCRYPT` 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_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-encapsulation algorithm. + * ``key`` is not supported for use with ``alg``. + * The output key attributes in ``attributes``, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key-encapsulation algorithm. + * ``key`` is not a public key or an asymmetric key pair, that is compatible with ``alg``. + * The output key attributes in ``attributes`` are not valid: + + - The key type is not valid for the shared secret. + - 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. + - The key's permitted-usage algorithm is invalid. + - The key attributes, as a whole, are invalid. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``ciphertext`` buffer is too small. + `PSA_ENCAPSULATE_CIPHERTEXT_SIZE()` or `PSA_ENCAPSULATE_CIPHERTEXT_MAX_SIZE` can be used to determine a sufficient buffer size. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_ENTROPY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. 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()`. + + The ``output_key`` location, policy, and type are taken from ``attributes``. + + The size of the returned key is always the bit-size of the shared secret, rounded up to a whole number of bytes. + The size of the shared secret is dependent on the key-encapsulation algorithm and the type and size of ``key``. + + It is recommended that the shared secret key is used as an input to a key derivation operation to produce additional cryptographic keys. + For some key-encapsulation algorithms, the shared secret key is also suitable for use as a key in cryptographic operations such as encryption. + Refer to the documentation of individual key-encapsulation algorithms for more information. + + The output ``ciphertext`` is to be sent to the other participant, who uses the decapsulation key to extract another copy of the shared secret key. + +.. function:: psa_decapsulate + + .. summary:: + Use a private key to decapsulate a shared secret key from a ciphertext. + + .. param:: psa_key_id_t key + Identifier of the key to use for the decapsulation. + It must be an asymmetric key pair. + It must permit the usage `PSA_KEY_USAGE_DECRYPT`. + .. param:: psa_algorithm_t alg + The key-encapsulation algorithm to use: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_ENCAPSULATION(alg)` is true. + .. param:: const uint8_t * ciphertext + The ciphertext received from the other participant. + .. param:: size_t ciphertext_length + Size of the ``ciphertext`` buffer in bytes. + .. param:: const psa_key_attributes_t * attributes + The attributes for the output key. + This function uses the attributes as follows: + + * The key type. + All key-encapsulation algorithms can output a key of type :code:`PSA_KEY_TYPE_DERIVE` or :code:`PSA_KEY_TYPE_HMAC`. + Key-encapsulation algorithms that produce a uniformly pseudorandom shared secret, can also output block-cipher key types, for example :code:`PSA_KEY_TYPE_AES`. + Refer to the documentation of individual key-encapsulation algorithms for more information. + + The following attributes must be set for keys used in cryptographic operations: + + * The key permitted-algorithm policy, see :secref:`permitted-algorithms`. + * The key usage flags, see :secref:`key-usage-flags`. + + The following attributes must be set for keys that do not use the default volatile lifetime: + + * The key lifetime, see :secref:`key-lifetimes`. + * The key identifier is required for a key with a persistent lifetime, see :secref:`key-identifiers`. + + The following attributes are optional: + + * If the key size is nonzero, it must be equal to the size, in bits, of the shared secret. + + .. 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 * output_key + On success, an identifier for the newly created shared secret key. + `PSA_KEY_ID_NULL` on failure. + + .. return:: psa_status_t + + .. retval:: PSA_SUCCESS + Success. + ``output_key`` contains the identifier for the shared secret key. + + .. note:: + In some key-encapsulation algorithms, decapsulation failure is not reported with a explicit error code. + Instead, an incorrect, pseudorandom key is output. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * ``key`` does not have the `PSA_KEY_USAGE_DECRYPT` 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_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-encapsulation algorithm. + * ``key`` is not supported for use with ``alg``. + * The output key attributes in ``attributes``, as a whole, are not supported, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key-encapsulation algorithm. + * ``key`` is not an asymmetric key pair, that is compatible with ``alg``. + * The output key attributes in ``attributes`` are not valid: + + - The key type is not valid for the shared secret. + - 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. + - The key's permitted-usage algorithm is invalid. + - The key attributes, as a whole, are invalid. + * ``ciphertext`` is obviously invalid for the selected algorithm and key. + For example, the implementation can detect that it has an incorrect length. + .. retval:: PSA_ERROR_INVALID_SIGNATURE + Authentication of the ciphertext fails. + + .. note:: + Some key-encapsulation algorithms do not report an authentication failure explicitly. + Instead, an incorrect, pseudorandom key is output. + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_ENTROPY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. 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()`. + + The ``output_key`` location, policy, and type are taken from ``attributes``. + + The size of the returned key is always the bit-size of the shared secret, rounded up to a whole number of bytes. + The size of the shared secret is dependent on the key-encapsulation algorithm and the type and size of ``key``. + + It is recommended that the shared secret key is used as an input to a key derivation operation to produce additional cryptographic keys. + For some key-encapsulation algorithms, the shared secret key is also suitable for use as a key in cryptographic operations such as encryption. + Refer to the documentation of individual key-encapsulation algorithms for more information. + + If the key-encapsulation protocol is executed correctly then, with overwhelming probability, the two copies of the shared secret are identical. + However, the protocol does not protect one participant against the other participant executing it incorrectly, or against a third party modifying data in transit. + + .. warning:: + A :code:`PSA_SUCCESS` result from `psa_decapsulate()` does not guarantee that the output key is identical to the key produced by the call to `psa_encapsulate()`. For example, :code:`PSA_SUCCESS` can be returned with a mismatched shared secret key value in the following situations: + + * The key-encapsulation algorithm does not authenticate the ciphertext. + Manipulated or corrupted ciphertext will not be detected during decapsulation. + * The key-encapsulation algorithm reports authentication failure implicitly, by returning a pseudorandom key value. + This is done to prevent disclosing information to an attacker that has manipulated the ciphertext. + * The key-encapsulation algorithm is probablistic, and will *extremely* rarely result in non-identical key values. + + It is strongly recommended that the application uses the output key in a way that will confirm that the shared secret keys are identical. + + .. admonition:: Implementation note + + For key-encapsulation algorithms which involve data padding when computing the ciphertext, the decapsulation algorithm **must not** report a distinct error status if invalid padding is detected. + + Instead, it is recommended that the decapsulation fails implicitly when invalid padding is detected, returning a pseudorandom key. + +Support macros +-------------- + +.. macro:: PSA_ENCAPSULATE_CIPHERTEXT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient ciphertext buffer size for `psa_encapsulate()`, in bytes. + + .. param:: key_type + A key type that is compatible with algorithm ``alg``. + .. param:: key_bits + The size of the key in bits. + .. param:: alg + A key-encapsulation algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_ENCAPSULATION(alg)` is true. + + .. return:: + A sufficient ciphertext buffer size for the specified algorithm, key type, and size. An implementation can return either ``0`` or a correct size for an algorithm, key type, and size that it recognizes, but does not support. If the parameters are not valid, the return value is unspecified. + + If the size of the ciphertext buffer is at least this large, it is guaranteed that `psa_encapsulate()` will not fail due to an insufficient buffer size. The actual size of the ciphertext might be smaller in any given call. + + See also `PSA_ENCAPSULATE_CIPHERTEXT_MAX_SIZE`. + +.. macro:: PSA_ENCAPSULATE_CIPHERTEXT_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient ciphertext buffer size for `psa_encapsulate()`, for any of the supported key types and key-encapsulation algorithms. + + If the size of the ciphertext buffer is at least this large, it is guaranteed that `psa_encapsulate()` will not fail due to an insufficient buffer size. + + See also `PSA_ENCAPSULATE_CIPHERTEXT_SIZE()`. diff --git a/doc/crypto/api/ops/pake.rst b/doc/crypto/api/ops/pake.rst index eb02d3a8..4274b973 100644 --- a/doc/crypto/api/ops/pake.rst +++ b/doc/crypto/api/ops/pake.rst @@ -1022,7 +1022,7 @@ Multi-part PAKE operations The shared secret is retrieved as a key. Its location, policy, and type are taken from ``attributes``. - The size of the returned key is always the bit-size of the PAKE shared secret, rounded up to a whole number of bytes. The size is of the shared secret is dependent on the PAKE algorithm and cipher suite. + The size of the returned key is always the bit-size of the PAKE shared secret, rounded up to a whole number of bytes. The size of the shared secret is dependent on the PAKE algorithm and cipher suite. This is the final call in a PAKE operation, which retrieves the shared secret as a key. It is recommended that this key is used as an input to a key derivation operation to produce additional cryptographic keys. diff --git a/doc/crypto/api/ops/rng.rst b/doc/crypto/api/ops/rng.rst index ffb2202c..c2f6dfe9 100644 --- a/doc/crypto/api/ops/rng.rst +++ b/doc/crypto/api/ops/rng.rst @@ -2,7 +2,7 @@ .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. header:: psa/crypto - :seq: 30 + :seq: 31 Other cryptographic services ============================ diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index a1784f9a..ffbc81a6 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -83,6 +83,7 @@ The CAT field in an algorithm identifier takes the values shown in :numref:`tabl Asymmetric signature, ``0x06``, See :secref:`sign-encoding` Asymmetric encryption, ``0x07``, See :secref:`pke-encoding` Key agreement, ``0x09``, See :secref:`ka-encoding` + Key encapsulation, ``0x0C``, See :secref:`key-encapsulation-encoding` PAKE, ``0x0A``, See :secref:`pake-encoding` .. rationale:: @@ -386,6 +387,29 @@ A combined key agreement is constructed by a bitwise OR of the standalone key ag 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-encapsulation-encoding: + +Key-encapsulation algorithm encoding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The algorithm identifier for key-encapsulation algorithms defined in this specification are encoded as shown in :numref:`fig-key-encapsulation-encoding`. + +.. figure:: /figure/encoding/kem_encoding.* + :name: fig-key-encapsulation-encoding + + Encapsulation algorithm encoding + +The defined values for ENCAPS-TYPE are shown in :numref:`table-key-encapsulation-type`. + +.. csv-table:: Encapsulation algorithm sub-type values + :name: table-key-encapsulation-type + :header-rows: 1 + :align: left + :widths: auto + + Encapsulation algorithm, ENCAPS-TYPE, Algorithm identifier, Algorithm value + ECIES (SEC1), ``0x01``, `PSA_ALG_ECIES_SEC1`, ``0x0C000100`` + .. _pake-encoding: PAKE algorithm encoding diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 8d5597c6..0056c395 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -33,6 +33,10 @@ Changes to the API See :secref:`asymmetric-key-encoding` and :secref:`appendix-specdef-key-values`. +* Added key-encapsulation functions, `psa_encapsulate()` and `psa_decapsulate()`. + + - Added `PSA_ALG_ECIES_SEC1` as a key-encapsulation algorithm that implements the key agreement steps of ECIES. + Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 11d1ea2d..1702167b 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -121,6 +121,9 @@ Algorithm macros #define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ (((alg) & 0x7f800000) == 0x08800000) + #define PSA_ALG_IS_KEY_ENCAPSULATION(alg) \ + (((alg) & 0x7f000000) == 0x0c000000) + #define PSA_ALG_IS_MAC(alg) \ (((alg) & 0x7f000000) == 0x03000000) diff --git a/doc/crypto/figure/encoding/kem_encoding.json b/doc/crypto/figure/encoding/kem_encoding.json new file mode 100644 index 00000000..369fbf98 --- /dev/null +++ b/doc/crypto/figure/encoding/kem_encoding.json @@ -0,0 +1,18 @@ +{ + "reg": [ + { "name": "0", "bits": 8 }, + { "name": "ENCAPS-TYPE", "bits": 8 }, + { "name": "0", "bits": 6 }, + { "name": "0", "bits": 1 }, + { "name": "0", "bits": 1 }, + { "name": "0x0C", "bits": 7 }, + { "name": "0", "bits": 1 } + ], + "options": { + "lanes": 1, + "fontfamily": "lato", + "fontsize": 11, + "vspace": 52, + "hspace": 600 + } +} diff --git a/doc/crypto/figure/encoding/kem_encoding.json.license b/doc/crypto/figure/encoding/kem_encoding.json.license new file mode 100644 index 00000000..a4671b12 --- /dev/null +++ b/doc/crypto/figure/encoding/kem_encoding.json.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/crypto/figure/encoding/kem_encoding.pdf b/doc/crypto/figure/encoding/kem_encoding.pdf new file mode 100644 index 00000000..e5b13513 Binary files /dev/null and b/doc/crypto/figure/encoding/kem_encoding.pdf differ diff --git a/doc/crypto/figure/encoding/kem_encoding.pdf.license b/doc/crypto/figure/encoding/kem_encoding.pdf.license new file mode 100644 index 00000000..a4671b12 --- /dev/null +++ b/doc/crypto/figure/encoding/kem_encoding.pdf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/crypto/figure/encoding/kem_encoding.svg b/doc/crypto/figure/encoding/kem_encoding.svg new file mode 100644 index 00000000..367a3bb1 --- /dev/null +++ b/doc/crypto/figure/encoding/kem_encoding.svg @@ -0,0 +1,2 @@ + +07815162122232430310ENCAPS-TYPE0000x0C0 \ No newline at end of file diff --git a/doc/crypto/figure/encoding/kem_encoding.svg.license b/doc/crypto/figure/encoding/kem_encoding.svg.license new file mode 100644 index 00000000..a4671b12 --- /dev/null +++ b/doc/crypto/figure/encoding/kem_encoding.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/crypto/overview/functionality.rst b/doc/crypto/overview/functionality.rst index c3a6a9b1..27acef04 100644 --- a/doc/crypto/overview/functionality.rst +++ b/doc/crypto/overview/functionality.rst @@ -41,6 +41,8 @@ Keys are created using one of the *key creation functions*: * `psa_key_derivation_output_key()` * `psa_key_derivation_output_key_custom()` * `psa_key_agreement()` +* `psa_encapsulate()` +* `psa_decapsulate()` * `psa_pake_get_shared_key()` * `psa_copy_key()` @@ -269,6 +271,7 @@ This specification defines interfaces for the following types of asymmetric cryp * Asymmetric encryption (also known as public key encryption). See :secref:`pke`. * Asymmetric signature. See :secref:`sign`. * Two-way key agreement (also known as key establishment). See :secref:`key-agreement`. +* Key encapsulation. See :secref:`key-encapsulation`. * Password-authenticated key exchange (PAKE). See :secref:`pake`. For asymmetric encryption, the API provides *single-part* functions. @@ -277,6 +280,8 @@ For asymmetric 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. +For key encapsulation, the API provides single-part functions. + For PAKE, the API provides a *multi-part* operation.