Botan 3.6.0
Crypto and TLS for C&
kyber_polynomial.h
Go to the documentation of this file.
1/*
2 * Crystals Kyber Polynomial Adapter
3 *
4 * (C) 2021-2024 Jack Lloyd
5 * (C) 2021-2022 Manuel Glaser and Michael Boric, Rohde & Schwarz Cybersecurity
6 * (C) 2021-2022 René Meusel and Hannes Rantzsch, neXenio GmbH
7 * (C) 2024 René Meusel, Rohde & Schwarz Cybersecurity
8 *
9 * Botan is released under the Simplified BSD License (see license.txt)
10 */
11
12#ifndef BOTAN_KYBER_POLYNOMIAL_H_
13#define BOTAN_KYBER_POLYNOMIAL_H_
14
15#include <botan/kyber.h>
16#include <botan/mem_ops.h>
17#include <botan/internal/kyber_constants.h>
18#include <botan/internal/pqcrystals.h>
19#include <botan/internal/pqcrystals_helpers.h>
20
21namespace Botan {
22
23class Kyber_Symmetric_Primitives;
24
25class KyberPolyTraits final : public CRYSTALS::Trait_Base<KyberConstants, KyberPolyTraits> {
26 private:
28
29 constexpr static T montgomery_reduce_coefficient(T2 a) {
30 const T u = static_cast<T>(a) * Q_inverse;
31 auto t = static_cast<T2>(u) * Q;
32 t = a - t;
33 t >>= sizeof(T) * 8;
34 return static_cast<T>(t);
35 }
36
37 constexpr static T barrett_reduce_coefficient(T a) {
38 constexpr T2 v = ((1U << 26) + Q / 2) / Q;
39 const T t = (v * a >> 26) * Q;
40 return a - t;
41 }
42
43 public:
44 /**
45 * NIST FIPS 203, Algorithm 9 (NTT)
46 *
47 * Produces the result of the NTT transformation without any montgomery
48 * factors in the coefficients. Zetas are pre-computed and stored in the
49 * zetas array. The zeta values contain the montgomery factor 2^16 mod q.
50 */
51 constexpr static void ntt(std::span<T, N> p) {
52 for(size_t len = N / 2, i = 0; len >= 2; len /= 2) {
53 for(size_t start = 0, j = 0; start < N; start = j + len) {
54 const auto zeta = zetas[++i];
55 for(j = start; j < start + len; ++j) {
56 const auto t = fqmul(zeta, p[j + len]);
57 p[j + len] = p[j] - t;
58 p[j] = p[j] + t;
59 }
60 }
61 }
62
64 }
65
66 /**
67 * NIST FIPS 203, Algorithm 10 (NTT^-1)
68 *
69 * The output is effectively multiplied by the montgomery parameter 2^16
70 * mod q so that the input factors 2^(-16) mod q are eliminated. Note
71 * that factors 2^(-16) mod q are introduced by multiplication and
72 * reduction of values not in montgomery domain.
73 *
74 * Produces the result of the inverse NTT transformation with a montgomery
75 * factor of (2^16 mod q) added (!). See above.
76 */
77 static constexpr void inverse_ntt(std::span<T, N> p) {
78 for(size_t len = 2, i = 127; len <= N / 2; len *= 2) {
79 for(size_t start = 0, j = 0; start < N; start = j + len) {
80 const auto zeta = zetas[i--];
81 for(j = start; j < start + len; ++j) {
82 const auto t = p[j];
83 p[j] = barrett_reduce_coefficient(t + p[j + len]);
84 p[j + len] = fqmul(zeta, p[j + len] - t);
85 }
86 }
87 }
88
89 for(auto& c : p) {
91 }
92 }
93
94 /**
95 * NIST FIPS 203, Algorithms 11 (MultiplyNTTs) and 12 (BaseCaseMultiply)
96 *
97 * The result contains factors of 2^(-16) mod q (i.e. the inverse montgomery factor).
98 * This factor is eliminated by the inverse NTT transformation, see above.
99 */
100 static constexpr void poly_pointwise_montgomery(std::span<T, N> result,
101 std::span<const T, N> lhs,
102 std::span<const T, N> rhs) {
103 /**
104 * NIST FIPS 203, Algorithm 12 (BaseCaseMultiply)
105 */
106 auto basemul = [](const auto a, const auto b, const T zeta) -> std::tuple<T, T> {
107 return {static_cast<T>(fqmul(a[0], b[0]) + fqmul(fqmul(a[1], b[1]), zeta)),
108 static_cast<T>(fqmul(a[0], b[1]) + fqmul(a[1], b[0]))};
109 };
110
111 auto Tq_elem_count = [](auto p) { return p.size() / 2; };
112
113 auto Tq_elem = [](auto p, size_t i) {
114 if constexpr(std::is_const_v<typename decltype(p)::element_type>) {
115 return std::array<T, 2>{p[2 * i], p[2 * i + 1]};
116 } else {
117 return std::tuple<T&, T&>{p[2 * i], p[2 * i + 1]};
118 }
119 };
120
121 for(size_t i = 0; i < Tq_elem_count(result) / 2; ++i) {
122 const auto zeta = zetas[64 + i];
123 Tq_elem(result, 2 * i) = basemul(Tq_elem(lhs, 2 * i), Tq_elem(rhs, 2 * i), zeta);
124 Tq_elem(result, 2 * i + 1) = basemul(Tq_elem(lhs, 2 * i + 1), Tq_elem(rhs, 2 * i + 1), -zeta);
125 }
126 }
127};
128
129} // namespace Botan
130
131#endif
static constexpr void barrett_reduce(std::span< T, N > poly)
Definition pqcrystals.h:120
static constexpr void poly_pointwise_montgomery(std::span< T, N > result, std::span< const T, N > lhs, std::span< const T, N > rhs)
static constexpr void inverse_ntt(std::span< T, N > p)
static constexpr void ntt(std::span< T, N > p)
int(* final)(unsigned char *, CTX *)
const SIMD_8x32 & b