From 6ad41e46737deb7934a93a103c2db3726554a420 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 7 Nov 2023 21:08:02 +0000 Subject: [PATCH 1/6] Add support for KDFs based on SP 800-108 recommendations --- doc/crypto/api.db/psa/crypto.h | 5 ++ doc/crypto/api/ops/kdf.rst | 111 +++++++++++++++++++++++++ doc/crypto/appendix/encodings.rst | 16 ++-- doc/crypto/appendix/history.rst | 1 + doc/crypto/appendix/specdef_values.rst | 8 +- doc/crypto/references | 8 +- 6 files changed, 140 insertions(+), 9 deletions(-) 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/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index 8355080f..e058f70e 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -153,6 +153,98 @@ 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 the HMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. + + This key derivation algorithm uses the following inputs, in any order: + + * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. + * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. + + Each input may only be passed once. + + This algorithm uses the output length as part of the derivation process. In the derivation this value is *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`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 *L* is calculated as *L* = :code:`8 * 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 *i* and output length *L* encoded as big-endian, 32-bit values. The resulting output stream *K*\ :sub:`1` || *K*\ :sub:`2` || *K*\ :sub:`3` || ... is computed as: + + *K*\ :sub:`i` = HMAC( *K*\ :sub:`IN`, [ *i* ]\ :sub:`4` || *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` ), for *i* = 1, 2, 3, ... + + Where [ *x* ]\ :sub:`n` is the big-endian, *n*-byte encoding of the integer *x*. + + .. rationale:: + + SP 800-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 the CMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. + + This key derivation algorithm uses the following inputs, in any order: + + * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. This must be a block-cipher key that is compatible with the CMAC algorithm. See also `PSA_ALG_CMAC`, and must be input using `psa_key_derivation_input_key()`. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. + * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. + + Each input may only be passed once. + + This algorithm uses the output length as part of the derivation process. In the derivation this value is *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`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 *L* is calculated as *L* = :code:`8 * 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 *i* and output length *L* are encoded as big-endian, 32-bit values. + * The mitigation to make the CMAC-based construction robust is implemented. + + The resulting output stream *K*\ :sub:`1` || *K*\ :sub:`2` || *K*\ :sub:`3` || ... is computed as: + + | *K*\ :sub:`0` = CMAC( *K*\ :sub:`IN`, *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` ) + | *K*\ :sub:`i` = CMAC( *K*\ :sub:`IN`, [ *i* ]\ :sub:`4` || *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` || *K*\ :sub:`0` ), for *i* = 1, 2, 3, ... + + Where [ *x* ]\ :sub:`n` is the big-endian, *n*-byte encoding of the integer *x*. + + .. rationale:: + + SP 800-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 +415,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 +639,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 +1224,19 @@ 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 an HMAC-based, SP 800-108 conformant, counter-mode KDF algorithm (: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 an HMAC-based, SP 800-108 conformant, counter-mode KDF 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_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 From c7f7f1249333fd694df699b12466abbecadfb3ab Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 13 Nov 2023 14:31:35 +0000 Subject: [PATCH 2/6] Xref from key types to new algorithms --- doc/crypto/api/keys/types.rst | 7 +++++++ 1 file changed, 7 insertions(+) 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) From dbde3f87a9bdce63459d87e6ac554ab8f662cf0c Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 09:58:04 +0000 Subject: [PATCH 3/6] Specify order of inputs for SP800-108 KDFs --- doc/crypto/api/ops/kdf.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index e058f70e..aa91a872 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -169,13 +169,13 @@ Key derivation algorithms This is the HMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. - This key derivation algorithm uses the following inputs, in any order: + This key derivation algorithm uses the following inputs: * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. - Each input may only be passed once. + 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 *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`29` - 1 bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. @@ -207,13 +207,13 @@ Key derivation algorithms This is the CMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. - This key derivation algorithm uses the following inputs, in any order: + This key derivation algorithm uses the following inputs: * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. This must be a block-cipher key that is compatible with the CMAC algorithm. See also `PSA_ALG_CMAC`, and must be input using `psa_key_derivation_input_key()`. * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. - Each input may only be passed once. + 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 *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`29` - 1 bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. From 4a584fab6e0d53244e2e4583383049b4d9044a85 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 11:25:39 +0000 Subject: [PATCH 4/6] Accurately describe the SP800-108 KDFs --- doc/crypto/api/ops/kdf.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index aa91a872..6b7b2f41 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -167,7 +167,7 @@ Key derivation algorithms Unspecified if ``hash_alg`` is not a supported hash algorithm. - This is the HMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. + 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: @@ -189,7 +189,7 @@ Key derivation algorithms .. rationale:: - SP 800-108 describes a set of general constructions for key derivation algorithms, with flexibility for specific implementation requirements. + :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|. @@ -205,7 +205,7 @@ Key derivation algorithms .. summary:: Macro to build a NIST SP 800-108 conformant, counter-mode KDF algorithm based on CMAC. - This is the CMAC-based, counter mode key derivation function specified by :cite-title:`SP800-108`, §4.1. + 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: @@ -233,7 +233,7 @@ Key derivation algorithms .. rationale:: - SP 800-108 describes a set of general constructions for key derivation algorithms, with flexibility for specific implementation requirements. + :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|. @@ -1228,14 +1228,13 @@ Support macros :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is an HMAC-based, SP 800-108 conformant, counter-mode KDF algorithm (:code:`PSA_ALG_SP800_108_COUNTER_HMAC(hash_alg)`). + 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 an HMAC-based, SP 800-108 conformant, counter-mode KDF algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported key derivation algorithm identifier. - + ``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 */ From 916816139ae0a7f8308b090a0a3a2aadd1a3f606 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 11:32:48 +0000 Subject: [PATCH 5/6] Constrain SP800-108 KDF Label input values --- doc/crypto/api/ops/kdf.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index 6b7b2f41..ea3499df 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -172,7 +172,7 @@ Key derivation algorithms This key derivation algorithm uses the following inputs: * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. - * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. If provided, it must not contain any null bytes. * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. Each input can only be passed once. Inputs must be passed in the order above. @@ -210,7 +210,7 @@ Key derivation algorithms This key derivation algorithm uses the following inputs: * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. This must be a block-cipher key that is compatible with the CMAC algorithm. See also `PSA_ALG_CMAC`, and must be input using `psa_key_derivation_input_key()`. - * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. + * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. If provided, it must not contain any null bytes. * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. Each input can only be passed once. Inputs must be passed in the order above. From 6b4ec8c8b45adb2078d91982be3847257e4c3201 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 28 Nov 2023 12:03:44 +0000 Subject: [PATCH 6/6] Use :math: role and directive for KDF formulae --- doc/crypto/api/ops/kdf.rst | 41 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/doc/crypto/api/ops/kdf.rst b/doc/crypto/api/ops/kdf.rst index ea3499df..911cf6d4 100644 --- a/doc/crypto/api/ops/kdf.rst +++ b/doc/crypto/api/ops/kdf.rst @@ -171,21 +171,23 @@ Key derivation algorithms This key derivation algorithm uses the following inputs: - * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. - * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. If provided, it must not contain any null bytes. - * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. + * `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 *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`29` - 1 bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. + 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 *L* is calculated as *L* = :code:`8 * psa_key_derivation_get_capacity()`. Subsequent calls to `psa_key_derivation_set_capacity()` are not permitted for this algorithm. + 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 *i* and output length *L* encoded as big-endian, 32-bit values. The resulting output stream *K*\ :sub:`1` || *K*\ :sub:`2` || *K*\ :sub:`3` || ... is computed as: + 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: - *K*\ :sub:`i` = HMAC( *K*\ :sub:`IN`, [ *i* ]\ :sub:`4` || *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` ), for *i* = 1, 2, 3, ... + .. math:: - Where [ *x* ]\ :sub:`n` is the big-endian, *n*-byte encoding of the integer *x*. + 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:: @@ -209,27 +211,30 @@ Key derivation algorithms This key derivation algorithm uses the following inputs: - * `PSA_KEY_DERIVATION_INPUT_SECRET` is the secret input keying material, *K*\ :sub:`IN`. This must be a block-cipher key that is compatible with the CMAC algorithm. See also `PSA_ALG_CMAC`, and must be input using `psa_key_derivation_input_key()`. - * `PSA_KEY_DERIVATION_INPUT_LABEL` is the *Label*. It is optional; if omitted, the *Label* is a zero-length string. If provided, it must not contain any null bytes. - * `PSA_KEY_DERIVATION_INPUT_CONTEXT` is the *Context*. It is optional; if omitted, the *Context* is a zero-length string. + * `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 *L*, the required output size in bits. After setup, the initial capacity of the key derivation operation is 2\ :sup:`29` - 1 bytes (``0x1fffffff``). The capacity can be set to a lower value by calling `psa_key_derivation_set_capacity()`. + 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 *L* is calculated as *L* = :code:`8 * psa_key_derivation_get_capacity()`. Subsequent calls to `psa_key_derivation_set_capacity()` are not permitted for this algorithm. + 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 *i* and output length *L* are encoded as big-endian, 32-bit values. + * 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 *K*\ :sub:`1` || *K*\ :sub:`2` || *K*\ :sub:`3` || ... is computed as: + 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*\ :sub:`0` = CMAC( *K*\ :sub:`IN`, *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` ) - | *K*\ :sub:`i` = CMAC( *K*\ :sub:`IN`, [ *i* ]\ :sub:`4` || *Label* || ``0x00`` || *Context* || [ *L* ]\ :sub:`4` || *K*\ :sub:`0` ), for *i* = 1, 2, 3, ... + K_i &= \text{CMAC}( K_{IN}, [i]_4\ ||\ Label\ ||\ \texttt{0x00}\ ||\ Context\ ||\ [L]_4\ ||\ K_0 ),\quad\text{for }i = 1, 2, 3, ... - Where [ *x* ]\ :sub:`n` is the big-endian, *n*-byte encoding of the integer *x*. + Where :math:`[x]_n` is the big-endian, :math:`n`-byte encoding of the integer :math:`x`. .. rationale::