/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 |