Coverage Report

Created: 2024-11-29 06:10

/src/botan/build/include/internal/botan/internal/pqcrystals.h
Line
Count
Source (jump to first uncovered line)
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
26
namespace Botan::CRYSTALS {
27
28
enum class Domain { Normal, NTT };
29
30
template <typename T>
31
concept crystals_constants =
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
 */
48
template <crystals_constants ConstantsT, typename DerivedT>
49
class Trait_Base {
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:
56
      using T2 = next_longer_int_t<T>;
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
0
      static constexpr size_t polys_in_polyvec(std::span<const T> polyvec) {
80
0
         BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
81
0
         return polyvec.size() / N;
82
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::polys_in_polyvec(std::__1::span<short const, 18446744073709551615ul>)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::polys_in_polyvec(std::__1::span<int const, 18446744073709551615ul>)
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
0
      static constexpr std::span<U, N> poly_in_polyvec(std::span<U> polyvec, size_t index) {
88
0
         BOTAN_DEBUG_ASSERT(polyvec.size() % N == 0);
89
0
         BOTAN_DEBUG_ASSERT(polyvec.size() / N > index);
90
0
         auto polyspan = polyvec.subspan(index * N, N);
91
0
         return std::span<U, N>{polyspan.data(), polyspan.size()};
92
0
      }
Unexecuted instantiation: _ZN5Botan8CRYSTALS10Trait_BaseINS_14KyberConstantsENS_15KyberPolyTraitsEE15poly_in_polyvecIKsQoosr3stdE7same_asINT_1TETL0__Esr3stdE7same_asIKS8_S9_EEENSt3__14spanIS7_Lm256EEENSC_IS7_Lm18446744073709551615EEEm
Unexecuted instantiation: _ZN5Botan8CRYSTALS10Trait_BaseINS_18DilithiumConstantsENS_19DilithiumPolyTraitsEE15poly_in_polyvecIKiQoosr3stdE7same_asINT_1TETL0__Esr3stdE7same_asIKS8_S9_EEENSt3__14spanIS7_Lm256EEENSC_IS7_Lm18446744073709551615EEEm
93
94
0
      static constexpr T fqmul(T a, T b) { return DerivedT::montgomery_reduce_coefficient(static_cast<T2>(a) * b); }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::fqmul(short, short)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::fqmul(int, int)
95
96
   public:
97
0
      static constexpr void poly_add(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
98
0
         for(size_t i = 0; i < N; ++i) {
99
0
            result[i] = lhs[i] + rhs[i];
100
0
         }
101
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::poly_add(std::__1::span<short, 256ul>, std::__1::span<short const, 256ul>, std::__1::span<short const, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::poly_add(std::__1::span<int, 256ul>, std::__1::span<int const, 256ul>, std::__1::span<int const, 256ul>)
102
103
0
      static constexpr void poly_sub(std::span<T, N> result, std::span<const T, N> lhs, std::span<const T, N> rhs) {
104
0
         for(size_t i = 0; i < N; ++i) {
105
0
            result[i] = lhs[i] - rhs[i];
106
0
         }
107
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::poly_sub(std::__1::span<short, 256ul>, std::__1::span<short const, 256ul>, std::__1::span<short const, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::poly_sub(std::__1::span<int, 256ul>, std::__1::span<int const, 256ul>, std::__1::span<int const, 256ul>)
108
109
      /// Adds Q if the coefficient is negative.
110
0
      static constexpr void poly_cadd_q(std::span<T, N> coeffs) {
111
0
         for(auto& coeff : coeffs) {
112
0
            using unsigned_T = std::make_unsigned_t<T>;
113
0
            const auto is_negative = CT::Mask<unsigned_T>::expand_top_bit(static_cast<unsigned_T>(coeff));
114
0
            coeff += is_negative.if_set_return(Q);
115
0
         }
116
0
      }
117
118
0
      static constexpr T to_montgomery(T a) { return fqmul(a, MONTY_SQUARED); }
119
120
0
      constexpr static void barrett_reduce(std::span<T, N> poly) {
121
0
         for(auto& coeff : poly) {
122
0
            coeff = DerivedT::barrett_reduce_coefficient(coeff);
123
0
         }
124
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::barrett_reduce(std::__1::span<short, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::barrett_reduce(std::__1::span<int, 256ul>)
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
0
                                                             std::span<const T> v) {
130
0
         clear_mem(w);
131
0
         std::array<T, N> t;
132
0
         for(size_t i = 0; i < polys_in_polyvec(u); ++i) {
133
0
            DerivedT::poly_pointwise_montgomery(t, poly_in_polyvec(u, i), poly_in_polyvec(v, i));
134
0
            poly_add(w, w, t);
135
0
         }
136
0
         barrett_reduce(w);
137
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::KyberConstants, Botan::KyberPolyTraits>::polyvec_pointwise_acc_montgomery(std::__1::span<short, 256ul>, std::__1::span<short const, 18446744073709551615ul>, std::__1::span<short const, 18446744073709551615ul>)
Unexecuted instantiation: Botan::CRYSTALS::Trait_Base<Botan::DilithiumConstants, Botan::DilithiumPolyTraits>::polyvec_pointwise_acc_montgomery(std::__1::span<int, 256ul>, std::__1::span<int const, 18446744073709551615ul>, std::__1::span<int const, 18446744073709551615ul>)
138
};
139
140
template <typename T>
141
concept crystals_trait =
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
154
namespace detail {
155
156
/**
157
 * Converts polynomials or polynomial vectors from one domain to another.
158
 */
159
template <Domain To, template <typename, Domain> class StructureT, crystals_trait Trait, Domain From>
160
   requires(To != From)
161
0
StructureT<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
0
   return StructureT<Trait, To>::from_domain_cast(std::move(p));
166
0
}
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE1ETtTyTnS3_ENS0_16PolynomialVectorETkNS0_14crystals_traitENS_15KyberPolyTraitsELS3_0EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE0ETtTyTnS3_ENS0_16PolynomialVectorETkNS0_14crystals_traitENS_15KyberPolyTraitsELS3_1EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE0ETtTyTnS3_ENS0_10PolynomialETkNS0_14crystals_traitENS_15KyberPolyTraitsELS3_1EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE1ETtTyTnS3_ENS0_16PolynomialVectorETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELS3_0EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE1ETtTyTnS3_ENS0_10PolynomialETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELS3_0EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
Unexecuted instantiation: _ZN5Botan8CRYSTALS6detail11domain_castILNS0_6DomainE0ETtTyTnS3_ENS0_16PolynomialVectorETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELS3_1EQneT_T2_EET0_IT1_XT_EEOS6_IS7_XT2_EE
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
 */
174
template <std::integral T, size_t N = std::dynamic_extent>
175
constexpr static bool ct_all_within_range(std::span<const T, N> range, T min, T max)
176
   requires(sizeof(T) <= 4)
177
0
{
178
0
   BOTAN_DEBUG_ASSERT(min < max);
179
180
0
   using unsigned_T = std::make_unsigned_t<T>;
181
0
   auto map = [](T v) -> unsigned_T {
182
0
      if constexpr(std::signed_integral<T>) {
183
0
         constexpr int64_t offset = -static_cast<int64_t>(std::numeric_limits<T>::min());
184
0
         return static_cast<unsigned_T>(static_cast<int64_t>(v) + offset);
185
      } else {
186
         return v;
187
      }
188
0
   };
Unexecuted instantiation: kyber_algos.cpp:_ZZN5Botan8CRYSTALS6detailL19ct_all_within_rangeITkNSt3__18integralEsLm256EEEbNS3_4spanIKT_XT0_EEES5_S5_QlestS5_Li4EENKUlsE_clEs
Unexecuted instantiation: dilithium_algos.cpp:_ZZN5Botan8CRYSTALS6detailL19ct_all_within_rangeITkNSt3__18integralEiLm256EEEbNS3_4spanIKT_XT0_EEES5_S5_QlestS5_Li4EENKUliE_clEi
189
190
0
   const auto umin = map(min);
191
0
   const auto umax = map(max);
192
193
0
   auto mask = CT::Mask<unsigned_T>::set();
194
0
   for(const T c : range) {
195
0
      mask &= CT::Mask<unsigned_T>::is_within_range(map(c), umin, umax);
196
0
   }
197
0
   return mask.as_bool();
198
0
}
Unexecuted instantiation: kyber_algos.cpp:_ZN5Botan8CRYSTALS6detailL19ct_all_within_rangeITkNSt3__18integralEsLm256EEEbNS3_4spanIKT_XT0_EEES5_S5_QlestS5_Li4E
Unexecuted instantiation: dilithium_algos.cpp:_ZN5Botan8CRYSTALS6detailL19ct_all_within_rangeITkNSt3__18integralEiLm256EEEbNS3_4spanIKT_XT0_EEES5_S5_QlestS5_Li4E
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
 */
210
template <crystals_trait Trait, Domain D = Domain::Normal>
211
class Polynomial {
212
   private:
213
      using ThisPolynomial = Polynomial<Trait, D>;
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
0
            m_coeffs_storage(std::move(other.m_coeffs_storage)),
237
0
            m_coeffs(owns_storage() ? std::span<T, Trait::N>(m_coeffs_storage) : other.m_coeffs) {}
Unexecuted instantiation: _ZN5Botan8CRYSTALS10PolynomialINS_15KyberPolyTraitsELNS0_6DomainE0EEC2ILS3_1EQneT0_TL0__EEONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS10PolynomialINS_19DilithiumPolyTraitsELNS0_6DomainE1EEC2ILS3_0EQneT0_TL0__EEONS1_IS2_XT_EEE
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)
247
0
      static Polynomial<Trait, D> from_domain_cast(Polynomial<Trait, OtherD>&& p) {
248
0
         return Polynomial<Trait, D>(std::move(p));
249
0
      }
Unexecuted instantiation: _ZN5Botan8CRYSTALS10PolynomialINS_15KyberPolyTraitsELNS0_6DomainE0EE16from_domain_castILS3_1EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS10PolynomialINS_19DilithiumPolyTraitsELNS0_6DomainE1EE16from_domain_castILS3_0EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
250
251
   public:
252
0
      Polynomial() : m_coeffs_storage(Trait::N), m_coeffs(m_coeffs_storage) { BOTAN_DEBUG_ASSERT(owns_storage()); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::Polynomial()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial()
253
254
0
      explicit Polynomial(std::span<T, Trait::N> coeffs) : m_coeffs(coeffs) { BOTAN_DEBUG_ASSERT(!owns_storage()); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::Polynomial(std::__1::span<short, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial(std::__1::span<short, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::Polynomial(std::__1::span<int, 256ul>)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial(std::__1::span<int, 256ul>)
255
256
      Polynomial(const ThisPolynomial& other) = delete;
257
258
      Polynomial(ThisPolynomial&& other) noexcept :
259
0
            m_coeffs_storage(std::move(other.m_coeffs_storage)), m_coeffs(other.m_coeffs) {}
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::Polynomial(Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>&&)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial(Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>&&)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::Polynomial(Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>&&)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::Polynomial(Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>&&)
260
261
      ThisPolynomial& operator=(const ThisPolynomial& other) = delete;
262
263
      ThisPolynomial& operator=(ThisPolynomial&& other) noexcept {
264
         if(this != &other) {
265
            BOTAN_ASSERT_NOMSG(owns_storage());
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
0
      ~Polynomial() = default;
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::~Polynomial()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::~Polynomial()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::~Polynomial()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::~Polynomial()
273
274
0
      constexpr size_t size() const { return m_coeffs.size(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::size() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::size() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::size() const
275
276
      constexpr Domain domain() const noexcept { return D; }
277
278
      ThisPolynomial clone() const {
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);
282
         BOTAN_DEBUG_ASSERT(res.owns_storage());
283
         return res;
284
      }
285
286
      /// @returns true if all coefficients are within the range [min, max]
287
0
      constexpr bool ct_validate_value_range(T min, T max) const noexcept {
288
0
         return detail::ct_all_within_range(coefficients(), min, max);
289
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::ct_validate_value_range(short, short) const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::ct_validate_value_range(int, int) const
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
0
      std::span<T, Trait::N> coefficients() { return m_coeffs; }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::coefficients()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::coefficients()
301
302
0
      std::span<const T, Trait::N> coefficients() const { return m_coeffs; }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::coefficients() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::coefficients() const
303
304
0
      T& operator[](size_t i) { return m_coeffs[i]; }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long)
305
306
0
      T operator[](size_t i) const { return m_coeffs[i]; }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long) const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long) const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long) const
307
308
0
      decltype(auto) begin() { return m_coeffs.begin(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::begin()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::begin()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::begin()
309
310
0
      decltype(auto) begin() const { return m_coeffs.begin(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::begin() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::begin() const
311
312
0
      decltype(auto) end() { return m_coeffs.end(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::end()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::end()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::end()
313
314
0
      decltype(auto) end() const { return m_coeffs.end(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::end() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::end() const
315
316
0
      constexpr bool owns_storage() const { return !m_coeffs_storage.empty(); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::owns_storage() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::owns_storage() const
317
318
0
      ThisPolynomial& reduce() {
319
0
         Trait::barrett_reduce(m_coeffs);
320
0
         return *this;
321
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::reduce()
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::reduce()
322
323
      ThisPolynomial& conditional_add_q() {
324
         Trait::poly_cadd_q(m_coeffs);
325
         return *this;
326
      }
327
328
0
      void _const_time_poison() const { CT::poison(m_coeffs); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::_const_time_poison() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::_const_time_poison() const
329
330
0
      void _const_time_unpoison() const { CT::unpoison(m_coeffs); }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::_const_time_unpoison() const
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::_const_time_unpoison() const
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
0
      decltype(auto) operator+=(const ThisPolynomial& other) {
337
0
         Trait::poly_add(m_coeffs, m_coeffs, other.m_coeffs);
338
0
         return *this;
339
0
      }
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::operator+=(Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0> const&)
Unexecuted instantiation: Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator+=(Botan::CRYSTALS::Polynomial<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1> const&)
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
0
      decltype(auto) operator-=(const ThisPolynomial& other) {
346
0
         Trait::poly_sub(m_coeffs, m_coeffs, other.m_coeffs);
347
0
         return *this;
348
0
      }
349
};
350
351
template <crystals_trait Trait, Domain D = Domain::Normal>
352
class PolynomialVector {
353
   private:
354
      using ThisPolynomialVector = PolynomialVector<Trait, D>;
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
0
            m_polys_storage(std::move(other.m_polys_storage)) {
377
0
         BOTAN_DEBUG_ASSERT(m_polys_storage.size() % Trait::N == 0);
378
0
         const size_t vecsize = m_polys_storage.size() / Trait::N;
379
0
         for(size_t i = 0; i < vecsize; ++i) {
380
0
            m_vec.emplace_back(
381
0
               Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
382
0
         }
383
0
      }
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_15KyberPolyTraitsELNS0_6DomainE1EEC2ILS3_0EQneT0_TL0__EEONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_15KyberPolyTraitsELNS0_6DomainE0EEC2ILS3_1EQneT0_TL0__EEONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_19DilithiumPolyTraitsELNS0_6DomainE1EEC2ILS3_0EQneT0_TL0__EEONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_19DilithiumPolyTraitsELNS0_6DomainE0EEC2ILS3_1EQneT0_TL0__EEONS1_IS2_XT_EEE
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)
393
0
      static PolynomialVector<Trait, D> from_domain_cast(PolynomialVector<Trait, OtherD>&& other) {
394
0
         return PolynomialVector<Trait, D>(std::move(other));
395
0
      }
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_15KyberPolyTraitsELNS0_6DomainE1EE16from_domain_castILS3_0EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_15KyberPolyTraitsELNS0_6DomainE0EE16from_domain_castILS3_1EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_19DilithiumPolyTraitsELNS0_6DomainE1EE16from_domain_castILS3_0EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS16PolynomialVectorINS_19DilithiumPolyTraitsELNS0_6DomainE0EE16from_domain_castILS3_1EQneT0_TL0__EES4_ONS1_IS2_XT_EEE
396
397
   public:
398
0
      PolynomialVector(size_t vecsize) : m_polys_storage(vecsize * Trait::N) {
399
0
         for(size_t i = 0; i < vecsize; ++i) {
400
0
            m_vec.emplace_back(
401
0
               Polynomial<Trait, D>(std::span{m_polys_storage}.subspan(i * Trait::N).template first<Trait::N>()));
402
0
         }
403
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::PolynomialVector(unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::PolynomialVector(unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::PolynomialVector(unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::PolynomialVector(unsigned long)
404
405
      PolynomialVector(const ThisPolynomialVector& other) = delete;
406
0
      PolynomialVector(ThisPolynomialVector&& other) noexcept = default;
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::PolynomialVector(Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>&&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::PolynomialVector(Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>&&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::PolynomialVector(Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>&&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::PolynomialVector(Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>&&)
407
      ThisPolynomialVector& operator=(const ThisPolynomialVector& other) = delete;
408
      ThisPolynomialVector& operator=(ThisPolynomialVector&& other) noexcept = default;
409
0
      ~PolynomialVector() = default;
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::~PolynomialVector()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::~PolynomialVector()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::~PolynomialVector()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::~PolynomialVector()
410
411
0
      size_t size() const { return m_vec.size(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::size() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::size() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::size() const
412
413
      constexpr Domain domain() const noexcept { return D; }
414
415
0
      ThisPolynomialVector clone() const {
416
0
         ThisPolynomialVector res(size());
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
0
         copy_mem(res.m_polys_storage, m_polys_storage);
422
423
0
         return res;
424
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::clone() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::clone() const
425
426
      /// @returns the number of non-zero coefficients in the polynomial vector
427
0
      size_t hamming_weight() const noexcept {
428
0
         size_t weight = 0;
429
0
         for(const auto c : m_polys_storage) {
430
0
            weight += (c != 0);
431
0
         }
432
0
         return weight;
433
0
      }
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
0
      std::span<const T> coefficients() const { return m_polys_storage; }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::coefficients() const
443
444
0
      ThisPolynomialVector& operator+=(const ThisPolynomialVector& other) {
445
0
         BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot add polynomial vectors of differing lengths");
446
0
         for(size_t i = 0; i < m_vec.size(); ++i) {
447
0
            Trait::poly_add(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
448
0
         }
449
0
         return *this;
450
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator+=(Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1> const&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::operator+=(Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0> const&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator+=(Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0> const&)
451
452
0
      ThisPolynomialVector& operator-=(const ThisPolynomialVector& other) {
453
0
         BOTAN_ASSERT(m_vec.size() == other.m_vec.size(), "cannot subtract polynomial vectors of differing lengths");
454
0
         for(size_t i = 0; i < m_vec.size(); ++i) {
455
0
            Trait::poly_sub(m_vec[i].coefficients(), m_vec[i].coefficients(), other.m_vec[i].coefficients());
456
0
         }
457
0
         return *this;
458
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::operator-=(Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1> const&)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator-=(Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0> const&)
459
460
0
      ThisPolynomialVector& reduce() {
461
0
         for(auto& p : m_vec) {
462
0
            Trait::barrett_reduce(p.coefficients());
463
0
         }
464
0
         return *this;
465
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::reduce()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::reduce()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::reduce()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::reduce()
466
467
0
      ThisPolynomialVector& conditional_add_q() {
468
0
         for(auto& v : m_vec) {
469
0
            Trait::poly_cadd_q(v.coefficients());
470
0
         }
471
0
         return *this;
472
0
      }
473
474
0
      Polynomial<Trait, D>& operator[](size_t i) { return m_vec[i]; }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long)
475
476
0
      const Polynomial<Trait, D>& operator[](size_t i) const { return m_vec[i]; }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long) const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::operator[](unsigned long) const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::operator[](unsigned long) const
477
478
0
      decltype(auto) begin() { return m_vec.begin(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::begin()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::begin()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::begin()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::begin()
479
480
0
      decltype(auto) begin() const { return m_vec.begin(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::begin() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::begin() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::begin() const
481
482
0
      decltype(auto) end() { return m_vec.end(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::end()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::end()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)1>::end()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::end()
483
484
0
      decltype(auto) end() const { return m_vec.end(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::end() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)0>::end() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::end() const
485
486
0
      void _const_time_poison() const { CT::poison_range(m_vec); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::_const_time_poison() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::_const_time_poison() const
487
488
0
      void _const_time_unpoison() const { CT::unpoison_range(m_vec); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::KyberPolyTraits, (Botan::CRYSTALS::Domain)1>::_const_time_unpoison() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialVector<Botan::DilithiumPolyTraits, (Botan::CRYSTALS::Domain)0>::_const_time_unpoison() const
489
};
490
491
template <crystals_trait Trait>
492
class PolynomialMatrix {
493
   private:
494
      using ThisPolynomialMatrix = PolynomialMatrix<Trait>;
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
502
      PolynomialMatrix(const ThisPolynomialMatrix& other) = delete;
503
      PolynomialMatrix(ThisPolynomialMatrix&& other) noexcept = default;
504
      ThisPolynomialMatrix& operator=(const ThisPolynomialMatrix& other) = delete;
505
      ThisPolynomialMatrix& operator=(ThisPolynomialMatrix&& other) noexcept = default;
506
0
      ~PolynomialMatrix() = default;
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::KyberPolyTraits>::~PolynomialMatrix()
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::DilithiumPolyTraits>::~PolynomialMatrix()
507
508
0
      size_t size() const { return m_mat.size(); }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::KyberPolyTraits>::size() const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::DilithiumPolyTraits>::size() const
509
510
0
      PolynomialMatrix(size_t rows, size_t cols) {
511
0
         m_mat.reserve(rows);
512
0
         for(size_t i = 0; i < rows; ++i) {
513
0
            m_mat.emplace_back(cols);
514
0
         }
515
0
      }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::KyberPolyTraits>::PolynomialMatrix(unsigned long, unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::DilithiumPolyTraits>::PolynomialMatrix(unsigned long, unsigned long)
516
517
0
      PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) { return m_mat[i]; }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::KyberPolyTraits>::operator[](unsigned long)
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::DilithiumPolyTraits>::operator[](unsigned long)
518
519
0
      const PolynomialVector<Trait, Domain::NTT>& operator[](size_t i) const { return m_mat[i]; }
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::KyberPolyTraits>::operator[](unsigned long) const
Unexecuted instantiation: Botan::CRYSTALS::PolynomialMatrix<Botan::DilithiumPolyTraits>::operator[](unsigned long) const
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
531
      void _const_time_unpoison() const { CT::unpoison_range(m_mat); }
532
};
533
534
namespace detail {
535
536
template <crystals_trait Trait, Domain D>
537
0
void montgomery(Polynomial<Trait, D>& p) {
538
0
   for(auto& c : p) {
539
0
      c = Trait::to_montgomery(c);
540
0
   }
541
0
}
542
543
template <crystals_trait Trait>
544
void dot_product(Polynomial<Trait, Domain::NTT>& out,
545
                 const PolynomialVector<Trait, Domain::NTT>& a,
546
0
                 const PolynomialVector<Trait, Domain::NTT>& b) {
547
0
   BOTAN_ASSERT(a.size() == b.size(), "Dot product requires equally sized PolynomialVectors");
548
0
   for(size_t i = 0; i < a.size(); ++i) {
549
0
      out += a[i] * b[i];
550
0
   }
551
0
   out.reduce();
552
0
}
553
554
}  // namespace detail
555
556
template <crystals_trait Trait>
557
0
Polynomial<Trait, Domain::NTT> ntt(Polynomial<Trait, Domain::Normal> p) {
558
0
   auto p_ntt = detail::domain_cast<Domain::NTT>(std::move(p));
559
0
   Trait::ntt(p_ntt.coefficients());
560
0
   return p_ntt;
561
0
}
562
563
template <crystals_trait Trait>
564
0
Polynomial<Trait, Domain::Normal> inverse_ntt(Polynomial<Trait, Domain::NTT> p_ntt) {
565
0
   auto p = detail::domain_cast<Domain::Normal>(std::move(p_ntt));
566
0
   Trait::inverse_ntt(p.coefficients());
567
0
   return p;
568
0
}
569
570
template <crystals_trait Trait>
571
0
PolynomialVector<Trait, Domain::NTT> ntt(PolynomialVector<Trait, Domain::Normal> polyvec) {
572
0
   auto polyvec_ntt = detail::domain_cast<Domain::NTT>(std::move(polyvec));
573
0
   for(auto& poly : polyvec_ntt) {
574
0
      Trait::ntt(poly.coefficients());
575
0
   }
576
0
   return polyvec_ntt;
577
0
}
Unexecuted instantiation: _ZN5Botan8CRYSTALS3nttITkNS0_14crystals_traitENS_15KyberPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE1EEENS3_IS4_LS5_0EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS3nttITkNS0_14crystals_traitENS_19DilithiumPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE1EEENS3_IS4_LS5_0EEE
578
579
template <crystals_trait Trait>
580
0
PolynomialVector<Trait, Domain::Normal> inverse_ntt(PolynomialVector<Trait, Domain::NTT> polyvec_ntt) {
581
0
   auto polyvec = detail::domain_cast<Domain::Normal>(std::move(polyvec_ntt));
582
0
   for(auto& poly : polyvec) {
583
0
      Trait::inverse_ntt(poly.coefficients());
584
0
   }
585
0
   return polyvec;
586
0
}
Unexecuted instantiation: _ZN5Botan8CRYSTALS11inverse_nttITkNS0_14crystals_traitENS_15KyberPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE0EEENS3_IS4_LS5_1EEE
Unexecuted instantiation: _ZN5Botan8CRYSTALS11inverse_nttITkNS0_14crystals_traitENS_19DilithiumPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE0EEENS3_IS4_LS5_1EEE
587
588
template <crystals_trait Trait, Domain D>
589
Polynomial<Trait, D> montgomery(Polynomial<Trait, D> p) {
590
   detail::montgomery(p);
591
   return p;
592
}
593
594
template <crystals_trait Trait, Domain D>
595
0
PolynomialVector<Trait, D> montgomery(PolynomialVector<Trait, D> polyvec) {
596
0
   for(auto& p : polyvec) {
597
0
      detail::montgomery(p);
598
0
   }
599
0
   return polyvec;
600
0
}
601
602
template <crystals_trait Trait>
603
PolynomialVector<Trait, Domain::Normal> operator+(const PolynomialVector<Trait, Domain::Normal>& a,
604
0
                                                  const PolynomialVector<Trait, Domain::Normal>& b) {
605
0
   BOTAN_DEBUG_ASSERT(a.size() == b.size());
606
0
   PolynomialVector<Trait, Domain::Normal> result(a.size());
607
0
   for(size_t i = 0; i < a.size(); ++i) {
608
0
      Trait::poly_add(result[i].coefficients(), a[i].coefficients(), b[i].coefficients());
609
0
   }
610
0
   return result;
611
0
}
612
613
template <crystals_trait Trait>
614
PolynomialVector<Trait, Domain::NTT> operator*(const PolynomialMatrix<Trait>& mat,
615
0
                                               const PolynomialVector<Trait, Domain::NTT>& vec) {
616
0
   PolynomialVector<Trait, Domain::NTT> result(mat.size());
617
0
   for(size_t i = 0; i < mat.size(); ++i) {
618
0
      Trait::polyvec_pointwise_acc_montgomery(result[i].coefficients(), mat[i].coefficients(), vec.coefficients());
619
0
   }
620
0
   return result;
621
0
}
Unexecuted instantiation: _ZN5Botan8CRYSTALSmlITkNS0_14crystals_traitENS_15KyberPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE1EEERKNS0_16PolynomialMatrixIS4_EERKS6_
Unexecuted instantiation: _ZN5Botan8CRYSTALSmlITkNS0_14crystals_traitENS_19DilithiumPolyTraitsEEENS0_16PolynomialVectorIT_LNS0_6DomainE1EEERKNS0_16PolynomialMatrixIS4_EERKS6_
622
623
template <crystals_trait Trait>
624
Polynomial<Trait, Domain::NTT> operator*(const PolynomialVector<Trait, Domain::NTT>& a,
625
0
                                         const PolynomialVector<Trait, Domain::NTT>& b) {
626
0
   Polynomial<Trait, Domain::NTT> result;
627
0
   detail::dot_product(result, a, b);
628
0
   return result;
629
0
}
630
631
template <crystals_trait Trait>
632
PolynomialVector<Trait, Domain::NTT> operator*(const Polynomial<Trait, Domain::NTT>& p,
633
0
                                               const PolynomialVector<Trait, Domain::NTT>& pv) {
634
0
   PolynomialVector<Trait, Domain::NTT> result(pv.size());
635
0
   for(size_t i = 0; i < pv.size(); ++i) {
636
0
      Trait::poly_pointwise_montgomery(result[i].coefficients(), p.coefficients(), pv[i].coefficients());
637
0
   }
638
0
   return result;
639
0
}
640
641
template <crystals_trait Trait>
642
Polynomial<Trait, Domain::NTT> operator*(const Polynomial<Trait, Domain::NTT>& a,
643
0
                                         const Polynomial<Trait, Domain::NTT>& b) {
644
0
   Polynomial<Trait, Domain::NTT> result;
645
0
   Trait::poly_pointwise_montgomery(result.coefficients(), a.coefficients(), b.coefficients());
646
0
   return result;
647
0
}
648
649
template <crystals_trait Trait>
650
0
PolynomialVector<Trait, Domain::Normal> operator<<(const PolynomialVector<Trait, Domain::Normal>& pv, size_t shift) {
651
0
   BOTAN_ASSERT_NOMSG(shift < sizeof(typename Trait::T) * 8);
652
0
   PolynomialVector<Trait, Domain::Normal> result(pv.size());
653
0
   for(size_t i = 0; i < pv.size(); ++i) {
654
0
      for(size_t j = 0; j < Trait::N; ++j) {
655
0
         result[i][j] = pv[i][j] << shift;
656
0
      }
657
0
   }
658
0
   return result;
659
0
}
660
661
}  // namespace Botan::CRYSTALS
662
663
#endif