From 506cf6c0724d05f8903575c223f8c40eaa65540a Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Thu, 24 Oct 2024 19:59:24 +0100 Subject: [PATCH 1/3] Add support for key wrapping * psa_wrap_key() and psa_unwrap_key() functions * AES-KW and AES-KWP algorithms --- doc/crypto/api.db/psa/crypto.h | 20 ++ doc/crypto/api/keys/policy.rst | 23 ++ doc/crypto/api/keys/types.rst | 2 + doc/crypto/api/ops/algorithms.rst | 14 + doc/crypto/api/ops/index.rst | 1 + doc/crypto/api/ops/key-wrapping.rst | 305 ++++++++++++++++++ doc/crypto/appendix/encodings.rst | 27 ++ doc/crypto/appendix/history.rst | 3 +- doc/crypto/appendix/specdef_values.rst | 3 + doc/crypto/figure/encoding/key-wrap.json | 18 ++ .../figure/encoding/key-wrap.json.license | 2 + doc/crypto/figure/encoding/key-wrap.pdf | Bin 0 -> 8171 bytes .../figure/encoding/key-wrap.pdf.license | 2 + doc/crypto/figure/encoding/key-wrap.svg | 2 + .../figure/encoding/key-wrap.svg.license | 2 + doc/crypto/references | 26 +- 16 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 doc/crypto/api/ops/key-wrapping.rst create mode 100644 doc/crypto/figure/encoding/key-wrap.json create mode 100644 doc/crypto/figure/encoding/key-wrap.json.license create mode 100644 doc/crypto/figure/encoding/key-wrap.pdf create mode 100644 doc/crypto/figure/encoding/key-wrap.pdf.license create mode 100644 doc/crypto/figure/encoding/key-wrap.svg create mode 100644 doc/crypto/figure/encoding/key-wrap.svg.license diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 30f82b0a..cc4bcfb1 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -58,6 +58,8 @@ typedef struct psa_custom_key_parameters_t { /* specification-defined value */ #define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ /* specification-defined value */ +#define PSA_ALG_AES_KW ((psa_algorithm_t)0x0B400100) +#define PSA_ALG_AES_KWP ((psa_algorithm_t)0x0BC00200) #define PSA_ALG_AES_MMO_ZIGBEE ((psa_algorithm_t)0x02000007) #define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x020000ff) #define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ @@ -110,6 +112,7 @@ typedef struct psa_custom_key_parameters_t { #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_KEY_WRAP(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 */ @@ -340,9 +343,11 @@ typedef struct psa_custom_key_parameters_t { #define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) #define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00001000) #define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t)0x00000400) +#define PSA_KEY_USAGE_UNWRAP ((psa_key_usage_t)0x00020000) #define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t)0x00008000) #define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00002000) #define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t)0x00000800) +#define PSA_KEY_USAGE_WRAP ((psa_key_usage_t)0x00010000) #define PSA_MAC_LENGTH(key_type, key_bits, alg) \ /* implementation-defined value */ #define PSA_MAC_MAX_SIZE /* implementation-defined value */ @@ -385,6 +390,9 @@ typedef struct psa_custom_key_parameters_t { /* implementation-defined value */ #define PSA_TLS12_ECJPAKE_TO_PMS_OUTPUT_SIZE 32 #define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE /* implementation-defined value */ +#define PSA_WRAP_KEY_OUTPUT_SIZE(wrap_key_type, alg, key_type, key_bits) \ + /* implementation-defined value */ +#define PSA_WRAP_KEY_PAIR_MAX_SIZE /* implementation-defined value */ #define PSA_XOF_OPERATION_INIT /* implementation-defined value */ psa_status_t psa_aead_abort(psa_aead_operation_t * operation); psa_status_t psa_aead_decrypt(psa_key_id_t key, @@ -744,6 +752,12 @@ psa_status_t psa_sign_message(psa_key_id_t key, uint8_t * signature, size_t signature_size, size_t * signature_length); +psa_status_t psa_unwrap_key(const psa_key_attributes_t * attributes, + psa_key_id_t wrapping_key, + psa_algorithm_t alg, + const uint8_t * data, + size_t data_length, + psa_key_id_t * key); psa_status_t psa_verify_hash(psa_key_id_t key, psa_algorithm_t alg, const uint8_t * hash, @@ -756,6 +770,12 @@ psa_status_t psa_verify_message(psa_key_id_t key, size_t input_length, const uint8_t * signature, size_t signature_length); +psa_status_t psa_wrap_key(psa_key_id_t wrapping_key, + psa_algorithm_t alg, + psa_key_id_t key, + uint8_t * data, + size_t data_size, + size_t * data_length); psa_status_t psa_xof_abort(psa_xof_operation_t * operation); psa_xof_operation_t psa_xof_operation_init(void); psa_status_t psa_xof_output(psa_xof_operation_t * operation, diff --git a/doc/crypto/api/keys/policy.rst b/doc/crypto/api/keys/policy.rst index f7482148..1e312c22 100644 --- a/doc/crypto/api/keys/policy.rst +++ b/doc/crypto/api/keys/policy.rst @@ -101,6 +101,8 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. - `PSA_KEY_USAGE_VERIFY_HASH` - `PSA_KEY_USAGE_DERIVE` - `PSA_KEY_USAGE_VERIFY_DERIVATION` + - `PSA_KEY_USAGE_WRAP` + - `PSA_KEY_USAGE_UNWRAP` The flag `PSA_KEY_USAGE_DERIVE_PUBLIC` is used in the function `psa_check_key_usage()` to query if a key can be used for the public role in the specified algorithm. @@ -293,6 +295,27 @@ The usage flags are encoded in a bitmask, which has the type `psa_key_usage_t`. The key must have the `PSA_KEY_USAGE_DERIVE` permission. * `PSA_ALG_HKDF` is invalid, as there is no such role in single-key derivation algorithms. +.. macro:: PSA_KEY_USAGE_WRAP + :definition: ((psa_key_usage_t)0x00010000) + + .. summary:: + Permission to wrap another key with the key. + + This flag is required to use the key in a key-wrapping operation. + The flag must be present on keys used with the following APIs: + + * `psa_wrap_key()` + +.. macro:: PSA_KEY_USAGE_UNWRAP + :definition: ((psa_key_usage_t)0x00020000) + + .. summary:: + Permission to unwrap another key with the key. + + This flag is required to use the key in a key-unwrapping operation. + The flag must be present on keys used with the following APIs: + + * `psa_unwrap_key()` .. function:: psa_set_key_usage_flags diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index 5a411938..467f9f5a 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -323,6 +323,8 @@ Symmetric keys * `PSA_ALG_CCM` * `PSA_ALG_GCM` * `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) + * `PSA_ALG_AES_KW` + * `PSA_ALG_AES_KWP` .. subsection:: Key format diff --git a/doc/crypto/api/ops/algorithms.rst b/doc/crypto/api/ops/algorithms.rst index 9582359e..2385e866 100644 --- a/doc/crypto/api/ops/algorithms.rst +++ b/doc/crypto/api/ops/algorithms.rst @@ -141,6 +141,20 @@ Algorithm categories See :secref:`aead-algorithms` for a list of defined AEAD algorithms. +.. macro:: PSA_ALG_IS_KEY_WRAP + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a key wrapping algorithm. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a key-wrapping algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + + See :secref:`key-wrapping-algorithms` for a list of defined key-wrapping algorithms. + .. macro:: PSA_ALG_IS_KEY_DERIVATION :definition: /* specification-defined value */ diff --git a/doc/crypto/api/ops/index.rst b/doc/crypto/api/ops/index.rst index 6f1d1624..576f1212 100644 --- a/doc/crypto/api/ops/index.rst +++ b/doc/crypto/api/ops/index.rst @@ -15,6 +15,7 @@ Cryptographic operation reference mac cipher aead + key-wrapping key-derivation signature pk-encryption diff --git a/doc/crypto/api/ops/key-wrapping.rst b/doc/crypto/api/ops/key-wrapping.rst new file mode 100644 index 00000000..b296ac64 --- /dev/null +++ b/doc/crypto/api/ops/key-wrapping.rst @@ -0,0 +1,305 @@ +.. SPDX-FileCopyrightText: Copyright 2024-2025 Arm Limited and/or its affiliates +.. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license + +.. header:: psa/crypto + :seq: 245 + +.. _key-wrapping: + +Key wrapping +============ + +Key wrapping is the process of encrypting a key, so that the resulting ciphertext can be stored, or transported, in a form that maintains the confidentiality of the key material. +Key unwrapping reverses this process, extracting the key from the ciphertext. +Some key-wrapping schemes also provide integrity protection, to ensure that modification of the ciphertext can be detected. + +Some key-wrapping algorithms operate on arbitrary data, and provide authenticated encryption that is specifically designed for key values. +For example, the AES Key-wrap algorithm AES-KW. +For this type of algorithm, the |API| provides a simple pair of functions, `psa_unwrap_key()` and `psa_wrap_key()`, that unwrap or wrap key data in the default export format. +When using one of these key-wrapping algorithms, the key attributes are managed by the application. + +.. note:: + Other key-wrapping schemes define both the format of the wrapped key material and the algorithm that is used to perform the wrapping. + For example PKCS#8 defines *EncryptedPrivateKeyInfo*, which is also described in :rfc-title:`5958`. + Wrapped-key formats typically encode the key type and wrapping algorithm within the output data, and can also include other key attributes. + This version of the |API| does not support these key-wrapping schemes, but this is planned for a future version. + +.. rationale:: + + Key-wrapping algorithms are categorized separately to other authenticated encryption algorithms in the |API|. Key-wrapping algorithms ideally have the following properties: + + * Deterministic --- not requiring a nonce or IV to be provided by the application, or generated randomly. + * Robust --- every bit of plaintext can affect every bit of ciphertext. + + As a result, key-wrapping algorithms are typically special-purpose authenticated encryption algorithms. + +.. _key-wrapping-algorithms: + +Key-wrapping algorithms +----------------------- + +.. macro:: PSA_ALG_AES_KW + :definition: ((psa_algorithm_t)0x0B400100) + + .. summary:: + The AES-KW key-wrapping algorithm. + + .. todo:: + Decide if we should support any 128-bit block-cipher, as described in SP800-38F. + If so, the name of this algorithm would need to change. + For example, to ``PSA_ALG_SP800_38_KEY_WRAP``? + + This is the NIST Key Wrap algorithm, using an AES key-encryption key, as defined in :cite-title:`SP800-38F`. + The algorithm is also defined in :rfc-title:`3394`. + + Keys to be wrapped must have a length equal to a multiple of the 'semi-block' size for AES. + That is, a multiple of 8 bytes. + + To wrap keys that are not a multiple of the AES semi-block size, `PSA_ALG_AES_KWP` can be used. + + .. subsection:: Compatible key types + + | `PSA_KEY_TYPE_AES` + +.. macro:: PSA_ALG_AES_KWP + :definition: ((psa_algorithm_t)0x0BC00200) + + .. summary:: + The AES-KWP key-wrapping algorithm with padding. + + .. todo:: + Decide if we should support any 128-bit block-cipher, as described in SP800-38F. + If so, the name of this algorithm would need to change. + For example, to ``PSA_ALG_SP800_38_KEY_WRAP_WITH_PADDING``? + + This is the NIST Key Wrap with Padding algorithm, using an AES key-encryption key, as defined in :cite-title:`SP800-38F`. + The algorithm is also defined in :rfc-title:`5649`. + + This algorithm can wrap a key of any length. + + .. subsection:: Compatible key types + + | `PSA_KEY_TYPE_AES` + +Key wrapping functions +---------------------- + +.. function:: psa_unwrap_key + + .. summary:: + Unwrap and import a key using a specified wrapping key. + + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + + The following attributes are required for all keys: + + * The key type determines how the decrypted ``data`` buffer is interpreted. + + 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 key size determined from ``data``. + + .. 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 wrapping_key + Identifier of the key to use for the unwrapping operation. + It must permit the usage `PSA_KEY_USAGE_UNWRAP`. + .. param:: psa_algorithm_t alg + The key-wrapping algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_WRAP(alg)` is true. + .. param:: const uint8_t * data + Buffer containing the wrapped key data. + The content of this buffer is unwrapped using the algorithm ``alg``, and then interpreted according to the type declared in ``attributes``. + .. param:: size_t data_length + Size of the ``data`` buffer in bytes. + .. 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. + If the key is persistent, the key material and the key's metadata have been saved to persistent storage. + .. 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_SIGNATURE + The wrapped key data could not be authenticated. + .. retval:: PSA_ERROR_INVALID_HANDLE + ``wrapping_key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-wrapping algorithm. + * ``wrapping_key`` is not supported for use with ``alg``. + * The key 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-wrapping algorithm. + * ``wrapping_key`` is not compatible with ``alg``. + * The key type is invalid. + * The key size is nonzero, and is incompatible with the wrapped key data in ``data``. + * 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. + * The key format is invalid. + * The key data is not correctly formatted for the key type. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * The wrapping key does not have the `PSA_KEY_USAGE_UNWRAP` 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_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_INSUFFICIENT_STORAGE + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_STORAGE_FAILURE + .. retval:: PSA_ERROR_DATA_CORRUPT + .. retval:: PSA_ERROR_DATA_INVALID + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + The key is unwrapped and extracted from the provided ``data`` buffer. Its location, policy, and type are taken from ``attributes``. + + The wrapped key data determines the key size. + :code:``psa_get_key_bits(attributes)`` must either match the determined key size or be ``0``. + Implementations must reject an attempt to import a key of size zero. + + .. note:: + A call to `psa_unwrap_key()` first applies the decryption procedure associated with the key-wrapping algorithm ``alg``, using the ``wrapping_key`` key, to the supplied ``data`` buffer. + If the decryption succeeds, the resulting plaintext, along with the provided ``attributes`` are then processed as if they were inputs to ``psa_import_key()``. + + The benefit of using `psa_unwrap_key()` is that the plaintext key material is not exposed outside of the cryptoprocessor. + + .. note:: + The |API| does not support asymmetric private key objects outside of a key pair. + When unwrapping a private key, the corresponding key-pair type is created. + If the imported key data does not contain the public key, then the implementation will reconstruct the public key from the private key as needed. + + .. admonition:: Implementation note + + It is recommended that the implementation supports unwrapping any key data that can be produced by a call to `psa_wrap_key()`, with the same key-wrapping algorithm and key, and matching key attributes. + + It is recommended that implementations reject wrapped key data if it might be erroneous, for example, if it is the wrong type or is truncated. + +.. function:: psa_wrap_key + + .. summary:: + Wrap and export a key using a specified wrapping key. + + .. param:: psa_key_id_t wrapping_key + Identifier of the key to use for the wrapping operation. + It must permit the usage `PSA_KEY_USAGE_WRAP`. + .. param:: psa_algorithm_t alg + The key-wrapping algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_KEY_WRAP(alg)` is true. + .. param:: psa_key_id_t key + Identifier of the key to wrap. + It must permit the usage `PSA_KEY_USAGE_EXPORT`. + .. param:: uint8_t * data + Buffer where the wrapped key data is to be written. + .. param:: size_t data_size + Size of the ``data`` buffer in bytes. + This must be appropriate for the key: + + * The required output size is :code:`PSA_WRAP_KEY_OUTPUT_SIZE(wrap_key_type, alg, type, bits)`, where ``wrap_key_type`` is the type of the wrapping key, ``alg`` is the key-wrapping algorithm, ``type`` is the type of the key being wrapped, and ``bits`` is the bit-size of the key being wrapped. + * `PSA_WRAP_KEY_PAIR_MAX_SIZE` evaluates to the maximum wrapped output size of any supported key pair, in any supported combination of key-wrapping algorithm, wrapping-key type, key format and options. + * This API defines no maximum size for wrapped symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. + .. param:: size_t * data_length + On success, the number of bytes that make up the wrapped key data. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + The first ``(*data_length)`` bytes of ``data`` contain the wrapped key. + .. retval:: PSA_ERROR_INVALID_HANDLE + The following conditions can result in this error: + + * ``wrapping_key`` is not a valid key identifier. + * ``key`` is not a valid key identifier. + .. retval:: PSA_ERROR_NOT_PERMITTED + The following conditions can result in this error: + + * The wrapping key does not have the `PSA_KEY_USAGE_WRAP` flag, or it does not permit the requested algorithm. + * The key to be wrapped does not have the `PSA_KEY_USAGE_EXPORT` flag. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * ``alg`` is not a key-wrapping algorithm. + * ``wrapping_key`` is not compatible with ``alg``. + * ``key`` has a size that is not valid for ``alg``. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The following conditions can result in this error: + + * ``alg`` is not supported or is not a key-wrapping algorithm. + * ``wrapping_key`` is not supported for use with ``alg``. + * The storage location of ``key`` does not support export of the key. + * The implementation does not support export of keys with the type of ``key``. + .. retval:: PSA_ERROR_BUFFER_TOO_SMALL + The size of the ``data`` buffer is too small. + `PSA_WRAP_KEY_OUTPUT_SIZE()` or `PSA_WRAP_KEY_PAIR_MAX_SIZE` can be used to determine a sufficient buffer size. + .. 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_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_BAD_STATE + The library requires initializing by a call to `psa_crypto_init()`. + + Wrap a key from the key store into a data buffer using a specified key-wrapping algorithm, and key-wrapping key. + On success, the output contains the wrapped key value. + The policy of the key to be wrapped must have the usage flag `PSA_KEY_USAGE_EXPORT` set. + + The output of this function can be passed to `psa_unwrap_key()`, specifying the same algorithm and wrapping key, with the same attributes as ``key``, to create an equivalent key object. + + .. note:: + A call to `psa_wrap_key()` first evaluates the key data for ``key``, as if `psa_export_key()` is called, but retaining the key data within the cryptoprocessor. + If this succeeds, the encryption procedure associated with the key-wrapping algorithm ``alg``, using the ``wrapping_key`` key, is applied to the key data. + The resulting ciphertext is then returned. + + +Support macros +-------------- + +.. macro:: PSA_WRAP_KEY_OUTPUT_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient output buffer size for `psa_wrap_key()`. + + .. param:: wrap_key_type + A supported key-wrapping key type. + .. param:: alg + A supported key-wrapping algorithm. + .. param:: key_type + A supported key type. + .. param:: key_bits + The size of the key in bits. + + .. return:: + If the parameters are valid and supported, return a buffer size in bytes that guarantees that `psa_wrap_key()` will not fail with :code:`PSA_ERROR_BUFFER_TOO_SMALL`. If the parameters are a valid combination that is not supported by the implementation, this macro must return either a sensible size or ``0``. If the parameters are not valid, the return value is unspecified. + + See also `PSA_WRAP_KEY_PAIR_MAX_SIZE`. + +.. macro:: PSA_WRAP_KEY_PAIR_MAX_SIZE + :definition: /* implementation-defined value */ + + .. summary:: + Sufficient buffer size for wrapping any asymmetric key pair. + + This value must be a sufficient buffer size when calling `psa_wrap_key()` to export any asymmetric key pair that is supported by the implementation, regardless of the exact key type and key size. + + See also `PSA_WRAP_KEY_OUTPUT_SIZE()`. diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index 24f09132..74dfed18 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -46,6 +46,8 @@ Algorithm identifiers are 32-bit integer values of the type `psa_algorithm_t`. A - [23] - For a cipher algorithm, this flag indicates a stream cipher when S=1. + For a key-wrapping algorithm, this flag indicates an algorithm that accepts non-aligned input lengths when S=1. + For a key-derivation algorithm, this flag indicates a key-stretching or password-hashing algorithm when S=1. * - B - [22] @@ -80,6 +82,7 @@ The CAT field in an algorithm identifier takes the values shown in :numref:`tabl MAC, ``0x03``, See :secref:`mac-encoding` Cipher, ``0x04``, See :secref:`cipher-encoding` AEAD, ``0x05``, See :secref:`aead-encoding` + Key wrapping, ``0x0B``, See :secref:`key-wrap-encoding` Key derivation, ``0x08``, See :secref:`kdf-encoding` Asymmetric signature, ``0x06``, See :secref:`sign-encoding` Asymmetric encryption, ``0x07``, See :secref:`pke-encoding` @@ -275,6 +278,30 @@ a. This is an AEAD mode of an underlying block cipher. The block cipher is dete b. This is the default algorithm identifier, specifying the default tag length for the algorithm. `PSA_ALG_AEAD_WITH_SHORTENED_TAG()` generates identifiers with alternative LEN values. `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG()` generates wildcard permitted-algorithm policies with W = 1. +.. _key-wrap-encoding: + +Key-wrapping algorithm encoding +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The algorithm identifier for key-wrapping algorithms defined in this specification are encoded as shown in :numref:`fig-key-wrap-fields`. + +.. figure:: ../figure/encoding/key-wrap.* + :name: fig-key-wrap-fields + + Key-wrapping algorithm encoding + +The defined values for S, B, and WRAP-TYPE are shown in :numref:`table-key-wrap-type`. + +.. csv-table:: Key-wrapping algorithm sub-type values + :name: table-key-wrap-type + :header-rows: 1 + :align: left + :widths: auto + + Key-wrapping algorithm, S, B, WRAP-TYPE, Algorithm identifier, Algorithm value + AES-KW, 0, 1, ``0x01``, `PSA_ALG_AES_KW`, ``0x0B400100`` + AES-KWP, 1, 1, ``0x02``, `PSA_ALG_AES_KWP`, ``0x0BC00200`` + .. _kdf-encoding: Key-derivation algorithm encoding diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 180326e8..66b5b760 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -71,6 +71,8 @@ Changes to the API - Added `PSA_ALG_ECIES_SEC1` as a key-encapsulation algorithm that implements the key agreement steps of ECIES. +* Added support for key wrapping using key-wrapping algorithms. See :secref:`key-wrapping`. + Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -859,7 +861,6 @@ Future additions Major additions to the API will be defined in future drafts and editions of a 1.x or 2.x version of this specification. Features that are being considered include: * Multi-part operations for hybrid cryptography. For example, this includes hash-and-sign for EdDSA, and hybrid encryption for ECIES. -* Key wrapping mechanisms to extract and import keys in an encrypted and authenticated form. * Key discovery mechanisms. This would enable an application to locate a key by its name or attributes. * Implementation capability description. This would enable an application to determine the algorithms, key types and storage lifetimes that the implementation provides. * An ownership and access control mechanism allowing a multi-client implementation to have privileged clients that are able to manage keys of other clients. diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 94821c53..cc331b3c 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -124,6 +124,9 @@ Algorithm macros #define PSA_ALG_IS_KEY_ENCAPSULATION(alg) \ (((alg) & 0x7f000000) == 0x0c000000) + #define PSA_ALG_IS_KEY_WRAP(alg) \ + (((alg) & 0x7f000000) == 0x0b000000) + #define PSA_ALG_IS_MAC(alg) \ (((alg) & 0x7f000000) == 0x03000000) diff --git a/doc/crypto/figure/encoding/key-wrap.json b/doc/crypto/figure/encoding/key-wrap.json new file mode 100644 index 00000000..bf34820f --- /dev/null +++ b/doc/crypto/figure/encoding/key-wrap.json @@ -0,0 +1,18 @@ +{ + "reg": [ + { "name": "0", "bits": 8 }, + { "name": "WRAP-TYPE", "bits": 8 }, + { "name": "0", "bits": 6 }, + { "name": "B", "bits": 1 }, + { "name": "S", "bits": 1 }, + { "name": "0x0B", "bits": 7 }, + { "name": "0", "bits": 1 } + ], + "options": { + "lanes": 1, + "fontfamily": "lato", + "fontsize": 11, + "vspace": 52, + "hspace": 600 + } +} diff --git a/doc/crypto/figure/encoding/key-wrap.json.license b/doc/crypto/figure/encoding/key-wrap.json.license new file mode 100644 index 00000000..17e2c3b5 --- /dev/null +++ b/doc/crypto/figure/encoding/key-wrap.json.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024-2025 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/key-wrap.pdf b/doc/crypto/figure/encoding/key-wrap.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b708f0c9808ae31ec9b2fb694262514e47b2bae4 GIT binary patch literal 8171 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 C*S`z^ literal 0 HcmV?d00001 diff --git a/doc/crypto/figure/encoding/key-wrap.pdf.license b/doc/crypto/figure/encoding/key-wrap.pdf.license new file mode 100644 index 00000000..17e2c3b5 --- /dev/null +++ b/doc/crypto/figure/encoding/key-wrap.pdf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024-2025 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/key-wrap.svg b/doc/crypto/figure/encoding/key-wrap.svg new file mode 100644 index 00000000..8170d07c --- /dev/null +++ b/doc/crypto/figure/encoding/key-wrap.svg @@ -0,0 +1,2 @@ + +07815162122232430310WRAP-TYPE0BS0x0B0 \ No newline at end of file diff --git a/doc/crypto/figure/encoding/key-wrap.svg.license b/doc/crypto/figure/encoding/key-wrap.svg.license new file mode 100644 index 00000000..17e2c3b5 --- /dev/null +++ b/doc/crypto/figure/encoding/key-wrap.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2024-2025 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/crypto/references b/doc/crypto/references index baf1fca4..6c2e31d6 100644 --- a/doc/crypto/references +++ b/doc/crypto/references @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2020-2024 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2020-2025 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. reference:: PSM @@ -401,3 +401,27 @@ :title: PSA Certified Crypto API 1.3 PQC Extension :doc_no: ARM AES 0119 :url: arm-software.github.io/psa-api/crypto + +.. reference:: RFC5958 + :title: Asymmetric Key Packages + :author: IETF + :publication: August 2010 + :url: tools.ietf.org/html/rfc5958.html + +.. reference:: RFC3394 + :title: Advanced Encryption Standard (AES) Key Wrap Algorithm + :author: IETF + :publication: September 2002 + :url: tools.ietf.org/html/rfc3394.html + +.. reference:: RFC5649 + :title: Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm + :author: IETF + :publication: August 2009 + :url: tools.ietf.org/html/rfc5649.html + +.. reference:: SP800-38F + :title: NIST Special Publication 800-38F: Recommendation for Block Cipher Modes of Operation: Methods for Key Wrapping + :author: NIST + :publication: December 2012 + :url: doi.org/10.6028/NIST.SP.800-38F From f57cb97d1d2fb10cc8e1ed5ba5e39311eba98f04 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 15 Sep 2025 16:33:42 +0100 Subject: [PATCH 2/3] Rename key-wrap algorithms to be agnostic of the block cipher --- doc/crypto/api.db/psa/crypto.h | 4 +-- doc/crypto/api/keys/types.rst | 10 ++++-- doc/crypto/api/ops/algorithms.rst | 1 + doc/crypto/api/ops/key-wrapping.rst | 50 ++++++++++++++++++----------- doc/crypto/appendix/encodings.rst | 4 +-- doc/crypto/appendix/history.rst | 4 +-- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index cc4bcfb1..d7f35295 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -58,8 +58,6 @@ typedef struct psa_custom_key_parameters_t { /* specification-defined value */ #define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ /* specification-defined value */ -#define PSA_ALG_AES_KW ((psa_algorithm_t)0x0B400100) -#define PSA_ALG_AES_KWP ((psa_algorithm_t)0x0BC00200) #define PSA_ALG_AES_MMO_ZIGBEE ((psa_algorithm_t)0x02000007) #define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x020000ff) #define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ @@ -144,6 +142,8 @@ typedef struct psa_custom_key_parameters_t { /* specification-defined value */ #define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) /* specification-defined value */ #define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) /* specification-defined value */ +#define PSA_ALG_KW ((psa_algorithm_t)0x0B400100) +#define PSA_ALG_KWP ((psa_algorithm_t)0x0BC00200) #define PSA_ALG_MD2 ((psa_algorithm_t)0x02000001) #define PSA_ALG_MD4 ((psa_algorithm_t)0x02000002) #define PSA_ALG_MD5 ((psa_algorithm_t)0x02000003) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index 467f9f5a..f54f1dfb 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -322,9 +322,9 @@ Symmetric keys * `PSA_ALG_ECB_NO_PADDING` * `PSA_ALG_CCM` * `PSA_ALG_GCM` + * `PSA_ALG_KW` + * `PSA_ALG_KWP` * `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) - * `PSA_ALG_AES_KW` - * `PSA_ALG_AES_KWP` .. subsection:: Key format @@ -371,6 +371,8 @@ Symmetric keys * `PSA_ALG_ECB_NO_PADDING` * `PSA_ALG_CCM` * `PSA_ALG_GCM` + * `PSA_ALG_KW` + * `PSA_ALG_KWP` * `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. subsection:: Key format @@ -465,6 +467,8 @@ Symmetric keys * `PSA_ALG_ECB_NO_PADDING` * `PSA_ALG_CCM` * `PSA_ALG_GCM` + * `PSA_ALG_KW` + * `PSA_ALG_KWP` * `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. subsection:: Key format @@ -502,6 +506,8 @@ Symmetric keys * `PSA_ALG_ECB_NO_PADDING` * `PSA_ALG_CCM` * `PSA_ALG_GCM` + * `PSA_ALG_KW` + * `PSA_ALG_KWP` * `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. subsection:: Key format diff --git a/doc/crypto/api/ops/algorithms.rst b/doc/crypto/api/ops/algorithms.rst index 2385e866..793912c0 100644 --- a/doc/crypto/api/ops/algorithms.rst +++ b/doc/crypto/api/ops/algorithms.rst @@ -20,6 +20,7 @@ The specific algorithm identifiers are described alongside the cryptographic ope * :secref:`mac-algorithms` * :secref:`cipher-algorithms` * :secref:`aead-algorithms` +* :secref:`key-wrapping-algorithms` * :secref:`key-derivation-algorithms` * :secref:`sign` * :secref:`asymmetric-encryption-algorithms` diff --git a/doc/crypto/api/ops/key-wrapping.rst b/doc/crypto/api/ops/key-wrapping.rst index b296ac64..d66eb98c 100644 --- a/doc/crypto/api/ops/key-wrapping.rst +++ b/doc/crypto/api/ops/key-wrapping.rst @@ -38,48 +38,54 @@ When using one of these key-wrapping algorithms, the key attributes are managed Key-wrapping algorithms ----------------------- -.. macro:: PSA_ALG_AES_KW +.. macro:: PSA_ALG_KW :definition: ((psa_algorithm_t)0x0B400100) .. summary:: - The AES-KW key-wrapping algorithm. + A key-wrapping algorithm based on the NIST Key Wrap (KW) mode of a block cipher. - .. todo:: - Decide if we should support any 128-bit block-cipher, as described in SP800-38F. - If so, the name of this algorithm would need to change. - For example, to ``PSA_ALG_SP800_38_KEY_WRAP``? + .. versionadded:: 1.4 - This is the NIST Key Wrap algorithm, using an AES key-encryption key, as defined in :cite-title:`SP800-38F`. - The algorithm is also defined in :rfc-title:`3394`. + KW is defined for block ciphers that have a 128-bit block size. + The underlying block cipher is determined by the key type. - Keys to be wrapped must have a length equal to a multiple of the 'semi-block' size for AES. + Keys to be wrapped must have a length equal to a multiple of the 'semi-block' size for the block cipher. That is, a multiple of 8 bytes. - To wrap keys that are not a multiple of the AES semi-block size, `PSA_ALG_AES_KWP` can be used. + To wrap keys that are not a multiple of the semi-block size, `PSA_ALG_KWP` can be used. + + This is the NIST Key Wrap algorithm, using any block-cipher that operates on 128-bit blocks, as defined in :cite-title:`SP800-38F`. + A definition of AES-KW is also found in :rfc-title:`3394`. .. subsection:: Compatible key types | `PSA_KEY_TYPE_AES` + | `PSA_KEY_TYPE_ARIA` + | `PSA_KEY_TYPE_CAMELLIA` + | `PSA_KEY_TYPE_SM4` -.. macro:: PSA_ALG_AES_KWP +.. macro:: PSA_ALG_KWP :definition: ((psa_algorithm_t)0x0BC00200) .. summary:: - The AES-KWP key-wrapping algorithm with padding. + A key-wrapping algorithm based on the NIST Key Wrap with Padding (KWP) mode of a block cipher. - .. todo:: - Decide if we should support any 128-bit block-cipher, as described in SP800-38F. - If so, the name of this algorithm would need to change. - For example, to ``PSA_ALG_SP800_38_KEY_WRAP_WITH_PADDING``? + .. versionadded:: 1.4 - This is the NIST Key Wrap with Padding algorithm, using an AES key-encryption key, as defined in :cite-title:`SP800-38F`. - The algorithm is also defined in :rfc-title:`5649`. + KWP is defined for block ciphers that have a 128-bit block size. + The underlying block cipher is determined by the key type. This algorithm can wrap a key of any length. + This is the NIST Key Wrap with Padding algorithm, using any block-cipher that operates on 128-bit blocks, as defined in :cite-title:`SP800-38F`. + A definition of AES-KWP is also found in :rfc-title:`5649`. + .. subsection:: Compatible key types | `PSA_KEY_TYPE_AES` + | `PSA_KEY_TYPE_ARIA` + | `PSA_KEY_TYPE_CAMELLIA` + | `PSA_KEY_TYPE_SM4` Key wrapping functions ---------------------- @@ -89,6 +95,8 @@ Key wrapping functions .. summary:: Unwrap and import a key using a specified wrapping key. + .. versionadded:: 1.4 + .. param:: const psa_key_attributes_t * attributes The attributes for the new key. @@ -200,6 +208,8 @@ Key wrapping functions .. summary:: Wrap and export a key using a specified wrapping key. + .. versionadded:: 1.4 + .. param:: psa_key_id_t wrapping_key Identifier of the key to use for the wrapping operation. It must permit the usage `PSA_KEY_USAGE_WRAP`. @@ -280,6 +290,8 @@ Support macros .. summary:: Sufficient output buffer size for `psa_wrap_key()`. + .. versionadded:: 1.4 + .. param:: wrap_key_type A supported key-wrapping key type. .. param:: alg @@ -300,6 +312,8 @@ Support macros .. summary:: Sufficient buffer size for wrapping any asymmetric key pair. + .. versionadded:: 1.4 + This value must be a sufficient buffer size when calling `psa_wrap_key()` to export any asymmetric key pair that is supported by the implementation, regardless of the exact key type and key size. See also `PSA_WRAP_KEY_OUTPUT_SIZE()`. diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index 74dfed18..50bfb290 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -299,8 +299,8 @@ The defined values for S, B, and WRAP-TYPE are shown in :numref:`table-key-wrap- :widths: auto Key-wrapping algorithm, S, B, WRAP-TYPE, Algorithm identifier, Algorithm value - AES-KW, 0, 1, ``0x01``, `PSA_ALG_AES_KW`, ``0x0B400100`` - AES-KWP, 1, 1, ``0x02``, `PSA_ALG_AES_KWP`, ``0x0BC00200`` + AES-KW, 0, 1, ``0x01``, `PSA_ALG_KW`, ``0x0B400100`` + AES-KWP, 1, 1, ``0x02``, `PSA_ALG_KWP`, ``0x0BC00200`` .. _kdf-encoding: diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 66b5b760..8f36ac0e 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -21,6 +21,8 @@ Changes to the API * Added `psa_check_key_usage()` to query a key's capabilities. * Add support for extendable-output functions (XOF). See :secref:`xof`. +* Added support for key wrapping using key-wrapping algorithms. + See :secref:`key-wrapping`. Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -71,8 +73,6 @@ Changes to the API - Added `PSA_ALG_ECIES_SEC1` as a key-encapsulation algorithm that implements the key agreement steps of ECIES. -* Added support for key wrapping using key-wrapping algorithms. See :secref:`key-wrapping`. - Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ From 01d3b2d7f54875abd797fcdf88195cdb0a59163a Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 15 Sep 2025 16:34:56 +0100 Subject: [PATCH 3/3] Fix minor issues from review --- doc/crypto/api/ops/key-wrapping.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/crypto/api/ops/key-wrapping.rst b/doc/crypto/api/ops/key-wrapping.rst index d66eb98c..951f1d2d 100644 --- a/doc/crypto/api/ops/key-wrapping.rst +++ b/doc/crypto/api/ops/key-wrapping.rst @@ -163,7 +163,6 @@ Key wrapping functions * The key usage flags include invalid values. * The key's permitted-usage algorithm is invalid. * The key attributes, as a whole, are invalid. - * The key format is invalid. * The key data is not correctly formatted for the key type. .. retval:: PSA_ERROR_NOT_PERMITTED The following conditions can result in this error: @@ -184,13 +183,12 @@ Key wrapping functions The wrapped key data determines the key size. :code:``psa_get_key_bits(attributes)`` must either match the determined key size or be ``0``. - Implementations must reject an attempt to import a key of size zero. + + Implementations must reject an attempt to unwrap a key if the determined key size is ``0``. .. note:: A call to `psa_unwrap_key()` first applies the decryption procedure associated with the key-wrapping algorithm ``alg``, using the ``wrapping_key`` key, to the supplied ``data`` buffer. - If the decryption succeeds, the resulting plaintext, along with the provided ``attributes`` are then processed as if they were inputs to ``psa_import_key()``. - - The benefit of using `psa_unwrap_key()` is that the plaintext key material is not exposed outside of the cryptoprocessor. + The resulting plaintext is retained within the cryptoprocessor, and used with the provided ``attributes`` to create a key, as if they were inputs to `psa_import_key()`. .. note:: The |API| does not support asymmetric private key objects outside of a key pair. @@ -225,8 +223,9 @@ Key wrapping functions This must be appropriate for the key: * The required output size is :code:`PSA_WRAP_KEY_OUTPUT_SIZE(wrap_key_type, alg, type, bits)`, where ``wrap_key_type`` is the type of the wrapping key, ``alg`` is the key-wrapping algorithm, ``type`` is the type of the key being wrapped, and ``bits`` is the bit-size of the key being wrapped. - * `PSA_WRAP_KEY_PAIR_MAX_SIZE` evaluates to the maximum wrapped output size of any supported key pair, in any supported combination of key-wrapping algorithm, wrapping-key type, key format and options. - * This API defines no maximum size for wrapped symmetric keys. Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. + * `PSA_WRAP_KEY_PAIR_MAX_SIZE` evaluates to the maximum wrapped output size of any supported key pair, in any supported combination of key-wrapping algorithm and wrapping-key type. + * This API defines no maximum size for wrapped symmetric keys. + Arbitrarily large data items can be stored in the key store, for example certificates that correspond to a stored private key or input material for key derivation. .. param:: size_t * data_length On success, the number of bytes that make up the wrapped key data. @@ -269,7 +268,7 @@ Key wrapping functions .. retval:: PSA_ERROR_BAD_STATE The library requires initializing by a call to `psa_crypto_init()`. - Wrap a key from the key store into a data buffer using a specified key-wrapping algorithm, and key-wrapping key. + Wrap a key from the key store into a data buffer using a specified key-wrapping algorithm and key-wrapping key. On success, the output contains the wrapped key value. The policy of the key to be wrapped must have the usage flag `PSA_KEY_USAGE_EXPORT` set.