]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add ML-DSA design document.
authorslontis <shane.lontis@oracle.com>
Mon, 13 Jan 2025 06:01:45 +0000 (17:01 +1100)
committerTomas Mraz <tomas@openssl.org>
Fri, 14 Feb 2025 09:46:03 +0000 (10:46 +0100)
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26400)

doc/designs/ml-dsa.md [new file with mode: 0644]
doc/man7/EVP_PKEY-ML-DSA.pod
doc/man7/EVP_SIGNATURE-ML-DSA.pod
doc/man7/OSSL_PROVIDER-default.pod

diff --git a/doc/designs/ml-dsa.md b/doc/designs/ml-dsa.md
new file mode 100644 (file)
index 0000000..acadcf8
--- /dev/null
@@ -0,0 +1,126 @@
+ML-DSA Design
+==============
+
+This document covers OpenSSL specific ML-DSA implementation details.
+FIPS 204 clearly states most of the requirements of ML-DSA and has comprehensive
+pseudo code for all its algorithms.
+
+The base code for OpenSSL has been derived from the BoringSSL C++ code.
+As OpenSSL is c code, templates can not be used. The OpenSSL code instead uses
+parameters to pass algorithm specific constants, and also uses these constants
+to run different conditional functions when required.
+
+ML_DSA Parameters & Per algorithm Functions
+-------------------------------------------
+
+FIPS 204 contains 3 algorithms for different security strengths.
+FIPS 204 Section 4 Table 1 & Table 2 specifies different constants that are
+stored in a table of ML_DSA_PARAM objects.
+The constants include key sizes and coefficient ranges.
+
+OpenSSL uses 3 key managers and 3 signature functions corresponding to the algorithms
+ML-DSA-44, ML-DSA-65 and ML-DSA-87.
+
+ML-DSA only uses SHAKE-128 and SHAKE-256 for digest operations, so these values
+are pre-fetched and stored within a ML_DSA key. Any functions that require these
+pre-fetched objects must pass either the key or the pre-fetched object within the key
+as a parameter. A temporary EVP_MD_CTX is created as needed and the shake object(s)
+are set into this ctx.
+
+Initially a separate object called ML_DSA_CTX object was passed around that
+contained 2 EVP_MD_CTX's containing the pre-fetched EVP_MD shake objects. It was
+modified to match the ML-KEM code.
+
+ML-DSA keys
+------------
+
+Once loaded an 'ML-DSA-KEY' object contains either a public key or a
+public/private key pair.
+When loading a private key, the public key is always generated. In the event
+that the public key is also supplied, an error will occur if the generated public
+key does not match the supplied public key.
+
+An ML_DSA polynomial contains 256 32 bit values which is 1K of space.
+Keys store vectors of size 'k' or 'l' plus a matrix of size 'k' * 'l',
+where (k, l) correspond to (4,4), (6,5) or (8,7). The key data could be large
+if buffers of the maximum size of (8,7) are used for the (4,4) use case.
+To save space rather than use fixed size buffers, allocations are used instead,
+for both the public and private elements. (i.e. The private allocations are not
+done when only a public key is loaded).
+
+Since keys consist of vectors and a matrix of polynomials, a single block
+is used to allocate all polynomials, and then the polynomial blocks are
+assigned to the individual vectors and matrix. This approach is also used when temporary
+vectors, matrices or polynomials are required
+
+Keys are not allowed to mutate, so checks are done during load to check that the
+public and private key components are not changed once set.
+
+ossl_ml_dsa_key_get_pub() and ossl_ml_dsa_key_get_priv() return the
+encoded forms of the key components (which are stored within the key).
+The hash of the encoded public key is also stored in the key.
+
+The key generation process uses a seed to create a private key, and the public
+key is then generated using this private key.
+
+For ACVP testing the seed may be supplied.
+
+Pure vs Pre Hashed Signature Generation
+----------------------------------------
+
+The normal signing process (called Pure ML-DSA Signature Generation)
+encodes the message internally as 0x00 || len(ctx) || ctx || message.
+where B<ctx> is some optional value of size 0x00..0xFF.
+
+ACVP Testing requires the ability to process raw messages without the above encoding.
+This will be controlled by settable parameters.
+
+Pre Hash ML-DSA Signature Generation encode the message as
+0x01 || len(ctx) || ctx || digest_OID || H(message).
+The scenario that is stated that this is useful for is when this encoded message
+is supplied from an external source.
+This ensures domain separation between signature variants
+
+Currently I do not support the Pre Hash variant as this does not sit well with the
+OpenSSL API's. The user could do the encoding themselves and then set the settable
+to not encode the passed in message.
+
+Signing API
+-------------
+
+As only the one-shot implementation is required and the message is not digested
+the API's used should be
+
+EVP_PKEY_sign_message_init(), EVP_PKEY_sign(),
+EVP_PKEY_verify_message_init(), EVP_PKEY_verify().
+
+Encoding/Decoding
+-----------------
+
+Where it makes sense to, WPACKET is used for output (such as signature generation)
+and PACKET for reading signature data.
+
+Constant Time Considerations
+----------------------------
+
+Similar code to BoringSSL will be added that allows ctgrind to be used to
+detect constant time issues.
+
+There are many places that do hashing in the code, and these are capable (although
+it is not likely) of returning errors. There is not attempt to deal with these cases.
+
+Changes from BoringSSL
+----------------------
+
+At the time of writing, BoringSSL code only supported ML-DSA-65. Since there
+is specialized code for encoding and decoding of different sizes of
+polynomial coefficients, code was added to support these different sizes
+(e.g hints have 1 bit coefficients so 8 coefficients can be packed into 1 byte)
+
+Differences between BoringSSL and FIPS 204 pseudo code
+------------------------------------------------------
+
+The symmetric modulus operation normally gives a result in the range -a/2 ... a/2.
+BoringSSL chose to keep the result positive by adding q and reducing once is required.
+
+Montgomery multiplication is used to speed up multiplications (See FIPS 204 Appendix A).
index 39bc6215fb4760b95e5bb86bd1620cb14104f97b..bb8802000fed3cf10799c116038416453c4b7215 100644 (file)
@@ -42,12 +42,19 @@ Use EVP_PKEY_CTX_set_params() after calling EVP_PKEY_keygen_init().
 =head2 Common ML-DSA parameters
 
 In addition to the common parameters that all keytypes should support (see
-L<provider-keymgmt(7)/Common parameters>), the implementation of these key types
-support the following.
+L<provider-keymgmt(7)/Common Information Parameters>, the implementation of
+these key types support the following.
 
 The following parameters are gettable using EVP_PKEY_get_octet_string_param(),
 and settable when using EVP_PKEY_fromdata().
 
+The following octet string parameters are gettable using
+L<EVP_PKEY_get_octet_string_param(3)> or L<EVP_PKEY_get_params(3)>.
+They can be set into L<EVP_PKEY_fromdata(3)>, and are returned by
+L<EVP_PKEY_todata(3)> given a suitable I<selection>.
+Once a public or private key is configured, it can no longer be modified,
+nor can another key component be added.
+
 =over 4
 
 =item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
index 010690cfb4518f6c8982d717f7e7a9311ec6a991..4fed0d9e19e7427ae9f57beb5260f6ed0c1367f0 100644 (file)
@@ -20,7 +20,7 @@ There are 3 different security categories also depending on the type.
 L<EVP_SIGNATURE_fetch(3)> can be used to explicitely fetch one of the 3
 algorithms which can then be used with L<EVP_PKEY_sign_message_init(3)>,
 L<EVP_PKEY_sign(3)>, L<EVP_PKEY_verify_message_init(3)>, and
-L<EVP_PKEY_verify(3)> to sign or verify one-shot messages.
+L<EVP_PKEY_verify(3)> to perform one-shot message signing or signature verification.
 
 The normal signing process (called Pure ML-DSA Signature Generation)
 encodes the message internally as 0x00 || len(ctx) || ctx || message.
index 8544e3263d55e74acbbc8da0270c3df370e2a7c9..02c6271c040b9d8a4bcbe5c5ee0a40eaaa195adc 100644 (file)
@@ -191,7 +191,11 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item SM2
 
-=item ML-DSA, see L<EVP_SIGNATURE-ML-DSA(7)>
+=item ML-DSA-44, see L<EVP_SIGNATURE-ML-DSA(7)>
+
+=item ML-DSA-65, see L<EVP_SIGNATURE-ML-DSA(7)>
+
+=item ML-DSA-87, see L<EVP_SIGNATURE-ML-DSA(7)>
 
 =item HMAC, see L<EVP_SIGNATURE-HMAC(7)>
 
@@ -267,7 +271,11 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item SM2, see L<EVP_KEYMGMT-SM2(7)>
 
-=item ML-DSA, see L<EVP_KEYMGMT-ML-DSA(7)>
+=item ML-DSA-44, see L<EVP_KEYMGMT-ML-DSA(7)>
+
+=item ML-DSA-65, see L<EVP_KEYMGMT-ML-DSA(7)>
+
+=item ML-DSA-87, see L<EVP_KEYMGMT-ML-DSA(7)>
 
 =back