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

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

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

69.51
/src/lib/pubkey/hss_lms/lms.cpp
1
/**
2
 * LMS - Leighton-Micali Hash-Based Signatures (RFC 8554)
3
 * (C) 2023 Jack Lloyd
4
 *     2023 Fabian Albert, Philippe Lieser - Rohde & Schwarz Cybersecurity GmbH
5
 *
6
 * Botan is released under the Simplified BSD License (see license.txt)
7
 */
8

9
#include <botan/internal/lms.h>
10

11
#include <botan/internal/loadstor.h>
12
#include <botan/internal/tree_hash.h>
13

14
namespace Botan {
15
namespace {
16

17
/**
18
 * @brief Domain-separation parameter when computing the hash of the leaf of an LMS tree.
19
 */
20
constexpr uint16_t D_LEAF = 0x8282;
21

22
/**
23
 * @brief Domain-separation parameter when computing the hash of an interior node of an LMS tree.
24
 */
25
constexpr uint16_t D_INTR = 0x8383;
26

27
/// Index of the layer in a tree starting with 0 for the bottom level to the root layer
28
using LMS_TreeLayerIndex = Strong<uint32_t, struct LMS_TreeLayerIndex_, EnableArithmeticWithPlainNumber>;
29

30
class TreeAddress final {
31
   public:
32
      explicit TreeAddress(uint32_t total_tree_height) : m_h(total_tree_height), m_r(0) {
1,253✔
33
         BOTAN_ARG_CHECK(total_tree_height > 0 && total_tree_height < 32, "Invalid tree height");
1,253✔
34
      }
35

36
      TreeAddress& set_address(LMS_TreeLayerIndex tree_layer, LMS_Tree_Node_Idx tree_index) {
38,907✔
37
         BOTAN_ARG_CHECK(tree_index.get() < (1 << m_h), "Invalid tree index");
38,907✔
38
         BOTAN_ARG_CHECK(tree_layer.get() <= m_h, "Invalid tree index");
38,907✔
39
         m_r = (1 << (m_h - tree_layer)).get() + tree_index.get();
38,907✔
40
         return *this;
38,907✔
41
      }
42

43
      uint32_t r() const { return m_r; }
21,490✔
44

45
      bool is_leaf() const { return m_r >= (1 << m_h); }
16,416✔
46

47
      LMS_Tree_Node_Idx q() const {
16,416✔
48
         BOTAN_STATE_CHECK(is_leaf());
16,416✔
49
         return LMS_Tree_Node_Idx(m_r - (1 << m_h.get()));
16,416✔
50
      }
51

52
   private:
53
      LMS_TreeLayerIndex m_h;
54
      uint32_t m_r;
55
};
56

57
auto get_hash_pair_func_for_identifier(const LMS_Params& lms_params, LMS_Identifier identifier) {
1,142✔
58
   return [hash = lms_params.hash(), I = std::move(identifier)](StrongSpan<LMS_Tree_Node> out,
1,283✔
59
                                                                const TreeAddress& address,
60
                                                                StrongSpan<const LMS_Tree_Node> left,
61
                                                                StrongSpan<const LMS_Tree_Node> right) {
62
      hash->update(I);
21,490✔
63
      hash->update(store_be(address.r()));
21,490✔
64
      hash->update(store_be(D_INTR));
21,490✔
65
      hash->update(left);
21,490✔
66
      hash->update(right);
21,490✔
67
      hash->final(out);
21,490✔
68
   };
22,632✔
69
}
70

71
void lms_gen_leaf(StrongSpan<LMS_Tree_Node> out,
17,417✔
72
                  const LMOTS_Public_Key& lmots_pk,
73
                  const TreeAddress& tree_address,
74
                  HashFunction& hash) {
75
   hash.update(lmots_pk.identifier());
17,417✔
76
   hash.update(store_be(tree_address.r()));
17,417✔
77
   hash.update(store_be(D_LEAF));
17,417✔
78
   hash.update(lmots_pk.K());
17,417✔
79
   hash.final(out);
17,417✔
80
}
17,417✔
81

82
auto lms_gen_leaf_func(const LMS_PrivateKey& lms_sk) {
141✔
83
   return [hash = lms_sk.lms_params().hash(), lms_sk](StrongSpan<LMS_Tree_Node> out, const TreeAddress& tree_address) {
141✔
84
      auto lmots_sk = LMOTS_Private_Key(lms_sk.lmots_params(), lms_sk.identifier(), tree_address.q(), lms_sk.seed());
16,416✔
85
      auto lmots_pk = LMOTS_Public_Key(lmots_sk);
16,416✔
86
      lms_gen_leaf(out, lmots_pk, tree_address, *hash);
16,416✔
87
   };
16,557✔
88
}
89

90
void lms_treehash(StrongSpan<LMS_Tree_Node> out_root,
141✔
91
                  std::optional<StrongSpan<LMS_AuthenticationPath>> out_auth_path,
92
                  std::optional<LMS_Tree_Node_Idx> leaf_idx,
93
                  const LMS_PrivateKey& lms_sk) {
94
   auto hash_pair_func = get_hash_pair_func_for_identifier(lms_sk.lms_params(), lms_sk.identifier());
141✔
95
   auto gen_leaf = lms_gen_leaf_func(lms_sk);
141✔
96
   TreeAddress lms_tree_address(lms_sk.lms_params().h());
141✔
97

98
   treehash(out_root,
282✔
99
            out_auth_path,
100
            leaf_idx,
101
            lms_sk.lms_params().m(),
141✔
102
            LMS_TreeLayerIndex(lms_sk.lms_params().h()),
141✔
103
            0,
104
            std::move(hash_pair_func),
105
            std::move(gen_leaf),
106
            lms_tree_address);
107
}
141✔
108

109
}  // namespace
110

111
LMS_Params LMS_Params::create_or_throw(LMS_Algorithm_Type type) {
2,765✔
112
   auto [hash_name, height] = [](const LMS_Algorithm_Type& lms_type) -> std::pair<std::string_view, uint8_t> {
2,760✔
113
      switch(lms_type) {
2,765✔
114
         case LMS_Algorithm_Type::SHA256_M32_H5:
777✔
115
            return {"SHA-256", static_cast<uint8_t>(5)};
777✔
116
         case LMS_Algorithm_Type::SHA256_M32_H10:
102✔
117
            return {"SHA-256", static_cast<uint8_t>(10)};
102✔
118
         case LMS_Algorithm_Type::SHA256_M32_H15:
×
119
            return {"SHA-256", static_cast<uint8_t>(15)};
×
120
         case LMS_Algorithm_Type::SHA256_M32_H20:
×
121
            return {"SHA-256", static_cast<uint8_t>(20)};
×
122
         case LMS_Algorithm_Type::SHA256_M32_H25:
×
123
            return {"SHA-256", static_cast<uint8_t>(25)};
×
124
         case LMS_Algorithm_Type::SHA256_M24_H5:
1,800✔
125
            return {"Truncated(SHA-256,192)", static_cast<uint8_t>(5)};
1,800✔
126
         case LMS_Algorithm_Type::SHA256_M24_H10:
×
127
            return {"Truncated(SHA-256,192)", static_cast<uint8_t>(10)};
×
128
         case LMS_Algorithm_Type::SHA256_M24_H15:
×
129
            return {"Truncated(SHA-256,192)", static_cast<uint8_t>(15)};
×
130
         case LMS_Algorithm_Type::SHA256_M24_H20:
×
131
            return {"Truncated(SHA-256,192)", static_cast<uint8_t>(20)};
×
132
         case LMS_Algorithm_Type::SHA256_M24_H25:
×
133
            return {"Truncated(SHA-256,192)", static_cast<uint8_t>(25)};
×
134
         case LMS_Algorithm_Type::SHAKE_M32_H5:
40✔
135
            return {"SHAKE-256(256)", static_cast<uint8_t>(5)};
40✔
136
         case LMS_Algorithm_Type::SHAKE_M32_H10:
×
137
            return {"SHAKE-256(256)", static_cast<uint8_t>(10)};
×
138
         case LMS_Algorithm_Type::SHAKE_M32_H15:
×
139
            return {"SHAKE-256(256)", static_cast<uint8_t>(15)};
×
140
         case LMS_Algorithm_Type::SHAKE_M32_H20:
×
141
            return {"SHAKE-256(256)", static_cast<uint8_t>(20)};
×
142
         case LMS_Algorithm_Type::SHAKE_M32_H25:
×
143
            return {"SHAKE-256(256)", static_cast<uint8_t>(25)};
×
144
         case LMS_Algorithm_Type::SHAKE_M24_H5:
41✔
145
            return {"SHAKE-256(192)", static_cast<uint8_t>(5)};
41✔
146
         case LMS_Algorithm_Type::SHAKE_M24_H10:
×
147
            return {"SHAKE-256(192)", static_cast<uint8_t>(10)};
×
148
         case LMS_Algorithm_Type::SHAKE_M24_H15:
×
149
            return {"SHAKE-256(192)", static_cast<uint8_t>(15)};
×
150
         case LMS_Algorithm_Type::SHAKE_M24_H20:
×
151
            return {"SHAKE-256(192)", static_cast<uint8_t>(20)};
×
152
         case LMS_Algorithm_Type::SHAKE_M24_H25:
×
153
            return {"SHAKE-256(192)", static_cast<uint8_t>(25)};
×
154
         default:
5✔
155
            throw Decoding_Error("Unsupported LMS algorithm type");
5✔
156
      }
157
   }(type);
2,765✔
158

159
   return LMS_Params(type, hash_name, height);
2,760✔
160
}
161

162
LMS_Params LMS_Params::create_or_throw(std::string_view hash_name, uint8_t height) {
29✔
163
   LMS_Algorithm_Type type = [](std::string_view hash, uint8_t h) -> LMS_Algorithm_Type {
87✔
164
      if(hash == "SHA-256") {
29✔
165
         switch(h) {
22✔
166
            case 5:
167
               return LMS_Algorithm_Type::SHA256_M32_H5;
168
            case 10:
2✔
169
               return LMS_Algorithm_Type::SHA256_M32_H10;
2✔
170
            case 15:
×
171
               return LMS_Algorithm_Type::SHA256_M32_H15;
×
172
            case 20:
×
173
               return LMS_Algorithm_Type::SHA256_M32_H20;
×
174
            case 25:
1✔
175
               return LMS_Algorithm_Type::SHA256_M32_H25;
1✔
176
            default:
×
177
               throw Decoding_Error("Unsupported height for hash function");
×
178
         }
179
      }
180
      if(hash == "Truncated(SHA-256,192)") {
7✔
181
         switch(h) {
7✔
182
            case 5:
183
               return LMS_Algorithm_Type::SHA256_M24_H5;
184
            case 10:
×
185
               return LMS_Algorithm_Type::SHA256_M24_H10;
×
186
            case 15:
×
187
               return LMS_Algorithm_Type::SHA256_M24_H15;
×
188
            case 20:
×
189
               return LMS_Algorithm_Type::SHA256_M24_H20;
×
190
            case 25:
×
191
               return LMS_Algorithm_Type::SHA256_M24_H25;
×
192
            default:
×
193
               throw Decoding_Error("Unsupported height for hash function");
×
194
         }
195
      }
196
      if(hash == "SHAKE-256(256)") {
×
197
         switch(h) {
×
198
            case 5:
199
               return LMS_Algorithm_Type::SHAKE_M32_H5;
200
            case 10:
×
201
               return LMS_Algorithm_Type::SHAKE_M32_H10;
×
202
            case 15:
×
203
               return LMS_Algorithm_Type::SHAKE_M32_H15;
×
204
            case 20:
×
205
               return LMS_Algorithm_Type::SHAKE_M32_H20;
×
206
            case 25:
×
207
               return LMS_Algorithm_Type::SHAKE_M32_H25;
×
208
            default:
×
209
               throw Decoding_Error("Unsupported height for hash function");
×
210
         }
211
      }
212
      if(hash == "SHAKE-256(192)") {
×
213
         switch(h) {
×
214
            case 5:
215
               return LMS_Algorithm_Type::SHAKE_M24_H5;
216
            case 10:
×
217
               return LMS_Algorithm_Type::SHAKE_M24_H10;
×
218
            case 15:
×
219
               return LMS_Algorithm_Type::SHAKE_M24_H15;
×
220
            case 20:
×
221
               return LMS_Algorithm_Type::SHAKE_M24_H20;
×
222
            case 25:
×
223
               return LMS_Algorithm_Type::SHAKE_M24_H25;
×
224
            default:
×
225
               throw Decoding_Error("Unsupported height for hash function");
×
226
         }
227
      }
228
      throw Decoding_Error("Unsupported hash function");
×
229
   }(hash_name, height);
29✔
230

231
   return LMS_Params(type, hash_name, height);
29✔
232
}
233

234
LMS_Params::LMS_Params(LMS_Algorithm_Type algorithm_type, std::string_view hash_name, uint8_t h) :
2,789✔
235
      m_algorithm_type(algorithm_type), m_h(h), m_hash_name(hash_name) {
2,789✔
236
   const auto hash = HashFunction::create_or_throw(m_hash_name);
2,789✔
237
   m_m = hash->output_length();
2,789✔
238
}
2,789✔
239

240
LMS_PublicKey LMS_PrivateKey::sign_and_get_pk(StrongSpan<LMS_Signature_Bytes> out_sig,
111✔
241
                                              LMS_Tree_Node_Idx q,
242
                                              const LMS_Message& msg) const {
243
   // Pre-alloc space for the signature
244
   BOTAN_ARG_CHECK(out_sig.size() == LMS_Signature::size(lms_params(), lmots_params()), "Invalid output buffer size");
111✔
245

246
   BufferStuffer sig_stuffer(out_sig);
111✔
247
   sig_stuffer.append(store_be(q));
111✔
248
   const LMOTS_Private_Key lmots_sk(lmots_params(), identifier(), q, seed());
111✔
249
   lmots_sk.sign(sig_stuffer.next<LMOTS_Signature_Bytes>(LMOTS_Signature::size(lmots_params())), msg);
111✔
250
   sig_stuffer.append(store_be(lms_params().algorithm_type()));
111✔
251
   const auto auth_path_buffer = sig_stuffer.next<LMS_AuthenticationPath>(lms_params().m() * lms_params().h());
111✔
252

253
   BOTAN_ASSERT_NOMSG(sig_stuffer.full());
111✔
254

255
   TreeAddress lms_tree_address(lms_params().h());
111✔
256
   LMS_Tree_Node pk_buffer(lms_params().m());
111✔
257
   lms_treehash(StrongSpan<LMS_Tree_Node>(pk_buffer.get()), auth_path_buffer, q, *this);
111✔
258

259
   CT::unpoison(pk_buffer);
111✔
260
   return LMS_PublicKey(lms_params(), lmots_params(), identifier(), std::move(pk_buffer));
333✔
261
}
111✔
262

263
LMS_PublicKey LMS_PublicKey::from_bytes_or_throw(BufferSlicer& slicer) {
367✔
264
   size_t total_remaining_bytes = slicer.remaining();
367✔
265
   // Alg. 6. 1. (4 bytes are sufficient until the next check)
266
   if(total_remaining_bytes < sizeof(LMS_Algorithm_Type)) {
367✔
267
      throw Decoding_Error("Too few bytes while parsing LMS public key.");
4✔
268
   }
269
   // Alg. 6. 2.a.
270
   auto lms_type = load_be<LMS_Algorithm_Type>(slicer.take<sizeof(LMS_Algorithm_Type)>());
363✔
271
   // Alg. 6. 2.c.
272
   auto lms_params = LMS_Params::create_or_throw(lms_type);
363✔
273
   // Alg. 6. 2.d.
274
   if(total_remaining_bytes < LMS_PublicKey::size(lms_params)) {
363✔
275
      throw Decoding_Error("Too few bytes while parsing LMS public key.");
44✔
276
   }
277
   // Alg. 6. 2.b.
278
   auto lmots_type = load_be<LMOTS_Algorithm_Type>(slicer.take<sizeof(LMOTS_Algorithm_Type)>());
363✔
279
   auto lmots_params = LMOTS_Params::create_or_throw(lmots_type);
319✔
280

281
   if(lms_params.hash_name() != lmots_params.hash_name()) {
319✔
282
      throw Decoding_Error("No support for HSS-LMS instances with multiple hash functions.");
×
283
   }
284

285
   // Alg. 6. 2.e.
286
   auto I = slicer.copy<LMS_Identifier>(LMS_IDENTIFIER_LEN);
319✔
287
   // Alg. 6. 2.f.
288
   auto lms_root = slicer.copy<LMS_Tree_Node>(lms_params.m());
319✔
289

290
   return LMS_PublicKey(std::move(lms_params), std::move(lmots_params), std::move(I), std::move(lms_root));
638✔
291
}
319✔
292

293
std::vector<uint8_t> LMS_PublicKey::to_bytes() const {
279✔
294
   // clang-format off
295
   return concat<std::vector<uint8_t>>(
279✔
296
      store_be(lms_params().algorithm_type()),
279✔
297
      store_be(lmots_params().algorithm_type()),
279✔
298
      identifier(),
279✔
299
      m_lms_root);
279✔
300
   // clang-format on
301
}
302

303
LMS_PublicKey::LMS_PublicKey(LMS_Params lms_params,
430✔
304
                             LMOTS_Params lmots_params,
305
                             LMS_Identifier I,
306
                             LMS_Tree_Node lms_root) :
430✔
307
      LMS_Instance(std::move(lms_params), std::move(lmots_params), std::move(I)), m_lms_root(std::move(lms_root)) {
430✔
308
   BOTAN_ARG_CHECK(identifier().size() == LMS_IDENTIFIER_LEN, "Invalid LMS identifier");
430✔
309
   BOTAN_ARG_CHECK(m_lms_root.size() == this->lms_params().m(), "Invalid LMS root");
430✔
310
}
430✔
311

312
size_t LMS_PublicKey::size(const LMS_Params& lms_params) {
500✔
313
   return sizeof(LMS_Algorithm_Type) + sizeof(LMOTS_Algorithm_Type) + LMS_IDENTIFIER_LEN + lms_params.m();
500✔
314
}
315

316
LMS_Signature LMS_Signature::from_bytes_or_throw(BufferSlicer& slicer) {
2,011✔
317
   size_t total_remaining_bytes = slicer.remaining();
2,011✔
318
   // Alg. 6a 1. (next 4 bytes are checked in LMOTS_Signature::from_bytes_or_throw)
319
   if(total_remaining_bytes < sizeof(LMS_Tree_Node_Idx)) {
2,011✔
320
      throw Decoding_Error("Too few signature bytes while parsing LMS signature.");
4✔
321
   }
322
   // Alg. 6a 2.a.
323
   auto q = load_be<LMS_Tree_Node_Idx>(slicer.take<sizeof(LMS_Tree_Node_Idx)>());
2,007✔
324

325
   // Alg. 6a 2.b.-e.
326
   auto lmots_sig = LMOTS_Signature::from_bytes_or_throw(slicer);
2,007✔
327
   LMOTS_Params lmots_params = LMOTS_Params::create_or_throw(lmots_sig.algorithm_type());
1,341✔
328

329
   if(slicer.remaining() < sizeof(LMS_Algorithm_Type)) {
1,341✔
330
      throw Decoding_Error("Too few signature bytes while parsing LMS signature.");
4✔
331
   }
332
   // Alg. 6a 2.f.
333
   auto lms_type = load_be<LMS_Algorithm_Type>(slicer.take<sizeof(LMS_Algorithm_Type)>());
1,466✔
334
   // Alg. 6a 2.h.
335
   LMS_Params lms_params = LMS_Params::create_or_throw(lms_type);
1,337✔
336
   // Alg. 6a 2.i. (signature is not exactly [...] bytes long)
337
   if(total_remaining_bytes < size(lms_params, lmots_params)) {
1,332✔
338
      throw Decoding_Error("Too few signature bytes while parsing LMS signature.");
120✔
339
   }
340

341
   // Alg. 6a 2.j.
342
   auto auth_path = slicer.copy<LMS_AuthenticationPath>(lms_params.m() * lms_params.h());
1,212✔
343

344
   return LMS_Signature(q, std::move(lmots_sig), lms_type, std::move(auth_path));
2,424✔
345
}
1,461✔
346

347
LMS_PublicKey::LMS_PublicKey(const LMS_PrivateKey& sk) :
30✔
348
      /* NOLINT(*-slicing) */ LMS_Instance(sk), m_lms_root(sk.lms_params().m()) {
30✔
349
   lms_treehash(StrongSpan<LMS_Tree_Node>(m_lms_root), std::nullopt, std::nullopt, sk);
30✔
350
}
30✔
351

352
bool LMS_PublicKey::verify_signature(const LMS_Message& msg, const LMS_Signature& sig) const {
1,007✔
353
   if(lms_root().size() != lms_params().m()) {
1,007✔
354
      // LMS public key (T[1] part) has unexpected length
355
      return false;
356
   }
357
   if(lms_params().algorithm_type() != sig.lms_type()) {
1,007✔
358
      // LMS algorithm type does not match with the signature's
359
      return false;
360
   }
361
   // Alg. 6a 2.g.
362
   if(lmots_params().algorithm_type() != sig.lmots_sig().algorithm_type()) {
1,007✔
363
      // LMOTS algorithm type does not match with the signature's
364
      return false;
365
   }
366
   // Alg. 6a 2.i.
367
   if(sig.q() >= (1ULL << uint64_t(lms_params().h()))) {
1,007✔
368
      return false;
369
   }
370
   // Alg 6. 3.
371
   std::optional<LMS_Tree_Node> Tc = lms_compute_root_from_sig(msg, sig);
1,001✔
372
   if(!Tc.has_value()) {
1,001✔
373
      return false;
374
   }
375
   // Alg 6. 4.
376
   return Tc.value() == lms_root();
1,001✔
377
}
1,001✔
378

379
std::optional<LMS_Tree_Node> LMS_PublicKey::lms_compute_root_from_sig(const LMS_Message& msg,
1,001✔
380
                                                                      const LMS_Signature& sig) const {
381
   // Alg. 6a 2.c, 2.g
382
   if(lms_params().algorithm_type() != sig.lms_type() ||
1,001✔
383
      lmots_params().algorithm_type() != sig.lmots_sig().algorithm_type()) {
1,001✔
384
      return std::nullopt;
×
385
   }
386
   try {
1,001✔
387
      const LMS_Params lms_params = LMS_Params::create_or_throw(sig.lms_type());
1,001✔
388
      const LMOTS_Signature& lmots_sig = sig.lmots_sig();
1,001✔
389
      const LMOTS_Params lmots_params = LMOTS_Params::create_or_throw(lmots_sig.algorithm_type());
1,001✔
390
      const LMOTS_K Kc = lmots_compute_pubkey_from_sig(lmots_sig, msg, identifier(), sig.q());
1,001✔
391
      const auto hash = lms_params.hash();
1,001✔
392

393
      auto hash_pair_func = get_hash_pair_func_for_identifier(lms_params, identifier());
2,002✔
394

395
      auto lms_address = TreeAddress(lms_params.h());
1,001✔
396
      lms_address.set_address(LMS_TreeLayerIndex(0), LMS_Tree_Node_Idx(sig.q().get()));
1,001✔
397

398
      LMOTS_Public_Key pk_candidate(lmots_params, identifier(), sig.q(), Kc);
2,002✔
399
      LMS_Tree_Node tmp(lms_params.m());
1,001✔
400
      lms_gen_leaf(tmp, pk_candidate, lms_address, *hash);
1,001✔
401

402
      LMS_Tree_Node root(lms_params.m());
1,001✔
403

404
      compute_root(StrongSpan<LMS_Tree_Node>(root),
1,001✔
405
                   sig.auth_path(),
406
                   sig.q(),
407
                   StrongSpan<const LMS_Tree_Node>(tmp),
408
                   lms_params.m(),
409
                   LMS_TreeLayerIndex(lms_params.h()),
1,001✔
410
                   0,
411
                   std::move(hash_pair_func),
412
                   lms_address);
413
      return LMS_Tree_Node(root);
2,002✔
414
   } catch(const Decoding_Error&) {
4,004✔
415
      return std::nullopt;
×
416
   }
×
417
}
418

419
size_t LMS_Signature::size(const LMS_Params& lms_params, const LMOTS_Params& lmots_params) {
1,714✔
420
   return sizeof(uint32_t) + LMOTS_Signature::size(lmots_params) + sizeof(uint32_t) + lms_params.h() * lms_params.m();
1,714✔
421
}
422

423
}  // namespace Botan
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