]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add SLH-DSA design document
authorslontis <shane.lontis@oracle.com>
Fri, 8 Nov 2024 06:23:18 +0000 (17:23 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Feb 2025 09:17:26 +0000 (10:17 +0100)
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25882)

CHANGES.md
doc/designs/slh-dsa.md [new file with mode: 0644]

index 8dd1ccfdd2d008912ee43ab496ecf23516c009f8..d96540bb211fc7a152da3ab115d027af8a2d7963 100644 (file)
@@ -39,7 +39,7 @@ OpenSSL 3.5
 
   *Neil Horman*
 
-* Add SLH-DSA as specified by FIPS 205.
+* Add SLH-DSA as specified in FIPS 205.
 
   *Shane Lontis*
 
diff --git a/doc/designs/slh-dsa.md b/doc/designs/slh-dsa.md
new file mode 100644 (file)
index 0000000..537fb1d
--- /dev/null
@@ -0,0 +1,99 @@
+SLH-DSA Design
+==============
+
+This document covers OpenSSL specific SLH-DSA implementation details.
+FIPS 205 clearly states most of the requirements of SLH-DSA and has comprehensive
+pseudo code for all its algorithms.
+
+SLH_DSA Parameters & Functions
+------------------------------
+
+There are 12 different parameter sets in FIPS 205. (See Section 11)
+There are constants related to these, as well as there being a group of functions
+associated with each set.
+
+The constants include things like hash sizes and tree heights.
+
+OpenSSL will have 12 different key managers and 12 corresponding signature functions.
+The names used are of the form "SLH-DSA-SHA2-128s" and "SLH-DSA-SHAKE-128f".
+
+There are 7 hash functions used. The algorithms using SHAKE have a much simpler
+set of 7 functions as they just use SHAKE-256 XOF (Even for the SHAKE-128 names).
+The SHA2 algorithms are much more complex and require HMAC, MGF1, and well as digests.
+There are 2 sets of functions for the SHA2 case.
+
+Some of the hash functions use an ADRS object. This is 32 bytes for SHAKE algorithms
+and 22 bytes for SHA2. Because SHA2 used a compressed format the ADRS functions are
+different.
+
+There are many functions required to implement the sign and verify paths, which include
+Merkle trees and WOTS+. The different functions normally call one of 2 of the
+7 hash functions, as well as calling ADRS functions to pass to the HASH functions.
+
+Rather that duplicating this code 12 times for every function, instead a
+SLH_DSA_CTX object is created.
+This contains the HASH functions, the ADRS functions, and the parameter constants.
+It also contains pre fetched algorithms.
+
+This SLH_DSA_CTX is then passed to all functions. This context is allocated in the
+providers SLH_DSA signature context.
+
+SLH-DSA keys
+------------
+
+SLH-DSA keys have 2 elements of size n for both the public and private keys.
+Since different algorithms have different key sizes, buffers of the maximum size
+will be used to hold the keys (since the keys are only a maximum of 64 bytes each)
+
+struct slh_dsa_key_st {
+    /* The public key consists of a SEED and ROOT values each of size |n| */
+    uint8_t pub[SLH_DSA_MAX_KEYLEN];
+    /* The private key consists of a SEED and PRF values of size |n| */
+    uint8_t priv[SLH_DSA_MAX_KEYLEN];
+    size_t key_len; /* This value is set to 2 * n if there is a public key */
+    /* contains the algorithm name and constants such as |n| */
+    const SLH_DSA_PARAMS *params;
+    int has_priv; /* Set to 1 if there is a private key component */
+};
+
+The fields 'key_len' and 'has_priv' are used to determine if a key has loaded
+the public and private key elements.
+The 'params' field is the parameter set which is resolved via the algorithm name.
+
+The FIPS 205 the SLH_DSA private key contains the public key.
+In OpenSSL these components are stored separately, so there must always be a
+public key in order for the key to be valid.
+
+The key generation process creates a private key and half of the public key
+using DRBG's. The public key root component is then computed based on these
+values. For ACVP testing these values are supplied as an ENTROPY parameter.
+It is assumed that from data will not deal with a partial public key, and if this
+is required the user should use the key generation operation.
+
+Pure vs Pre Hashed Signature Generation
+----------------------------------------
+
+The normal signing process (called Pure SLH-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 for the message to not be encoded also. This
+will be controlled by settable parameters.
+
+Pre Hash SLH-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.
+
+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.
+
+Buffers
+-------
+
+Many functions need to pass around key elements and return signature buffers of
+various sizes which are often updated in loops in parts, all of these sizes
+are known quantities. Currently there is no attempt to use wpacket to pass
+around these sizes. asserts are currently done by the child functions to check
+that the expected size does not exceed the size passed in by the parent.