xref: /freebsd/crypto/openssl/doc/designs/slh-dsa.md (revision 24e4dcf4ba5e9dedcf89efd358ea3e1fe5867020)
1SLH-DSA Design
2==============
3
4This document covers OpenSSL specific SLH-DSA implementation details.
5FIPS 205 clearly states most of the requirements of SLH-DSA and has comprehensive
6pseudo code for all its algorithms.
7
8SLH_DSA Parameters & Functions
9------------------------------
10
11There are 12 different parameter sets in FIPS 205. (See Section 11)
12There are constants related to these, as well as there being a group of functions
13associated with each set.
14
15The constants include things like hash sizes and tree heights.
16
17OpenSSL will have 12 different key managers and 12 corresponding signature functions.
18The names used are of the form "SLH-DSA-SHA2-128s" and "SLH-DSA-SHAKE-128f".
19
20There are 7 hash functions used. The algorithms using SHAKE have a much simpler
21set of 7 functions as they just use SHAKE-256 XOF (Even for the SHAKE-128 names).
22The SHA2 algorithms are much more complex and require HMAC, MGF1, as well as digests.
23There are 2 sets of functions for the SHA2 case.
24
25Some of the hash functions use an ADRS object. This is 32 bytes for SHAKE algorithms
26and 22 bytes for SHA2. Because SHA2 used a compressed format the ADRS functions are
27different.
28
29There are many functions required to implement the sign and verify paths, which include
30Merkle trees and WOTS+. The different functions normally call one of 2 of the
317 hash functions, as well as calling ADRS functions to pass to the HASH functions.
32
33Rather that duplicating this code 12 times for every function, the constants are
34stored within the SLH_DSA_KEY. This contains the HASH functions,
35the ADRS functions, and the parameter constants. It also contains pre fetched algorithms.
36A SLH_DSA_HASH_CTX object is also created, that references the key, as well as
37containing per operation hash context objects.
38This SLH_DSA_HASH_CTX is then passed to all functions. This context is allocated in the
39provider's SLH_DSA signature context.
40
41SLH-DSA keys
42------------
43
44SLH-DSA keys have 2 elements of size `n` for both the public and private keys.
45Since different algorithms have different key sizes, buffers of the maximum size
46will be used to hold the keys (since the keys are only a maximum of 64 bytes each)
47
48struct slh_dsa_key_st {
49    /* The public key consists of a SEED and ROOT values each of size |n| */
50    uint8_t pub[SLH_DSA_MAX_KEYLEN];
51    /* The private key consists of a SEED and PRF values of size |n| */
52    uint8_t priv[SLH_DSA_MAX_KEYLEN];
53    size_t key_len; /* This value is set to 2 * n if there is a public key */
54    /* contains the algorithm name and constants such as |n| */
55    const SLH_DSA_PARAMS *params;
56    int has_priv; /* Set to 1 if there is a private key component */
57    ...
58};
59
60The fields `key_len` and `has_priv` are used to determine if a key has loaded
61the public and private key elements.
62The `params` field is the parameter set which is resolved via the algorithm name.
63
64In FIPS 205 the SLH_DSA private key contains the public key.
65In OpenSSL these components are stored separately, so there must always be a
66public key in order for the key to be valid.
67
68The key generation process creates a private key and half of the public key
69using DRBG's. The public key root component is then computed based on these
70values. For ACVP testing these values are supplied as an ENTROPY parameter.
71It is assumed that from data will not deal with a partial public key, and if this
72is required the user should use the key generation operation.
73
74Pure vs Pre Hashed Signature Generation
75----------------------------------------
76
77The normal signing process (called Pure SLH-DSA Signature Generation)
78encodes the message internally as 0x00 || len(ctx) || ctx || message.
79where `ctx` is some optional value of size 0x00..0xFF.
80
81ACVP Testing requires the ability for the message to not be encoded also. This
82will be controlled by settable parameters.
83
84Pre Hash SLH-DSA Signature Generation encodes the message as
85
86```c
870x01 || len(ctx) || ctx || digest_OID || H(message).
88```
89
90The scenario that is stated that this is useful for is when this encoded message
91is supplied from an external source.
92
93Currently we do not support the Pre Hash variant as this does not sit well with the
94OpenSSL API's.
95
96Signing API
97-------------
98
99As only the one-shot implementation is required and the message is not digested
100the API's used should be
101
102EVP_PKEY_sign_message_init(), EVP_PKEY_sign(),
103EVP_PKEY_verify_message_init(), EVP_PKEY_verify().
104
105OpenSSL command line support
106----------------------------
107
108For backwards compatibility reasons EVP_DigestSignInit_ex(), EVP_DigestSign(),
109EVP_DigestVerifyInit_ex() and EVP_DigestVerify() may also be used, but the digest
110passed in `mdname` must be NULL (i.e. it effectively behaves the same as above).
111Passing a non NULL digest results in an error.
112
113OSSL_PKEY_PARAM_MANDATORY_DIGEST must return "" in the key manager getter and
114OSSL_SIGNATURE_PARAM_ALGORITHM_ID in the signature context getter.
115
116Buffers
117-------
118
119There are many functions pass buffers of size `n` Where n is one of 16,24,32
120depending on the algorithm name. These are used for key elements and hashes, so
121PACKETS are not used for these.
122
123Where it makes sense to, WPACKET is used for output (such as signature generation)
124and PACKET for reading signature data.
125
126Constant Time Considerations
127----------------------------
128
129As the security of SLH-DSA depends only on hash functions, we do not foresee
130there being any constant time issues. Some if statements have been added to
131detect failures in hash operations, and these errors are propagated all the way
132up the function call stack. These errors should not happen in general so should
133not affect the security of the algorithms.
134