Botan 3.9.0
Crypto and TLS for C&
pcurves_solinas.h
Go to the documentation of this file.
1/*
2* (C) 2024 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_PCURVES_SOLINAS_REDC_HELPER_H_
8#define BOTAN_PCURVES_SOLINAS_REDC_HELPER_H_
9
10#include <botan/internal/mp_core.h>
11
12namespace Botan {
13
14/*
15Helpers for modular reduction of Solinas primes, such as P-256 and P-384.
16
17Instead of explicitly forming the various integers and adding/subtracting them
18row-by-row, we compute the entire sum in one pass, column by column. To prevent
19overflow/underflow the accumulator is a signed 64-bit integer, while the various
20limbs are (at least for all NIST curves aside from P-192) 32 bit integers.
21
22For more background on Solinas primes / Solinas reduction see
23
24* J. Solinas 'Generalized Mersenne Numbers'
25 <https://cacr.uwaterloo.ca/techreports/1999/corr99-39.pdf>
26* NIST SP 800-186 Appendix G.1
27 <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf>
28* Handbook of Elliptic And Hyperelliptic Curve Cryptography ยง 10.4.3
29
30*/
31
32template <WordType W>
33constexpr uint32_t get_uint32(const W xw[], size_t i) {
34 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
35
36 if constexpr(WordInfo<W>::bits == 32) {
37 return xw[i];
38 } else {
39 return static_cast<uint32_t>(xw[i / 2] >> ((i % 2) * 32));
40 }
41}
42
43template <WordType W, size_t N>
44class SolinasAccum final {
45 public:
46 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
47
48 static constexpr size_t N32 = N * (WordInfo<W>::bits / 32);
49
50 constexpr explicit SolinasAccum(std::array<W, N>& r) : m_r(r) {}
51
52 constexpr void accum(int64_t v) {
53 BOTAN_DEBUG_ASSERT(m_idx < N32);
54
55 m_S += v;
56 const uint32_t r = static_cast<uint32_t>(m_S);
57 m_S >>= 32;
58
59 if constexpr(WordInfo<W>::bits == 32) {
60 m_r[m_idx] = r;
61 } else {
62 m_r[m_idx / 2] |= static_cast<uint64_t>(r) << (32 * (m_idx % 2));
63 }
64
65 m_idx += 1;
66 }
67
68 constexpr W final_carry(int64_t C) {
69 m_S += C;
70 BOTAN_DEBUG_ASSERT(m_S >= 0);
71 return static_cast<W>(m_S);
72 }
73
74 private:
75 std::array<W, N>& m_r;
76 int64_t m_S = 0;
77 size_t m_idx = 0;
78};
79
80/**
81* Set r to r - C. Then if r < 0, add P to r
82*/
83template <size_t N, WordType W>
84constexpr inline void solinas_correct_redc(std::array<W, N>& r, const std::array<W, N>& P, const std::array<W, N>& C) {
85 W borrow = 0;
86 for(size_t i = 0; i != N; ++i) {
87 r[i] = word_sub(r[i], C[i], &borrow);
88 }
89
90 const auto mask = CT::Mask<W>::expand(borrow).value();
91
92 W carry = 0;
93
94 for(size_t i = 0; i != N; ++i) {
95 r[i] = word_add(r[i], P[i] & mask, &carry);
96 }
97}
98
99} // namespace Botan
100
101#endif
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static constexpr Mask< T > expand(T v)
Definition ct_utils.h:420
constexpr void accum(int64_t v)
static constexpr size_t N32
constexpr W final_carry(int64_t C)
constexpr SolinasAccum(std::array< W, N > &r)
constexpr auto word_sub(W x, W y, W *carry) -> W
Definition mp_asmi.h:280
constexpr auto word_add(W x, W y, W *carry) -> W
Definition mp_asmi.h:191
constexpr uint32_t get_uint32(const W xw[], size_t i)
void carry(int64_t &h0, int64_t &h1)
constexpr void solinas_correct_redc(std::array< W, N > &r, const std::array< W, N > &P, const std::array< W, N > &C)