Botan 3.6.0
Crypto and TLS for C&
dilithium_polynomial.h
Go to the documentation of this file.
1/*
2 * Crystals Dilithium Polynomial Adapter
3 *
4 * (C) 2022-2023 Jack Lloyd
5 * (C) 2022 Manuel Glaser - Rohde & Schwarz Cybersecurity
6 * (C) 2022-2023 Michael Boric, René Meusel - Rohde & Schwarz Cybersecurity
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_DILITHIUM_POLYNOMIAL_H_
13#define BOTAN_DILITHIUM_POLYNOMIAL_H_
14
15#include <botan/mem_ops.h>
16#include <botan/internal/dilithium_constants.h>
17#include <botan/internal/pqcrystals.h>
18#include <botan/internal/pqcrystals_helpers.h>
19
20namespace Botan {
21
22class DilithiumPolyTraits final : public CRYSTALS::Trait_Base<DilithiumConstants, DilithiumPolyTraits> {
23 private:
25
26 static constexpr T montgomery_reduce_coefficient(T2 a) {
27 const T2 t = static_cast<T>(static_cast<T2>(static_cast<T>(a)) * Q_inverse);
28 return (a - static_cast<T2>(t) * Q) >> (sizeof(T) * 8);
29 }
30
31 static constexpr T barrett_reduce_coefficient(T a) {
32 // 2**22 is roughly Q/2 and 2**23 is roughly Q
33 const T t = (a + (1 << 22)) >> 23;
34 a = a - t * Q;
35 return a;
36 }
37
38 public:
39 /**
40 * NIST FIPS 204, Algorithm 41 (NTT)
41 *
42 * Note: ntt(), inverse_ntt() and operator* have side effects on the
43 * montgomery factor of the involved coefficients!
44 * It is assumed that EXACTLY ONE vector or matrix multiplication
45 * is performed between transforming in and out of NTT domain.
46 *
47 * Produces the result of the NTT transformation without any montgomery
48 * factors in the coefficients.
49 */
50 static constexpr void ntt(std::span<T, N> coeffs) {
51 size_t j;
52 size_t k = 0;
53
54 for(size_t len = N / 2; len > 0; len >>= 1) {
55 for(size_t start = 0; start < N; start = j + len) {
56 const T zeta = zetas[++k];
57 for(j = start; j < start + len; ++j) {
58 // Zetas contain the montgomery parameter 2^32 mod q
59 T t = fqmul(zeta, coeffs[j + len]);
60 coeffs[j + len] = coeffs[j] - t;
61 coeffs[j] = coeffs[j] + t;
62 }
63 }
64 }
65 }
66
67 /**
68 * NIST FIPS 204, Algorithm 42 (NTT^-1).
69 *
70 * The output is effectively multiplied by the montgomery parameter 2^32
71 * mod q so that the input factors 2^(-32) mod q are eliminated. Note
72 * that factors 2^(-32) mod q are introduced by multiplication and
73 * reduction of values not in montgomery domain.
74 *
75 * Produces the result of the inverse NTT transformation with a montgomery
76 * factor of (2^32 mod q) added (!). See above.
77 */
78 static constexpr void inverse_ntt(std::span<T, N> coeffs) {
79 size_t j;
80 size_t k = N;
81 for(size_t len = 1; len < N; len <<= 1) {
82 for(size_t start = 0; start < N; start = j + len) {
83 const T zeta = -zetas[--k];
84 for(j = start; j < start + len; ++j) {
85 T t = coeffs[j];
86 coeffs[j] = t + coeffs[j + len];
87 coeffs[j + len] = t - coeffs[j + len];
88 // Zetas contain the montgomery parameter 2^32 mod q
89 coeffs[j + len] = fqmul(zeta, coeffs[j + len]);
90 }
91 }
92 }
93
94 for(auto& coeff : coeffs) {
95 coeff = fqmul(coeff, F_WITH_MONTY_SQUARED);
96 }
97 }
98
99 /**
100 * Multiplication of two polynomials @p lhs and @p rhs in NTT domain.
101 *
102 * Produces the result of the multiplication in NTT domain, with a factor
103 * of (2^-32 mod q) in each element due to montgomery reduction.
104 */
105 static constexpr void poly_pointwise_montgomery(std::span<T, N> result,
106 std::span<const T, N> lhs,
107 std::span<const T, N> rhs) {
108 for(size_t i = 0; i < N; ++i) {
109 result[i] = fqmul(lhs[i], rhs[i]);
110 }
111 }
112};
113
114} // namespace Botan
115
116#endif
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 ntt(std::span< T, N > coeffs)
static constexpr void inverse_ntt(std::span< T, N > coeffs)
int(* final)(unsigned char *, CTX *)