Botan 3.9.0
Crypto and TLS for C&
pqcrystals.h
Go to the documentation of this file.
1/*
2 * PQ CRYSTALS Common Structures
3 *
4 * Further changes
5 * (C) 2021-2024 Jack Lloyd
6 * (C) 2021-2022 Manuel Glaser and Michael Boric, Rohde & Schwarz Cybersecurity
7 * (C) 2021-2022 René Meusel and Hannes Rantzsch, neXenio GmbH
8 * (C) 2024 René Meusel, Fabian Albert, Rohde & Schwarz Cybersecurity
9 *
10 * Botan is released under the Simplified BSD License (see license.txt)
11 */
12
13#ifndef BOTAN_PQ_CRYSTALS_H_
14#define BOTAN_PQ_CRYSTALS_H_
15
16#include <concepts>
17#include <limits>
18#include <span>
19#include <vector>
20
21#include <botan/assert.h>
22#include <botan/mem_ops.h>
23#include <botan/internal/ct_utils.h>
24#include <botan/internal/pqcrystals_helpers.h>
25
26namespace Botan::CRYSTALS {
27
28enum class Domain : uint8_t { Normal, NTT };
29
30template <typename T>
32 std::signed_integral<typename T::T> && std::integral<decltype(T::N)> && std::integral<decltype(T::Q)> &&
33 std::integral<decltype(T::F)> && std::unsigned_integral<decltype(T::NTT_Degree)> &&
34 std::integral<decltype(T::ROOT_OF_UNITY)>;
35
36/**
37 * This implements basic polynomial operations for Kyber and Dilithium
38 * based on the given algorithm constants (@p ConstantsT) and back-
39 * references some of the operations to the actual implementation
40 * into the derived class (CRTP @p DerivedT).
41 *
42 * Polynomial parameters are passed as spans of coefficients for maximum
43 * flexibility.
44 *
45 * It is assumed that this is subclassed with the actual implementation
46 * with establishing a CRTP back-reference.
47 */
48template <crystals_constants ConstantsT, typename DerivedT>
50 public:
51 using T = typename ConstantsT::T;
52 static constexpr T N = ConstantsT::N;
53 static constexpr T Q = ConstantsT::Q;
54
55 protected:
57
58 /// \name Pre-computed algorithm constants
59 /// @{
60
61 static constexpr T Q_inverse = modular_inverse(Q);
62 static constexpr T MONTY = montgomery_R(Q);
63 static constexpr T MONTY_SQUARED = montgomery_R2(Q);
64
65 // Contains the constant f from Algorithm 36 multiplied two times by
66 // the montgomery parameter, i.e. 2^(2*32) mod q. The first montgomery
67 // factor is then removed by the reduction in the loop. The second one
68 // is required to eliminate factors 2^(-32) mod q in coeffs introduced
69 // by previous montgomery multiplications in a single vector/matrix
70 // multiplication operation.
71 static constexpr T F_WITH_MONTY_SQUARED = (static_cast<T2>(ConstantsT::F) * MONTY_SQUARED) % Q;
72
73 static constexpr auto zetas = precompute_zetas<ConstantsT::NTT_Degree>(Q, MONTY, ConstantsT::ROOT_OF_UNITY);
74
75 /// @}
76
77 protected:
78 Trait_Base() = default; // NOLINT(*crtp-constructor-accessibility)
79
80 /// @returns the number of polynomials in the polynomial vector @p polyvec.
81 static constexpr size_t polys_in_polyvec(std::span<const T> polyvec) {
82 BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
83 return polyvec.size() / N;
84 }
85
86 /// @returns the @p index-th polynomial in the polynomial vector @p polyvec.
87 template <typename U>
88 requires(std::same_as<T, U> || std::same_as<const T, U>)
89 static constexpr std::span<U, N> poly_in_polyvec(std::span<U> polyvec, size_t index) {
90 BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
91 BOTAN_DEBUG_ASSERT(polyvec.size() / N > index);
92 auto polyspan = polyvec.subspan(index * N, N);
93 return std::span<U, N>{polyspan.data(), polyspan.size()};
94 }
95
96 static constexpr T fqmul(T a, T b) { return DerivedT::montgomery_reduce_coefficient(static_cast<T2>(a) * b); }
97
98 public:
99 static constexpr void poly_add(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
100 for(size_t i = 0; i < N; ++i) {
101 result[i] = lhs[i] + rhs[i];
102 }
103 }
104
105 static constexpr void poly_sub(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
106 for(size_t i = 0; i < N; ++i) {
107 result[i] = lhs[i] - rhs[i];
108 }
109 }
110
111 /// Adds Q if the coefficient is negative.
112 static constexpr void poly_cadd_q(std::span<T, N> coeffs) {
113 for(auto& coeff : coeffs) {
114 using unsigned_T = std::make_unsigned_t<T>;
115 const auto is_negative = CT::Mask<unsigned_T>::expand_top_bit(static_cast<unsigned_T>(coeff));
116 coeff += is_negative.if_set_return(Q);
117 }
118 }
119
120 static constexpr T to_montgomery(T a) { return fqmul(a, MONTY_SQUARED); }
121
122 constexpr static void barrett_reduce(std::span<T, N> poly) {
123 for(auto& coeff : poly) {
124 coeff = DerivedT::barrett_reduce_coefficient(coeff);
125 }
126 }
127
128 /// Multiplication and accumulation of 2 polynomial vectors @p u and @p v.
129 static constexpr void polyvec_pointwise_acc_montgomery(std::span<T, N> w,
130 std::span<const T> u,
131 std::span<const T> v) {
132 clear_mem(w);
133 std::array<T, N> t{};
134 for(size_t i = 0; i < polys_in_polyvec(u); ++i) {
135 DerivedT::poly_pointwise_montgomery(t, poly_in_polyvec(u, i), poly_in_polyvec(v, i));
136 poly_add(w, w, t);
137 }
139 }
140};
141
142template <typename T>
144 std::signed_integral<typename T::T> && sizeof(typename T::T) <= 4 && std::integral<decltype(T::N)> &&
145 T::N % 2 == 0 &&
146 requires(std::span<typename T::T, T::N> polyspan, std::span<typename T::T> polyvecspan, typename T::T coeff) {
147 { T::to_montgomery(coeff) };
148 { T::barrett_reduce(polyspan) };
149 { T::poly_cadd_q(polyspan) };
150 { T::ntt(polyspan) };
151 { T::inverse_ntt(polyspan) };
152 { T::poly_pointwise_montgomery(polyspan, polyspan, polyspan) };
153 { T::polyvec_pointwise_acc_montgomery(polyspan, polyvecspan, polyvecspan) };
154 };
155
156namespace detail {
157
158/**
159 * Converts polynomials or polynomial vectors from one domain to another.
160 */
161template <Domain To, template <typename, Domain> class StructureT, crystals_trait Trait, Domain From>
162 requires(To != From)
163StructureT<Trait, To> domain_cast(StructureT<Trait, From>&& p) {
164 // The public factory method `from_domain_cast` is just a workaround for
165 // Xcode and NDK not understanding the friend declaration to allow this
166 // to directly call the private constructor.
167 return StructureT<Trait, To>::from_domain_cast(std::move(p));
168}
169
170/**
171 * Ensures that all values in the @p range are within the range [min, max]
172 * using constant-time operations.
173 *
174 * @returns true if all values are within the range, false otherwise.
175 */
176template <std::integral T, size_t N = std::dynamic_extent>
177constexpr static bool ct_all_within_range(std::span<const T, N> range, T min, T max)
178 requires(sizeof(T) <= 4)
179{
180 BOTAN_DEBUG_ASSERT(min < max);
181
182 using unsigned_T = std::make_unsigned_t<T>;
183 auto map = [](T v) -> unsigned_T {
184 if constexpr(std::signed_integral<T>) {
185 constexpr int64_t offset = -static_cast<int64_t>(std::numeric_limits<T>::min());
186 return static_cast<unsigned_T>(static_cast<int64_t>(v) + offset);
187 } else {
188 return v;
189 }
190 };
191
192 const auto umin = map(min);
193 const auto umax = map(max);
194
195 auto mask = CT::Mask<unsigned_T>::set();
196 for(const T c : range) {
197 mask &= CT::Mask<unsigned_T>::is_within_range(map(c), umin, umax);
198 }
199 return mask.as_bool();
200}
201
202} // namespace detail
203
204/**
205 * Represents a polynomial with Trait::N coefficients of type Trait::T.
206 * The domain of the polynomial can be either Domain::Normal or Domain::NTT and
207 * this information is represented in the C++ type system.
208 *
209 * Polynomials may either own their storage of piggy-back on external storage
210 * when they are part of a PolynomialVector.
211 */
212template <crystals_trait Trait, Domain D = Domain::Normal>
214 private:
215 using ThisPolynomial = Polynomial<Trait, D>;
216 using T = typename Trait::T;
217
218 private:
219 // TODO: perhaps secure vector
220 std::vector<T> m_coeffs_storage;
221 std::span<T, Trait::N> m_coeffs;
222
223 private:
224 template <crystals_trait OtherTrait, Domain OtherD>
225 friend class Polynomial;
226
227 template <Domain To, template <typename, Domain> class StructureT, crystals_trait C, Domain From>
228 requires(To != From)
229 friend StructureT<C, To> detail::domain_cast(StructureT<C, From>&&);
230
231 /**
232 * This constructor is used to convert a Polynomial from one domain to another.
233 * The friend declarations above facilitate this.
234 */
235 template <Domain OtherD>
236 requires(D != OtherD)
237 explicit Polynomial(Polynomial<Trait, OtherD>&& other) noexcept : // NOLINT(*-rvalue-reference-param-not-moved)
238 m_coeffs_storage(std::move(other.m_coeffs_storage)),
239 m_coeffs(owns_storage() ? std::span<T, Trait::N>(m_coeffs_storage) : other.m_coeffs) {}
240
241 public:
242 // Workaround, because Xcode and NDK don't understand the
243 // `detail::domain_cast` friend declaration.
244 //
245 // TODO: Try to remove this and use the c'tor directly in
246 // `detail::domain_cast` after updating the compilers.
247 template <Domain OtherD>
248 requires(D != OtherD)
252
253 public:
254 Polynomial() : m_coeffs_storage(Trait::N), m_coeffs(m_coeffs_storage) { BOTAN_DEBUG_ASSERT(owns_storage()); }
255
256 explicit Polynomial(std::span<T, Trait::N> coeffs) : m_coeffs(coeffs) { BOTAN_DEBUG_ASSERT(!owns_storage()); }
257
258 Polynomial(const ThisPolynomial& other) = delete;
259
260 Polynomial(ThisPolynomial&& other) noexcept :
261 m_coeffs_storage(std::move(other.m_coeffs_storage)), m_coeffs(other.m_coeffs) {}
262
263 ThisPolynomial& operator=(const ThisPolynomial& other) = delete;
264
265 ThisPolynomial& operator=(ThisPolynomial&& other) noexcept {
266 if(this != &other) {
268 m_coeffs_storage = std::move(other.m_coeffs_storage);
269 m_coeffs = std::span<T, Trait::N>(m_coeffs_storage);
270 }
271 return *this;
272 }
273
274 ~Polynomial() = default;
275
276 constexpr size_t size() const { return m_coeffs.size(); }
277
278 constexpr Domain domain() const noexcept { return D; }
279
280 ThisPolynomial clone() const {
281 ThisPolynomial res;
282 copy_mem(res.m_coeffs_storage, m_coeffs);
283 res.m_coeffs = std::span<T, Trait::N>(res.m_coeffs_storage);
285 return res;
286 }
287
288 /// @returns true if all coefficients are within the range [min, max]
289 constexpr bool ct_validate_value_range(T min, T max) const noexcept {
290 return detail::ct_all_within_range(coefficients(), min, max);
291 }
292
293 /// @returns the number of non-zero coefficients in the polynomial
294 constexpr size_t hamming_weight() const noexcept {
295 size_t weight = 0;
296 for(const auto c : m_coeffs) {
297 weight += (c != 0);
298 }
299 return weight;
300 }
301
302 std::span<T, Trait::N> coefficients() { return m_coeffs; }
303
304 std::span<const T, Trait::N> coefficients() const { return m_coeffs; }
305
306 T& operator[](size_t i) { return m_coeffs[i]; }
307
308 T operator[](size_t i) const { return m_coeffs[i]; }
309
310 decltype(auto) begin() { return m_coeffs.begin(); }
311
312 decltype(auto) begin() const { return m_coeffs.begin(); }
313
314 decltype(auto) end() { return m_coeffs.end(); }
315
316 decltype(auto) end() const { return m_coeffs.end(); }
317
318 constexpr bool owns_storage() const { return !m_coeffs_storage.empty(); }
319
320 ThisPolynomial& reduce() {
321 Trait::barrett_reduce(m_coeffs);
322 return *this;
323 }
324
325 ThisPolynomial& conditional_add_q() {
326 Trait::poly_cadd_q(m_coeffs);
327 return *this;
328 }
329
330 void _const_time_poison() const { CT::poison(m_coeffs); }
331
332 void _const_time_unpoison() const { CT::unpoison(m_coeffs); }
333
334 /**
335 * Adds two polynomials element-wise. Does not perform a reduction after the addition.
336 * Therefore this operation might cause an integer overflow.
337 */
338 decltype(auto) operator+=(const ThisPolynomial& other) {
339 Trait::poly_add(m_coeffs, m_coeffs, other.m_coeffs);
340 return *this;
341 }
342
343 /**
344 * Subtracts two polynomials element-wise. Does not perform a reduction after the subtraction.
345 * Therefore this operation might cause an integer underflow.
346 */
347 decltype(auto) operator-=(const ThisPolynomial& other) {
348 Trait::poly_sub(m_coeffs, m_coeffs, other.m_coeffs);
349 return *this;
350 }
351};
352
353template <crystals_trait Trait, Domain D = Domain::Normal>
355 private:
356 using ThisPolynomialVector = PolynomialVector<Trait, D>;
357 using T = typename Trait::T;
358
359 private:
360 std::vector<T> m_polys_storage;
361 std::vector<Polynomial<Trait, D>> m_vec;
362
363 private:
364 template <crystals_trait OtherTrait, Domain OtherD>
365 friend class PolynomialVector;
366
367 template <Domain To, template <typename, Domain> class StructureT, crystals_trait C, Domain From>
368 requires(To != From)
369 friend StructureT<C, To> detail::domain_cast(StructureT<C, From>&&);
370
371 /**
372 * This constructor is used to convert a PolynomialVector from one domain to another.
373 * The friend declarations above facilitate this.
374 */
375 template <Domain OtherD>
376 requires(D != OtherD)
377 /* NOLINTNEXTLINE(*rvalue-reference-param-not-moved) */ explicit PolynomialVector(
378 PolynomialVector<Trait, OtherD>&& other) noexcept :
379 m_polys_storage(std::move(other.m_polys_storage)) {
380 BOTAN_DEBUG_ASSERT(m_polys_storage.size() % Trait::N == 0);
381 const size_t vecsize = m_polys_storage.size() / Trait::N;
382 for(size_t i = 0; i < vecsize; ++i) {
383 m_vec.emplace_back(
384 Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
385 }
386 }
387
388 public:
389 // Workaround, because Xcode and NDK don't understand the
390 // `detail::domain_cast` friend declaration above.
391 //
392 // TODO: Try to remove this and use the c'tor directly in
393 // `detail::domain_cast` after updating the compilers.
394 template <Domain OtherD>
395 requires(D != OtherD)
399
400 public:
401 explicit PolynomialVector(size_t vecsize) : m_polys_storage(vecsize * Trait::N) {
402 for(size_t i = 0; i < vecsize; ++i) {
403 m_vec.emplace_back(
404 Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
405 }
406 }
407
408 PolynomialVector(const ThisPolynomialVector& other) = delete;
409 PolynomialVector(ThisPolynomialVector&& other) noexcept = default;
410 ThisPolynomialVector& operator=(const ThisPolynomialVector& other) = delete;
411 ThisPolynomialVector& operator=(ThisPolynomialVector&& other) noexcept = default;
412 ~PolynomialVector() = default;
413
414 size_t size() const { return m_vec.size(); }
415
416 constexpr Domain domain() const noexcept { return D; }
417
418 ThisPolynomialVector clone() const {
419 ThisPolynomialVector res(size());
420
421 // The default-constructed PolynomialVector has set up res.m_vec to
422 // point to res.m_polys_storage. Therefore we can just copy the data
423 // into res.m_polys_storage to fill the non-owning polynomials.
424 copy_mem(res.m_polys_storage, m_polys_storage);
425
426 return res;
427 }
428
429 /// @returns the number of non-zero coefficients in the polynomial vector
430 size_t hamming_weight() const noexcept {
431 size_t weight = 0;
432 for(const auto c : m_polys_storage) {
433 weight += (c != 0);
434 }
435 return weight;
436 }
437
438 /// @returns true if all coefficients are within the range [min, max]
439 constexpr bool ct_validate_value_range(T min, T max) const noexcept {
440 return detail::ct_all_within_range(coefficients(), min, max);
441 }
442
443 std::span<T> coefficients() { return m_polys_storage; }
444
445 std::span<const T> coefficients() const { return m_polys_storage; }
446
447 ThisPolynomialVector& operator+=(const ThisPolynomialVector& other) {
448 BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot add polynomial vectors of differing lengths");
449 for(size_t i = 0; i < m_vec.size(); ++i) {
450 Trait::poly_add(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
451 }
452 return *this;
453 }
454
455 ThisPolynomialVector& operator-=(const ThisPolynomialVector& other) {
456 BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot subtract polynomial vectors of differing lengths");
457 for(size_t i = 0; i < m_vec.size(); ++i) {
458 Trait::poly_sub(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
459 }
460 return *this;
461 }
462
463 ThisPolynomialVector& reduce() {
464 for(auto& p : m_vec) {
465 Trait::barrett_reduce(p.coefficients());
466 }
467 return *this;
468 }
469
470 ThisPolynomialVector& conditional_add_q() {
471 for(auto& v : m_vec) {
472 Trait::poly_cadd_q(v.coefficients());
473 }
474 return *this;
475 }
476
477 Polynomial<Trait, D>& operator[](size_t i) { return m_vec[i]; }
478
479 const Polynomial<Trait, D>& operator[](size_t i) const { return m_vec[i]; }
480
481 decltype(auto) begin() { return m_vec.begin(); }
482
483 decltype(auto) begin() const { return m_vec.begin(); }
484
485 decltype(auto) end() { return m_vec.end(); }
486
487 decltype(auto) end() const { return m_vec.end(); }
488
489 void _const_time_poison() const { CT::poison_range(m_vec); }
490
492};
493
494template <crystals_trait Trait>
496 private:
497 using ThisPolynomialMatrix = PolynomialMatrix<Trait>;
498
499 private:
500 std::vector<PolynomialVector<Trait, Domain::NTT>> m_mat;
501
502 public:
503 explicit PolynomialMatrix(std::vector<PolynomialVector<Trait>> mat) : m_mat(std::move(mat)) {}
504
505 PolynomialMatrix(const ThisPolynomialMatrix& other) = delete;
506 PolynomialMatrix(ThisPolynomialMatrix&& other) noexcept = default;
507 ThisPolynomialMatrix& operator=(const ThisPolynomialMatrix& other) = delete;
508 ThisPolynomialMatrix& operator=(ThisPolynomialMatrix&& other) noexcept = default;
509 ~PolynomialMatrix() = default;
510
511 size_t size() const { return m_mat.size(); }
512
513 PolynomialMatrix(size_t rows, size_t cols) {
514 m_mat.reserve(rows);
515 for(size_t i = 0; i < rows; ++i) {
516 m_mat.emplace_back(cols);
517 }
518 }
519
520 PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) { return m_mat[i]; }
521
522 const PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) const { return m_mat[i]; }
523
524 decltype(auto) begin() { return m_mat.begin(); }
525
526 decltype(auto) begin() const { return m_mat.begin(); }
527
528 decltype(auto) end() { return m_mat.end(); }
529
530 decltype(auto) end() const { return m_mat.end(); }
531
532 void _const_time_poison() const { CT::poison_range(m_mat); }
533
535};
536
537namespace detail {
538
539template <crystals_trait Trait, Domain D>
541 for(auto& c : p) {
542 c = Trait::to_montgomery(c);
543 }
544}
545
546template <crystals_trait Trait>
550 BOTAN_ASSERT(a.size() == b.size(), "Dot product requires equally sized PolynomialVectors");
551 for(size_t i = 0; i < a.size(); ++i) {
552 out += a[i] * b[i];
553 }
554 out.reduce();
555}
556
557} // namespace detail
558
559template <crystals_trait Trait>
561 auto p_ntt = detail::domain_cast<Domain::NTT>(std::move(p));
562 Trait::ntt(p_ntt.coefficients());
563 return p_ntt;
564}
565
566template <crystals_trait Trait>
568 auto p = detail::domain_cast<Domain::Normal>(std::move(p_ntt));
569 Trait::inverse_ntt(p.coefficients());
570 return p;
571}
572
573template <crystals_trait Trait>
575 auto polyvec_ntt = detail::domain_cast<Domain::NTT>(std::move(polyvec));
576 for(auto& poly : polyvec_ntt) {
577 Trait::ntt(poly.coefficients());
578 }
579 return polyvec_ntt;
580}
581
582template <crystals_trait Trait>
584 auto polyvec = detail::domain_cast<Domain::Normal>(std::move(polyvec_ntt));
585 for(auto& poly : polyvec) {
586 Trait::inverse_ntt(poly.coefficients());
587 }
588 return polyvec;
589}
590
591template <crystals_trait Trait, Domain D>
596
597template <crystals_trait Trait, Domain D>
599 for(auto& p : polyvec) {
601 }
602 return polyvec;
603}
604
605template <crystals_trait Trait>
608 BOTAN_DEBUG_ASSERT(a.size() == b.size());
610 for(size_t i = 0; i < a.size(); ++i) {
611 Trait::poly_add(result[i].coefficients(), a[i].coefficients(), b[i].coefficients());
612 }
613 return result;
614}
615
616template <crystals_trait Trait>
620 for(size_t i = 0; i < mat.size(); ++i) {
621 Trait::polyvec_pointwise_acc_montgomery(result[i].coefficients(), mat[i].coefficients(), vec.coefficients());
622 }
623 return result;
624}
625
626template <crystals_trait Trait>
633
634template <crystals_trait Trait>
638 for(size_t i = 0; i < pv.size(); ++i) {
639 Trait::poly_pointwise_montgomery(result[i].coefficients(), p.coefficients(), pv[i].coefficients());
640 }
641 return result;
642}
643
644template <crystals_trait Trait>
648 Trait::poly_pointwise_montgomery(result.coefficients(), a.coefficients(), b.coefficients());
649 return result;
650}
651
652template <crystals_trait Trait>
653PolynomialVector<Trait, Domain::Normal> operator<<(const PolynomialVector<Trait, Domain::Normal>& pv, size_t shift) {
654 BOTAN_ASSERT_NOMSG(shift < sizeof(typename Trait::T) * 8);
655 PolynomialVector<Trait, Domain::Normal> result(pv.size());
656 for(size_t i = 0; i < pv.size(); ++i) {
657 for(size_t j = 0; j < Trait::N; ++j) {
658 result[i][j] = pv[i][j] << shift;
659 }
660 }
661 return result;
662}
663
664} // namespace Botan::CRYSTALS
665
666#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
PolynomialMatrix(size_t rows, size_t cols)
Definition pqcrystals.h:513
PolynomialVector< Trait, Domain::NTT > & operator[](size_t i)
Definition pqcrystals.h:520
PolynomialMatrix(ThisPolynomialMatrix &&other) noexcept=default
ThisPolynomialMatrix & operator=(const ThisPolynomialMatrix &other)=delete
decltype(auto) end() const
Definition pqcrystals.h:530
PolynomialMatrix(const ThisPolynomialMatrix &other)=delete
const PolynomialVector< Trait, Domain::NTT > & operator[](size_t i) const
Definition pqcrystals.h:522
ThisPolynomialMatrix & operator=(ThisPolynomialMatrix &&other) noexcept=default
PolynomialMatrix(std::vector< PolynomialVector< Trait > > mat)
Definition pqcrystals.h:503
decltype(auto) begin() const
Definition pqcrystals.h:526
ThisPolynomialVector & operator=(const ThisPolynomialVector &other)=delete
Polynomial< Trait, D > & operator[](size_t i)
Definition pqcrystals.h:477
std::span< const T > coefficients() const
Definition pqcrystals.h:445
ThisPolynomialVector & reduce()
Definition pqcrystals.h:463
constexpr Domain domain() const noexcept
Definition pqcrystals.h:416
ThisPolynomialVector & operator-=(const ThisPolynomialVector &other)
Definition pqcrystals.h:455
size_t hamming_weight() const noexcept
Definition pqcrystals.h:430
PolynomialVector(const ThisPolynomialVector &other)=delete
ThisPolynomialVector & operator=(ThisPolynomialVector &&other) noexcept=default
decltype(auto) begin() const
Definition pqcrystals.h:483
const Polynomial< Trait, D > & operator[](size_t i) const
Definition pqcrystals.h:479
ThisPolynomialVector clone() const
Definition pqcrystals.h:418
PolynomialVector(ThisPolynomialVector &&other) noexcept=default
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:439
ThisPolynomialVector & conditional_add_q()
Definition pqcrystals.h:470
decltype(auto) end() const
Definition pqcrystals.h:487
static PolynomialVector< Trait, D > from_domain_cast(PolynomialVector< Trait, OtherD > &&other)
Definition pqcrystals.h:396
ThisPolynomialVector & operator+=(const ThisPolynomialVector &other)
Definition pqcrystals.h:447
Polynomial(const ThisPolynomial &other)=delete
constexpr bool owns_storage() const
Definition pqcrystals.h:318
void _const_time_unpoison() const
Definition pqcrystals.h:332
ThisPolynomial & operator=(ThisPolynomial &&other) noexcept
Definition pqcrystals.h:265
T operator[](size_t i) const
Definition pqcrystals.h:308
Polynomial(std::span< T, Trait::N > coeffs)
Definition pqcrystals.h:256
Polynomial(ThisPolynomial &&other) noexcept
Definition pqcrystals.h:260
ThisPolynomial & conditional_add_q()
Definition pqcrystals.h:325
std::span< const T, Trait::N > coefficients() const
Definition pqcrystals.h:304
ThisPolynomial & operator=(const ThisPolynomial &other)=delete
constexpr size_t hamming_weight() const noexcept
Definition pqcrystals.h:294
static Polynomial< Trait, D > from_domain_cast(Polynomial< Trait, OtherD > &&p)
Definition pqcrystals.h:249
decltype(auto) end() const
Definition pqcrystals.h:316
std::span< T, Trait::N > coefficients()
Definition pqcrystals.h:302
constexpr size_t size() const
Definition pqcrystals.h:276
void _const_time_poison() const
Definition pqcrystals.h:330
constexpr Domain domain() const noexcept
Definition pqcrystals.h:278
ThisPolynomial & reduce()
Definition pqcrystals.h:320
ThisPolynomial clone() const
Definition pqcrystals.h:280
decltype(auto) begin() const
Definition pqcrystals.h:312
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:289
static constexpr void barrett_reduce(std::span< T, N > poly)
Definition pqcrystals.h:122
static constexpr T Q
Definition pqcrystals.h:53
static constexpr T to_montgomery(T a)
Definition pqcrystals.h:120
static constexpr T F_WITH_MONTY_SQUARED
Definition pqcrystals.h:71
static constexpr void poly_sub(std::span< T, N > result, std::span< const T, N > lhs, std::span< const T, N > rhs)
Definition pqcrystals.h:105
next_longer_int_t< T > T2
Definition pqcrystals.h:56
static constexpr T N
Definition pqcrystals.h:52
static constexpr T MONTY
Definition pqcrystals.h:62
static constexpr T Q_inverse
Definition pqcrystals.h:61
static constexpr T MONTY_SQUARED
Definition pqcrystals.h:63
static constexpr void poly_cadd_q(std::span< T, N > coeffs)
Adds Q if the coefficient is negative.
Definition pqcrystals.h:112
static constexpr T fqmul(T a, T b)
Definition pqcrystals.h:96
static constexpr auto zetas
Definition pqcrystals.h:73
static constexpr void poly_add(std::span< T, N > result, std::span< const T, N > lhs, std::span< const T, N > rhs)
Definition pqcrystals.h:99
typename ConstantsT::T T
Definition pqcrystals.h:51
static constexpr size_t polys_in_polyvec(std::span< const T > polyvec)
Definition pqcrystals.h:81
static constexpr std::span< U, N > poly_in_polyvec(std::span< U > polyvec, size_t index)
Definition pqcrystals.h:89
static constexpr void polyvec_pointwise_acc_montgomery(std::span< T, N > w, std::span< const T > u, std::span< const T > v)
Multiplication and accumulation of 2 polynomial vectors u and v.
Definition pqcrystals.h:129
static constexpr Mask< T > set()
Definition ct_utils.h:410
static constexpr Mask< T > expand_top_bit(T v)
Definition ct_utils.h:443
static constexpr Mask< T > is_within_range(T v, T l, T u)
Definition ct_utils.h:498
void dot_product(Polynomial< Trait, Domain::NTT > &out, const PolynomialVector< Trait, Domain::NTT > &a, const PolynomialVector< Trait, Domain::NTT > &b)
Definition pqcrystals.h:547
void montgomery(Polynomial< Trait, D > &p)
Definition pqcrystals.h:540
StructureT< Trait, To > domain_cast(StructureT< Trait, From > &&p)
Definition pqcrystals.h:163
Polynomial< Trait, D > montgomery(Polynomial< Trait, D > p)
Definition pqcrystals.h:592
PolynomialVector< Trait, Domain::NTT > operator*(const PolynomialMatrix< Trait > &mat, const PolynomialVector< Trait, Domain::NTT > &vec)
Definition pqcrystals.h:617
PolynomialVector< Trait, Domain::Normal > operator+(const PolynomialVector< Trait, Domain::Normal > &a, const PolynomialVector< Trait, Domain::Normal > &b)
Definition pqcrystals.h:606
Polynomial< Trait, Domain::NTT > ntt(Polynomial< Trait, Domain::Normal > p)
Definition pqcrystals.h:560
PolynomialVector< Trait, Domain::Normal > operator<<(const PolynomialVector< Trait, Domain::Normal > &pv, size_t shift)
Definition pqcrystals.h:653
Polynomial< Trait, Domain::Normal > inverse_ntt(Polynomial< Trait, Domain::NTT > p_ntt)
Definition pqcrystals.h:567
constexpr void poison_range(const R &r)
Definition ct_utils.h:179
constexpr void unpoison_range(const R &r)
Definition ct_utils.h:187
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:65
constexpr void poison(const T *p, size_t n)
Definition ct_utils.h:54
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
consteval T modular_inverse(T q, T2 m=T2(1)<< sizeof(T) *8)
std::conditional_t< sizeof(T)==1, int16_t, std::conditional_t< sizeof(T)==2, int32_t, std::conditional_t< sizeof(T)==4, int64_t, void > > > next_longer_int_t
consteval T montgomery_R2(T q)
consteval T montgomery_R(T q)
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:119