• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5344970392

22 Jun 2023 11:25AM UTC coverage: 91.735% (+0.02%) from 91.713%
5344970392

push

github

randombit
Fix another clang-tidy warning

78152 of 85193 relevant lines covered (91.74%)

12378091.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/src/tests/test_sphincsplus.cpp
1
/*
2
* (C) 2023 Jack Lloyd
3
*     2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "test_rng.h"
9
#include "tests.h"
10

11
#if(defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)) && defined(BOTAN_HAS_AES)
12

13
   #include <botan/assert.h>
14
   #include <botan/hash.h>
15
   #include <botan/pk_algs.h>
16
   #include <botan/pubkey.h>
17
   #include <botan/secmem.h>
18
   #include <botan/sp_parameters.h>
19
   #include <botan/sphincsplus.h>
20
   #include <botan/internal/loadstor.h>
21
   #include <botan/internal/sp_hash.h>
22

23
   #include "test_pubkey.h"
24

25
namespace Botan_Tests {
26

27
/**
28
 * Test all implemented SPHINCS+ instances using the data of the KAT files
29
 * generated by the reference implementation (Round 3.1
30
 *  (https://github.com/sphincs/sphincsplus/))
31
 */
32
class SPHINCS_Plus_Test final : public Text_Based_Test {
×
33
   public:
34
      SPHINCS_Plus_Test() : Text_Based_Test("pubkey/sphincsplus.vec", "SphincsParameterSet,seed,pk,sk,msg,HashSig") {}
3✔
35

36
      bool skip_this_test(const std::string&, const VarMap& vars) override {
12✔
37
         auto params = Botan::Sphincs_Parameters::create(vars.get_req_str("SphincsParameterSet"));
24✔
38

39
   #if not defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
40
         if(params.hash_type() == Botan::Sphincs_Hash_Type::Shake256) {
41
            return true;
42
         }
43
   #endif
44

45
   #if not defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2)
46
         if(params.hash_type() == Botan::Sphincs_Hash_Type::Sha256) {
47
            return true;
48
         }
49
   #endif
50

51
         // Execute the small (slow) instances only with --run-long-tests
52
         switch(params.parameter_set()) {
12✔
53
            case Botan::Sphincs_Parameter_Set::Sphincs128Fast:
54
            case Botan::Sphincs_Parameter_Set::Sphincs192Fast:
55
            case Botan::Sphincs_Parameter_Set::Sphincs256Fast:
56
               return false;
57
            case Botan::Sphincs_Parameter_Set::Sphincs128Small:
6✔
58
            case Botan::Sphincs_Parameter_Set::Sphincs192Small:
6✔
59
            case Botan::Sphincs_Parameter_Set::Sphincs256Small:
6✔
60
               return !Test::run_long_tests();
6✔
61
         }
62
         BOTAN_ASSERT_UNREACHABLE();
×
63
      }
64

65
      Test::Result run_one_test(const std::string&, const VarMap& vars) final {
12✔
66
         Test::Result result("SPHINCS+ ");
12✔
67

68
         auto params = Botan::Sphincs_Parameters::create(vars.get_req_str("SphincsParameterSet"));
24✔
69

70
         const std::vector<uint8_t> seed_ref = vars.get_req_bin("seed");
12✔
71
         const std::vector<uint8_t> msg_ref = vars.get_req_bin("msg");
12✔
72
         const std::vector<uint8_t> pk_ref = vars.get_req_bin("pk");
12✔
73
         const std::vector<uint8_t> sk_ref = vars.get_req_bin("sk");
12✔
74
         const std::vector<uint8_t> sig_hash = vars.get_req_bin("HashSig");
12✔
75

76
         // Depending on the SPHINCS+ configuration the resulting signature is
77
         // hashed either with SHA-3 or SHA-256 to reduce the inner dependencies
78
         // on other hash function modules.
79
         auto hash_algo_spec = [&]() -> std::string {
24✔
80
            if(params.hash_type() == Botan::Sphincs_Hash_Type::Shake256) {
12✔
81
               return "SHA-3(256)";
6✔
82
            } else {
83
               return "SHA-256";
6✔
84
            }
85
         }();
12✔
86
         auto hash = Botan::HashFunction::create(hash_algo_spec);
12✔
87

88
         /*
89
          * To get sk_seed || sk_prf || pk_seed and opt_rand from the given seed
90
          * (from KAT), we create a CTR_DRBG_AES256 rng and "simulate" the
91
          * invocation-pattern in the reference. We feed the created randomness
92
          * to the fixed output rng, to allow for our (slightly different)
93
          * invocation-pattern.
94
          */
95
         auto kat_rng = CTR_DRBG_AES256(seed_ref);
12✔
96
         Fixed_Output_RNG fixed_rng;
12✔
97
         fixed_rng.add_entropy(kat_rng.random_vec<std::vector<uint8_t>>(3 * params.n()));
12✔
98

99
         // push the entropy used for signing twice, as we want to perform two
100
         // signing operations
101
         const auto entropy_for_signing = kat_rng.random_vec<std::vector<uint8_t>>(1 * params.n());
12✔
102
         fixed_rng.add_entropy(entropy_for_signing);
12✔
103
         fixed_rng.add_entropy(entropy_for_signing);
12✔
104

105
         // Generate Keypair
106
         Botan::SphincsPlus_PrivateKey priv_key(fixed_rng, params);
12✔
107

108
         result.test_is_eq("public key bits", priv_key.public_key_bits(), pk_ref);
24✔
109
         result.test_is_eq("private key bits", unlock(priv_key.private_key_bits()), sk_ref);
48✔
110

111
         // Signature with generated Keypair
112
         auto signer = Botan::PK_Signer(priv_key, fixed_rng, "Randomized");  // TODO: No KAT for 'deterministic'?
12✔
113
         auto signature = signer.sign_message(msg_ref.data(), msg_ref.size(), fixed_rng);
12✔
114

115
         result.test_is_eq("signature creation", unlock(hash->process(signature)), sig_hash);
48✔
116

117
         // Verification with generated Keypair
118
         Botan::PK_Verifier verifier(*priv_key.public_key(), params.algorithm_identifier());
24✔
119
         bool verify_success =
12✔
120
            verifier.verify_message(msg_ref.data(), msg_ref.size(), signature.data(), signature.size());
12✔
121
         result.confirm("verification of valid signature", verify_success);
24✔
122

123
         // Run additional parsing and re-verification tests on one parameter
124
         // set only to save test runtime. Given the current test vector we will
125
         // run this exactly once per hash function.
126
         if(params.parameter_set() == Botan::Sphincs_Parameter_Set::Sphincs128Fast) {
12✔
127
            // Deserialization of Keypair from test vector
128
            Botan::SphincsPlus_PrivateKey deserialized_priv_key(sk_ref, params);
2✔
129
            Botan::SphincsPlus_PublicKey deserialized_pub_key(pk_ref, params);
2✔
130

131
            // Signature with deserialized Keypair
132
            auto deserialized_signer = Botan::PK_Signer(deserialized_priv_key, fixed_rng, "Randomized");
2✔
133
            auto deserialized_signature = deserialized_signer.sign_message(msg_ref.data(), msg_ref.size(), fixed_rng);
2✔
134

135
            result.test_is_eq(
6✔
136
               "signature creation after deserialization", unlock(hash->process(deserialized_signature)), sig_hash);
6✔
137

138
            // Verification with deserialized Keypair
139
            Botan::PK_Verifier deserialized_verifier(deserialized_pub_key, params.algorithm_identifier());
2✔
140
            bool verify_success_deserialized =
2✔
141
               deserialized_verifier.verify_message(msg_ref.data(), msg_ref.size(), signature.data(), signature.size());
2✔
142
            result.confirm("verification of valid signature after deserialization", verify_success_deserialized);
4✔
143

144
            // Verification of invalid signature
145
            auto broken_sig = Test::mutate_vec(deserialized_signature);
2✔
146
            bool verify_fail = deserialized_verifier.verify_message(
2✔
147
               msg_ref.data(), msg_ref.size(), broken_sig.data(), broken_sig.size());
2✔
148
            result.confirm("verification of invalid signature", !verify_fail);
4✔
149

150
            bool verify_success_after_fail =
2✔
151
               deserialized_verifier.verify_message(msg_ref.data(), msg_ref.size(), signature.data(), signature.size());
2✔
152
            result.confirm("verification of valid signature after broken signature", verify_success_after_fail);
6✔
153
         }
4✔
154

155
         return result;
24✔
156
      }
120✔
157
};
158

159
class SPHINCS_Plus_Keygen_Tests final : public PK_Key_Generation_Test {
×
160
   public:
161
      std::vector<std::string> keygen_params() const override {
1✔
162
         // clang-format off
163
         return {
1✔
164
   #if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
165
            "SphincsPlus-shake-128s-r3.1",
166
            "SphincsPlus-shake-128f-r3.1",
167
            "SphincsPlus-shake-192s-r3.1",
168
            "SphincsPlus-shake-192f-r3.1",
169
            "SphincsPlus-shake-256s-r3.1",
170
            "SphincsPlus-shake-256f-r3.1",
171
   #endif
172
   #if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2)
173
            "SphincsPlus-sha2-128s-r3.1",
174
            "SphincsPlus-sha2-128f-r3.1",
175
            "SphincsPlus-sha2-192s-r3.1",
176
            "SphincsPlus-sha2-192f-r3.1",
177
            "SphincsPlus-sha2-256s-r3.1",
178
            "SphincsPlus-sha2-256f-r3.1",
179
   #endif
180
         };
13✔
181
         // clang-format on
182
      }
183

184
      std::string algo_name() const override { return "SPHINCS+"; }
36✔
185
};
186

187
BOTAN_REGISTER_TEST("pubkey", "sphincsplus", SPHINCS_Plus_Test);
188
BOTAN_REGISTER_TEST("pubkey", "sphincsplus_keygen", SPHINCS_Plus_Keygen_Tests);
189

190
}  // namespace Botan_Tests
191

192
#endif  // BOTAN_HAS_SPHINCS_PLUS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc