From 3263b68b29eeb4af23d1903ce9449b44cbc6c746 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 23 Sep 2024 21:00:23 +0100 Subject: [PATCH 01/13] Define key types and algorithms for FIPS 204 ML-DSA --- doc/crypto/api.db/psa/crypto.h | 14 ++ doc/crypto/api/keys/types.rst | 117 ++++++++++++ doc/crypto/api/ops/algorithms.rst | 2 + doc/crypto/api/ops/hash.rst | 15 +- doc/crypto/api/ops/signature.rst | 242 +++++++++++++++++++++++++ doc/crypto/appendix/encodings.rst | 18 +- doc/crypto/appendix/history.rst | 3 + doc/crypto/appendix/specdef_values.rst | 30 ++- doc/crypto/references | 12 ++ 9 files changed, 444 insertions(+), 9 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 8cc8cf5c..7878af6d 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -72,6 +72,9 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_CMAC ((psa_algorithm_t)0x03c00200) #define PSA_ALG_CTR ((psa_algorithm_t)0x04c01000) #define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) /* specification-defined value */ +#define PSA_ALG_DETERMINISTIC_HASH_ML_DSA(hash_alg) \ + /* specification-defined value */ +#define PSA_ALG_DETERMINISTIC_ML_DSA ((psa_algorithm_t) 0x06004500) #define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t)0x04404400) #define PSA_ALG_ECDH ((psa_algorithm_t)0x09020000) #define PSA_ALG_ECDSA(hash_alg) /* specification-defined value */ @@ -82,6 +85,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_FULL_LENGTH_MAC(mac_alg) /* specification-defined value */ #define PSA_ALG_GCM ((psa_algorithm_t)0x05500200) #define PSA_ALG_GET_HASH(alg) /* specification-defined value */ +#define PSA_ALG_HASH_ML_DSA(hash_alg) /* specification-defined value */ #define PSA_ALG_HKDF(hash_alg) /* specification-defined value */ #define PSA_ALG_HKDF_EXPAND(hash_alg) /* specification-defined value */ #define PSA_ALG_HKDF_EXTRACT(hash_alg) /* specification-defined value */ @@ -92,12 +96,14 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) /* specification-defined value */ #define PSA_ALG_IS_CIPHER(alg) /* specification-defined value */ #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) /* specification-defined value */ +#define PSA_ALG_IS_DETERMINISTIC_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_ECDH(alg) /* specification-defined value */ #define PSA_ALG_IS_ECDSA(alg) /* specification-defined value */ #define PSA_ALG_IS_FFDH(alg) /* specification-defined value */ #define PSA_ALG_IS_HASH(alg) /* specification-defined value */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) /* specification-defined value */ #define PSA_ALG_IS_HASH_EDDSA(alg) /* specification-defined value */ +#define PSA_ALG_IS_HASH_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF_EXPAND(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF_EXTRACT(alg) /* specification-defined value */ @@ -108,9 +114,12 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ /* specification-defined value */ #define PSA_ALG_IS_MAC(alg) /* specification-defined value */ +#define PSA_ALG_IS_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) /* specification-defined value */ +#define PSA_ALG_IS_PURE_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) /* specification-defined value */ +#define PSA_ALG_IS_RANDOMIZED_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) #define PSA_ALG_IS_RSA_OAEP(alg) /* specification-defined value */ @@ -140,6 +149,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_MD2 ((psa_algorithm_t)0x02000001) #define PSA_ALG_MD4 ((psa_algorithm_t)0x02000002) #define PSA_ALG_MD5 ((psa_algorithm_t)0x02000003) +#define PSA_ALG_ML_DSA ((psa_algorithm_t) 0x06004400) #define PSA_ALG_NONE ((psa_algorithm_t)0) #define PSA_ALG_OFB ((psa_algorithm_t)0x04c01200) #define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t)0x08800200) @@ -156,6 +166,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x02000011) #define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x02000012) #define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x02000013) +#define PSA_ALG_SHAKE128_256 ((psa_algorithm_t)0x02000016) #define PSA_ALG_SHAKE256_512 ((psa_algorithm_t)0x02000015) #define PSA_ALG_SHA_1 ((psa_algorithm_t)0x02000005) #define PSA_ALG_SHA_224 ((psa_algorithm_t)0x02000008) @@ -297,6 +308,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) /* specification-defined value */ #define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) /* specification-defined value */ #define PSA_KEY_TYPE_IS_KEY_PAIR(type) /* specification-defined value */ +#define PSA_KEY_TYPE_IS_ML_DSA(type) /* specification-defined value */ #define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) /* specification-defined value */ #define PSA_KEY_TYPE_IS_RSA(type) /* specification-defined value */ #define PSA_KEY_TYPE_IS_SPAKE2P(type) /* specification-defined value */ @@ -307,6 +319,8 @@ typedef struct psa_custom_key_parameters_t { #define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) /* specification-defined value */ #define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ /* specification-defined value */ +#define PSA_KEY_TYPE_ML_DSA_KEY_PAIR ((psa_key_type_t)0x7002) +#define PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) #define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) #define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t)0x1203) #define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t)0x1205) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index ea18391c..c337edb9 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -1165,6 +1165,123 @@ The curve type affects the key format, the key derivation procedure, and the alg .. return:: psa_ecc_family_t The elliptic curve family id, if ``type`` is a supported elliptic curve key. Unspecified if ``type`` is not a supported elliptic curve key. +.. _ml-keys: + +Module Lattice keys +------------------- + +The |API| supports Module Lattice cryptography as defined in :cite-title:`FIPS203` and :cite-title:`FIPS204`. + +There are two related, but separate, algorithms: + +* A key encapsulation method, ML-KEM. +* A signature method, ML-DSA. + +These algorithms have distinct asymmetric key types. + +.. macro:: PSA_KEY_TYPE_ML_DSA_KEY_PAIR + :definition: ((psa_key_type_t)0x7002) + + .. summary:: + ML-DSA key pair: both the private and public key. + + The key attribute size of an ML-DSA key is the numeric ML-DSA parameter-set identifier defined in `[FIPS204]`. + The values are based on the dimensions of the matrix :math:`A`, and do not directly define the key size in bytes: + + * ML-DSA-44 : ``key_bits = 44`` + * ML-DSA-65 : ``key_bits = 65`` + * ML-DSA-87 : ``key_bits = 87`` + + See also §4 in `[FIPS204]`. + + .. subsection:: Compatible algorithms + + .. hlist:: + + * `PSA_ALG_ML_DSA` + * `PSA_ALG_HASH_ML_DSA` + * `PSA_ALG_DETERMINISTIC_ML_DSA` + * `PSA_ALG_DETERMINISTIC_HASH_ML_DSA` + + .. subsection:: Key format + + .. todo:: + Decide if the default ML-DSA key-pair format is the 32-byte seed :math:`\xi`, or the :math:`(pk,sk)` tuple (which is 3.8kB - 7.4kB in size). + + The seed cannot be recomputed from the (pk, sk) pair. + If the seed is the default format, then importing a (pk, sk) pair results in a key that cannot be exported in the default format. + + I suspect this means that the default export format should be the (pk, sk) pair. + The API permits implementation storage as a seed (for internally generated keys), and the API could provide an alternative format or format option to export/import the seed instead of the (pk, sk) pair (for an implementation and key-pair that still retain the generating seed). + + An ML-DSA key pair is the :math:`(pk,sk)` pair of public key and secret key. + + The data format for import and export of the key-pair is the concatenation of the public key and secret keys, :math:`pk\ ||\ sk`, where :math:`pk` and :math:`sk` are the octet strings returned by the ``ML-DSA.KeyGen()`` operation defined in `[FIPS204]` §5.1. + + The size of the key pair depends on the ML-DSA parameter set as follows: + + .. csv-table:: + :align: left + :header-rows: 1 + + Parameter set, Key-pair size in bytes + ML-DSA-44, 3872 + ML-DSA-65, 5984 + ML-DSA-87, 7488 + + See `PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. + + .. subsection:: Key derivation + + :issue:`TBD` + + .. todo:: + + As ML-DSA keys are generated from a 32-byte seed, it would be very straight-forward to enable key-derivation of an ML-DSA key pair as part of a KDF. + + However, this is not described anywhere as an expected use case with ML-DSA. + +.. macro:: PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY + :definition: ((psa_key_type_t)0x4002) + + .. summary:: + ML-DSA public key. + + The key attribute size of an ML-DSA public key is the same as the corresponding private key. See `PSA_KEY_TYPE_ML_DSA_KEY_PAIR`. + + .. subsection:: Compatible algorithms + + .. hlist:: + + * `PSA_ALG_ML_DSA` + * `PSA_ALG_HASH_ML_DSA` + * `PSA_ALG_DETERMINISTIC_ML_DSA` + * `PSA_ALG_DETERMINISTIC_HASH_ML_DSA` + + .. subsection:: Key format + + An ML-DSA public key is the :math:`pk` output of the ``ML-DSA.KeyGen()`` operation defined in `[FIPS204]` §5.1. + + The size of the public key depends on the ML-DSA parameter set as follows: + + .. csv-table:: + :align: left + :header-rows: 1 + + Parameter set, Public-key size in bytes + ML-DSA-44, 1312 + ML-DSA-65, 1952 + ML-DSA-87, 2592 + +.. macro:: PSA_KEY_TYPE_IS_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether a key type is an ML-DSA key, either a key pair or a public key. + + .. param:: type + A key type: a value of type `psa_key_type_t`. + .. _dh-keys: Diffie Hellman keys diff --git a/doc/crypto/api/ops/algorithms.rst b/doc/crypto/api/ops/algorithms.rst index 98517b75..7ab28307 100644 --- a/doc/crypto/api/ops/algorithms.rst +++ b/doc/crypto/api/ops/algorithms.rst @@ -233,7 +233,9 @@ Support macros The following composite algorithms require a hash algorithm: * `PSA_ALG_DETERMINISTIC_ECDSA()` + * `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` * `PSA_ALG_ECDSA()` + * `PSA_ALG_HASH_ML_DSA()` * `PSA_ALG_HKDF()` * `PSA_ALG_HKDF_EXPAND()` * `PSA_ALG_HKDF_EXTRACT()` diff --git a/doc/crypto/api/ops/hash.rst b/doc/crypto/api/ops/hash.rst index 9f2e7089..91191c99 100644 --- a/doc/crypto/api/ops/hash.rst +++ b/doc/crypto/api/ops/hash.rst @@ -178,13 +178,26 @@ Hash algorithms SHA3-512 is defined in :cite:`FIPS202`. +.. macro:: PSA_ALG_SHAKE128_256 + :definition: ((psa_algorithm_t)0x02000016) + + .. summary:: + The first 256 bits (32 bytes) of the SHAKE128 output. + + This can be used as pre-hashing for ML-DSA (see `PSA_ALG_HASH_ML_DSA()`). + + SHAKE128 is defined in :cite:`FIPS202`. + + .. note:: + For other scenarios where a hash function based on SHA3 or SHAKE is required, SHA3-256 is recommended. SHA3-256 has the same output size, and a theoretically higher security strength. + .. macro:: PSA_ALG_SHAKE256_512 :definition: ((psa_algorithm_t)0x02000015) .. summary:: The first 512 bits (64 bytes) of the SHAKE256 output. - This is the prehashing for Ed448ph (see `PSA_ALG_ED448PH`). + This is the pre-hashing for Ed448ph (see `PSA_ALG_ED448PH`), and can be used as pre-hashing for ML-DSA (see `PSA_ALG_HASH_ML_DSA()`). SHAKE256 is defined in :cite:`FIPS202`. diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index d802a9ea..1993b3bc 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -347,6 +347,248 @@ Asymmetric signature algorithms When used with `psa_sign_hash()` or `psa_verify_hash()`, the ``hash`` parameter to the call should be used as :math:`\text{PH}(M)` in the algorithms defined in :RFC:`8032#5.2`. +.. _ml-dsa-algorithms: + +Module Lattice signature algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ML-DSA signature and verification scheme is defined in :cite-title:`FIPS204`. +`[FIPS204]` defines three parameter sets which provide differing security strengths. + +ML-DSA keys are large: 1.2kB - 2.5kB for the public key, and triple that for the key pair. +ML-DSA signatures are much larger than those for RSA and Elliptic curve schemes, between 2.4kB and 4.6kB, depending on the selected parameter set. + +See `[FIPS204]` §4 for details on the parameter sets, and the key and generated signature sizes. + +The generation of an ML-DSA key depends on the full parameter specification. +The encoding of each parameter set into the key attributes is described in :secref:`ml-keys`. + +`[FIPS204]` defines pure and pre-hashed variants of the signature scheme, which can either be hedged (randomized) or deterministic. +Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_ALG_DETERMINISTIC_ML_DSA`, `PSA_ALG_HASH_ML_DSA()`, and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`. + +* The pre-hashed signature computation generates distinct signatures to a pure signature, even with the same key and message hashing algorithm. + + When verifying a signature it is necessary to know which algorithm was used to generate it. + +* Hedging incorporates fresh randomness in the signature computation, resulting in distinct signatures on every signing operation when given identical inputs. + Deterministic signatures do not require additional random data, and result in an identical signature for the same inputs. + + Signature verification does not distinguish between a hedged and a deterministic signature. + Either form of algorithm can be used when verifying a signature. + +.. note:: + Contexts are not supported in the current version of this specification because there is no suitable signature interface that can take the context as a parameter. + A empty context string is used when computing or verifying ML-DSA signatures. + + A future version of this specification may add suitable functions and extend this algorithm to support contexts. + +.. macro:: PSA_ALG_ML_DSA + :definition: ((psa_algorithm_t) 0x06004400) + + .. summary:: + Stateless hash-based digital signature algorithm without pre-hashing (ML-DSA), using hedging. + + This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. + + This is the pure ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, using hedging. + ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + + This algorithm is randomized: each invocation returns a different, equally valid signature. + + .. note:: + See the general comments in :secref:`ml-dsa-algorithms`. + + .. note:: + To sign or verify the pre-computed hash of a message using ML-DSA, the HashML-DSA algorithms (`PSA_ALG_HASH_ML_DSA()` and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`) can also be used with `psa_sign_hash()` and `psa_verify_hash()`. + + The signature produced by HashML-DSA is distinct from that produced by ML-DSA. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_ML_DSA_KEY_PAIR` + | :code:`PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` (signature verification only) + +.. macro:: PSA_ALG_DETERMINISTIC_ML_DSA + :definition: ((psa_algorithm_t) 0x06004500) + + .. summary:: + Deterministic stateless hash-based digital signature algorithm without pre-hashing (ML-DSA). + + This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. + + This is the pure ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, without hedging. + ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + + This algorithm is deterministic: each invocation with the same inputs returns an identical signature. + + .. note:: + See the general comments in :secref:`ml-dsa-algorithms`. + + .. note:: + To sign or verify the pre-computed hash of a message using ML-DSA, the HashML-DSA algorithms (`PSA_ALG_HASH_ML_DSA()` and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`) can also be used with `psa_sign_hash()` and `psa_verify_hash()`. + + The signature produced by HashML-DSA is distinct from that produced by ML-DSA. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_ML_DSA_KEY_PAIR` + | :code:`PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` (signature verification only) + +.. macro:: PSA_ALG_HASH_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Stateless hash-based digital signature algorithm with pre-hashing (HashML-DSA), using hedging. + + .. param:: hash_alg + A hash algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + This includes `PSA_ALG_ANY_HASH` when specifying the algorithm in a key policy. + + .. return:: + The corresponding HashML-DSA signature algorithm, using ``hash_alg`` to pre-hash the message. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + + This algorithm can be used with both the message and hash signature functions. + + This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, using hedging. + ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + + This algorithm is randomized: each invocation returns a different, equally valid signature. + + .. note:: + See the general comments in :secref:`ml-dsa-algorithms`. + + .. note:: + The signature produced by HashML-DSA is distinct from that produced by ML-DSA. + + .. subsection:: Usage + + This is a hash-and-sign algorithm. To calculate a signature, use one of the following approaches: + + * Call `psa_sign_message()` with the message. + + * Calculate the hash of the message with `psa_hash_compute()`, or with a multi-part hash operation, using the ``hash_alg`` hash algorithm. + Note that ``hash_alg`` can be extracted from the signature algorithm using :code:`PSA_ALG_GET_HASH(sig_alg)`. + Then sign the calculated hash with `psa_sign_hash()`. + + Verifying a signature is similar, using `psa_verify_message()` or `psa_verify_hash()` instead of the signature function. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_ML_DSA_KEY_PAIR` + | :code:`PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` (signature verification only) + +.. macro:: PSA_ALG_DETERMINISTIC_HASH_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Deterministic stateless hash-based digital signature algorithm with pre-hashing (HashML-DSA). + + .. param:: hash_alg + A hash algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + This includes `PSA_ALG_ANY_HASH` when specifying the algorithm in a key policy. + + .. return:: + The corresponding deterministic HashML-DSA signature algorithm, using ``hash_alg`` to pre-hash the message. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + + This algorithm can be used with both the message and hash signature functions. + + This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, without hedging. + ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + + This algorithm is deterministic: each invocation with the same inputs returns an identical signature. + + .. note:: + See the general comments in :secref:`ml-dsa-algorithms`. + + .. note:: + The signature produced by HashML-DSA is distinct from that produced by ML-DSA. + + .. subsection:: Usage + + See `PSA_ALG_HASH_ML_DSA()` for example usage. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_ML_DSA_KEY_PAIR` + | :code:`PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` (signature verification only) + +.. macro:: PSA_ALG_IS_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is ML-DSA or HashML-DSA. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is an ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + + This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + +.. macro:: PSA_ALG_IS_DETERMINISTIC_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is deterministic ML-DSA or HashML-DSA. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a deterministic ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + + This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + + See also `PSA_ALG_IS_ML_DSA()` and `PSA_ALG_IS_RANDOMIZED_ML_DSA()`. + +.. macro:: PSA_ALG_IS_RANDOMIZED_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is randomized ML-DSA or HashML-DSA. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a randomized ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + + This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + + See also `PSA_ALG_IS_ML_DSA()` and `PSA_ALG_IS_DETERMINISTIC_ML_DSA()`. + +.. macro:: PSA_ALG_IS_PURE_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is pure ML-DSA. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a pure ML-DSA algorithm, ``0`` otherwise. + + This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + +.. macro:: PSA_ALG_IS_HASH_ML_DSA + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is HashML-DSA. + + .. param:: alg + An algorithm identifier: a value of type `psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a HashML-DSA algorithm, ``0`` otherwise. + + This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. Asymmetric signature functions ------------------------------ diff --git a/doc/crypto/appendix/encodings.rst b/doc/crypto/appendix/encodings.rst index a1784f9a..a9971773 100644 --- a/doc/crypto/appendix/encodings.rst +++ b/doc/crypto/appendix/encodings.rst @@ -308,17 +308,21 @@ H = HASH-TYPE (see :numref:`table-hash-type`) for message signature algorithms t :widths: auto Signature algorithm, SIGN-TYPE, Algorithm identifier, Algorithm value - RSA PKCS#1 v1.5, ``0x02``, :code:`PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg)`, ``0x060002hh`` :sup:`a` + RSA PKCS#1 v1.5, ``0x02``, :code:`PSA_ALG_RSA_PKCS1V15_SIGN(hash)`, ``0x060002hh`` :sup:`a` RSA PKCS#1 v1.5 no hash :sup:`b`, ``0x02``, `PSA_ALG_RSA_PKCS1V15_SIGN_RAW`, ``0x06000200`` - RSA PSS, ``0x03``, :code:`PSA_ALG_RSA_PSS(hash_alg)`, ``0x060003hh`` :sup:`a` - RSA PSS any salt length, ``0x13``, :code:`PSA_ALG_RSA_PSS_ANY_SALT(hash_alg)`, ``0x060013hh`` :sup:`a` - Randomized ECDSA, ``0x06``, :code:`PSA_ALG_ECDSA(hash_alg)`, ``0x060006hh`` :sup:`a` + RSA PSS, ``0x03``, :code:`PSA_ALG_RSA_PSS(hash)`, ``0x060003hh`` :sup:`a` + RSA PSS any salt length, ``0x13``, :code:`PSA_ALG_RSA_PSS_ANY_SALT(hash)`, ``0x060013hh`` :sup:`a` + Randomized ECDSA, ``0x06``, :code:`PSA_ALG_ECDSA(hash)`, ``0x060006hh`` :sup:`a` Randomized ECDSA no hash :sup:`b`, ``0x06``, `PSA_ALG_ECDSA_ANY`, ``0x06000600`` - Deterministic ECDSA, ``0x07``, :code:`PSA_ALG_DETERMINISTIC_ECDSA(hash_alg)`, ``0x060007hh`` :sup:`a` + Deterministic ECDSA, ``0x07``, :code:`PSA_ALG_DETERMINISTIC_ECDSA(hash)`, ``0x060007hh`` :sup:`a` PureEdDSA, ``0x08``, `PSA_ALG_PURE_EDDSA`, ``0x06000800`` HashEdDSA, ``0x09``, `PSA_ALG_ED25519PH` and `PSA_ALG_ED448PH`, ``0x060009hh`` :sup:`c` + Hedged ML-DSA, ``0x44``, `PSA_ALG_ML_DSA`, ``0x06004400`` + Deterministic ML-DSA, ``0x45``, `PSA_ALG_DETERMINISTIC_ML_DSA`, ``0x06004500`` + Hedged HashML-DSA, ``0x46``, :code:`PSA_ALG_HASH_ML_DSA(hash)`, ``0x060046hh`` :sup:`a` + Deterministic HashML-DSA, ``0x47``, :code:`PSA_ALG_DETERMINISTIC_HASH_ML_DSA(hash)`, ``0x060047hh`` :sup:`a` -a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash_alg``, used to construct the signature algorithm. +a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash``, used to construct the signature algorithm. b. Asymmetric signature algorithms without hashing can only be used with `psa_sign_hash()` and `psa_verify_hash()`. @@ -597,6 +601,8 @@ The defined values for NP-FAMILY and P are shown in :numref:`table-np-type`. Key family, Public/pair, PAIR, NP-FAMILY, P, Key type, Key value RSA, Public key, 0, 0, 1, `PSA_KEY_TYPE_RSA_PUBLIC_KEY`, ``0x4001`` , Key pair, 3, 0, 1, `PSA_KEY_TYPE_RSA_KEY_PAIR`, ``0x7001`` + ML-DSA, Public key, 0, 1, 0, `PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY`, ``0x4002`` + , Key pair, 3, 1, 0, `PSA_KEY_TYPE_ML_DSA_KEY_PAIR`, ``0x7002`` .. _ecc-key-encoding: diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index a0e7d299..09e48851 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -33,6 +33,9 @@ Changes to the API See :secref:`asymmetric-key-encoding` and :secref:`appendix-specdef-key-values`. +* Added support for FIPS 204 ML-DSA signature algorithm and keys. + See :secref:`ml-keys` and :secref:`ml-dsa-algorithms`. + Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 11d1ea2d..4aecac8a 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -39,6 +39,9 @@ Algorithm macros #define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ ((psa_algorithm_t) (0x06000700 | ((hash_alg) & 0x000000ff))) + #define PSA_ALG_DETERMINISTIC_HASH_ML_DSA(hash_alg) \ + ((psa_algorithm_t) (0x06004700 | ((hash_alg) & 0x000000ff))) + #define PSA_ALG_ECDSA(hash_alg) \ ((psa_algorithm_t) (0x06000600 | ((hash_alg) & 0x000000ff))) @@ -48,6 +51,9 @@ Algorithm macros #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? PSA_ALG_NONE : 0x02000000 | ((alg) & 0x000000ff)) + #define PSA_ALG_HASH_ML_DSA(hash_alg) \ + ((psa_algorithm_t) (0x06004600 | ((hash_alg) & 0x000000ff))) + #define PSA_ALG_HKDF(hash_alg) \ ((psa_algorithm_t) (0x08000100 | ((hash_alg) & 0x000000ff))) @@ -78,6 +84,9 @@ Algorithm macros #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000700) + #define PSA_ALG_IS_DETERMINISTIC_ML_DSA(alg) \ + (((alg) & ~0x000002ff) == 0x06004500) + #define PSA_ALG_IS_ECDH(alg) \ (((alg) & 0x7fff0000) == 0x09020000) @@ -92,11 +101,15 @@ Algorithm macros #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg)) + PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ + PSA_ALG_IS_HASH_ML_DSA(alg)) #define PSA_ALG_IS_HASH_EDDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000900) + #define PSA_ALG_IS_HASH_ML_DSA(alg) \ + (((alg) & ~0x000001ff) == 0x06004600) + #define PSA_ALG_IS_HKDF(alg) \ (((alg) & ~0x000000ff) == 0x08000100) @@ -124,15 +137,24 @@ Algorithm macros #define PSA_ALG_IS_MAC(alg) \ (((alg) & 0x7f000000) == 0x03000000) + #define PSA_ALG_IS_ML_DSA(alg) \ + (((alg) & ~0x000003ff) == 0x06004400) + #define PSA_ALG_IS_PAKE(alg) \ (((alg) & 0x7f000000) == 0x0a000000) #define PSA_ALG_IS_PBKDF2_HMAC(alg) \ (((alg) & ~0x000000ff) == 0x08800100) + #define PSA_ALG_IS_PURE_ML_DSA(alg) \ + (((alg) & ~0x000001ff) == 0x06004400) + #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000600) + #define PSA_ALG_IS_RANDOMIZED_ML_DSA(alg) \ + (((alg) & ~0x000002ff) == 0x06004400) + #define PSA_ALG_IS_RSA_OAEP(alg) \ (((alg) & ~0x000000ff) == 0x07000300) @@ -152,7 +174,8 @@ Algorithm macros (((alg) & 0x7f000000) == 0x06000000) #define PSA_ALG_IS_SIGN_HASH(alg) \ - PSA_ALG_IS_SIGN(alg) + (PSA_ALG_IS_SIGN(alg) && \ + (alg) != PSA_ALG_PURE_EDDSA && !PSA_ALG_IS_PURE_ML_DSA(alg)) #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ (PSA_ALG_IS_SIGN(alg) && \ @@ -298,6 +321,9 @@ Key type macros #define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ (((type) & 0x7000) == 0x7000) + #define PSA_KEY_TYPE_IS_ML_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == 0x4002) + #define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ (((type) & 0x7000) == 0x4000) diff --git a/doc/crypto/references b/doc/crypto/references index 196e15df..5325eb2e 100644 --- a/doc/crypto/references +++ b/doc/crypto/references @@ -396,3 +396,15 @@ :author: Thread Group :publication: July 2022 :url: www.threadgroup.org/ThreadSpec + +.. reference:: FIPS203 + :title: FIPS Publication 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard + :author: NIST + :publication: August 2024 + :url: doi.org/10.6028/NIST.FIPS.203 + +.. reference:: FIPS204 + :title: FIPS Publication 204: Module-Lattice-Based Digital Signature Standard + :author: NIST + :publication: August 2024 + :url: doi.org/10.6028/NIST.FIPS.204 From 01fa88ce82ae08c0e4dbc24740b785dd59fb6ace Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:08:43 +0100 Subject: [PATCH 02/13] Use the seed as the ML-DSA key pair export format. --- doc/crypto/api/keys/types.rst | 50 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index c337edb9..ead513be 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -1205,41 +1205,47 @@ These algorithms have distinct asymmetric key types. .. subsection:: Key format - .. todo:: - Decide if the default ML-DSA key-pair format is the 32-byte seed :math:`\xi`, or the :math:`(pk,sk)` tuple (which is 3.8kB - 7.4kB in size). + An ML-DSA key pair is the :math:`(pk,sk)` pair of public key and secret key, which are generated from a secret 32-byte seed, :math:`\xi`. See [FIPS204]` §5.1. - The seed cannot be recomputed from the (pk, sk) pair. - If the seed is the default format, then importing a (pk, sk) pair results in a key that cannot be exported in the default format. + The data format for import and export of the key pair is the 32-byte seed :math:`\xi`. - I suspect this means that the default export format should be the (pk, sk) pair. - The API permits implementation storage as a seed (for internally generated keys), and the API could provide an alternative format or format option to export/import the seed instead of the (pk, sk) pair (for an implementation and key-pair that still retain the generating seed). + .. rationale:: - An ML-DSA key pair is the :math:`(pk,sk)` pair of public key and secret key. + The IETF working group responsible for defining the format of the ML-DSA keys in *SubjectPublicKeyInfo* and *OneAsymmetricKey* structures is discussing the formats at present (September 2024), with the current consensus to using just the seed value as the private key, for the following reasons: - The data format for import and export of the key-pair is the concatenation of the public key and secret keys, :math:`pk\ ||\ sk`, where :math:`pk` and :math:`sk` are the octet strings returned by the ``ML-DSA.KeyGen()`` operation defined in `[FIPS204]` §5.1. + * ML-DSA key-pairs are several kB in size, but can be recomputed efficiently from the initial 32-byte seed. + * There is no need to validate an imported ML-DSA private key --- every 32-byte seed values is valid. + * The public key cannot be derived from the secret key, so a key pair must store both the secret key and the public key. + The size of the key pair depends on the ML-DSA parameter set as follows: - The size of the key pair depends on the ML-DSA parameter set as follows: + .. csv-table:: + :align: left + :header-rows: 1 - .. csv-table:: - :align: left - :header-rows: 1 + Parameter set, Key-pair size in bytes + ML-DSA-44, 3872 + ML-DSA-65, 5984 + ML-DSA-87, 7488 - Parameter set, Key-pair size in bytes - ML-DSA-44, 3872 - ML-DSA-65, 5984 - ML-DSA-87, 7488 + * It is better for the standard to choose a single format to improve interoperability. + + One consequence is that to enable future export of the private key (for example, a wrapped copy in a CMS or *EncryptedPrivateKeyInfo* structure), the implementation MUST store the seed :math:`\xi`, even if it also computes and stores the :math:`(pk,sk)` pair. See `PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. - .. subsection:: Key derivation + .. admonition:: Implementation note + + An implementation can optionally compute and store the :math:`(pk,sk)` values, to accelerate operations that use the key. + It is recommended that an implementation retains the seed :math:`\xi` with the key pair, in order to export the key, or copy the key to a different location. - :issue:`TBD` + .. subsection:: Key derivation - .. todo:: + A call to `psa_key_derivation_output_key()` will draw 32 bytes of output and use these as the 32-byte ML-DSA key-pair seed, :math:`xi`. + The key-pair :math:`(pk, sk)` is generated from the seed as defined by ``ML-DSA.KeyGen_internal()`` in `[FIPS204]` §6.1. - As ML-DSA keys are generated from a 32-byte seed, it would be very straight-forward to enable key-derivation of an ML-DSA key pair as part of a KDF. + .. admonition:: Implementation note - However, this is not described anywhere as an expected use case with ML-DSA. + It is :scterm:`implementation defined` whether the seed :math:`xi` is expanded to :math:`(pk, sk)` at the point of derivation, or only just before the key is used. .. macro:: PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY :definition: ((psa_key_type_t)0x4002) @@ -1260,7 +1266,7 @@ These algorithms have distinct asymmetric key types. .. subsection:: Key format - An ML-DSA public key is the :math:`pk` output of the ``ML-DSA.KeyGen()`` operation defined in `[FIPS204]` §5.1. + An ML-DSA public key is the :math:`pk` output of ``ML-DSA.KeyGen()``, defined in `[FIPS204]` §5.1. The size of the public key depends on the ML-DSA parameter set as follows: From a6993f974f29325e8638b2d170d75d5fcf6bb445 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:10:37 +0100 Subject: [PATCH 03/13] Do not group ML-DSA keys and ML-KEM keys together. --- doc/crypto/api/keys/types.rst | 15 ++++----------- doc/crypto/api/ops/signature.rst | 14 +++++++------- doc/crypto/appendix/history.rst | 2 +- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index ead513be..f49c9100 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -1165,19 +1165,12 @@ The curve type affects the key format, the key derivation procedure, and the alg .. return:: psa_ecc_family_t The elliptic curve family id, if ``type`` is a supported elliptic curve key. Unspecified if ``type`` is not a supported elliptic curve key. -.. _ml-keys: +.. _ml-dsa-keys: -Module Lattice keys -------------------- - -The |API| supports Module Lattice cryptography as defined in :cite-title:`FIPS203` and :cite-title:`FIPS204`. - -There are two related, but separate, algorithms: - -* A key encapsulation method, ML-KEM. -* A signature method, ML-DSA. +Module Lattice-based Signature keys +----------------------------------- -These algorithms have distinct asymmetric key types. +The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined in :cite-title:`FIPS204`. .. macro:: PSA_KEY_TYPE_ML_DSA_KEY_PAIR :definition: ((psa_key_type_t)0x7002) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 1993b3bc..4f7a0c59 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -349,8 +349,8 @@ Asymmetric signature algorithms .. _ml-dsa-algorithms: -Module Lattice signature algorithms -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Module Lattice-based signature algorithms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ML-DSA signature and verification scheme is defined in :cite-title:`FIPS204`. `[FIPS204]` defines three parameter sets which provide differing security strengths. @@ -361,7 +361,7 @@ ML-DSA signatures are much larger than those for RSA and Elliptic curve schemes, See `[FIPS204]` §4 for details on the parameter sets, and the key and generated signature sizes. The generation of an ML-DSA key depends on the full parameter specification. -The encoding of each parameter set into the key attributes is described in :secref:`ml-keys`. +The encoding of each parameter set into the key attributes is described in :secref:`ml-dsa-keys`. `[FIPS204]` defines pure and pre-hashed variants of the signature scheme, which can either be hedged (randomized) or deterministic. Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_ALG_DETERMINISTIC_ML_DSA`, `PSA_ALG_HASH_ML_DSA()`, and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`. @@ -391,7 +391,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. This is the pure ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, using hedging. - ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. This algorithm is randomized: each invocation returns a different, equally valid signature. @@ -417,7 +417,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. This is the pure ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, without hedging. - ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. This algorithm is deterministic: each invocation with the same inputs returns an identical signature. @@ -452,7 +452,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This algorithm can be used with both the message and hash signature functions. This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, using hedging. - ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. This algorithm is randomized: each invocation returns a different, equally valid signature. @@ -497,7 +497,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This algorithm can be used with both the message and hash signature functions. This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, without hedging. - ML-DSA requires an ML key, which determines the ML-DSA parameter set for the operation. + ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. This algorithm is deterministic: each invocation with the same inputs returns an identical signature. diff --git a/doc/crypto/appendix/history.rst b/doc/crypto/appendix/history.rst index 09e48851..e197b9f7 100644 --- a/doc/crypto/appendix/history.rst +++ b/doc/crypto/appendix/history.rst @@ -34,7 +34,7 @@ Changes to the API See :secref:`asymmetric-key-encoding` and :secref:`appendix-specdef-key-values`. * Added support for FIPS 204 ML-DSA signature algorithm and keys. - See :secref:`ml-keys` and :secref:`ml-dsa-algorithms`. + See :secref:`ml-dsa-keys` and :secref:`ml-dsa-algorithms`. Clarifications and fixes ~~~~~~~~~~~~~~~~~~~~~~~~ From ac438ffddc80ae1981e75a66a914eb327a2a676e Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:11:01 +0100 Subject: [PATCH 04/13] Fix spelling --- doc/crypto/api/ops/signature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 4f7a0c59..8f23160d 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -1015,7 +1015,7 @@ Support macros .. return:: ``1`` if ``alg`` is a hash-and-sign algorithm that signs exactly the hash value, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. - A wildcard signature algorithm policy, using `PSA_ALG_ANY_HASH`, returns the same value as the signature algorithm parameterised with a valid hash algorithm. + A wildcard signature algorithm policy, using `PSA_ALG_ANY_HASH`, returns the same value as the signature algorithm parameterized with a valid hash algorithm. This macro identifies algorithms that can be used with `psa_sign_hash()` that use the exact message hash value as an input the signature operation. For example, if :code:`PSA_ALG_IS_HASH_AND_SIGN(alg)` is true, the following call sequence is equivalent to :code:`psa_sign_message(key, alg, msg, msg_len, ...)`: From a747d1927a2f2271b07445ea2dee5a6144644893 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:12:59 +0100 Subject: [PATCH 05/13] Treat hedged/deterministic ML-DSA verification algorithms as equivalent when checking policy --- doc/crypto/api/ops/signature.rst | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 8f23160d..7be728da 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -374,7 +374,10 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL Deterministic signatures do not require additional random data, and result in an identical signature for the same inputs. Signature verification does not distinguish between a hedged and a deterministic signature. - Either form of algorithm can be used when verifying a signature. + Either hedged or deterministic algorithms can be used when verifying a signature. + + When computing a signature, the key's permitted-algorithm policy must match the requested algorithm, treating hedged and deterministic versions as distinct. + When verifying a signature, the hedged and deterministic versions of each algorithm are considered equivalent when checking the key's permitted-algorithm policy. .. note:: Contexts are not supported in the current version of this specification because there is no suitable signature interface that can take the context as a parameter. @@ -398,6 +401,11 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. note:: See the general comments in :secref:`ml-dsa-algorithms`. + When `PSA_ALG_ML_DSA` is used as a permitted algorithm in a key policy, this permits: + + * `PSA_ALG_ML_DSA` as the algorithm in a call to `psa_sign_message()`. + * `PSA_ALG_ML_DSA` or `PSA_ALG_DETERMINISTIC_ML_DSA` as the algorithm in a call to `psa_verify_message()`. + .. note:: To sign or verify the pre-computed hash of a message using ML-DSA, the HashML-DSA algorithms (`PSA_ALG_HASH_ML_DSA()` and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`) can also be used with `psa_sign_hash()` and `psa_verify_hash()`. @@ -424,6 +432,11 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. note:: See the general comments in :secref:`ml-dsa-algorithms`. + When `PSA_ALG_DETERMINISTIC_ML_DSA` is used as a permitted algorithm in a key policy, this permits: + + * `PSA_ALG_DETERMINISTIC_ML_DSA` as the algorithm in a call to `psa_sign_message()`. + * `PSA_ALG_ML_DSA` or `PSA_ALG_DETERMINISTIC_ML_DSA` as the algorithm in a call to `psa_verify_message()`. + .. note:: To sign or verify the pre-computed hash of a message using ML-DSA, the HashML-DSA algorithms (`PSA_ALG_HASH_ML_DSA()` and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`) can also be used with `psa_sign_hash()` and `psa_verify_hash()`. @@ -459,6 +472,11 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. note:: See the general comments in :secref:`ml-dsa-algorithms`. + When `PSA_ALG_HASH_ML_DSA()` is used as a permitted algorithm in a key policy, this permits: + + * `PSA_ALG_HASH_ML_DSA()` as the algorithm in a call to `psa_sign_message()` and `psa_sign_hash()`. + * `PSA_ALG_HASH_ML_DSA()` or `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` as the algorithm in a call to `psa_verify_message()` and `psa_verify_hash()`. + .. note:: The signature produced by HashML-DSA is distinct from that produced by ML-DSA. @@ -504,6 +522,11 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. note:: See the general comments in :secref:`ml-dsa-algorithms`. + When `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` is used as a permitted algorithm in a key policy, this permits: + + * `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` as the algorithm in a call to `psa_sign_message()` and `psa_sign_hash()`. + * `PSA_ALG_HASH_ML_DSA()` or `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` as the algorithm in a call to `psa_verify_message()` and `psa_verify_hash()`. + .. note:: The signature produced by HashML-DSA is distinct from that produced by ML-DSA. From 2345aae0d3facf4de0177cb69f22d6f73af38c68 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:13:50 +0100 Subject: [PATCH 06/13] Provide rationale for distinct hedged/deterministic algorithms --- doc/crypto/api/ops/signature.rst | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 7be728da..5575c150 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -366,9 +366,9 @@ The encoding of each parameter set into the key attributes is described in :secr `[FIPS204]` defines pure and pre-hashed variants of the signature scheme, which can either be hedged (randomized) or deterministic. Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_ALG_DETERMINISTIC_ML_DSA`, `PSA_ALG_HASH_ML_DSA()`, and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`. -* The pre-hashed signature computation generates distinct signatures to a pure signature, even with the same key and message hashing algorithm. +* The pre-hashed signature computation --- *HashML-DSA* --- generates distinct signatures to a pure signature --- *ML-DSA* ---, with the same key and message hashing algorithm. - When verifying a signature it is necessary to know which algorithm was used to generate it. + An ML-DSA signature can only be verified with an ML-DSA algorithm. A HashML-DSA signature can only be verified with a HashML-DSA algorithm. * Hedging incorporates fresh randomness in the signature computation, resulting in distinct signatures on every signing operation when given identical inputs. Deterministic signatures do not require additional random data, and result in an identical signature for the same inputs. @@ -385,6 +385,19 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL A future version of this specification may add suitable functions and extend this algorithm to support contexts. +.. todo:: + Decide if these general comments are better kept in a common place (here), or if they should be repeated with as appropriate in each of the four algorithm definitions? + +.. rationale:: + + The use of fresh randomness, or not, when computing a signature looks primarily like an implementation decision based on the capability of the system, and its vulnerability to specific threats, following the recommendations in `[FIPS204]`. + + However, the |API| gives distinct algorithm identifiers for the hedged and deterministic variants of both ML-DSA and HashML-DSA, for the following reasons: + + * `[FIPS204]` recommends that ML-DSA signing keys are only used to compute either deterministic, or hedged, signatures, but not both. + Supporting this requires separate algorithm identifiers, and requiring an exact policy match for signature computation. + * Some application use cases might specifically require deterministic signatures, or might require the use of hedging to mitigate possible message confidentiality threats. + .. macro:: PSA_ALG_ML_DSA :definition: ((psa_algorithm_t) 0x06004400) From b757c94a6a9d0638225108bc7f37f0763d57db8c Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:23:58 +0100 Subject: [PATCH 07/13] Reflect the algorithm distinction between ML-DSA and HashML-DSA * PSA_ALG_IS_ML_DSA() checks for ML-DSA, and returns 0 for HashML-DSA. Replaces the use of PSA_ALG_IS_PURE_ML_DSA() * Removed PSA_ALG_IS_DETERMINISTIC_ML_DSA() and PSA_ALG_IS_RANDOMIZED_ML_DSA() * Added PSA_ALG_IS_DETERMINISTIC_HASH_ML_DSA() and PSA_ALG_IS_HEDGED_HASH_ML_DSA() * Use "hedged" instead of "randomized" in ML-DSA algorithm identifiers and descriptions --- doc/crypto/api.db/psa/crypto.h | 6 ++-- doc/crypto/api/ops/signature.rst | 44 +++++++++++--------------- doc/crypto/appendix/specdef_values.rst | 15 ++++----- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/doc/crypto/api.db/psa/crypto.h b/doc/crypto/api.db/psa/crypto.h index 7878af6d..60c41233 100644 --- a/doc/crypto/api.db/psa/crypto.h +++ b/doc/crypto/api.db/psa/crypto.h @@ -96,7 +96,8 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) /* specification-defined value */ #define PSA_ALG_IS_CIPHER(alg) /* specification-defined value */ #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) /* specification-defined value */ -#define PSA_ALG_IS_DETERMINISTIC_ML_DSA(alg) /* specification-defined value */ +#define PSA_ALG_IS_DETERMINISTIC_HASH_ML_DSA(alg) \ + /* specification-defined value */ #define PSA_ALG_IS_ECDH(alg) /* specification-defined value */ #define PSA_ALG_IS_ECDSA(alg) /* specification-defined value */ #define PSA_ALG_IS_FFDH(alg) /* specification-defined value */ @@ -104,6 +105,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_HASH_AND_SIGN(alg) /* specification-defined value */ #define PSA_ALG_IS_HASH_EDDSA(alg) /* specification-defined value */ #define PSA_ALG_IS_HASH_ML_DSA(alg) /* specification-defined value */ +#define PSA_ALG_IS_HEDGED_HASH_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF_EXPAND(alg) /* specification-defined value */ #define PSA_ALG_IS_HKDF_EXTRACT(alg) /* specification-defined value */ @@ -117,9 +119,7 @@ typedef struct psa_custom_key_parameters_t { #define PSA_ALG_IS_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) /* specification-defined value */ -#define PSA_ALG_IS_PURE_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) /* specification-defined value */ -#define PSA_ALG_IS_RANDOMIZED_ML_DSA(alg) /* specification-defined value */ #define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ PSA_ALG_IS_STANDALONE_KEY_AGREEMENT(alg) #define PSA_ALG_IS_RSA_OAEP(alg) /* specification-defined value */ diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 5575c150..07032c5e 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -556,75 +556,67 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is ML-DSA or HashML-DSA. + Whether the specified algorithm is ML-DSA, without pre-hashing. .. param:: alg An algorithm identifier: a value of type `psa_algorithm_t`. .. return:: - ``1`` if ``alg`` is an ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + ``1`` if ``alg`` is a pure ML-DSA algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. -.. macro:: PSA_ALG_IS_DETERMINISTIC_ML_DSA + .. note:: + Use `PSA_ALG_IS_HASH_ML_DSA()` to determine if an algorithm identifier is a HashML-DSA algorithm. + +.. macro:: PSA_ALG_IS_HASH_ML_DSA :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is deterministic ML-DSA or HashML-DSA. + Whether the specified algorithm is HashML-DSA. .. param:: alg An algorithm identifier: a value of type `psa_algorithm_t`. .. return:: - ``1`` if ``alg`` is a deterministic ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + ``1`` if ``alg`` is a HashML-DSA algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. - See also `PSA_ALG_IS_ML_DSA()` and `PSA_ALG_IS_RANDOMIZED_ML_DSA()`. + .. note:: + Use `PSA_ALG_IS_ML_DSA()` to determine if an algorithm identifier is a pre-hashed ML-DSA algorithm. -.. macro:: PSA_ALG_IS_RANDOMIZED_ML_DSA +.. macro:: PSA_ALG_IS_DETERMINISTIC_HASH_ML_DSA :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is randomized ML-DSA or HashML-DSA. + Whether the specified algorithm is deterministic HashML-DSA. .. param:: alg An algorithm identifier: a value of type `psa_algorithm_t`. .. return:: - ``1`` if ``alg`` is a randomized ML-DSA or HashML-DSA algorithm, ``0`` otherwise. + ``1`` if ``alg`` is a deterministic HashML-DSA algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. - See also `PSA_ALG_IS_ML_DSA()` and `PSA_ALG_IS_DETERMINISTIC_ML_DSA()`. + See also `PSA_ALG_IS_HASH_ML_DSA()` and `PSA_ALG_IS_HEDGED_HASH_ML_DSA()`. -.. macro:: PSA_ALG_IS_PURE_ML_DSA +.. macro:: PSA_ALG_IS_HEDGED_HASH_ML_DSA :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is pure ML-DSA. + Whether the specified algorithm is hedged HashML-DSA. .. param:: alg An algorithm identifier: a value of type `psa_algorithm_t`. .. return:: - ``1`` if ``alg`` is a pure ML-DSA algorithm, ``0`` otherwise. + ``1`` if ``alg`` is a hedged HashML-DSA algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. -.. macro:: PSA_ALG_IS_HASH_ML_DSA - :definition: /* specification-defined value */ - - .. summary:: - Whether the specified algorithm is HashML-DSA. - - .. param:: alg - An algorithm identifier: a value of type `psa_algorithm_t`. - - .. return:: - ``1`` if ``alg`` is a HashML-DSA algorithm, ``0`` otherwise. - - This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. + See also `PSA_ALG_IS_HASH_ML_DSA()` and `PSA_ALG_IS_DETERMINISTIC_HASH_ML_DSA()`. Asymmetric signature functions ------------------------------ diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index 4aecac8a..fe1b326f 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -84,8 +84,8 @@ Algorithm macros #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000700) - #define PSA_ALG_IS_DETERMINISTIC_ML_DSA(alg) \ - (((alg) & ~0x000002ff) == 0x06004500) + #define PSA_ALG_IS_DETERMINISTIC_HASH_ML_DSA(alg) \ + (((alg) & ~0x000000ff) == 0x06004700) #define PSA_ALG_IS_ECDH(alg) \ (((alg) & 0x7fff0000) == 0x09020000) @@ -110,6 +110,9 @@ Algorithm macros #define PSA_ALG_IS_HASH_ML_DSA(alg) \ (((alg) & ~0x000001ff) == 0x06004600) + #define PSA_ALG_IS_HEDGED_HASH_ML_DSA(alg) \ + (((alg) & ~0x000000ff) == 0x06004600) + #define PSA_ALG_IS_HKDF(alg) \ (((alg) & ~0x000000ff) == 0x08000100) @@ -138,7 +141,7 @@ Algorithm macros (((alg) & 0x7f000000) == 0x03000000) #define PSA_ALG_IS_ML_DSA(alg) \ - (((alg) & ~0x000003ff) == 0x06004400) + (((alg) & ~0x00000100) == 0x06004400) #define PSA_ALG_IS_PAKE(alg) \ (((alg) & 0x7f000000) == 0x0a000000) @@ -146,15 +149,9 @@ Algorithm macros #define PSA_ALG_IS_PBKDF2_HMAC(alg) \ (((alg) & ~0x000000ff) == 0x08800100) - #define PSA_ALG_IS_PURE_ML_DSA(alg) \ - (((alg) & ~0x000001ff) == 0x06004400) - #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ (((alg) & ~0x000000ff) == 0x06000600) - #define PSA_ALG_IS_RANDOMIZED_ML_DSA(alg) \ - (((alg) & ~0x000002ff) == 0x06004400) - #define PSA_ALG_IS_RSA_OAEP(alg) \ (((alg) & ~0x000000ff) == 0x07000300) From 30915a40a1cb5c52561205f7f933178cac6ed435 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 25 Sep 2024 18:30:38 +0100 Subject: [PATCH 08/13] Correct algorithm summary text --- doc/crypto/api/ops/signature.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 07032c5e..64b1b090 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -402,7 +402,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL :definition: ((psa_algorithm_t) 0x06004400) .. summary:: - Stateless hash-based digital signature algorithm without pre-hashing (ML-DSA), using hedging. + Module lattice-based digital signature algorithm without pre-hashing (ML-DSA). This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. @@ -433,7 +433,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL :definition: ((psa_algorithm_t) 0x06004500) .. summary:: - Deterministic stateless hash-based digital signature algorithm without pre-hashing (ML-DSA). + Deterministic module lattice-based digital signature algorithm without pre-hashing (ML-DSA). This algorithm can be only used with the `psa_sign_message()` and `psa_verify_message()` functions. @@ -464,7 +464,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL :definition: /* specification-defined value */ .. summary:: - Stateless hash-based digital signature algorithm with pre-hashing (HashML-DSA), using hedging. + Module lattice-based digital signature algorithm with pre-hashing (HashML-DSA). .. param:: hash_alg A hash algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. @@ -514,7 +514,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL :definition: /* specification-defined value */ .. summary:: - Deterministic stateless hash-based digital signature algorithm with pre-hashing (HashML-DSA). + Deterministic module lattice-based digital signature algorithm with pre-hashing (HashML-DSA). .. param:: hash_alg A hash algorithm: a value of type `psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. From 809eb4530f75cc1c4abd62add54a4b10b3e387cd Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Thu, 26 Sep 2024 23:06:06 +0100 Subject: [PATCH 09/13] fixup: missing change in example macro implementations --- doc/crypto/appendix/specdef_values.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypto/appendix/specdef_values.rst b/doc/crypto/appendix/specdef_values.rst index fe1b326f..00a3a03c 100644 --- a/doc/crypto/appendix/specdef_values.rst +++ b/doc/crypto/appendix/specdef_values.rst @@ -172,7 +172,7 @@ Algorithm macros #define PSA_ALG_IS_SIGN_HASH(alg) \ (PSA_ALG_IS_SIGN(alg) && \ - (alg) != PSA_ALG_PURE_EDDSA && !PSA_ALG_IS_PURE_ML_DSA(alg)) + (alg) != PSA_ALG_PURE_EDDSA && !PSA_ALG_IS_ML_DSA(alg)) #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ (PSA_ALG_IS_SIGN(alg) && \ From ce5a8fd2916d915275e4ec575b6185bd4e42ed34 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Thu, 26 Sep 2024 23:06:42 +0100 Subject: [PATCH 10/13] Add FIPS204 recommendations for algorithm selection --- doc/crypto/api/ops/signature.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index 64b1b090..df9ff191 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -394,8 +394,6 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL However, the |API| gives distinct algorithm identifiers for the hedged and deterministic variants of both ML-DSA and HashML-DSA, for the following reasons: - * `[FIPS204]` recommends that ML-DSA signing keys are only used to compute either deterministic, or hedged, signatures, but not both. - Supporting this requires separate algorithm identifiers, and requiring an exact policy match for signature computation. * Some application use cases might specifically require deterministic signatures, or might require the use of hedging to mitigate possible message confidentiality threats. .. macro:: PSA_ALG_ML_DSA @@ -442,6 +440,10 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This algorithm is deterministic: each invocation with the same inputs returns an identical signature. + .. warning:: + It is recommended to use the hedged `PSA_ALG_ML_DSA` algorithm instead, when supported by the implementation. + See `[FIPS204]` §3.4. + .. note:: See the general comments in :secref:`ml-dsa-algorithms`. @@ -480,6 +482,9 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, using hedging. ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. + .. note:: + For the pre-hashing, `[FIPS204]` §5.4 recommends the use of an approved hash function with an equivalent, or better, security strength than the chosen ML-DSA parameter set. + This algorithm is randomized: each invocation returns a different, equally valid signature. .. note:: @@ -530,8 +535,15 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL This is the pre-hashed ML-DSA digital signature algorithm, defined by :cite-title:`FIPS204`, without hedging. ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. + .. note:: + For the pre-hashing, `[FIPS204]` §5.4 recommends the use of an approved hash function with an equivalent, or better, security strength than the chosen ML-DSA parameter set. + This algorithm is deterministic: each invocation with the same inputs returns an identical signature. + .. warning:: + It is recommended to use the hedged `PSA_ALG_HASH_ML_DSA()` algorithm instead, when supported by the implementation. + See `[FIPS204]` §3.4. + .. note:: See the general comments in :secref:`ml-dsa-algorithms`. From 70d06a77928150308c36a77568b991f3c249f3f7 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 30 Sep 2024 14:23:09 +0100 Subject: [PATCH 11/13] Clarification on ML-DSA deterministic vs hedged * Reworked the layout of the ML-DSA introduction, using rubric subtitles to improve the structure * Added specific notes for applications and for implementations regarding the use of deterministic variants --- doc/crypto/api/ops/signature.rst | 58 +++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index df9ff191..c11405d3 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -353,9 +353,9 @@ Module Lattice-based signature algorithms ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ML-DSA signature and verification scheme is defined in :cite-title:`FIPS204`. -`[FIPS204]` defines three parameter sets which provide differing security strengths. +ML-DSA has three parameter sets which provide differing security strengths. -ML-DSA keys are large: 1.2kB - 2.5kB for the public key, and triple that for the key pair. +ML-DSA keys are large: 1.2--2.5kB for the public key, and triple that for the key pair. ML-DSA signatures are much larger than those for RSA and Elliptic curve schemes, between 2.4kB and 4.6kB, depending on the selected parameter set. See `[FIPS204]` §4 for details on the parameter sets, and the key and generated signature sizes. @@ -366,35 +366,52 @@ The encoding of each parameter set into the key attributes is described in :secr `[FIPS204]` defines pure and pre-hashed variants of the signature scheme, which can either be hedged (randomized) or deterministic. Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_ALG_DETERMINISTIC_ML_DSA`, `PSA_ALG_HASH_ML_DSA()`, and `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()`. -* The pre-hashed signature computation --- *HashML-DSA* --- generates distinct signatures to a pure signature --- *ML-DSA* ---, with the same key and message hashing algorithm. +.. _ml-dsa-deterministic-signatures: - An ML-DSA signature can only be verified with an ML-DSA algorithm. A HashML-DSA signature can only be verified with a HashML-DSA algorithm. +.. rubric:: Hedged and deterministic signatures -* Hedging incorporates fresh randomness in the signature computation, resulting in distinct signatures on every signing operation when given identical inputs. - Deterministic signatures do not require additional random data, and result in an identical signature for the same inputs. +Hedging incorporates fresh randomness in the signature computation, resulting in distinct signatures on every signing operation when given identical inputs. +Deterministic signatures do not require additional random data, and result in an identical signature for the same inputs. - Signature verification does not distinguish between a hedged and a deterministic signature. - Either hedged or deterministic algorithms can be used when verifying a signature. +Signature verification does not distinguish between a hedged and a deterministic signature. +Either hedged or deterministic algorithms can be used when verifying a signature. - When computing a signature, the key's permitted-algorithm policy must match the requested algorithm, treating hedged and deterministic versions as distinct. - When verifying a signature, the hedged and deterministic versions of each algorithm are considered equivalent when checking the key's permitted-algorithm policy. +When computing a signature, the key's permitted-algorithm policy must match the requested algorithm, treating hedged and deterministic versions as distinct. +When verifying a signature, the hedged and deterministic versions of each algorithm are considered equivalent when checking the key's permitted-algorithm policy. .. note:: - Contexts are not supported in the current version of this specification because there is no suitable signature interface that can take the context as a parameter. - A empty context string is used when computing or verifying ML-DSA signatures. - A future version of this specification may add suitable functions and extend this algorithm to support contexts. + The hedged version provides message secrecy and some protection against side-channels. + `[FIPS204]` recommends that users should use the hedged version if either of these issues are a concern. + The deterministic variant should only be used if the implementation does not include any source of randomness. -.. todo:: - Decide if these general comments are better kept in a common place (here), or if they should be repeated with as appropriate in each of the four algorithm definitions? +.. admonition:: Implementation note + + `[FIPS204]` recommends that implementations use an approved random number generator to provide the random value in the hedged version. + However, it notes that use of the hedged variant with a weak RNG is generally preferable to the deterministic variant. .. rationale:: - The use of fresh randomness, or not, when computing a signature looks primarily like an implementation decision based on the capability of the system, and its vulnerability to specific threats, following the recommendations in `[FIPS204]`. + The use of fresh randomness, or not, when computing a signature seems like an implementation decision based on the capability of the system, and its vulnerability to specific threats, following the recommendations in `[FIPS204]`. + + However, the |API| gives distinct algorithm identifiers for the hedged and deterministic variants, to enable an application use case to require a specific variant. + +.. rubric:: Pure and pre-hashed algorithms + +The pre-hashed signature computation *HashML-DSA* generates distinct signatures to a pure signature *ML-DSA*, with the same key and message hashing algorithm. - However, the |API| gives distinct algorithm identifiers for the hedged and deterministic variants of both ML-DSA and HashML-DSA, for the following reasons: +An ML-DSA signature can only be verified with an ML-DSA algorithm. +A HashML-DSA signature can only be verified with a HashML-DSA algorithm. - * Some application use cases might specifically require deterministic signatures, or might require the use of hedging to mitigate possible message confidentiality threats. +.. rubric:: Contexts + +Contexts are not supported in the current version of this specification because there is no suitable signature interface that can take the context as a parameter. +A empty context string is used when computing or verifying ML-DSA signatures. + +A future version of this specification may add suitable functions and extend this algorithm to support contexts. + +.. todo:: + Decide if these general comments are better kept in a common place (here), or if they should be repeated with as appropriate in each of the four algorithm definitions? .. macro:: PSA_ALG_ML_DSA :definition: ((psa_algorithm_t) 0x06004400) @@ -442,7 +459,7 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. warning:: It is recommended to use the hedged `PSA_ALG_ML_DSA` algorithm instead, when supported by the implementation. - See `[FIPS204]` §3.4. + See the `notes on deterministic signatures `_. .. note:: See the general comments in :secref:`ml-dsa-algorithms`. @@ -542,7 +559,8 @@ Four algorithms are defined to support these variants: `PSA_ALG_ML_DSA`, `PSA_AL .. warning:: It is recommended to use the hedged `PSA_ALG_HASH_ML_DSA()` algorithm instead, when supported by the implementation. - See `[FIPS204]` §3.4. + See the `notes on deterministic signatures `_. + .. note:: See the general comments in :secref:`ml-dsa-algorithms`. From c724f7a7810c6fdb1980fe3e9b93b9064d0c3ef9 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 1 Oct 2024 13:19:39 +0100 Subject: [PATCH 12/13] Add warning about ongoing standardization of ML-DSA key formats --- doc/crypto/api/keys/types.rst | 18 +++++++++++++++--- doc/crypto/api/ops/signature.rst | 18 ++---------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index f49c9100..93a3c1c5 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -1198,7 +1198,14 @@ The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined .. subsection:: Key format - An ML-DSA key pair is the :math:`(pk,sk)` pair of public key and secret key, which are generated from a secret 32-byte seed, :math:`\xi`. See [FIPS204]` §5.1. + .. warning:: + + The key format may change in a final version of this API. + The standardization of exchange formats for ML-DSA public and private keys is in progress, but final documents have not been published. + + The current proposed format is based on the current expected outcome of that process. + + An ML-DSA key pair is the :math:`(pk,sk)` pair of public key and secret key, which are generated from a secret 32-byte seed, :math:`\xi`. See `[FIPS204]` §5.1. The data format for import and export of the key pair is the 32-byte seed :math:`\xi`. @@ -1222,8 +1229,6 @@ The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined * It is better for the standard to choose a single format to improve interoperability. - One consequence is that to enable future export of the private key (for example, a wrapped copy in a CMS or *EncryptedPrivateKeyInfo* structure), the implementation MUST store the seed :math:`\xi`, even if it also computes and stores the :math:`(pk,sk)` pair. - See `PSA_KEY_TYPE_ML_DSA_PUBLIC_KEY` for the data format used when exporting the public key with `psa_export_public_key()`. .. admonition:: Implementation note @@ -1259,6 +1264,13 @@ The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined .. subsection:: Key format + .. warning:: + + The key format may change in a final version of this API. + The standardization of exchange formats for ML-DSA public and private keys is in progress, but final documents have not been published. + + The current proposed format is based on the current expected outcome of that process. + An ML-DSA public key is the :math:`pk` output of ``ML-DSA.KeyGen()``, defined in `[FIPS204]` §5.1. The size of the public key depends on the ML-DSA parameter set as follows: diff --git a/doc/crypto/api/ops/signature.rst b/doc/crypto/api/ops/signature.rst index c11405d3..a0dfa268 100644 --- a/doc/crypto/api/ops/signature.rst +++ b/doc/crypto/api/ops/signature.rst @@ -410,9 +410,6 @@ A empty context string is used when computing or verifying ML-DSA signatures. A future version of this specification may add suitable functions and extend this algorithm to support contexts. -.. todo:: - Decide if these general comments are better kept in a common place (here), or if they should be repeated with as appropriate in each of the four algorithm definitions? - .. macro:: PSA_ALG_ML_DSA :definition: ((psa_algorithm_t) 0x06004400) @@ -425,9 +422,7 @@ A future version of this specification may add suitable functions and extend thi ML-DSA requires an ML-DSA key, which determines the ML-DSA parameter set for the operation. This algorithm is randomized: each invocation returns a different, equally valid signature. - - .. note:: - See the general comments in :secref:`ml-dsa-algorithms`. + See the `notes on hedged signatures `_. When `PSA_ALG_ML_DSA` is used as a permitted algorithm in a key policy, this permits: @@ -461,9 +456,6 @@ A future version of this specification may add suitable functions and extend thi It is recommended to use the hedged `PSA_ALG_ML_DSA` algorithm instead, when supported by the implementation. See the `notes on deterministic signatures `_. - .. note:: - See the general comments in :secref:`ml-dsa-algorithms`. - When `PSA_ALG_DETERMINISTIC_ML_DSA` is used as a permitted algorithm in a key policy, this permits: * `PSA_ALG_DETERMINISTIC_ML_DSA` as the algorithm in a call to `psa_sign_message()`. @@ -503,9 +495,7 @@ A future version of this specification may add suitable functions and extend thi For the pre-hashing, `[FIPS204]` §5.4 recommends the use of an approved hash function with an equivalent, or better, security strength than the chosen ML-DSA parameter set. This algorithm is randomized: each invocation returns a different, equally valid signature. - - .. note:: - See the general comments in :secref:`ml-dsa-algorithms`. + See the `notes on hedged signatures `_. When `PSA_ALG_HASH_ML_DSA()` is used as a permitted algorithm in a key policy, this permits: @@ -561,10 +551,6 @@ A future version of this specification may add suitable functions and extend thi It is recommended to use the hedged `PSA_ALG_HASH_ML_DSA()` algorithm instead, when supported by the implementation. See the `notes on deterministic signatures `_. - - .. note:: - See the general comments in :secref:`ml-dsa-algorithms`. - When `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` is used as a permitted algorithm in a key policy, this permits: * `PSA_ALG_DETERMINISTIC_HASH_ML_DSA()` as the algorithm in a call to `psa_sign_message()` and `psa_sign_hash()`. From 229d01881b483b2cfaccf914aa814563b05f5c1d Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 4 Oct 2024 17:22:31 +0100 Subject: [PATCH 13/13] Provide reference to IETF LAMPS draft for ML-DSA key formats --- doc/crypto/api/keys/types.rst | 2 ++ doc/crypto/references | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/doc/crypto/api/keys/types.rst b/doc/crypto/api/keys/types.rst index 93a3c1c5..396f614d 100644 --- a/doc/crypto/api/keys/types.rst +++ b/doc/crypto/api/keys/types.rst @@ -1202,6 +1202,7 @@ The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined The key format may change in a final version of this API. The standardization of exchange formats for ML-DSA public and private keys is in progress, but final documents have not been published. + See :cite-title:`LAMPS-MLDSA`. The current proposed format is based on the current expected outcome of that process. @@ -1268,6 +1269,7 @@ The |API| supports Module Lattice-based digital signatures (ML-DSA), as defined The key format may change in a final version of this API. The standardization of exchange formats for ML-DSA public and private keys is in progress, but final documents have not been published. + See :cite-title:`LAMPS-MLDSA`. The current proposed format is based on the current expected outcome of that process. diff --git a/doc/crypto/references b/doc/crypto/references index 5325eb2e..d9c7d995 100644 --- a/doc/crypto/references +++ b/doc/crypto/references @@ -408,3 +408,9 @@ :author: NIST :publication: August 2024 :url: doi.org/10.6028/NIST.FIPS.204 + +.. reference:: LAMPS-MLDSA + :title: Internet X.509 Public Key Infrastructure: Algorithm Identifiers for ML-DSA (Draft 04) + :author: IETF + :publication: July 2024 (DRAFT) + :url: datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates-04