Botan 3.6.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 { 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 /// @returns the number of polynomials in the polynomial vector @p polyvec.
79 static constexpr size_t polys_in_polyvec(std::span<const T> polyvec) {
80 BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
81 return polyvec.size() / N;
82 }
83
84 /// @returns the @p index-th polynomial in the polynomial vector @p polyvec.
85 template <typename U>
86 requires(std::same_as<T, U> || std::same_as<const T, U>)
87 static constexpr std::span<U, N> poly_in_polyvec(std::span<U> polyvec, size_t index) {
88 BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
89 BOTAN_DEBUG_ASSERT(polyvec.size() / N > index);
90 auto polyspan = polyvec.subspan(index * N, N);
91 return std::span<U, N>{polyspan.data(), polyspan.size()};
92 }
93
94 static constexpr T fqmul(T a, T b) { return DerivedT::montgomery_reduce_coefficient(static_cast<T2>(a) * b); }
95
96 public:
97 static constexpr void poly_add(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
98 for(size_t i = 0; i < N; ++i) {
99 result[i] = lhs[i] + rhs[i];
100 }
101 }
102
103 static constexpr void poly_sub(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
104 for(size_t i = 0; i < N; ++i) {
105 result[i] = lhs[i] - rhs[i];
106 }
107 }
108
109 /// Adds Q if the coefficient is negative.
110 static constexpr void poly_cadd_q(std::span<T, N> coeffs) {
111 for(auto& coeff : coeffs) {
112 using unsigned_T = std::make_unsigned_t<T>;
113 const auto is_negative = CT::Mask<unsigned_T>::expand_top_bit(static_cast<unsigned_T>(coeff));
114 coeff += is_negative.if_set_return(Q);
115 }
116 }
117
118 static constexpr T to_montgomery(T a) { return fqmul(a, MONTY_SQUARED); }
119
120 constexpr static void barrett_reduce(std::span<T, N> poly) {
121 for(auto& coeff : poly) {
122 coeff = DerivedT::barrett_reduce_coefficient(coeff);
123 }
124 }
125
126 /// Multiplication and accumulation of 2 polynomial vectors @p u and @p v.
127 static constexpr void polyvec_pointwise_acc_montgomery(std::span<T, N> w,
128 std::span<const T> u,
129 std::span<const T> v) {
130 clear_mem(w);
131 std::array<T, N> t;
132 for(size_t i = 0; i < polys_in_polyvec(u); ++i) {
133 DerivedT::poly_pointwise_montgomery(t, poly_in_polyvec(u, i), poly_in_polyvec(v, i));
134 poly_add(w, w, t);
135 }
137 }
138};
139
140template <typename T>
142 std::signed_integral<typename T::T> && sizeof(typename T::T) <= 4 && std::integral<decltype(T::N)> &&
143 T::N % 2 == 0 &&
144 requires(std::span<typename T::T, T::N> polyspan, std::span<typename T::T> polyvecspan, typename T::T coeff) {
145 { T::to_montgomery(coeff) };
146 { T::barrett_reduce(polyspan) };
147 { T::poly_cadd_q(polyspan) };
148 { T::ntt(polyspan) };
149 { T::inverse_ntt(polyspan) };
150 { T::poly_pointwise_montgomery(polyspan, polyspan, polyspan) };
151 { T::polyvec_pointwise_acc_montgomery(polyspan, polyvecspan, polyvecspan) };
152 };
153
154namespace detail {
155
156/**
157 * Converts polynomials or polynomial vectors from one domain to another.
158 */
159template <Domain To, template <typename, Domain> class StructureT, crystals_trait Trait, Domain From>
160 requires(To != From)
161StructureT<Trait, To> domain_cast(StructureT<Trait, From>&& p) {
162 // The public factory method `from_domain_cast` is just a workaround for
163 // Xcode and NDK not understanding the friend declaration to allow this
164 // to directly call the private constructor.
165 return StructureT<Trait, To>::from_domain_cast(std::move(p));
166}
167
168/**
169 * Ensures that all values in the @p range are within the range [min, max]
170 * using constant-time operations.
171 *
172 * @returns true if all values are within the range, false otherwise.
173 */
174template <std::integral T, size_t N = std::dynamic_extent>
175constexpr static bool ct_all_within_range(std::span<const T, N> range, T min, T max)
176 requires(sizeof(T) <= 4)
177{
178 BOTAN_DEBUG_ASSERT(min < max);
179
180 using unsigned_T = std::make_unsigned_t<T>;
181 auto map = [](T v) -> unsigned_T {
182 if constexpr(std::signed_integral<T>) {
183 constexpr int64_t offset = -static_cast<int64_t>(std::numeric_limits<T>::min());
184 return static_cast<unsigned_T>(static_cast<int64_t>(v) + offset);
185 } else {
186 return v;
187 }
188 };
189
190 const auto umin = map(min);
191 const auto umax = map(max);
192
193 auto mask = CT::Mask<unsigned_T>::set();
194 for(const T c : range) {
195 mask &= CT::Mask<unsigned_T>::is_within_range(map(c), umin, umax);
196 }
197 return mask.as_bool();
198}
199
200} // namespace detail
201
202/**
203 * Represents a polynomial with Trait::N coefficients of type Trait::T.
204 * The domain of the polynomial can be either Domain::Normal or Domain::NTT and
205 * this information is represented in the C++ type system.
206 *
207 * Polynomials may either own their storage of piggy-back on external storage
208 * when they are part of a PolynomialVector.
209 */
210template <crystals_trait Trait, Domain D = Domain::Normal>
212 private:
214 using T = typename Trait::T;
215
216 private:
217 // TODO: perhaps secure vector
218 std::vector<T> m_coeffs_storage;
219 std::span<T, Trait::N> m_coeffs;
220
221 private:
222 template <crystals_trait OtherTrait, Domain OtherD>
223 friend class Polynomial;
224
225 template <Domain To, template <typename, Domain> class StructureT, crystals_trait C, Domain From>
226 requires(To != From)
227 friend StructureT<C, To> detail::domain_cast(StructureT<C, From>&&);
228
229 /**
230 * This constructor is used to convert a Polynomial from one domain to another.
231 * The friend declarations above facilitate this.
232 */
233 template <Domain OtherD>
234 requires(D != OtherD)
235 explicit Polynomial(Polynomial<Trait, OtherD>&& other) noexcept :
236 m_coeffs_storage(std::move(other.m_coeffs_storage)),
237 m_coeffs(owns_storage() ? std::span<T, Trait::N>(m_coeffs_storage) : other.m_coeffs) {}
238
239 public:
240 // Workaround, because Xcode and NDK don't understand the
241 // `detail::domain_cast` friend declaration.
242 //
243 // TODO: Try to remove this and use the c'tor directly in
244 // `detail::domain_cast` after updating the compilers.
245 template <Domain OtherD>
246 requires(D != OtherD)
250
251 public:
252 Polynomial() : m_coeffs_storage(Trait::N), m_coeffs(m_coeffs_storage) { BOTAN_DEBUG_ASSERT(owns_storage()); }
253
254 explicit Polynomial(std::span<T, Trait::N> coeffs) : m_coeffs(coeffs) { BOTAN_DEBUG_ASSERT(!owns_storage()); }
255
256 Polynomial(const ThisPolynomial& other) = delete;
257
258 Polynomial(ThisPolynomial&& other) noexcept :
259 m_coeffs_storage(std::move(other.m_coeffs_storage)), m_coeffs(other.m_coeffs) {}
260
261 ThisPolynomial& operator=(const ThisPolynomial& other) = delete;
262
264 if(this != &other) {
266 m_coeffs_storage = std::move(other.m_coeffs_storage);
267 m_coeffs = std::span<T, Trait::N>(m_coeffs_storage);
268 }
269 return *this;
270 }
271
272 ~Polynomial() = default;
273
274 constexpr size_t size() const { return m_coeffs.size(); }
275
276 constexpr Domain domain() const noexcept { return D; }
277
279 ThisPolynomial res;
280 copy_mem(res.m_coeffs_storage, m_coeffs);
281 res.m_coeffs = std::span<T, Trait::N>(res.m_coeffs_storage);
283 return res;
284 }
285
286 /// @returns true if all coefficients are within the range [min, max]
287 constexpr bool ct_validate_value_range(T min, T max) const noexcept {
288 return detail::ct_all_within_range(coefficients(), min, max);
289 }
290
291 /// @returns the number of non-zero coefficients in the polynomial
292 constexpr size_t hamming_weight() const noexcept {
293 size_t weight = 0;
294 for(const auto c : m_coeffs) {
295 weight += (c != 0);
296 }
297 return weight;
298 }
299
300 std::span<T, Trait::N> coefficients() { return m_coeffs; }
301
302 std::span<const T, Trait::N> coefficients() const { return m_coeffs; }
303
304 T& operator[](size_t i) { return m_coeffs[i]; }
305
306 T operator[](size_t i) const { return m_coeffs[i]; }
307
308 decltype(auto) begin() { return m_coeffs.begin(); }
309
310 decltype(auto) begin() const { return m_coeffs.begin(); }
311
312 decltype(auto) end() { return m_coeffs.end(); }
313
314 decltype(auto) end() const { return m_coeffs.end(); }
315
316 constexpr bool owns_storage() const { return !m_coeffs_storage.empty(); }
317
319 Trait::barrett_reduce(m_coeffs);
320 return *this;
321 }
322
324 Trait::poly_cadd_q(m_coeffs);
325 return *this;
326 }
327
328 void _const_time_poison() const { CT::poison(m_coeffs); }
329
330 void _const_time_unpoison() const { CT::unpoison(m_coeffs); }
331
332 /**
333 * Adds two polynomials element-wise. Does not perform a reduction after the addition.
334 * Therefore this operation might cause an integer overflow.
335 */
336 decltype(auto) operator+=(const ThisPolynomial& other) {
337 Trait::poly_add(m_coeffs, m_coeffs, other.m_coeffs);
338 return *this;
339 }
340
341 /**
342 * Subtracts two polynomials element-wise. Does not perform a reduction after the subtraction.
343 * Therefore this operation might cause an integer underflow.
344 */
345 decltype(auto) operator-=(const ThisPolynomial& other) {
346 Trait::poly_sub(m_coeffs, m_coeffs, other.m_coeffs);
347 return *this;
348 }
349};
350
351template <crystals_trait Trait, Domain D = Domain::Normal>
353 private:
355 using T = typename Trait::T;
356
357 private:
358 std::vector<T> m_polys_storage;
359 std::vector<Polynomial<Trait, D>> m_vec;
360
361 private:
362 template <crystals_trait OtherTrait, Domain OtherD>
363 friend class PolynomialVector;
364
365 template <Domain To, template <typename, Domain> class StructureT, crystals_trait C, Domain From>
366 requires(To != From)
367 friend StructureT<C, To> detail::domain_cast(StructureT<C, From>&&);
368
369 /**
370 * This constructor is used to convert a PolynomialVector from one domain to another.
371 * The friend declarations above facilitate this.
372 */
373 template <Domain OtherD>
374 requires(D != OtherD)
375 explicit PolynomialVector(PolynomialVector<Trait, OtherD>&& other) noexcept :
376 m_polys_storage(std::move(other.m_polys_storage)) {
377 BOTAN_DEBUG_ASSERT(m_polys_storage.size() % Trait::N == 0);
378 const size_t vecsize = m_polys_storage.size() / Trait::N;
379 for(size_t i = 0; i < vecsize; ++i) {
380 m_vec.emplace_back(
381 Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
382 }
383 }
384
385 public:
386 // Workaround, because Xcode and NDK don't understand the
387 // `detail::domain_cast` friend declaration above.
388 //
389 // TODO: Try to remove this and use the c'tor directly in
390 // `detail::domain_cast` after updating the compilers.
391 template <Domain OtherD>
392 requires(D != OtherD)
396
397 public:
398 PolynomialVector(size_t vecsize) : m_polys_storage(vecsize * Trait::N) {
399 for(size_t i = 0; i < vecsize; ++i) {
400 m_vec.emplace_back(
401 Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
402 }
403 }
404
406 PolynomialVector(ThisPolynomialVector&& other) noexcept = default;
409 ~PolynomialVector() = default;
410
411 size_t size() const { return m_vec.size(); }
412
413 constexpr Domain domain() const noexcept { return D; }
414
417
418 // The default-constructed PolynomialVector has set up res.m_vec to
419 // point to res.m_polys_storage. Therefore we can just copy the data
420 // into res.m_polys_storage to fill the non-owning polynomials.
421 copy_mem(res.m_polys_storage, m_polys_storage);
422
423 return res;
424 }
425
426 /// @returns the number of non-zero coefficients in the polynomial vector
427 size_t hamming_weight() const noexcept {
428 size_t weight = 0;
429 for(const auto c : m_polys_storage) {
430 weight += (c != 0);
431 }
432 return weight;
433 }
434
435 /// @returns true if all coefficients are within the range [min, max]
436 constexpr bool ct_validate_value_range(T min, T max) const noexcept {
437 return detail::ct_all_within_range(coefficients(), min, max);
438 }
439
440 std::span<T> coefficients() { return m_polys_storage; }
441
442 std::span<const T> coefficients() const { return m_polys_storage; }
443
445 BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot add polynomial vectors of differing lengths");
446 for(size_t i = 0; i < m_vec.size(); ++i) {
447 Trait::poly_add(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
448 }
449 return *this;
450 }
451
453 BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot subtract polynomial vectors of differing lengths");
454 for(size_t i = 0; i < m_vec.size(); ++i) {
455 Trait::poly_sub(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
456 }
457 return *this;
458 }
459
461 for(auto& p : m_vec) {
462 Trait::barrett_reduce(p.coefficients());
463 }
464 return *this;
465 }
466
468 for(auto& v : m_vec) {
469 Trait::poly_cadd_q(v.coefficients());
470 }
471 return *this;
472 }
473
474 Polynomial<Trait, D>& operator[](size_t i) { return m_vec[i]; }
475
476 const Polynomial<Trait, D>& operator[](size_t i) const { return m_vec[i]; }
477
478 decltype(auto) begin() { return m_vec.begin(); }
479
480 decltype(auto) begin() const { return m_vec.begin(); }
481
482 decltype(auto) end() { return m_vec.end(); }
483
484 decltype(auto) end() const { return m_vec.end(); }
485
486 void _const_time_poison() const { CT::poison_range(m_vec); }
487
489};
490
491template <crystals_trait Trait>
493 private:
495
496 private:
497 std::vector<PolynomialVector<Trait, Domain::NTT>> m_mat;
498
499 public:
500 PolynomialMatrix(std::vector<PolynomialVector<Trait>> mat) : m_mat(std::move(mat)) {}
501
503 PolynomialMatrix(ThisPolynomialMatrix&& other) noexcept = default;
506 ~PolynomialMatrix() = default;
507
508 size_t size() const { return m_mat.size(); }
509
510 PolynomialMatrix(size_t rows, size_t cols) {
511 m_mat.reserve(rows);
512 for(size_t i = 0; i < rows; ++i) {
513 m_mat.emplace_back(cols);
514 }
515 }
516
517 PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) { return m_mat[i]; }
518
519 const PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) const { return m_mat[i]; }
520
521 decltype(auto) begin() { return m_mat.begin(); }
522
523 decltype(auto) begin() const { return m_mat.begin(); }
524
525 decltype(auto) end() { return m_mat.end(); }
526
527 decltype(auto) end() const { return m_mat.end(); }
528
529 void _const_time_poison() const { CT::poison_range(m_mat); }
530
532};
533
534namespace detail {
535
536template <crystals_trait Trait, Domain D>
538 for(auto& c : p) {
539 c = Trait::to_montgomery(c);
540 }
541}
542
543template <crystals_trait Trait>
547 BOTAN_ASSERT(a.size() == b.size(), "Dot product requires equally sized PolynomialVectors");
548 for(size_t i = 0; i < a.size(); ++i) {
549 out += a[i] * b[i];
550 }
551 out.reduce();
552}
553
554} // namespace detail
555
556template <crystals_trait Trait>
558 auto p_ntt = detail::domain_cast<Domain::NTT>(std::move(p));
559 Trait::ntt(p_ntt.coefficients());
560 return p_ntt;
561}
562
563template <crystals_trait Trait>
565 auto p = detail::domain_cast<Domain::Normal>(std::move(p_ntt));
566 Trait::inverse_ntt(p.coefficients());
567 return p;
568}
569
570template <crystals_trait Trait>
572 auto polyvec_ntt = detail::domain_cast<Domain::NTT>(std::move(polyvec));
573 for(auto& poly : polyvec_ntt) {
574 Trait::ntt(poly.coefficients());
575 }
576 return polyvec_ntt;
577}
578
579template <crystals_trait Trait>
581 auto polyvec = detail::domain_cast<Domain::Normal>(std::move(polyvec_ntt));
582 for(auto& poly : polyvec) {
583 Trait::inverse_ntt(poly.coefficients());
584 }
585 return polyvec;
586}
587
588template <crystals_trait Trait, Domain D>
593
594template <crystals_trait Trait, Domain D>
596 for(auto& p : polyvec) {
598 }
599 return polyvec;
600}
601
602template <crystals_trait Trait>
605 BOTAN_DEBUG_ASSERT(a.size() == b.size());
607 for(size_t i = 0; i < a.size(); ++i) {
608 Trait::poly_add(result[i].coefficients(), a[i].coefficients(), b[i].coefficients());
609 }
610 return result;
611}
612
613template <crystals_trait Trait>
617 for(size_t i = 0; i < mat.size(); ++i) {
618 Trait::polyvec_pointwise_acc_montgomery(result[i].coefficients(), mat[i].coefficients(), vec.coefficients());
619 }
620 return result;
621}
622
623template <crystals_trait Trait>
630
631template <crystals_trait Trait>
635 for(size_t i = 0; i < pv.size(); ++i) {
636 Trait::poly_pointwise_montgomery(result[i].coefficients(), p.coefficients(), pv[i].coefficients());
637 }
638 return result;
639}
640
641template <crystals_trait Trait>
645 Trait::poly_pointwise_montgomery(result.coefficients(), a.coefficients(), b.coefficients());
646 return result;
647}
648
649template <crystals_trait Trait>
650PolynomialVector<Trait, Domain::Normal> operator<<(const PolynomialVector<Trait, Domain::Normal>& pv, size_t shift) {
651 BOTAN_ASSERT_NOMSG(shift < sizeof(typename Trait::T) * 8);
652 PolynomialVector<Trait, Domain::Normal> result(pv.size());
653 for(size_t i = 0; i < pv.size(); ++i) {
654 for(size_t j = 0; j < Trait::N; ++j) {
655 result[i][j] = pv[i][j] << shift;
656 }
657 }
658 return result;
659}
660
661} // namespace Botan::CRYSTALS
662
663#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
PolynomialMatrix(size_t rows, size_t cols)
Definition pqcrystals.h:510
PolynomialVector< Trait, Domain::NTT > & operator[](size_t i)
Definition pqcrystals.h:517
PolynomialMatrix(ThisPolynomialMatrix &&other) noexcept=default
ThisPolynomialMatrix & operator=(const ThisPolynomialMatrix &other)=delete
decltype(auto) end() const
Definition pqcrystals.h:527
PolynomialMatrix(const ThisPolynomialMatrix &other)=delete
const PolynomialVector< Trait, Domain::NTT > & operator[](size_t i) const
Definition pqcrystals.h:519
ThisPolynomialMatrix & operator=(ThisPolynomialMatrix &&other) noexcept=default
PolynomialMatrix(std::vector< PolynomialVector< Trait > > mat)
Definition pqcrystals.h:500
decltype(auto) begin() const
Definition pqcrystals.h:523
ThisPolynomialVector & operator=(const ThisPolynomialVector &other)=delete
Polynomial< Trait, D > & operator[](size_t i)
Definition pqcrystals.h:474
std::span< const T > coefficients() const
Definition pqcrystals.h:442
ThisPolynomialVector & reduce()
Definition pqcrystals.h:460
constexpr Domain domain() const noexcept
Definition pqcrystals.h:413
ThisPolynomialVector & operator-=(const ThisPolynomialVector &other)
Definition pqcrystals.h:452
size_t hamming_weight() const noexcept
Definition pqcrystals.h:427
PolynomialVector(const ThisPolynomialVector &other)=delete
ThisPolynomialVector & operator=(ThisPolynomialVector &&other) noexcept=default
decltype(auto) begin() const
Definition pqcrystals.h:480
const Polynomial< Trait, D > & operator[](size_t i) const
Definition pqcrystals.h:476
ThisPolynomialVector clone() const
Definition pqcrystals.h:415
PolynomialVector(ThisPolynomialVector &&other) noexcept=default
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:436
ThisPolynomialVector & conditional_add_q()
Definition pqcrystals.h:467
decltype(auto) end() const
Definition pqcrystals.h:484
static PolynomialVector< Trait, D > from_domain_cast(PolynomialVector< Trait, OtherD > &&other)
Definition pqcrystals.h:393
ThisPolynomialVector & operator+=(const ThisPolynomialVector &other)
Definition pqcrystals.h:444
Polynomial(const ThisPolynomial &other)=delete
constexpr bool owns_storage() const
Definition pqcrystals.h:316
void _const_time_unpoison() const
Definition pqcrystals.h:330
ThisPolynomial & operator=(ThisPolynomial &&other) noexcept
Definition pqcrystals.h:263
T operator[](size_t i) const
Definition pqcrystals.h:306
Polynomial(std::span< T, Trait::N > coeffs)
Definition pqcrystals.h:254
Polynomial(ThisPolynomial &&other) noexcept
Definition pqcrystals.h:258
ThisPolynomial & conditional_add_q()
Definition pqcrystals.h:323
std::span< const T, Trait::N > coefficients() const
Definition pqcrystals.h:302
ThisPolynomial & operator=(const ThisPolynomial &other)=delete
constexpr size_t hamming_weight() const noexcept
Definition pqcrystals.h:292
static Polynomial< Trait, D > from_domain_cast(Polynomial< Trait, OtherD > &&p)
Definition pqcrystals.h:247
decltype(auto) end() const
Definition pqcrystals.h:314
std::span< T, Trait::N > coefficients()
Definition pqcrystals.h:300
constexpr size_t size() const
Definition pqcrystals.h:274
void _const_time_poison() const
Definition pqcrystals.h:328
constexpr Domain domain() const noexcept
Definition pqcrystals.h:276
ThisPolynomial & reduce()
Definition pqcrystals.h:318
ThisPolynomial clone() const
Definition pqcrystals.h:278
decltype(auto) begin() const
Definition pqcrystals.h:310
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:287
static constexpr void barrett_reduce(std::span< T, N > poly)
Definition pqcrystals.h:120
static constexpr T Q
Definition pqcrystals.h:53
static constexpr T to_montgomery(T a)
Definition pqcrystals.h:118
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:103
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:110
static constexpr T fqmul(T a, T b)
Definition pqcrystals.h:94
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:97
typename ConstantsT::T T
Definition pqcrystals.h:51
static constexpr size_t polys_in_polyvec(std::span< const T > polyvec)
Definition pqcrystals.h:79
static constexpr std::span< U, N > poly_in_polyvec(std::span< U > polyvec, size_t index)
Definition pqcrystals.h:87
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:127
static constexpr Mask< T > set()
Definition ct_utils.h:379
static constexpr Mask< T > expand_top_bit(T v)
Definition ct_utils.h:407
static constexpr Mask< T > is_within_range(T v, T l, T u)
Definition ct_utils.h:462
FE_25519 T
Definition ge.cpp:34
void dot_product(Polynomial< Trait, Domain::NTT > &out, const PolynomialVector< Trait, Domain::NTT > &a, const PolynomialVector< Trait, Domain::NTT > &b)
Definition pqcrystals.h:544
void montgomery(Polynomial< Trait, D > &p)
Definition pqcrystals.h:537
StructureT< Trait, To > domain_cast(StructureT< Trait, From > &&p)
Definition pqcrystals.h:161
Polynomial< Trait, D > montgomery(Polynomial< Trait, D > p)
Definition pqcrystals.h:589
PolynomialVector< Trait, Domain::NTT > operator*(const PolynomialMatrix< Trait > &mat, const PolynomialVector< Trait, Domain::NTT > &vec)
Definition pqcrystals.h:614
PolynomialVector< Trait, Domain::Normal > operator+(const PolynomialVector< Trait, Domain::Normal > &a, const PolynomialVector< Trait, Domain::Normal > &b)
Definition pqcrystals.h:603
Polynomial< Trait, Domain::NTT > ntt(Polynomial< Trait, Domain::Normal > p)
Definition pqcrystals.h:557
PolynomialVector< Trait, Domain::Normal > operator<<(const PolynomialVector< Trait, Domain::Normal > &pv, size_t shift)
Definition pqcrystals.h:650
Polynomial< Trait, Domain::Normal > inverse_ntt(Polynomial< Trait, Domain::NTT > p_ntt)
Definition pqcrystals.h:564
constexpr void unpoison_range(R &&r)
Definition ct_utils.h:183
constexpr void poison_range(R &&r)
Definition ct_utils.h:175
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:64
constexpr void poison(const T *p, size_t n)
Definition ct_utils.h:53
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)
const SIMD_8x32 & b
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120