Botan 3.5.0
Crypto and TLS for C&
dilithium.cpp
Go to the documentation of this file.
1/*
2* Crystals Dilithium Digital Signature Algorithms
3* Based on the public domain reference implementation by the
4* designers (https://github.com/pq-crystals/dilithium)
5*
6* Further changes
7* (C) 2021-2023 Jack Lloyd
8* (C) 2021-2022 Manuel Glaser - Rohde & Schwarz Cybersecurity
9* (C) 2021-2023 Michael Boric, René Meusel - Rohde & Schwarz Cybersecurity
10*
11* Botan is released under the Simplified BSD License (see license.txt)
12*/
13
14#include <botan/dilithium.h>
15
16#include <botan/exceptn.h>
17#include <botan/hash.h>
18#include <botan/rng.h>
19
20#include <botan/internal/dilithium_polynomials.h>
21#include <botan/internal/fmt.h>
22#include <botan/internal/parsing.h>
23#include <botan/internal/pk_ops_impl.h>
24#include <botan/internal/shake.h>
25#include <botan/internal/stl_util.h>
26
27#include <algorithm>
28#include <array>
29#include <iterator>
30#include <span>
31#include <vector>
32
33namespace Botan {
34namespace {
35
36std::pair<Dilithium::PolynomialVector, Dilithium::PolynomialVector> calculate_t0_and_t1(
37 const DilithiumModeConstants& mode,
38 const std::vector<uint8_t>& rho,
39 Dilithium::PolynomialVector s1,
40 const Dilithium::PolynomialVector& s2) {
41 /* Generate matrix */
43
44 /* Matrix-vector multiplication */
45 s1.ntt();
47 t.reduce();
48 t.invntt_tomont();
49
50 /* Add error vector s2 */
51 t.add_polyvec(s2);
52
53 /* Extract t and write public key */
54 t.cadd_q();
55
56 Dilithium::PolynomialVector t0(mode.k());
57 Dilithium::PolynomialVector t1(mode.k());
59
60 return {std::move(t0), std::move(t1)};
61}
62
63DilithiumMode::Mode dilithium_mode_from_string(std::string_view str) {
64 if(str == "Dilithium-4x4-r3") {
66 }
67 if(str == "Dilithium-4x4-AES-r3") {
69 }
70 if(str == "Dilithium-6x5-r3") {
72 }
73 if(str == "Dilithium-6x5-AES-r3") {
75 }
76 if(str == "Dilithium-8x7-r3") {
78 }
79 if(str == "Dilithium-8x7-AES-r3") {
81 }
82
83 throw Invalid_Argument(fmt("'{}' is not a valid Dilithium mode name", str));
84}
85
86} // namespace
87
88DilithiumMode::DilithiumMode(const OID& oid) : m_mode(dilithium_mode_from_string(oid.to_formatted_string())) {}
89
90DilithiumMode::DilithiumMode(std::string_view str) : m_mode(dilithium_mode_from_string(str)) {}
91
95
96std::string DilithiumMode::to_string() const {
97 switch(m_mode) {
99 return "Dilithium-4x4-r3";
101 return "Dilithium-4x4-AES-r3";
103 return "Dilithium-6x5-r3";
105 return "Dilithium-6x5-AES-r3";
107 return "Dilithium-8x7-r3";
109 return "Dilithium-8x7-AES-r3";
110 }
111
113}
114
115class Dilithium_PublicKeyInternal {
116 public:
117 Dilithium_PublicKeyInternal(DilithiumModeConstants mode) : m_mode(std::move(mode)) {}
118
119 Dilithium_PublicKeyInternal(DilithiumModeConstants mode, std::span<const uint8_t> raw_pk) :
120 m_mode(std::move(mode)) {
121 BOTAN_ASSERT_NOMSG(raw_pk.size() == m_mode.public_key_bytes());
122
123 BufferSlicer s(raw_pk);
124 m_rho = s.copy_as_vector(DilithiumModeConstants::SEEDBYTES);
126 m_mode);
127
128 BOTAN_ASSERT_NOMSG(s.remaining() == 0);
129 BOTAN_STATE_CHECK(m_t1.m_vec.size() == m_mode.k());
130
131 m_raw_pk_shake256 = compute_raw_pk_shake256();
132 }
133
134 Dilithium_PublicKeyInternal(DilithiumModeConstants mode,
135 std::vector<uint8_t> rho,
136 const Dilithium::PolynomialVector& s1,
137 const Dilithium::PolynomialVector& s2) :
138 m_mode(std::move(mode)),
139 m_rho(std::move(rho)),
140 m_t1([&] { return calculate_t0_and_t1(m_mode, m_rho, s1, s2).second; }()) {
141 BOTAN_ASSERT_NOMSG(!m_rho.empty());
142 BOTAN_ASSERT_NOMSG(!m_t1.m_vec.empty());
143 m_raw_pk_shake256 = compute_raw_pk_shake256();
144 }
145
146 Dilithium_PublicKeyInternal(DilithiumModeConstants mode,
147 std::vector<uint8_t> rho,
148 Dilithium::PolynomialVector t1) :
149 m_mode(std::move(mode)), m_rho(std::move(rho)), m_t1(std::move(t1)) {
150 BOTAN_ASSERT_NOMSG(!m_rho.empty());
151 BOTAN_ASSERT_NOMSG(!m_t1.m_vec.empty());
152 m_raw_pk_shake256 = compute_raw_pk_shake256();
153 }
154
155 ~Dilithium_PublicKeyInternal() = default;
156
157 Dilithium_PublicKeyInternal(const Dilithium_PublicKeyInternal&) = delete;
158 Dilithium_PublicKeyInternal(Dilithium_PublicKeyInternal&&) = delete;
159 Dilithium_PublicKeyInternal& operator=(const Dilithium_PublicKeyInternal& other) = delete;
160 Dilithium_PublicKeyInternal& operator=(Dilithium_PublicKeyInternal&& other) = delete;
161
162 std::vector<uint8_t> raw_pk() const { return concat<std::vector<uint8_t>>(m_rho, m_t1.polyvec_pack_t1()); }
163
164 const std::vector<uint8_t>& raw_pk_shake256() const {
165 BOTAN_STATE_CHECK(m_raw_pk_shake256.size() == DilithiumModeConstants::SEEDBYTES);
166 return m_raw_pk_shake256;
167 }
168
169 const Dilithium::PolynomialVector& t1() const { return m_t1; }
170
171 const std::vector<uint8_t>& rho() const { return m_rho; }
172
173 const DilithiumModeConstants& mode() const { return m_mode; }
174
175 private:
176 std::vector<uint8_t> compute_raw_pk_shake256() const {
177 SHAKE_256 shake(DilithiumModeConstants::SEEDBYTES * 8);
178 shake.update(m_rho);
179 shake.update(m_t1.polyvec_pack_t1());
180 return shake.final_stdvec();
181 }
182
183 const DilithiumModeConstants m_mode;
184 std::vector<uint8_t> m_raw_pk_shake256;
185 std::vector<uint8_t> m_rho;
186 Dilithium::PolynomialVector m_t1;
187};
188
189class Dilithium_PrivateKeyInternal {
190 public:
191 Dilithium_PrivateKeyInternal(DilithiumModeConstants mode) : m_mode(std::move(mode)) {}
192
193 Dilithium_PrivateKeyInternal(DilithiumModeConstants mode,
194 std::vector<uint8_t> rho,
197 Dilithium::PolynomialVector s1,
198 Dilithium::PolynomialVector s2,
199 Dilithium::PolynomialVector t0) :
200 m_mode(std::move(mode)),
201 m_rho(std::move(rho)),
202 m_tr(std::move(tr)),
203 m_key(std::move(key)),
204 m_t0(std::move(t0)),
205 m_s1(std::move(s1)),
206 m_s2(std::move(s2)) {}
207
208 Dilithium_PrivateKeyInternal(DilithiumModeConstants mode, std::span<const uint8_t> sk) :
209 Dilithium_PrivateKeyInternal(std::move(mode)) {
210 BOTAN_ASSERT_NOMSG(sk.size() == m_mode.private_key_bytes());
211
212 BufferSlicer s(sk);
213 m_rho = s.copy_as_vector(DilithiumModeConstants::SEEDBYTES);
214 m_key = s.copy_as_secure_vector(DilithiumModeConstants::SEEDBYTES);
215 m_tr = s.copy_as_secure_vector(DilithiumModeConstants::SEEDBYTES);
217 s.take(m_mode.l() * m_mode.polyeta_packedbytes()), m_mode.l(), m_mode);
219 s.take(m_mode.k() * m_mode.polyeta_packedbytes()), m_mode.k(), m_mode);
221 m_mode);
222 }
223
224 secure_vector<uint8_t> raw_sk() const {
226 m_rho, m_key, m_tr, m_s1.polyvec_pack_eta(m_mode), m_s2.polyvec_pack_eta(m_mode), m_t0.polyvec_pack_t0());
227 }
228
229 const DilithiumModeConstants& mode() const { return m_mode; }
230
231 const std::vector<uint8_t>& rho() const { return m_rho; }
232
233 const secure_vector<uint8_t>& get_key() const { return m_key; }
234
235 const secure_vector<uint8_t>& tr() const { return m_tr; }
236
237 const Dilithium::PolynomialVector& s1() const { return m_s1; }
238
239 const Dilithium::PolynomialVector& s2() const { return m_s2; }
240
241 const Dilithium::PolynomialVector& t0() const { return m_t0; }
242
243 private:
244 const DilithiumModeConstants m_mode;
245 std::vector<uint8_t> m_rho;
246 secure_vector<uint8_t> m_tr, m_key;
247 Dilithium::PolynomialVector m_t0, m_s1, m_s2;
248};
249
250class Dilithium_Signature_Operation final : public PK_Ops::Signature {
251 public:
252 Dilithium_Signature_Operation(const Dilithium_PrivateKey& priv_key_dilithium, bool randomized) :
253 m_priv_key(priv_key_dilithium),
254 m_matrix(
255 Dilithium::PolynomialMatrix::generate_matrix(m_priv_key.m_private->rho(), m_priv_key.m_private->mode())),
256 m_shake(DilithiumModeConstants::CRHBYTES * 8),
257 m_randomized(randomized) {
258 m_shake.update(m_priv_key.m_private->tr());
259 }
260
261 void update(const uint8_t msg[], size_t msg_len) override { m_shake.update(msg, msg_len); }
262
263 secure_vector<uint8_t> sign(RandomNumberGenerator& rng) override {
264 const auto mu = m_shake.final_stdvec();
265
266 // Get set up for the next message (if any)
267 m_shake.update(m_priv_key.m_private->tr());
268
269 const auto& mode = m_priv_key.m_private->mode();
270
271 const auto rhoprime = (m_randomized) ? rng.random_vec(DilithiumModeConstants::CRHBYTES)
272 : mode.CRH(concat(m_priv_key.m_private->get_key(), mu));
273
274 /* Transform vectors */
275 auto s1 = m_priv_key.m_private->s1();
276 s1.ntt();
277
278 auto s2 = m_priv_key.m_private->s2();
279 s2.ntt();
280
281 auto t0 = m_priv_key.m_private->t0();
282 t0.ntt();
283
284 // Note: nonce (as requested by `polyvecl_uniform_gamma1`) is actually just uint16_t
285 // but to avoid an integer overflow, we use uint32_t as the loop variable.
286 for(uint32_t nonce = 0; nonce <= std::numeric_limits<uint16_t>::max(); ++nonce) {
287 /* Sample intermediate vector y */
288 Dilithium::PolynomialVector y(mode.l());
289
290 y.polyvecl_uniform_gamma1(rhoprime, static_cast<uint16_t>(nonce), mode);
291
292 auto z = y;
293 z.ntt();
294
295 /* Matrix-vector multiplication */
297 m_matrix.get_matrix(), z, mode);
298
299 w1.reduce();
300 w1.invntt_tomont();
301
302 /* Decompose w and call the random oracle */
303 w1.cadd_q();
304
305 auto w1_w0 = w1.polyvec_decompose(mode);
306
307 auto packed_w1 = std::get<0>(w1_w0).polyvec_pack_w1(mode);
308
309 SHAKE_256 shake256_variable(DilithiumModeConstants::SEEDBYTES * 8);
310 shake256_variable.update(mu.data(), DilithiumModeConstants::CRHBYTES);
311 shake256_variable.update(packed_w1.data(), packed_w1.size());
312 auto sm = shake256_variable.final();
313
314 auto cp = Dilithium::Polynomial::poly_challenge(sm.data(), mode);
315 cp.ntt();
316
317 /* Compute z, reject if it reveals secret */
318 s1.polyvec_pointwise_poly_montgomery(z, cp);
319
320 z.invntt_tomont();
321 z.add_polyvec(y);
322
323 z.reduce();
324 if(z.polyvec_chknorm(mode.gamma1() - mode.beta())) {
325 continue;
326 }
327
328 /* Check that subtracting cs2 does not change high bits of w and low bits
329 * do not reveal secret information */
330 Dilithium::PolynomialVector h(mode.k());
331 s2.polyvec_pointwise_poly_montgomery(h, cp);
332 h.invntt_tomont();
333 std::get<1>(w1_w0) -= h;
334 std::get<1>(w1_w0).reduce();
335
336 if(std::get<1>(w1_w0).polyvec_chknorm(mode.gamma2() - mode.beta())) {
337 continue;
338 }
339
340 /* Compute hints for w1 */
341 t0.polyvec_pointwise_poly_montgomery(h, cp);
342 h.invntt_tomont();
343 h.reduce();
344 if(h.polyvec_chknorm(mode.gamma2())) {
345 continue;
346 }
347
348 std::get<1>(w1_w0).add_polyvec(h);
349 std::get<1>(w1_w0).cadd_q();
350
351 auto n =
352 Dilithium::PolynomialVector::generate_hint_polyvec(h, std::get<1>(w1_w0), std::get<0>(w1_w0), mode);
353 if(n > mode.omega()) {
354 continue;
355 }
356
357 /* Write signature */
358 return pack_sig(sm, z, h);
359 }
360
361 throw Internal_Error("Dilithium signature loop did not terminate");
362 }
363
364 size_t signature_length() const override {
365 const auto& dilithium_math = m_priv_key.m_private->mode();
366 return dilithium_math.crypto_bytes();
367 }
368
369 AlgorithmIdentifier algorithm_identifier() const override;
370
371 std::string hash_function() const override { return "SHAKE-256(512)"; }
372
373 private:
374 // Bit-pack signature sig = (c, z, h).
376 const Dilithium::PolynomialVector& z,
377 const Dilithium::PolynomialVector& h) {
379 size_t position = 0;
380 const auto& mode = m_priv_key.m_private->mode();
381 secure_vector<uint8_t> sig(mode.crypto_bytes());
382
383 std::copy(c.begin(), c.end(), sig.begin());
385
386 for(size_t i = 0; i < mode.l(); ++i) {
387 z.m_vec[i].polyz_pack(&sig[position + i * mode.polyz_packedbytes()], mode);
388 }
389 position += mode.l() * mode.polyz_packedbytes();
390
391 /* Encode h */
392 for(size_t i = 0; i < mode.omega() + mode.k(); ++i) {
393 sig[i + position] = 0;
394 }
395
396 size_t k = 0;
397 for(size_t i = 0; i < mode.k(); ++i) {
398 for(size_t j = 0; j < DilithiumModeConstants::N; ++j) {
399 if(h.m_vec[i].m_coeffs[j] != 0) {
400 sig[position + k] = static_cast<uint8_t>(j);
401 k++;
402 }
403 }
404 sig[position + mode.omega() + i] = static_cast<uint8_t>(k);
405 }
406 return sig;
407 }
408
409 const Dilithium_PrivateKey m_priv_key;
410 const Dilithium::PolynomialMatrix m_matrix;
411 SHAKE_256 m_shake;
412 bool m_randomized;
413};
414
415AlgorithmIdentifier Dilithium_Signature_Operation::algorithm_identifier() const {
416 return m_priv_key.algorithm_identifier();
417}
418
419class Dilithium_Verification_Operation final : public PK_Ops::Verification {
420 public:
421 Dilithium_Verification_Operation(const Dilithium_PublicKey& pub_dilithium) :
422 m_pub_key(pub_dilithium.m_public),
423 m_matrix(Dilithium::PolynomialMatrix::generate_matrix(m_pub_key->rho(), m_pub_key->mode())),
424 m_pk_hash(m_pub_key->raw_pk_shake256()),
425 m_shake(DilithiumModeConstants::CRHBYTES * 8) {
426 m_shake.update(m_pk_hash);
427 }
428
429 /*
430 * Add more data to the message currently being signed
431 * @param msg the message
432 * @param msg_len the length of msg in bytes
433 */
434 void update(const uint8_t msg[], size_t msg_len) override { m_shake.update(msg, msg_len); }
435
436 /*
437 * Perform a verification operation
438 * @param rng a random number generator
439 */
440 bool is_valid_signature(const uint8_t* sig, size_t sig_len) override {
441 /* Compute CRH(H(rho, t1), msg) */
442 const auto mu = m_shake.final_stdvec();
443
444 // Reset the SHAKE context for the next message
445 m_shake.update(m_pk_hash);
446
447 const auto& mode = m_pub_key->mode();
448
449 if(sig_len != mode.crypto_bytes()) {
450 return false;
451 }
452
453 Dilithium::PolynomialVector z(mode.l());
454 Dilithium::PolynomialVector h(mode.k());
455 std::vector<uint8_t> signature(sig, sig + sig_len);
456 std::array<uint8_t, DilithiumModeConstants::SEEDBYTES> c;
457 if(Dilithium::PolynomialVector::unpack_sig(c, z, h, signature, mode)) {
458 return false;
459 }
460
461 if(z.polyvec_chknorm(mode.gamma1() - mode.beta())) {
462 return false;
463 }
464
465 /* Matrix-vector multiplication; compute Az - c2^dt1 */
466 auto cp = Dilithium::Polynomial::poly_challenge(c.data(), mode);
467 cp.ntt();
468
469 Dilithium::PolynomialVector t1 = m_pub_key->t1();
470 t1.polyvec_shiftl();
471 t1.ntt();
472 t1.polyvec_pointwise_poly_montgomery(t1, cp);
473
474 z.ntt();
475
476 auto w1 =
478 w1 -= t1;
479 w1.reduce();
480 w1.invntt_tomont();
481 w1.cadd_q();
482 w1.polyvec_use_hint(w1, h, mode);
483 auto packed_w1 = w1.polyvec_pack_w1(mode);
484
485 /* Call random oracle and verify challenge */
486 SHAKE_256 shake256_variable(DilithiumModeConstants::SEEDBYTES * 8);
487 shake256_variable.update(mu.data(), mu.size());
488 shake256_variable.update(packed_w1.data(), packed_w1.size());
489 auto c2 = shake256_variable.final();
490
491 BOTAN_ASSERT_NOMSG(c.size() == c2.size());
492 return std::equal(c.begin(), c.end(), c2.begin());
493 }
494
495 std::string hash_function() const override { return "SHAKE-256(512)"; }
496
497 private:
498 std::shared_ptr<Dilithium_PublicKeyInternal> m_pub_key;
499 const Dilithium::PolynomialMatrix m_matrix;
500 const std::vector<uint8_t> m_pk_hash;
501 SHAKE_256 m_shake;
502};
503
504Dilithium_PublicKey::Dilithium_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> pk) :
505 Dilithium_PublicKey(pk, DilithiumMode(alg_id.oid())) {}
506
509 BOTAN_ARG_CHECK(pk.empty() || pk.size() == mode.public_key_bytes(),
510 "dilithium public key does not have the correct byte count");
511
512 m_public = std::make_shared<Dilithium_PublicKeyInternal>(std::move(mode), pk);
513}
514
518
522
524 return m_public->mode().oid();
525}
526
528 return m_public->mode().public_key_bytes();
529}
530
532 return m_public->mode().nist_security_strength();
533}
534
535std::vector<uint8_t> Dilithium_PublicKey::raw_public_key_bits() const {
536 return m_public->raw_pk();
537}
538
539std::vector<uint8_t> Dilithium_PublicKey::public_key_bits() const {
540 // Currently, there isn't a finalized definition of an ASN.1 structure for
541 // Dilithium aka ML-DSA public keys. Therefore, we return the raw public key bits.
542 return raw_public_key_bits();
543}
544
546 return true; // ???
547}
548
549std::unique_ptr<Private_Key> Dilithium_PublicKey::generate_another(RandomNumberGenerator& rng) const {
550 return std::make_unique<Dilithium_PrivateKey>(rng, m_public->mode().mode());
551}
552
553std::unique_ptr<PK_Ops::Verification> Dilithium_PublicKey::create_verification_op(std::string_view params,
554 std::string_view provider) const {
555 BOTAN_ARG_CHECK(params.empty() || params == "Pure", "Unexpected parameters for verifying with Dilithium");
556 if(provider.empty() || provider == "base") {
557 return std::make_unique<Dilithium_Verification_Operation>(*this);
558 }
559 throw Provider_Not_Found(algo_name(), provider);
560}
561
562std::unique_ptr<PK_Ops::Verification> Dilithium_PublicKey::create_x509_verification_op(
563 const AlgorithmIdentifier& alg_id, std::string_view provider) const {
564 if(provider.empty() || provider == "base") {
565 if(alg_id != this->algorithm_identifier()) {
566 throw Decoding_Error("Unexpected AlgorithmIdentifier for Dilithium X.509 signature");
567 }
568 return std::make_unique<Dilithium_Verification_Operation>(*this);
569 }
570 throw Provider_Not_Found(algo_name(), provider);
571}
572
575
577
579
580 // seed is a concatenation of rho || rhoprime || key
581 std::vector<uint8_t> rho(seed.begin(), seed.begin() + DilithiumModeConstants::SEEDBYTES);
585 seed.end());
586
590
591 /* Sample short vectors s1 and s2 */
594
597
598 auto [t0, t1] = calculate_t0_and_t1(mode, rho, s1, s2);
599
600 m_public = std::make_shared<Dilithium_PublicKeyInternal>(mode, rho, std::move(t1));
601
602 /* Compute H(rho, t1) == H(pk) and write secret key */
603 auto tr = mode.H(m_public->raw_pk(), DilithiumModeConstants::SEEDBYTES);
604
605 m_private = std::make_shared<Dilithium_PrivateKeyInternal>(
606 std::move(mode), std::move(rho), std::move(tr), std::move(key), std::move(s1), std::move(s2), std::move(t0));
607}
608
609Dilithium_PrivateKey::Dilithium_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> sk) :
610 Dilithium_PrivateKey(sk, DilithiumMode(alg_id.oid())) {}
611
614 BOTAN_ARG_CHECK(sk.size() == mode.private_key_bytes(), "dilithium private key does not have the correct byte count");
615 m_private = std::make_shared<Dilithium_PrivateKeyInternal>(std::move(mode), sk);
616 m_public = std::make_shared<Dilithium_PublicKeyInternal>(
617 m_private->mode(), m_private->rho(), m_private->s1(), m_private->s2());
618}
619
623
625 return m_private->raw_sk();
626}
627
629 std::string_view params,
630 std::string_view provider) const {
631 BOTAN_UNUSED(rng);
632
633 BOTAN_ARG_CHECK(params.empty() || params == "Deterministic" || params == "Randomized",
634 "Unexpected parameters for signing with Dilithium");
635
636 const bool randomized = (params == "Randomized");
637 if(provider.empty() || provider == "base") {
638 return std::make_unique<Dilithium_Signature_Operation>(*this, randomized);
639 }
640 throw Provider_Not_Found(algo_name(), provider);
641}
642
643std::unique_ptr<Public_Key> Dilithium_PrivateKey::public_key() const {
644 return std::make_unique<Dilithium_PublicKey>(*this);
645}
646} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:137
void update(const uint8_t in[], size_t length)
Definition buf_comp.h:35
std::vector< uint8_t > final_stdvec()
Definition buf_comp.h:84
decltype(auto) H(std::span< const uint8_t > seed, size_t out_len) const
OID object_identifier() const
Definition dilithium.cpp:92
std::string to_string() const
Definition dilithium.cpp:96
DilithiumMode(Mode mode)
Definition dilithium.h:26
const std::vector< PolynomialVector > & get_matrix() const
static PolynomialMatrix generate_matrix(const std::vector< uint8_t > &rho, const DilithiumModeConstants &mode)
static PolynomialVector unpack_t1(std::span< const uint8_t > packed_t1, const DilithiumModeConstants &mode)
static bool unpack_sig(std::array< uint8_t, DilithiumModeConstants::SEEDBYTES > &c, PolynomialVector &z, PolynomialVector &h, const std::vector< uint8_t > &sig, const DilithiumModeConstants &mode)
secure_vector< uint8_t > polyvec_pack_t0() const
secure_vector< uint8_t > polyvec_pack_eta(const DilithiumModeConstants &mode) const
static PolynomialVector unpack_t0(std::span< const uint8_t > buffer, const DilithiumModeConstants &mode)
static void fill_polyvec_uniform_eta(PolynomialVector &v, const secure_vector< uint8_t > &seed, uint16_t nonce, const DilithiumModeConstants &mode)
static void fill_polyvecs_power2round(PolynomialVector &v1, PolynomialVector &v0, const PolynomialVector &v)
static PolynomialVector generate_polyvec_matrix_pointwise_montgomery(const std::vector< PolynomialVector > &mat, const PolynomialVector &v, const DilithiumModeConstants &mode)
std::vector< uint8_t > polyvec_pack_t1() const
static PolynomialVector unpack_eta(std::span< const uint8_t > buffer, size_t size, const DilithiumModeConstants &mode)
static size_t generate_hint_polyvec(PolynomialVector &h, const PolynomialVector &v0, const PolynomialVector &v1, const DilithiumModeConstants &mode)
static Polynomial poly_challenge(const uint8_t *seed, const DilithiumModeConstants &mode)
Dilithium_PrivateKey(RandomNumberGenerator &rng, DilithiumMode mode)
secure_vector< uint8_t > raw_private_key_bits() const override
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &, std::string_view params, std::string_view provider) const override
secure_vector< uint8_t > private_key_bits() const override
std::unique_ptr< Public_Key > public_key() const override
AlgorithmIdentifier algorithm_identifier() const override
std::vector< uint8_t > public_key_bits() const override
OID object_identifier() const override
bool check_key(RandomNumberGenerator &, bool) const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
size_t key_length() const override
std::string algo_name() const override
size_t estimated_strength() const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::vector< uint8_t > raw_public_key_bits() const override
std::shared_ptr< Dilithium_PublicKeyInternal > m_public
Definition dilithium.h:97
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
void random_vec(std::span< uint8_t > v)
Definition rng.h:179
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
constexpr T rho(T x)
Definition rotate.h:51
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:262
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61