diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 8d74b591..8e338060 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -106,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_SP800_108_COUNTER_HMAC(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 */ @@ -144,6 +146,9 @@ typedef /* implementation-defined type */ psa_mac_operation_t; #define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0200000c) #define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0200000d) #define PSA_ALG_SM3 ((psa_algorithm_t)0x02000014) +#define PSA_ALG_SP800_108_COUNTER_CMAC ((psa_algorithm_t)0x08000800) +#define PSA_ALG_SP800_108_COUNTER_HMAC(hash_alg) \ + /* specification-defined value */ #define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t)0x04800100) #define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t)0x08000609) #define PSA_ALG_TLS12_PRF(hash_alg) /* specification-defined value */ diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index 9173d139..8861a7f7 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -106,6 +106,8 @@ Symmetric keys | `PSA_ALG_HKDF` (non-secret inputs) | `PSA_ALG_HKDF_EXPAND` (non-secret inputs) | `PSA_ALG_HKDF_EXTRACT` (non-secret inputs) + | `PSA_ALG_SP800_108_COUNTER_HMAC` (non-secret inputs) + | `PSA_ALG_SP800_108_COUNTER_CMAC` (non-secret inputs) | `PSA_ALG_TLS12_PRF` (non-secret inputs) | `PSA_ALG_TLS12_PSK_TO_MS` (non-secret inputs) @@ -130,6 +132,7 @@ Symmetric keys .. subsection:: Compatible algorithms | `PSA_ALG_HMAC` + | `PSA_ALG_SP800_108_COUNTER_HMAC` (secret input) .. macro:: PSA_KEY_TYPE_DERIVE :definition: ((psa_key_type_t)0x1200) @@ -234,6 +237,7 @@ Symmetric keys | `PSA_ALG_ECB_NO_PADDING` | `PSA_ALG_CCM` | `PSA_ALG_GCM` + | `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. macro:: PSA_KEY_TYPE_ARIA :definition: ((psa_key_type_t)0x2406) @@ -268,6 +272,7 @@ Symmetric keys | `PSA_ALG_ECB_NO_PADDING` | `PSA_ALG_CCM` | `PSA_ALG_GCM` + | `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. macro:: PSA_KEY_TYPE_DES :definition: ((psa_key_type_t)0x2301) @@ -333,6 +338,7 @@ Symmetric keys | `PSA_ALG_ECB_NO_PADDING` | `PSA_ALG_CCM` | `PSA_ALG_GCM` + | `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. macro:: PSA_KEY_TYPE_SM4 :definition: ((psa_key_type_t)0x2405) @@ -359,6 +365,7 @@ Symmetric keys | `PSA_ALG_ECB_NO_PADDING` | `PSA_ALG_CCM` | `PSA_ALG_GCM` + | `PSA_ALG_SP800_108_COUNTER_CMAC` (secret input) .. macro:: PSA_KEY_TYPE_ARC4 :definition: ((psa_key_type_t)0x2002) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index 8355080f..911cf6d4 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -153,6 +153,103 @@ Key derivation algorithms | `PSA_KEY_TYPE_DERIVE` (for the pseudorandom key) | `PSA_KEY_TYPE_RAW_DATA` (for the info string) +.. macro:: PSA_ALG_SP800_108_COUNTER_HMAC + :definition: /* specification-defined value */ + + .. summary:: + Macro to build a NIST SP 800-108 conformant, counter-mode KDF algorithm based on HMAC. + + .. param:: hash_alg + A hash algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + + .. return:: + The corresponding key derivation algorithm. For example, the counter-mode KDF using HMAC-SHA-256 is :code:`PSA_ALG_SP800_108_COUNTER_HMAC(PSA_ALG_SHA_256)`. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + + This is an HMAC-based, counter mode key derivation function, using the construction recommended by :cite-title:`SP800-108`, §4.1. + + This key derivation algorithm uses the following inputs: + + * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, :math:`K_{IN}`. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the :math:`Label`. It is optional; if omitted, :math:`Label` is a zero-length string. If provided, it must not contain any null bytes. + * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the :math:`Context`. It is optional; if omitted, :math:`Context` is a zero-length string. + + Each input can only be passed once. Inputs must be passed in the order above. + + This algorithm uses the output length as part of the derivation process. In the derivation this value is :math:`L`, the required output size in bits. After setup, the initial capacity of the key derivation operation is :math:`2^{29}-1` bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. + + When the first output is requested, the value of :math:`L` is calculated as :math:`L=8*cap`, where :math:`cap` is the value of `psa_key_derivation_get_capacity()`. Subsequent calls to `psa_key_derivation_set_capacity()` are not permitted for this algorithm. + + The derivation is constructed as described in :cite:`SP800-108` §4.1, with the iteration counter :math:`i` and output length :math:`L` encoded as big-endian, 32-bit values. The resulting output stream :math:`K_1\ ||\ K_2\ ||\ K_3\ ||\ ...` is computed as: + + .. math:: + + K_i = \text{HMAC}( K_{IN}, [i]_4\ ||\ Label\ ||\ \texttt{0x00}\ ||\ Context\ ||\ [L]_4 ),\quad\text{for }i = 1, 2, 3, ... + + Where :math:`[x]_n` is the big-endian, :math:`n`-byte encoding of the integer :math:`x`. + + .. rationale:: + + :cite:`SP800-108` describes a set of general constructions for key derivation algorithms, with flexibility for specific implementation requirements. + + The precise definition provided here enables compatibility between different implementations of the |API|. + + .. subsection:: Compatible key types + + | `PSA_KEY_TYPE_HMAC` (for the secret key) + | `PSA_KEY_TYPE_DERIVE` (for the secret key) + | `PSA_KEY_TYPE_RAW_DATA` (for the other inputs) + +.. macro:: PSA_ALG_SP800_108_COUNTER_CMAC + :definition: ((psa_algorithm_t)0x08000800) + + .. summary:: + Macro to build a NIST SP 800-108 conformant, counter-mode KDF algorithm based on CMAC. + + This is a CMAC-based, counter mode key derivation function, using the construction recommended by :cite-title:`SP800-108`, §4.1. + + This key derivation algorithm uses the following inputs: + + * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, :math:`K_{IN}`. This must be a block-cipher key that is compatible with the CMAC algorithm, and must be input using `psa_key_derivation_input_key()`. See also `PSA_ALG_CMAC`. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the :math:`Label`. It is optional; if omitted, :math:`Label` is a zero-length string. If provided, it must not contain any null bytes. + * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the :math:`Context`. It is optional; if omitted, :math:`Context` is a zero-length string. + + Each input can only be passed once. Inputs must be passed in the order above. + + This algorithm uses the output length as part of the derivation process. In the derivation this value is :math:`L`, the required output size in bits. After setup, the initial capacity of the key derivation operation is :math:`2^{29}-1` bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. + + When the first output is requested, the value of :math:`L` is calculated as :math:`L=8*cap`, where :math:`cap` is the value of `psa_key_derivation_get_capacity()`. Subsequent calls to `psa_key_derivation_set_capacity()` are not permitted for this algorithm. + + The derivation is constructed as described in :cite:`SP800-108` §4.1, with the following details: + + * The iteration counter :math:`i` and output length :math:`L` are encoded as big-endian, 32-bit values. + * The mitigation to make the CMAC-based construction robust is implemented. + + The resulting output stream :math:`K_1\ ||\ K_2\ ||\ K_3\ ||\ ...` is computed as: + + .. math:: + + K_0 &= \text{CMAC}( K_{IN}, Label\ ||\ \texttt{0x00}\ ||\ Context\ ||\ [L]_4\ ) + + K_i &= \text{CMAC}( K_{IN}, [i]_4\ ||\ Label\ ||\ \texttt{0x00}\ ||\ Context\ ||\ [L]_4\ ||\ K_0 ),\quad\text{for }i = 1, 2, 3, ... + + Where :math:`[x]_n` is the big-endian, :math:`n`-byte encoding of the integer :math:`x`. + + .. rationale:: + + :cite:`SP800-108` describes a set of general constructions for key derivation algorithms, with flexibility for specific implementation requirements. + + The precise definition provided here enables compatibility between different implementations of the |API|. + + .. subsection:: Compatible key types + + | `PSA_KEY_TYPE_AES` (for the secret key) + | `PSA_KEY_TYPE_ARIA` (for the secret key) + | `PSA_KEY_TYPE_CAMELLIA` (for the secret key) + | `PSA_KEY_TYPE_SM4` (for the secret key) + | `PSA_KEY_TYPE_RAW_DATA` (for the other inputs) + .. macro:: PSA_ALG_TLS12_PRF :definition: /* specification-defined value */ @@ -323,6 +420,8 @@ Input step types This is typically a key of type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or the shared secret resulting from a key agreement obtained via `psa_key_derivation_key_agreement()`. + For some algorithms, a specific type of key is required. For example, see `PSA_ALG_SP800_108_COUNTER_CMAC`. + The secret can also be a direct input passed to `psa_key_derivation_input_bytes()`. In this case, the derivation operation cannot be used to derive keys: the operation will not permit a call to `psa_key_derivation_output_key()`. .. macro:: PSA_KEY_DERIVATION_INPUT_OTHER_SECRET @@ -545,6 +644,10 @@ Key derivation functions The capacity of a key derivation operation is the maximum number of bytes that the key derivation operation can return from this point onwards. + .. note:: + + For some algorithms, the capacity value can affect the output of the key derivation. For example, see `PSA_ALG_SP800_108_COUNTER_HMAC`. + .. function:: psa_key_derivation_input_bytes .. summary:: @@ -1126,6 +1229,18 @@ Support macros .. return:: ``1`` if ``alg`` is an HKDF-Expand algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported key derivation algorithm identifier. +.. macro:: PSA_ALG_IS_SP800_108_COUNTER_HMAC + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a key derivation algorithm constructed using :code:`PSA_ALG_SP800_108_COUNTER_HMAC(hash_alg)`. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a key derivation algorithm constructed using :code:`PSA_ALG_SP800_108_COUNTER_HMAC()`, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported key derivation algorithm identifier. + .. macro:: PSA_ALG_IS_TLS12_PRF :definition: /* specification-defined value */ diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index dd1ed94f..2e80aa76 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -265,16 +265,18 @@ The permitted values of HASH-TYPE (see :numref:`table-hash-type`) depend on the :widths: auto Key derivation algorithm, S, KDF-TYPE, Algorithm identifier, Algorithm value - HKDF, 0, ``0x01``, :code:`PSA_ALG_HKDF(hash_alg)`, ``0x080001hh`` :sup:`a` - TLS-1.2 PRF, 0, ``0x02``, :code:`PSA_ALG_TLS12_PRF(hash_alg)`, ``0x080002hh`` :sup:`a` - TLS-1.2 PSK-to-MasterSecret, 0, ``0x03``, :code:`PSA_ALG_TLS12_PSK_TO_MS(hash_alg)`, ``0x080003hh`` :sup:`a` + HKDF, 0, ``0x01``, :code:`PSA_ALG_HKDF(hash)`, ``0x080001hh`` :sup:`a` + TLS-1.2 PRF, 0, ``0x02``, :code:`PSA_ALG_TLS12_PRF(hash)`, ``0x080002hh`` :sup:`a` + TLS-1.2 PSK-to-MasterSecret, 0, ``0x03``, :code:`PSA_ALG_TLS12_PSK_TO_MS(hash)`, ``0x080003hh`` :sup:`a` + HKDF-Extract, 0, ``0x04``, :code:`PSA_ALG_HKDF_EXTRACT(hash)`, ``0x080004hh`` :sup:`a` + HKDF-Expand, 0, ``0x05``, :code:`PSA_ALG_HKDF_EXPAND(hash)`, ``0x080005hh`` :sup:`a` TLS 1.2 ECJPAKE-to-PMS, 0, ``0x06``, :code:`PSA_ALG_TLS12_ECJPAKE_TO_PMS`, ``0x08000609`` - HKDF-Extract, 0, ``0x04``, :code:`PSA_ALG_HKDF_EXTRACT(hash_alg)`, ``0x080004hh`` :sup:`a` - HKDF-Expand, 0, ``0x05``, :code:`PSA_ALG_HKDF_EXPAND(hash_alg)`, ``0x080005hh`` :sup:`a` - PBKDF2-HMAC, 1, ``0x01``, :code:`PSA_ALG_PBKDF2_HMAC(hash_alg)`, ``0x088001hh`` :sup:`a` + SP 800-108 Counter HMAC, 0, ``0x07``, :code:`PSA_ALG_SP800_108_COUNTER_HMAC(hash)`, ``0x080007hh`` :sup:`a` + SP 800-108 Counter CMAC, 0, ``0x08``, :code:`PSA_ALG_SP800_108_COUNTER_CMAC`, ``0x08000800`` + PBKDF2-HMAC, 1, ``0x01``, :code:`PSA_ALG_PBKDF2_HMAC(hash)`, ``0x088001hh`` :sup:`a` PBKDF2-AES-CMAC-PRF-128, 1, ``0x02``, :code:`PSA_ALG_PBKDF2_AES_CMAC_PRF_128`, ``0x08800200`` -a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash_alg``, used to construct the key derivation algorithm. +a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash``, used to construct the key derivation algorithm. .. _sign-encoding: diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 80072b7c..433d1704 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -20,6 +20,7 @@ Changes to the API * Added support for TLS 1.2 ECJPAKE-to-PMS key-derivation. See `PSA_ALG_TLS12_ECJPAKE_TO_PMS`. * 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. +* Defined key derivation algorithms based on the Counter mode recommendations in :cite-title:`SP800-108`. See `PSA_ALG_SP800_108_COUNTER_HMAC()` and `PSA_ALG_SP800_108_COUNTER_CMAC`. * 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()`. diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 29092a29..75849640 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2020-2022 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. _appendix-specdef-values: @@ -152,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_SP800_108_COUNTER_HMAC(alg) \ + (((alg) & ~0x000000ff) == 0x08000700) + #define PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) \ (((alg) & 0x7f00ffff) == 0x09000000) @@ -193,6 +196,9 @@ Algorithm macros #define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg) \ ((psa_algorithm_t)(0x06001300 | ((hash_alg) & 0x000000ff))) + #define PSA_ALG_SP800_108_COUNTER_HMAC(hash_alg) \ + ((psa_algorithm_t) (0x08000700 | ((hash_alg) & 0x000000ff))) + #define PSA_ALG_TLS12_PRF(hash_alg) \ ((psa_algorithm_t) (0x08000200 | ((hash_alg) & 0x000000ff))) diff --git a/doc/crypto/references b/doc/crypto/references index c8dba282..73c889b6 100644 --- a/doc/crypto/references +++ b/doc/crypto/references @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2020-2022 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. reference:: PSA-PAKE @@ -147,6 +147,12 @@ :publication: November 2017 :url: doi.org/10.6028/NIST.SP.800-67r2 +.. reference:: SP800-108 + :title: NIST Special Publication 800-108r1: Recommendation for Key Derivation Using Pseudorandom Functions + :author: NIST + :publication: August 2022 + :url: doi.org/10.6028/NIST.SP.800-108r1 + .. reference:: RFC1319 :title: The MD2 Message-Digest Algorithm :author: IETF