Botan 3.11.0
Crypto and TLS for C&
pcurves_secp224r1.cpp
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#include <botan/internal/pcurves_instance.h>
8
9#include <botan/internal/pcurves_solinas.h>
10#include <botan/internal/pcurves_wrap.h>
11
12namespace Botan::PCurve {
13
14namespace {
15
16namespace secp224r1 {
17
18template <typename Params>
19class Secp224r1Rep final {
20 public:
21 static constexpr auto P = Params::P;
22 static constexpr size_t N = Params::N;
23 typedef typename Params::W W;
24
25 constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
26 const int64_t X00 = get_uint32(z.data(), 0);
27 const int64_t X01 = get_uint32(z.data(), 1);
28 const int64_t X02 = get_uint32(z.data(), 2);
29 const int64_t X03 = get_uint32(z.data(), 3);
30 const int64_t X04 = get_uint32(z.data(), 4);
31 const int64_t X05 = get_uint32(z.data(), 5);
32 const int64_t X06 = get_uint32(z.data(), 6);
33 const int64_t X07 = get_uint32(z.data(), 7);
34 const int64_t X08 = get_uint32(z.data(), 8);
35 const int64_t X09 = get_uint32(z.data(), 9);
36 const int64_t X10 = get_uint32(z.data(), 10);
37 const int64_t X11 = get_uint32(z.data(), 11);
38 const int64_t X12 = get_uint32(z.data(), 12);
39 const int64_t X13 = get_uint32(z.data(), 13);
40
41 const int64_t S0 = 0x00000001 + X00 - X07 - X11;
42 const int64_t S1 = 0x00000000 + X01 - X08 - X12;
43 const int64_t S2 = 0x00000000 + X02 - X09 - X13;
44 const int64_t S3 = 0xFFFFFFFF + X03 + X07 + X11 - X10;
45 const int64_t S4 = 0xFFFFFFFF + X04 + X08 + X12 - X11;
46 const int64_t S5 = 0xFFFFFFFF + X05 + X09 + X13 - X12;
47 const int64_t S6 = 0xFFFFFFFF + X06 + X10 - X13;
48
49 std::array<W, N> r = {};
50
51 SolinasAccum sum(r);
52
53 sum.accum(S0);
54 sum.accum(S1);
55 sum.accum(S2);
56 sum.accum(S3);
57 sum.accum(S4);
58 sum.accum(S5);
59 sum.accum(S6);
60 const auto S = sum.final_carry(0);
61
62 BOTAN_DEBUG_ASSERT(S <= 2);
63
64 solinas_correct_redc<N>(r, P, p224_mul_mod_224(S));
65
66 return r;
67 }
68
69 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
70
71 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
72
73 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
74
75 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
76
77 private:
78 // Return (i*P-224) % 2**224
79 //
80 // Assumes i is small
81 constexpr static std::array<W, N> p224_mul_mod_224(W i) {
82 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
83
84 // For small i, multiples of P-224 have a simple structure so it's faster to
85 // compute the value directly vs a (constant time) table lookup
86
87 auto r = P;
88
89 if constexpr(WordInfo<W>::bits == 32) {
90 r[3] -= i;
91 r[0] += i;
92 } else {
93 const W i32 = i << 32;
94 r[1] -= i32;
95 r[0] += i;
96 }
97 return r;
98 }
99};
100
101// clang-format off
102
103class Params final : public EllipticCurveParameters<
104 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
105 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
106 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
107 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
108 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
109 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"> {
110};
111
112// clang-format on
113
114class Curve final : public EllipticCurve<Params, Secp224r1Rep> {
115 public:
116 // Return the square of the inverse of x
117 static constexpr FieldElement fe_invert2(const FieldElement& x) {
118 auto z = x.square();
119 z *= x;
120 z = z.square();
121 z *= x;
122 auto t0 = z;
123 t0.square_n(3);
124 t0 *= z;
125 auto t1 = t0;
126 t1.square_n(6);
127 t0 *= t1;
128 t0.square_n(3);
129 z *= t0;
130 t0 = z.square();
131 t0 *= x;
132 t1 = t0;
133 t1.square_n(16);
134 t0 *= t1;
135 t1 = t0;
136 t1.square_n(15);
137 z *= t1;
138 t1 = z;
139 t1.square_n(47);
140 z *= t1;
141 z = z.square();
142 z *= x;
143 t1 = z;
144 t1.square_n(32);
145 t0 *= t1;
146 t0.square_n(96);
147 z *= t0;
148 return z.square();
149 }
150
151 static constexpr Scalar scalar_invert(const Scalar& x) {
152 // Generated using https://github.com/mmcloughlin/addchain
153 auto t6 = x.square();
154 auto z = t6.square();
155 auto t3 = x * z;
156 auto t2 = t3 * t6;
157 auto t8 = t2 * z;
158 auto t7 = t8 * z;
159 auto t5 = t7 * z;
160 auto t0 = t5 * t6;
161 auto t1 = t0 * t6;
162 auto t4 = t1 * z;
163 z = t4 * t6;
164 t6 *= z;
165 auto t10 = t6.square();
166 auto t9 = t10 * x;
167 t10.square_n(5);
168 t9 *= t10;
169 t10.square_n(5);
170 t9 *= t10;
171 t10 = t9;
172 t10.square_n(16);
173 t10 *= t9;
174 auto t11 = t10;
175 t11.square_n(32);
176 t11 *= t10;
177 t11.square_n(32);
178 t10 *= t11;
179 t10.square_n(16);
180 t9 *= t10;
181 t9.square_n(7);
182 t8 *= t9;
183 t8.square_n(4);
184 t8 *= t3;
185 t8.square_n(8);
186 t8 *= t1;
187 t8.square_n(10);
188 t8 *= t1;
189 t8.square_n(7);
190 t7 *= t8;
191 t7.square_n(11);
192 t6 *= t7;
193 t6.square_n(9);
194 t5 *= t6;
195 t5.square_n(5);
196 t4 *= t5;
197 t4.square_n(3);
198 t4 *= t3;
199 t4.square_n(5);
200 t4 *= t3;
201 t4.square_n(5);
202 t3 *= t4;
203 t3.square_n(8);
204 t3 *= t0;
205 t3.square_n(4);
206 t2 *= t3;
207 t2.square_n(8);
208 t1 *= t2;
209 t1.square_n(9);
210 t0 *= t1;
211 t0.square_n(8);
212 z *= t0;
213 z = z.square();
214 z *= x;
215 return z;
216 }
217};
218
219} // namespace secp224r1
220
221} // namespace
222
223std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp224r1() {
225}
226
227} // namespace Botan::PCurve
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static std::shared_ptr< const PrimeOrderCurve > instance()
constexpr void accum(int64_t v)
constexpr W final_carry(int64_t C)
constexpr uint32_t get_uint32(const W xw[], size_t i)
constexpr void solinas_correct_redc(std::array< W, N > &r, const std::array< W, N > &P, const std::array< W, N > &C)