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>
74 T u1 = 0, v1 = 1, u2 = 1, v2 = 0;
79 std::tie(a,
b) = std::make_tuple(
static_cast<T>(
b - q * a), a);
80 std::tie(u1, v1, u2, v2) = std::make_tuple(u2, v2,
static_cast<T>(u1 - q * u2),
static_cast<T>(v1 - q * v2));
84 return {.gcd =
b, .u = u1, .v = v1};
92template <std::
integral T, std::
integral T2 = next_
longer_
int_t<T>>
93 requires(
sizeof(
T) <= 4)
106template <
size_t degree, std::
integral T>
107consteval static auto precompute_zetas(
T q,
T monty,
T root_of_unity) {
110 std::array<T, degree> result = {0};
112 auto bitreverse = [](
size_t k) ->
size_t {
115 for(
size_t i = 0; i < l; ++i) {
116 r |= ((k >> i) & 1) << (l - 1 - i);
121 auto pow = [q](
T base,
size_t exp) -> T2 {
123 for(
size_t i = 0; i < exp; ++i) {
124 res = (res * base) % q;
129 auto csubq = [q](
T a) ->
T {
return a <= q / 2 ? a : a - q; };
131 for(
size_t i = 0; i < result.size(); ++i) {
132 result[i] = csubq(pow(root_of_unity, bitreverse(i)) * monty % q);
144template <
typename XofT,
size_t bound>
145 requires requires(XofT xof) {
146 { xof.template output<1>() } -> std::convertible_to<std::span<const uint8_t, 1>>;
147 { xof.template output<42>() } -> std::convertible_to<std::span<const uint8_t, 42>>;
151 template <
size_t bytes,
typename MapFnT>
152 using MappedValueT = std::invoke_result_t<MapFnT, std::array<uint8_t, bytes>>;
155 template <
size_t bytes>
160 template <
size_t bytes,
typename T>
167 requires std::default_initializable<XofT>
168 : m_bytes_consumed(0) {}
170 explicit Bounded_XOF(XofT xof) : m_xof(xof), m_bytes_consumed(0) {}
175 template <
typename PredicateFnT = decltype(default_predicate<1, u
int8_t>)>
176 requires std::invocable<PredicateFnT, uint8_t>
178 return next<1>([](
const auto bytes) {
return bytes[0]; }, std::forward<PredicateFnT>(predicate));
186 template <
size_t bytes,
188 typename PredicateFnT =
decltype(
default_predicate<bytes, MappedValueT<bytes, MapFnT>>)>
189 requires std::invocable<MapFnT, std::array<uint8_t, bytes>> &&
190 std::invocable<PredicateFnT, MappedValueT<bytes, MapFnT>>
192 PredicateFnT&& predicate =
default_predicate<bytes, MappedValueT<bytes, MapFnT>>) {
194 auto output = transformer(take<bytes>());
195 if(predicate(output)) {
202 template <
size_t bytes>
203 constexpr std::array<uint8_t, bytes> take() {
204 m_bytes_consumed += bytes;
205 if(m_bytes_consumed > bound) {
208 return m_xof.template output<bytes>();
213 size_t m_bytes_consumed;
220template <
size_t bound>
constexpr auto next(MapFnT &&transformer=default_transformer< bytes >, PredicateFnT &&predicate=default_predicate< bytes, MappedValueT< bytes, MapFnT > >)
static constexpr bool default_predicate(T)
static constexpr auto default_transformer(std::array< uint8_t, bytes > x)
constexpr auto next_byte(PredicateFnT &&predicate=default_predicate< 1, uint8_t >)
int(* final)(unsigned char *, CTX *)
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)
consteval T montgomery_R(T q)
consteval eea_result< T > extended_euclidean_algorithm(T a, T b)
constexpr auto bitlen(size_t x)
constexpr uint8_t ceil_log2(T x)