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

randombit / botan / 26995937053

04 Jun 2026 09:38PM UTC coverage: 89.394% (-2.3%) from 91.672%
26995937053

push

github

web-flow
Merge pull request #5642 from randombit/jack/prefetch-in-ks

Improve prefetching for table based implementations

110588 of 123708 relevant lines covered (89.39%)

11056434.37 hits per line

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

95.9
/src/tests/test_xmss.cpp
1
/*
2
* Extended Hash-Based Signatures Tests
3
*
4
* (C) 2014,2015 Jack Lloyd
5
* (C) 2016,2018 Matthias Gierlings
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
**/
9

10
#include "tests.h"
11

12
#if defined(BOTAN_HAS_XMSS_RFC8391)
13
   #include "test_pubkey.h"
14
   #include "test_rng.h"
15
   #include <botan/asn1_obj.h>
16
   #include <botan/hash.h>
17
   #include <botan/hex.h>
18
   #include <botan/pubkey.h>
19
   #include <botan/xmss.h>
20
   #include <botan/internal/buffer_slicer.h>
21
   #include <botan/internal/loadstor.h>
22
#endif
23

24
namespace Botan_Tests {
25

26
namespace {
27

28
#if defined(BOTAN_HAS_XMSS_RFC8391)
29

30
class XMSS_Signature_Tests final : public PK_Signature_Generation_Test {
31
   public:
32
      XMSS_Signature_Tests() :
1✔
33
            PK_Signature_Generation_Test("XMSS", "pubkey/xmss_sig.vec", "Params,Msg,PrivateKey,Signature") {}
2✔
34

35
      bool skip_this_test(const std::string& /*header*/, const VarMap& vars) override {
27✔
36
         if(Test::run_long_tests() == false) {
27✔
37
            const std::string params = vars.get_req_str("Params");
×
38

39
            if(params == "SHAKE_10_256" || params == "SHA2_10_192") {
×
40
               return false;
41
            }
42

43
            return true;
×
44
         }
×
45

46
         return false;
47
      }
48

49
      std::string default_padding(const VarMap& vars) const override { return vars.get_req_str("Params"); }
27✔
50

51
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
27✔
52
         const std::vector<uint8_t> raw_key = vars.get_req_bin("PrivateKey");
27✔
53
         const Botan::secure_vector<uint8_t> sec_key(raw_key.begin(), raw_key.end());
27✔
54

55
         return std::make_unique<Botan::XMSS_PrivateKey>(Botan::AlgorithmIdentifier(), sec_key);
81✔
56
      }
27✔
57
};
58

59
class XMSS_Signature_Verify_Tests final : public PK_Signature_Verification_Test {
60
   public:
61
      XMSS_Signature_Verify_Tests() :
1✔
62
            PK_Signature_Verification_Test("XMSS", "pubkey/xmss_verify.vec", "Params,Msg,PublicKey,Signature") {}
2✔
63

64
      std::string default_padding(const VarMap& vars) const override { return vars.get_req_str("Params"); }
63✔
65

66
      std::unique_ptr<Botan::Public_Key> load_public_key(const VarMap& vars) override {
63✔
67
         const std::vector<uint8_t> raw_key = vars.get_req_bin("PublicKey");
63✔
68
         return std::make_unique<Botan::XMSS_PublicKey>(Botan::AlgorithmIdentifier(), raw_key);
189✔
69
      }
63✔
70
};
71

72
class XMSS_Signature_Verify_Invalid_Tests final : public PK_Signature_NonVerification_Test {
73
   public:
74
      XMSS_Signature_Verify_Invalid_Tests() :
1✔
75
            PK_Signature_NonVerification_Test(
76
               "XMSS", "pubkey/xmss_invalid.vec", "Params,Msg,PublicKey,InvalidSignature") {}
2✔
77

78
      std::string default_padding(const VarMap& vars) const override { return vars.get_req_str("Params"); }
336✔
79

80
      std::unique_ptr<Botan::Public_Key> load_public_key(const VarMap& vars) override {
336✔
81
         const std::vector<uint8_t> raw_key = vars.get_req_bin("PublicKey");
336✔
82
         return std::make_unique<Botan::XMSS_PublicKey>(Botan::AlgorithmIdentifier(), raw_key);
1,008✔
83
      }
336✔
84
};
85

86
class XMSS_Keygen_Tests final : public PK_Key_Generation_Test {
1✔
87
   public:
88
      std::vector<std::string> keygen_params() const override { return {"XMSS-SHA2_10_256", "XMSS-SHA2_10_192"}; }
1✔
89

90
      std::string algo_name() const override { return "XMSS"; }
2✔
91

92
      std::unique_ptr<Botan::Public_Key> public_key_from_raw(std::string_view /* keygen_params */,
2✔
93
                                                             std::string_view /* provider */,
94
                                                             std::span<const uint8_t> raw_pk) const override {
95
         Botan::BufferSlicer s(raw_pk);
2✔
96
         const auto oid = Botan::XMSS_Parameters::xmss_algorithm_t(Botan::load_be(s.take<4>()));
2✔
97
         const auto p = Botan::XMSS_Parameters::from_id(oid);
2✔
98
         auto root = s.copy_as_secure_vector(p.element_size());
2✔
99
         auto public_seed = s.copy_as_secure_vector(p.element_size());
2✔
100

101
         return std::make_unique<Botan::XMSS_PublicKey>(oid, std::move(root), std::move(public_seed));
4✔
102
      }
2✔
103
};
104

105
/**
106
 * Tests that the key generation is compatible with the reference implementation
107
 *   based on: https://github.com/XMSS/xmss-reference/tree/171ccbd
108
 */
109
class XMSS_Keygen_Reference_Test final : public Text_Based_Test {
×
110
   public:
111
      XMSS_Keygen_Reference_Test() :
1✔
112
            Text_Based_Test("pubkey/xmss_keygen_reference.vec",
113
                            "Params,SecretSeed,PublicSeed,SecretPrf,PublicKey,PrivateKey") {}
2✔
114

115
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) final {
7✔
116
         Test::Result result(vars.get_req_str("Params"));
7✔
117

118
         Fixed_Output_RNG fixed_rng;
7✔
119
         auto add_entropy = [&](auto v) { fixed_rng.add_entropy(v.data(), v.size()); };
21✔
120

121
         // The order of the RNG values is dependent on the order they are pulled
122
         // from the RNG in the production implementation.
123
         add_entropy(vars.get_req_bin("PublicSeed"));  // XMSS_PublicKey constructor's initializer list
14✔
124
         add_entropy(vars.get_req_bin("SecretPrf"));   // XMSS_PrivateKey constructor's call to ..._Internal constructor
14✔
125
         add_entropy(vars.get_req_bin("SecretSeed"));  // XMSS_PrivateKey constructor's call to ..._Internal constructor
14✔
126

127
         const auto xmss_algo = Botan::XMSS_Parameters::xmss_id_from_string(vars.get_req_str("Params"));
7✔
128
         const Botan::XMSS_PrivateKey keypair(xmss_algo, fixed_rng);
7✔
129

130
         result.test_bin_eq("Generated private key matches", keypair.raw_private_key(), vars.get_req_bin("PrivateKey"));
14✔
131
         result.test_bin_eq("Generated public key matches", keypair.raw_public_key(), vars.get_req_bin("PublicKey"));
7✔
132

133
         return result;
14✔
134
      }
7✔
135

136
      bool skip_this_test(const std::string& /*header*/, const VarMap& vars) override {
7✔
137
         const std::string param_str = vars.get_req_str("Params");
7✔
138
         const auto params = Botan::XMSS_Parameters::from_name(param_str);
7✔
139
         const bool hash_available = Botan::HashFunction::create(params.hash_function_name()) != nullptr;
7✔
140
         const bool fast_params = param_str == "XMSS-SHA2_10_256";
7✔
141
         return !(hash_available && (fast_params || Test::run_long_tests()));
7✔
142
      }
7✔
143
};
144

145
std::vector<Test::Result> xmss_statefulness() {
1✔
146
   auto rng = Test::new_rng(__func__);
1✔
147

148
   auto sign_something = [&rng](auto& sk) {
3✔
149
      auto msg = Botan::hex_decode("deadbeef");
3✔
150

151
      Botan::PK_Signer signer(sk, *rng, "SHA2_10_256");
3✔
152
      signer.sign_message(msg, *rng);
5✔
153
   };
4✔
154

155
   return {CHECK("signing alters state",
1✔
156
                 [&](auto& result) {
1✔
157
                    Botan::XMSS_PrivateKey sk(Botan::XMSS_Parameters::XMSS_SHA2_10_256, *rng);
1✔
158
                    result.test_opt_u64_eq("allows 1024 signatures", sk.remaining_operations(), 1024);
1✔
159

160
                    sign_something(sk);
1✔
161

162
                    result.test_opt_u64_eq("allows 1023 signatures", sk.remaining_operations(), 1023);
1✔
163
                 }),
1✔
164

165
           CHECK("state can become exhausted", [&](auto& result) {
1✔
166
              const auto skbytes = Botan::hex_decode(
1✔
167
                 "000000011BBB81273E8057724A2A894593A1A688B3271410B3BEAB9F5587337BCDCBBF5C4E43AB"
168
                 "0AB2F88258E5AC54BB252E39335AE9B0D4AF0C0347EA45B8AA0AA3804C000003FFAC0C29C1ACD3"
169
                 //                                                         ~~1023~~
170
                 "19DA96E9C8EE4E28C2078441A76B6BB8BAFD358F67FBCBFC559B55C37C01FFADBB118099759EEB"
171
                 "A3B07643F73BCB4AAC546E244B57782D6BEABC");
172
              Botan::XMSS_PrivateKey sk(skbytes);
1✔
173
              result.test_opt_u64_eq("allow one last signature", sk.remaining_operations(), 1);
1✔
174

175
              sign_something(sk);
1✔
176

177
              result.test_opt_u64_eq("allow no more signatures", sk.remaining_operations(), 0);
1✔
178
              result.test_throws("no more signing", [&] { sign_something(sk); });
2✔
179
           })};
4✔
180
}
2✔
181

182
std::vector<Test::Result> xmss_legacy_private_key() {
1✔
183
   const auto legacy_xmss_public_key = Botan::hex_decode(
1✔
184
      "00000001C49B128365E23D97C2D36A2AC26E0B448FCEF77A5ED68EFDC460E787D0EDB67"
185
      "68EAC3E82B04B84571C49684ED822F8179FDFF1C825DA9F9EA78F5D50A21E6341");
1✔
186

187
   // With Botan 3.0 we implemented a multi-target attack mitigation as
188
   // suggested by NIST's SP.800-208. This private key was generated before that.
189
   const auto legacy_xmss_private_key = Botan::hex_decode(
1✔
190
      "04818800000001C49B128365E23D97C2D36A2AC26E0B448FCEF77A5ED68EFDC460E787D"
191
      "0EDB6768EAC3E82B04B84571C49684ED822F8179FDFF1C825DA9F9EA78F5D50A21E6341"
192
      "0000000059FF2307F3D05577B1B259A64B5D8DB8FDF51A4EA898D23B3F4F574961ED7A6"
193
      "A7F42ADD11F527ED757E79183A2FABA0E37E1C3C8C6E6468B4AB44305D3920DAE");
1✔
194

195
   const auto legacy_signature = Botan::hex_decode(
1✔
196
      "0000000049BB2EDE36E46FD63C5DBA3F60A2F628E3116452DAB39A60A4E321110EC45D1"
197
      "CE7CD3F33F736B8ACABB9D2FA0764645F1FD708E84B82BED1D94B2FD4A4AF72DE4B68AE"
198
      "2B7E95A99B752C6CD74DF3180754A2B663F164616B07E0212224CA3A66887DDA3083090"
199
      "010310D9F16BB087DE1F346FD2C2693AC5DE11DE24181A21AF3F2CFF6535C11D2072078"
200
      "D291E939BC95C8F3CD4A59225774EB291B8CDE7A90AF03030BF05F71FCD2BD0C4462E6B"
201
      "9FAC751B5E896370966357B3032A2650895502566FFCD99C309548C5091785DC145A511"
202
      "E591F39495EF86B1CFBBA654BB289A3B61BCB4C5967773182396D384E76D6007FD9698C"
203
      "55F8F4DA4A21EA97FBDF7B40B4289917B51067307BAC0507DBB39E4B618B799AAD8D08D"
204
      "FB4C10B648AFC66BFB071472FC6ADEC311008FF1D4C4F32BE664DCEF829375E3A92A0F0"
205
      "C9D7C4613B778172ACF81F7EFEE1D76A4AF0C1195292BE694F655374B68C3DB9E4C82F2"
206
      "8FF2EEC3AE9B5D1EDC807608E1A08246408CECBE5816BCC6585A9558A8EAE57619EAEE3"
207
      "1DE879138FAE3EACBFF180F71ED4BD28497BDCDE4CF37D40FDDE92D3422A1DA99CEEDC4"
208
      "063656E81E3F9398E9333BB3BCE7A0FC594D12F9A9E82D3FE89E66C49F07144737D56B1"
209
      "B0DCE1B98AC3B3619C4D85C77416C286998652A0A08A9F0D5B51BBD4040C0A07373130C"
210
      "1E9C0194F649018D67AF050353BE08E3E5E750D7E9D85C9C7283F5293212C8D372BBFDA"
211
      "8D28A581B42C90BE0C5E68FC63A3E0812656EB0D57CE9758ADD8436F57B9FD402EE42E9"
212
      "25CA68A52BEEE972871C9559819C9BAED8FD3BA508DCC9945415B603330A82CAEAA8001"
213
      "9EB1332E191E06EC8FA325BCE49B903BFC4244608A42E673D3DFA8202F49AE5C150AB56"
214
      "D4C720E32719498835D35D7062FCF2A969F552B11672CB7061E7C565B960C2BA8EB0780"
215
      "49365202674D07617DD516D2C598C71669D43EE63852BC758ABFD042097FEC7E3F9B855"
216
      "9AF3043630F00AEB9DF8B549076FBB2F786D0BD16C889439F45D441AF3EBC16E70AF7B5"
217
      "98D36A9F3A5FA05D5D438D1A563C9AC11B73A6A9976AD3DC78190F3289F35D019D5DF59"
218
      "DD3262608643509C25FF4C6056C7528BB551680F6A5E637F60C5951593F7E701C297DA0"
219
      "FDB289D1D47E2CE1F5E3CD6703069F773860152C903962B0F8704E6B89201296C05D6DA"
220
      "81CC0E3848E8C07400A9B3962013642E25F2332FC820463890D97F3BD34DDC4318E2EA1"
221
      "E65BE4F5613854856497BE2C4B894731DCD45209038C80855EB4150EE5D4CC6BE6859A6"
222
      "D71A02AD693E2F43BD5736859B7F295BA068503510347637ABF19D67F984BAA9AFE577B"
223
      "BC4EFF50FD7F2F56305DF9F0393DDB02F20BA554DFF9ACF6748E8FFE433267CCBE0C434"
224
      "900672987D00197116F61FACE800C42FAA1957D95679F4CDCA392E5CAC26E84F523D23D"
225
      "C209C19E8E42FAF1269A6C07BDC3E89304E479D2F71A7BCDDBF485BA65662013DD4F35C"
226
      "1CB7CBB7FD9388DD048AA5CB5AF01A7DB63E20BCB43B2C7AB2CBC9C9232CE5099055915"
227
      "6D18B0BD44B46C813CC2E0C29361790B3EE61EF6946AE3197A8B0226B47E8931A9841DA"
228
      "6A976EB1A105F0487AFD294BE69B4021BF60EFDA826DC69C1A2BAE015CD0D13DD614E8A"
229
      "71B885FFB9CDBF8BCF157BAF08D1A4EE24573235617F70049511AFF40D9243D2398C8F0"
230
      "05790D86F0956473BDBC5DEF4DFB12597F6BE67E3265E062356D4122D30B3BCDC60D736"
231
      "0D82FB0943DF88DC761018C7E43F7653A899D517709DE33AB2866BD44748A32E96BDCA2"
232
      "84763EEEEFAEF347FD8D31AE7BF98C21498240C5BBACD9F16A7B4C8B98C9AB1F9F10E17"
233
      "8F45483CBB6DFE3CF47EEB87CB5A563105DC2AA6B3174B407A3C20FDF82B4E7A825FD4E"
234
      "80FCD3A63A9FDA6182A69A1289A0A8EECB5AC381BC53048ECBFCAF26E4BA46179081325"
235
      "DBD89ACF9EF115667368F6604E2856AD107B5CA6BFA8E9253146D9CFB32E4359A2E7A3D"
236
      "3F6DCDA5EDCD09558B904D13D3CFA5E02D409EC6C610FBF9D0E1F34C9D5AF4F18F43527"
237
      "AA0A2BB687A12AE426E3A73BD75493DCCAAABEA83E1DB0BF9CC7589EE169A8A8C5FAAA7"
238
      "7D69405D9347D9642202E50B27229AE0A8E7482F06AC4FB9F039CECE7F056EC01F83549"
239
      "6977D845641254ACF420B6766F8CD1CE13DD9041B2BE7369EFE20FC5359DFD31166FBFF"
240
      "5D1C6EBB1FFB0A6C29CC64DE9F30EE3C643A3168403911B7DDA3E7B23090C444960FCE5"
241
      "6F9F1077D0D54658DAD1C65D388448982ACE87D426595CD38F50BF88755036551976A00"
242
      "310E66E0CB8BCBF5A51AE0F6418079F29C5F56DA9F7FD787B821C6346205C520794079F"
243
      "11858E7530CF494377F998E33323030D82A44D84F5209CC608F38C950D88B6A169D297F"
244
      "101A0D3E7DA3152F7D698ED3F6F6EE79B4F87E6032B98907E2FEC3AD1F44FA7816B568A"
245
      "31AF329B19636788498BE3C21A5676BDEB987F1BA213C8E86F5D39CEC9571EB5198645C"
246
      "D39EA26BE5598D47F3324F3D763D4E892A13C579F964B72369B40800B30088DE6140E94"
247
      "5B5F03C67015EC4E03065EC9126C2417F827EC526C852020D73BB6F97DED24081399D7B"
248
      "F7EE644B16A7BC601F32A312CFB98FF0E954DF0FCD2C61154B3D8CCC32DCFCCB172033D"
249
      "5F5ACB03369E323429123FB9EAB658CB072EA9CD058CAD76D78A6F0BA01BB5D36172DE7"
250
      "4DE17704A055509B3BDBE7032F4A0E3E7329CC646D06DE7C7ECF5EF030362CE079D3C3B"
251
      "DDB605A04918C16FE79251B7705DAC88A0C84E7C692E1AFF59968DE28CBDF001BBEA509"
252
      "A8A270B6BFD7E653B2228418E73F40A14F491FAEBAC8C11F346FB51C8E10DB63ED5C287"
253
      "DA7DDC692B8FE6998AC85EA29D4F9B5FEB3E062FFEEA23DAD536DDE783AFE43606D9685"
254
      "09F4695E55FE935DF20B8E9EFEE01DD21E733C22830A6E6086EBB4AC7CFB5DC5C6F9FBE"
255
      "F131BF636A129723E5D663FDCCF181AB996D158146602D567B48CEF809E4D3E5B7A7B64"
256
      "3C48EFCA7621534397B623AF23AE6F2BE7F2D7A6FBB2D7B64B96526B73DBA66A29F4260"
257
      "2BD9FF72A165431C15A570A5731D9426210F946FC682F181944F40DFB68314ACA43E321"
258
      "4AFDF11EA825B79425F0C864E354CA7E6C447AE9E0796AAB2B6720516D3FC0B73CFE98E"
259
      "F0D8E8D80A59DB9ADA0F03CF0444E1BED9ED9A75FBB6FD6D5BAD4F5FF66C8987ADA6F9F"
260
      "CA06CBAD1C9E329B844CC5BBF6CCC52852DE44B72EECAF34802043107542F5BFEA73944"
261
      "611AB035D6D7A8EBD3101F321A54C1DADC600419F8DA6BF3967E5B9E708BC4C3E901623"
262
      "E8FB6E87825757498A24A921EC601CC15399237D9C4115B678E8968A2095818D9261C4E"
263
      "8F94B9DCE3F74EC7E0479F6F6AB13676954390EF3B45D2292BF664D618CFE5ECFFBD391"
264
      "872B4F9F306A09B1238E7561942C7065FD14208F4D4A42752A9A747A29B8BE3C1658EDC"
265
      "6B250DBD1599FBB09A7F148A7AEFEAB26ADB728A330DD3F616C8A736D1BF4EA17F2C3BF"
266
      "A5E22C249FA9D1E7DA08DB351709C4");
1✔
267

268
   Botan::XMSS_PrivateKey legacy_secret_key =
1✔
269
      Botan::XMSS_PrivateKey(Botan::AlgorithmIdentifier(), legacy_xmss_private_key);
1✔
270
   auto public_key_from_secret_key = legacy_secret_key.public_key();
1✔
271
   Botan::XMSS_PublicKey legacy_public_key =
1✔
272
      Botan::XMSS_PublicKey(Botan::AlgorithmIdentifier(), legacy_xmss_public_key);
1✔
273

274
   const auto message = Botan::hex_decode("deadcafe");
1✔
275
   const auto* const algo_name = "SHA2_10_256";
1✔
276

277
   auto rng = Test::new_rng(__func__);
1✔
278

279
   return {
1✔
280
      CHECK("Use a legacy private key to create a signature",
281
            [&](auto& result) {
1✔
282
               Botan::PK_Signer signer(legacy_secret_key, *rng, algo_name);
1✔
283
               auto signature = signer.sign_message(message, *rng);
2✔
284

285
               Botan::PK_Verifier verifier(*public_key_from_secret_key, algo_name);
1✔
286
               result.test_is_true("legacy private key generates signatures that are still verifiable",
2✔
287
                                   verifier.verify_message(message, signature));
1✔
288
            }),
1✔
289

290
      CHECK("Verify a legacy signature",
291
            [&](auto& result) {
1✔
292
               Botan::PK_Verifier verifier(*public_key_from_secret_key, algo_name);
1✔
293
               result.test_is_true("legacy private key generates signatures that are still verifiable",
2✔
294
                                   verifier.verify_message(message, legacy_signature));
1✔
295
            }),
1✔
296

297
      CHECK("Verify a new signature by a legacy private key with a legacy public key",
298
            [&](auto& result) {
1✔
299
               Botan::PK_Signer signer(legacy_secret_key, *rng, algo_name);
1✔
300
               auto signature = signer.sign_message(message, *rng);
2✔
301

302
               Botan::PK_Verifier verifier(legacy_public_key, algo_name);
1✔
303
               result.test_is_true("legacy private key generates signatures that are still verifiable",
2✔
304
                                   verifier.verify_message(message, legacy_signature));
1✔
305
            }),
1✔
306
   };
5✔
307
}
3✔
308

309
BOTAN_REGISTER_TEST("pubkey", "xmss_sign", XMSS_Signature_Tests);
310
BOTAN_REGISTER_TEST("pubkey", "xmss_verify", XMSS_Signature_Verify_Tests);
311
BOTAN_REGISTER_TEST("pubkey", "xmss_verify_invalid", XMSS_Signature_Verify_Invalid_Tests);
312
BOTAN_REGISTER_TEST("pubkey", "xmss_keygen", XMSS_Keygen_Tests);
313
BOTAN_REGISTER_TEST("pubkey", "xmss_keygen_reference", XMSS_Keygen_Reference_Test);
314
BOTAN_REGISTER_TEST_FN("pubkey", "xmss_unit_tests", xmss_statefulness, xmss_legacy_private_key);
315

316
#endif
317

318
}  // namespace
319

320
}  // namespace Botan_Tests
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

© 2026 Coveralls, Inc