11#ifndef BOTAN_PQ_CRYSTALS_HELPERS_H_
12#define BOTAN_PQ_CRYSTALS_HELPERS_H_
19#include <botan/exceptn.h>
20#include <botan/internal/bit_ops.h>
26template <std::
unsigned_
integral T>
27 requires(
sizeof(T) <= 4)
29 std::conditional_t<
sizeof(T) == 1, uint16_t,
30 std::conditional_t<
sizeof(T) == 2, uint32_t,
31 std::conditional_t<
sizeof(T) == 4, uint64_t,
void>>>;
33template <std::
signed_
integral T>
34 requires(
sizeof(T) <= 4)
36 std::conditional_t<
sizeof(T) == 1, int16_t,
37 std::conditional_t<
sizeof(T) == 2, int32_t,
38 std::conditional_t<
sizeof(T) == 4, int64_t,
void>>>;
42template <std::
integral T>
43 requires(size_t(
sizeof(T)) <= 4)
45 using T_unsigned = std::make_unsigned_t<T>;
47 return (T2(1) << (
sizeof(T) * 8)) % q;
50template <std::
integral T>
51 requires(size_t(
sizeof(T)) <= 4)
57template <std::
integral T>
68template <std::
integral T>
82 std::tie(a, b) = std::make_tuple(
static_cast<T
>(b - q * a), a);
83 std::tie(u1, v1, u2, v2) = std::make_tuple(u2, v2,
static_cast<T
>(u1 - q * u2),
static_cast<T
>(v1 - q * v2));
87 return {.gcd = b, .u = u1, .v = v1};
95template <std::
integral T, std::
integral T2 = next_
longer_
int_t<T>>
96 requires(
sizeof(T) <= 4)
109template <
size_t degree, std::
integral T>
110consteval static auto precompute_zetas(T q, T monty, T root_of_unity) {
113 std::array<T, degree> result = {0};
115 auto bitreverse = [](
size_t k) ->
size_t {
118 for(
size_t i = 0; i < l; ++i) {
119 r |= ((k >> i) & 1) << (l - 1 - i);
124 auto pow = [q](T base,
size_t exp) -> T2 {
126 for(
size_t i = 0; i < exp; ++i) {
127 res = (res * base) % q;
132 auto csubq = [q](T a) -> T {
return a <= q / 2 ? a : a - q; };
134 for(
size_t i = 0; i < result.size(); ++i) {
135 result[i] = csubq(pow(root_of_unity, bitreverse(i)) * monty % q);
147template <
typename XofT,
size_t bound>
148 requires requires(XofT xof) {
149 { xof.template output<1>() } -> std::convertible_to<std::span<const uint8_t, 1>>;
150 { xof.template output<42>() } -> std::convertible_to<std::span<const uint8_t, 42>>;
154 template <
size_t bytes,
typename MapFnT>
155 using MappedValueT = std::invoke_result_t<MapFnT, std::array<uint8_t, bytes>>;
158 template <
size_t bytes>
163 template <
size_t bytes,
typename T>
170 requires std::default_initializable<XofT>
171 : m_bytes_consumed(0) {}
173 explicit Bounded_XOF(XofT xof) : m_xof(xof), m_bytes_consumed(0) {}
178 template <
typename PredicateFnT = decltype(default_predicate<1, u
int8_t>)>
179 requires std::invocable<PredicateFnT, uint8_t>
181 return next<1>([](
const auto bytes) {
return bytes[0]; }, std::forward<PredicateFnT>(predicate));
189 template <
size_t bytes,
191 typename PredicateFnT =
decltype(
default_predicate<bytes, MappedValueT<bytes, MapFnT>>)>
192 requires std::invocable<MapFnT, std::array<uint8_t, bytes>> &&
193 std::invocable<PredicateFnT, MappedValueT<bytes, MapFnT>>
195 const PredicateFnT& predicate =
default_predicate<bytes, MappedValueT<bytes, MapFnT>>) {
197 auto output = transformer(take<bytes>());
198 if(predicate(output)) {
205 template <
size_t bytes>
206 constexpr std::array<uint8_t, bytes> take() {
207 m_bytes_consumed += bytes;
208 if(m_bytes_consumed > bound) {
211 return m_xof.template output<bytes>();
216 size_t m_bytes_consumed;
223template <
size_t bound>
static constexpr bool default_predicate(T)
static constexpr auto default_transformer(std::array< uint8_t, bytes > x)
constexpr auto next(const MapFnT &transformer=default_transformer< bytes >, const PredicateFnT &predicate=default_predicate< bytes, MappedValueT< bytes, MapFnT > >)
constexpr auto next_byte(PredicateFnT &&predicate=default_predicate< 1, uint8_t >)
consteval T modular_inverse(T q, T2 m=T2(1)<< sizeof(T) *8)
std::conditional_t< sizeof(T)==1, int16_t, std::conditional_t< sizeof(T)==2, int32_t, std::conditional_t< sizeof(T)==4, int64_t, void > > > next_longer_int_t
std::conditional_t< sizeof(T)==1, uint16_t, std::conditional_t< sizeof(T)==2, uint32_t, std::conditional_t< sizeof(T)==4, uint64_t, void > > > next_longer_uint_t
consteval T montgomery_R2(T q)
detail::Bounded_XOF< XOF &, bound > Bounded_XOF
consteval T montgomery_R(T q)
consteval eea_result< T > extended_euclidean_algorithm(T a, T b)
constexpr uint8_t ceil_log2(T x)
constexpr auto bitlen(size_t x)