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