Skip to content

Commit

Permalink
Apply review suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
FAlbertDev committed Sep 20, 2024
1 parent 9e71fdb commit fdc2290
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 258 deletions.
18 changes: 16 additions & 2 deletions doc/api_ref/pubkey.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,29 @@ A post-quantum secure hash-based signature scheme similar to XMSS. Contains
support for multitrees. It is stateful, meaning the private key changes after
each signature.

SLH-DSA
~~~~~~~
SLH-DSA (FIPS 205)
~~~~~~~~~~~~~~~~~~

The Stateless Hash-Based Digital Signature Standard (SLH-DSA)
is the FIPS 205 post-quantum secure signature scheme whose security is solely
based on the security of a hash function. Unlike XMSS, it is a stateless
signature scheme, meaning that the private key does not change with each
signature. It has high security but very long signatures and high runtime.

Support for SLH-DSA is implemented in the modules ``slh_dsa_sha2`` and ``slh_dsa_shake``.

Additionally, support for the pre-standardized version "SPHINCS+" is retained
for the time being. The implemented specification is commonly referred to as
version 3.1 of the SPHINCS+ submission to NIST's third round of the
PQC competition. This is not compatible with the "Initial Public Draft" version of
FIPS 205 for which Botan does not offer an implementation. Also, Botan does not
support the Haraka hash function.

Currently, two flavors of SPHINCS+ are implemented in separate Botan modules:

* ``sphincsplus_shake``, that uses Keccak (SHAKE) hash functions
* ``sphincsplus_sha2``, that uses SHA-256

FrodoKEM
~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Public Key Cryptography
* RSA signatures and encryption
* DH and ECDH key agreement
* Signature schemes ECDSA, DSA, Ed25519, Ed448, ECGDSA, ECKCDSA, SM2, GOST 34.10
* Post-quantum signature schemes Dilithium, HSS/LMS, SLH-DSA, XMSS
* Post-quantum signature schemes Dilithium, HSS/LMS, SLH-DSA (SPHINCS+), XMSS
* Post-quantum key agreement schemes McEliece, Kyber, and FrodoKEM
* ElGamal encryption
* Padding schemes OAEP, PSS, PKCS #1 v1.5, X9.31
Expand Down
14 changes: 0 additions & 14 deletions src/build-data/oids.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,6 @@
2.16.840.1.101.3.4.3.30 = SLH-DSA-SHAKE-256s
2.16.840.1.101.3.4.3.31 = SLH-DSA-SHAKE-256f

# NIST: SLH-DSA (pre-hash)
2.16.840.1.101.3.4.3.35 = Hash-SLH-DSA-SHA2-128s-with-SHA256
2.16.840.1.101.3.4.3.36 = Hash-SLH-DSA-SHA2-128f-with-SHA256
2.16.840.1.101.3.4.3.37 = Hash-SLH-DSA-SHA2-192s-with-SHA512
2.16.840.1.101.3.4.3.38 = Hash-SLH-DSA-SHA2-192f-with-SHA512
2.16.840.1.101.3.4.3.39 = Hash-SLH-DSA-SHA2-256s-with-SHA512
2.16.840.1.101.3.4.3.40 = Hash-SLH-DSA-SHA2-256f-with-SHA512
2.16.840.1.101.3.4.3.41 = Hash-SLH-DSA-SHAKE-128s-with-SHAKE128
2.16.840.1.101.3.4.3.42 = Hash-SLH-DSA-SHAKE-128f-with-SHAKE128
2.16.840.1.101.3.4.3.43 = Hash-SLH-DSA-SHAKE-192s-with-SHAKE256
2.16.840.1.101.3.4.3.44 = Hash-SLH-DSA-SHAKE-192f-with-SHAKE256
2.16.840.1.101.3.4.3.45 = Hash-SLH-DSA-SHAKE-256s-with-SHAKE256
2.16.840.1.101.3.4.3.46 = Hash-SLH-DSA-SHAKE-256f-with-SHAKE256

# XMSS
1.3.6.1.4.1.25258.1.5 = XMSS-draft6
1.3.6.1.4.1.25258.1.8 = XMSS-draft12
Expand Down
57 changes: 42 additions & 15 deletions src/cli/speed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ class Speed final : public Command {
"McEliece",
"Kyber",
"SLH-DSA",
"SPHINCS+",
"FrodoKEM",
"HSS-LMS",
};
Expand Down Expand Up @@ -662,7 +663,9 @@ class Speed final : public Command {
#endif
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
else if(algo == "SLH-DSA") {
bench_sphincs_plus(provider, msec);
bench_slh_dsa(provider, msec, true /* SLH-DSA */);
} else if(algo == "SPHINCS+") {
bench_slh_dsa(provider, msec, false /* SPHINCS+ */);
}
#endif
#if defined(BOTAN_HAS_FRODOKEM)
Expand Down Expand Up @@ -2264,21 +2267,45 @@ class Speed final : public Command {
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
void bench_sphincs_plus(const std::string& provider, std::chrono::milliseconds msec) {
void bench_slh_dsa(const std::string& provider, std::chrono::milliseconds msec, bool is_slh_dsa) {
// Sphincs_Parameter_Set set, Sphincs_Hash_Type hash
std::vector<std::string> sphincs_params{
"SphincsPlus-sha2-128s-r3.1", "SphincsPlus-sha2-128f-r3.1", "SphincsPlus-sha2-192s-r3.1",
"SphincsPlus-sha2-192f-r3.1", "SphincsPlus-sha2-256s-r3.1", "SphincsPlus-sha2-256f-r3.1",
"SphincsPlus-shake-128s-r3.1", "SphincsPlus-shake-128f-r3.1", "SphincsPlus-shake-192s-r3.1",
"SphincsPlus-shake-192f-r3.1", "SphincsPlus-shake-256s-r3.1", "SphincsPlus-shake-256f-r3.1",

"SLH-DSA-SHA2-128s", "SLH-DSA-SHA2-128f", "SLH-DSA-SHA2-192s",
"SLH-DSA-SHA2-192f", "SLH-DSA-SHA2-256s", "SLH-DSA-SHA2-256f",
"SLH-DSA-SHAKE-128s", "SLH-DSA-SHAKE-128f", "SLH-DSA-SHAKE-192s",
"SLH-DSA-SHAKE-192f", "SLH-DSA-SHAKE-256s", "SLH-DSA-SHAKE-256f",
};

for(auto params_str : sphincs_params) {
std::vector<std::string> instances_to_bench = [&]() -> std::vector<std::string> {
if(is_slh_dsa) {
// Bench the SLH-DSA instances
return {
"SLH-DSA-SHA2-128s",
"SLH-DSA-SHA2-128f",
"SLH-DSA-SHA2-192s",
"SLH-DSA-SHA2-192f",
"SLH-DSA-SHA2-256s",
"SLH-DSA-SHA2-256f",
"SLH-DSA-SHAKE-128s",
"SLH-DSA-SHAKE-128f",
"SLH-DSA-SHAKE-192s",
"SLH-DSA-SHAKE-192f",
"SLH-DSA-SHAKE-256s",
"SLH-DSA-SHAKE-256f",
};
} else {
// Bench the SPHINCS+ Round 3.1 instances
return {
"SphincsPlus-sha2-128s-r3.1",
"SphincsPlus-sha2-128f-r3.1",
"SphincsPlus-sha2-192s-r3.1",
"SphincsPlus-sha2-192f-r3.1",
"SphincsPlus-sha2-256s-r3.1",
"SphincsPlus-sha2-256f-r3.1",
"SphincsPlus-shake-128s-r3.1",
"SphincsPlus-shake-128f-r3.1",
"SphincsPlus-shake-192s-r3.1",
"SphincsPlus-shake-192f-r3.1",
"SphincsPlus-shake-256s-r3.1",
"SphincsPlus-shake-256f-r3.1",
};
}
}();

for(auto params_str : instances_to_bench) {
auto sp_params = Botan::Sphincs_Parameters::create(params_str);
if(!sp_params.is_available()) {
continue;
Expand Down
26 changes: 1 addition & 25 deletions src/lib/asn1/oid_maps.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* OID maps
*
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2024-09-13
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2024-09-20
*
* All manual edits to this file will be lost. Edit the script
* then regenerate this source file.
Expand Down Expand Up @@ -280,19 +280,7 @@ std::unordered_map<std::string, std::string> OID_Map::load_oid2str_map() {
{"2.16.840.1.101.3.4.3.3", "DSA/SHA-384"},
{"2.16.840.1.101.3.4.3.30", "SLH-DSA-SHAKE-256s"},
{"2.16.840.1.101.3.4.3.31", "SLH-DSA-SHAKE-256f"},
{"2.16.840.1.101.3.4.3.35", "Hash-SLH-DSA-SHA2-128s-with-SHA256"},
{"2.16.840.1.101.3.4.3.36", "Hash-SLH-DSA-SHA2-128f-with-SHA256"},
{"2.16.840.1.101.3.4.3.37", "Hash-SLH-DSA-SHA2-192s-with-SHA512"},
{"2.16.840.1.101.3.4.3.38", "Hash-SLH-DSA-SHA2-192f-with-SHA512"},
{"2.16.840.1.101.3.4.3.39", "Hash-SLH-DSA-SHA2-256s-with-SHA512"},
{"2.16.840.1.101.3.4.3.4", "DSA/SHA-512"},
{"2.16.840.1.101.3.4.3.40", "Hash-SLH-DSA-SHA2-256f-with-SHA512"},
{"2.16.840.1.101.3.4.3.41", "Hash-SLH-DSA-SHAKE-128s-with-SHAKE128"},
{"2.16.840.1.101.3.4.3.42", "Hash-SLH-DSA-SHAKE-128f-with-SHAKE128"},
{"2.16.840.1.101.3.4.3.43", "Hash-SLH-DSA-SHAKE-192s-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.44", "Hash-SLH-DSA-SHAKE-192f-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.45", "Hash-SLH-DSA-SHAKE-256s-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.46", "Hash-SLH-DSA-SHAKE-256f-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.5", "DSA/SHA-3(224)"},
{"2.16.840.1.101.3.4.3.6", "DSA/SHA-3(256)"},
{"2.16.840.1.101.3.4.3.7", "DSA/SHA-3(384)"},
Expand Down Expand Up @@ -438,18 +426,6 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"HMAC(SHA-512-256)", OID({1, 2, 840, 113549, 2, 13})},
{"HSS-LMS", OID({1, 2, 840, 113549, 1, 9, 16, 3, 17})},
{"HSS-LMS-Private-Key", OID({1, 3, 6, 1, 4, 1, 25258, 1, 13})},
{"Hash-SLH-DSA-SHA2-128f-with-SHA256", OID({2, 16, 840, 1, 101, 3, 4, 3, 36})},
{"Hash-SLH-DSA-SHA2-128s-with-SHA256", OID({2, 16, 840, 1, 101, 3, 4, 3, 35})},
{"Hash-SLH-DSA-SHA2-192f-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 38})},
{"Hash-SLH-DSA-SHA2-192s-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 37})},
{"Hash-SLH-DSA-SHA2-256f-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 40})},
{"Hash-SLH-DSA-SHA2-256s-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 39})},
{"Hash-SLH-DSA-SHAKE-128f-with-SHAKE128", OID({2, 16, 840, 1, 101, 3, 4, 3, 42})},
{"Hash-SLH-DSA-SHAKE-128s-with-SHAKE128", OID({2, 16, 840, 1, 101, 3, 4, 3, 41})},
{"Hash-SLH-DSA-SHAKE-192f-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 44})},
{"Hash-SLH-DSA-SHAKE-192s-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 43})},
{"Hash-SLH-DSA-SHAKE-256f-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 46})},
{"Hash-SLH-DSA-SHAKE-256s-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 45})},
{"KeyWrap.AES-128", OID({2, 16, 840, 1, 101, 3, 4, 1, 5})},
{"KeyWrap.AES-192", OID({2, 16, 840, 1, 101, 3, 4, 1, 25})},
{"KeyWrap.AES-256", OID({2, 16, 840, 1, 101, 3, 4, 1, 45})},
Expand Down
2 changes: 1 addition & 1 deletion src/lib/pubkey/sphincsplus/sphincsplus_common/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SPHINCS_PLUS_COMMON -> 20230426

<module_info>
name -> "SLH-DSA (common)"
brief -> "Base implementation of SLH-DSA"
brief -> "Base implementation of Stateless Hash Function DSA"
type -> "Internal"
</module_info>

Expand Down
2 changes: 1 addition & 1 deletion src/lib/pubkey/sphincsplus/sphincsplus_common/sp_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class BOTAN_TEST_API Sphincs_Address final {
}

/*
* Sets the type without clearing the other fields (instead of of the specs setTypeAndClear).
* Sets the type without clearing the other fields (contrary to the specs setTypeAndClear).
* This adaption is used for optimization purposes.
*/
Sphincs_Address& set_type(Sphincs_Address_Type type) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sp_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ std::unique_ptr<Sphincs_Hash_Functions> Sphincs_Hash_Functions::create(const Sph
#if defined(BOTAN_HAS_SPHINCS_PLUS_SHA2_BASED)
return std::make_unique<Sphincs_Hash_Functions_Sha2>(sphincs_params, pub_seed);
#else
throw Not_Implemented("SLH-DSA with SHA-256 is not available in this build");
throw Not_Implemented("SLH-DSA (or SPHINCS+) with SHA-256 is not available in this build");
#endif

case Sphincs_Hash_Type::Shake256:
#if defined(BOTAN_HAS_SPHINCS_PLUS_SHAKE_BASED)
return std::make_unique<Sphincs_Hash_Functions_Shake>(sphincs_params, pub_seed);
#else
throw Not_Implemented("SLH-DSA with SHAKE is not available in this build");
throw Not_Implemented("SLH-DSA (or SPHINCS+) with SHAKE is not available in this build");
#endif

case Sphincs_Hash_Type::Haraka:
Expand Down
4 changes: 2 additions & 2 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sp_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ class BOTAN_TEST_API Sphincs_Hash_Functions {
* @param msg message
*/
virtual void PRF_msg(StrongSpan<SphincsMessageRandomness> out,
const SphincsSecretPRF& sk_prf,
const SphincsOptionalRandomness& opt_rand,
StrongSpan<const SphincsSecretPRF> sk_prf,
StrongSpan<const SphincsOptionalRandomness> opt_rand,
std::span<const uint8_t> msg) = 0;

template <typename... BufferTs>
Expand Down
Loading

0 comments on commit fdc2290

Please sign in to comment.