Botan 3.6.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 const auto correction = p224_mul_mod_224(S);
65 W borrow = bigint_sub2(r.data(), N, correction.data(), N);
66
67 bigint_cnd_add(borrow, r.data(), N, P.data(), N);
68
69 return r;
70 }
71
72 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
73
74 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
75
76 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
77
78 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
79
80 private:
81 // Return (i*P-224) % 2**224
82 //
83 // Assumes i is small
84 constexpr static std::array<W, N> p224_mul_mod_224(W i) {
85 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
86
87 // For small i, multiples of P-224 have a simple structure so it's faster to
88 // compute the value directly vs a (constant time) table lookup
89
90 auto r = P;
91
92 if constexpr(WordInfo<W>::bits == 32) {
93 r[3] -= i;
94 r[0] += i;
95 } else {
96 const W i32 = i << 32;
97 r[1] -= i32;
98 r[0] += i;
99 }
100 return r;
101 }
102};
103
104// clang-format off
105class Params final : public EllipticCurveParameters<
106 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
107 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
108 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
109 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
110 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
111 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"> {
112};
113
114// clang-format on
115
116class Curve final : public EllipticCurve<Params, Secp224r1Rep> {
117 public:
118 // Return the square of the inverse of x
119 static FieldElement fe_invert2(const FieldElement& x) {
120 auto z = x.square();
121 z *= x;
122 z = z.square();
123 z *= x;
124 auto t0 = z;
125 t0.square_n(3);
126 t0 *= z;
127 auto t1 = t0;
128 t1.square_n(6);
129 t0 *= t1;
130 t0.square_n(3);
131 z *= t0;
132 t0 = z.square();
133 t0 *= x;
134 t1 = t0;
135 t1.square_n(16);
136 t0 *= t1;
137 t1 = t0;
138 t1.square_n(15);
139 z *= t1;
140 t1 = z;
141 t1.square_n(47);
142 z *= t1;
143 z = z.square();
144 z *= x;
145 t1 = z;
146 t1.square_n(32);
147 t0 *= t1;
148 t0.square_n(96);
149 z *= t0;
150 return z.square();
151 }
152
153 static Scalar scalar_invert(const Scalar& x) {
154 // Generated using https://github.com/mmcloughlin/addchain
155 auto t6 = x.square();
156 auto z = t6.square();
157 auto t3 = x * z;
158 auto t2 = t3 * t6;
159 auto t8 = t2 * z;
160 auto t7 = t8 * z;
161 auto t5 = t7 * z;
162 auto t0 = t5 * t6;
163 auto t1 = t0 * t6;
164 auto t4 = t1 * z;
165 z = t4 * t6;
166 t6 *= z;
167 auto t10 = t6.square();
168 auto t9 = t10 * x;
169 t10.square_n(5);
170 t9 *= t10;
171 t10.square_n(5);
172 t9 *= t10;
173 t10 = t9;
174 t10.square_n(16);
175 t10 *= t9;
176 auto t11 = t10;
177 t11.square_n(32);
178 t11 *= t10;
179 t11.square_n(32);
180 t10 *= t11;
181 t10.square_n(16);
182 t9 *= t10;
183 t9.square_n(7);
184 t8 *= t9;
185 t8.square_n(4);
186 t8 *= t3;
187 t8.square_n(8);
188 t8 *= t1;
189 t8.square_n(10);
190 t8 *= t1;
191 t8.square_n(7);
192 t7 *= t8;
193 t7.square_n(11);
194 t6 *= t7;
195 t6.square_n(9);
196 t5 *= t6;
197 t5.square_n(5);
198 t4 *= t5;
199 t4.square_n(3);
200 t4 *= t3;
201 t4.square_n(5);
202 t4 *= t3;
203 t4.square_n(5);
204 t3 *= t4;
205 t3.square_n(8);
206 t3 *= t0;
207 t3.square_n(4);
208 t2 *= t3;
209 t2.square_n(8);
210 t1 *= t2;
211 t1.square_n(9);
212 t0 *= t1;
213 t0.square_n(8);
214 z *= t0;
215 z = z.square();
216 z *= x;
217 return z;
218 }
219};
220
221} // namespace secp224r1
222
223} // namespace
224
225std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp224r1() {
227}
228
229} // namespace Botan::PCurve
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
static std::shared_ptr< const PrimeOrderCurve > secp224r1()
Definition pcurves.cpp:26
static std::shared_ptr< const PrimeOrderCurve > instance()
constexpr void accum(int64_t v)
constexpr W final_carry(int64_t C)
int(* final)(unsigned char *, CTX *)
constexpr uint32_t get_uint32(const W xw[], size_t i)
constexpr W bigint_cnd_add(W cnd, W x[], size_t x_size, const W y[], size_t y_size)
Definition mp_core.h:42
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:291