Botan 3.6.1
Crypto and TLS for C&
pcurves_secp521r1.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_wrap.h>
10
11namespace Botan::PCurve {
12
13namespace {
14
15namespace secp521r1 {
16
17template <typename Params>
18class P521Rep final {
19 public:
20 static constexpr auto P = Params::P;
21 static constexpr size_t N = Params::N;
22 typedef typename Params::W W;
23
24 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
25
26 constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
27 constexpr W TOP_MASK = static_cast<W>(0x1FF);
28
29 /*
30 * Extract the high part of z (z >> 521)
31 */
32 std::array<W, N> t;
33
34 for(size_t i = 0; i != N; ++i) {
35 t[i] = z[(N - 1) + i] >> 9;
36 }
37
38 for(size_t i = 0; i != N - 1; ++i) {
39 t[i] |= z[(N - 1) + i + 1] << (WordInfo<W>::bits - 9);
40 }
41
42 // Now t += z & (2**521-1)
43 W carry = word8_add2(t.data(), z.data(), static_cast<W>(0));
44
45 if constexpr(WordInfo<W>::bits == 32) {
46 constexpr size_t HN = N / 2;
47 carry = word8_add2(t.data() + HN, z.data() + HN, carry);
48 }
49
50 // Now add the (partial) top words; this can't carry out
51 // since both inputs are at most 2**9-1
52 t[N - 1] += (z[N - 1] & TOP_MASK) + carry;
53
54 // But might be greater than modulus:
55 std::array<W, N> r;
56 bigint_monty_maybe_sub<N>(r.data(), static_cast<W>(0), t.data(), P.data());
57
58 return r;
59 }
60
61 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
62
63 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
64
65 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
66};
67
68// clang-format off
69class Params final : public EllipticCurveParameters<
70 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
71 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
72 "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
73 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
74 "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
75 "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
76 -4> {
77};
78
79// clang-format on
80
81class Curve final : public EllipticCurve<Params, P521Rep> {
82 public:
83 // Return the square of the inverse of x
84 static FieldElement fe_invert2(const FieldElement& x) {
85 // Addition chain from https://eprint.iacr.org/2014/852.pdf page 6
86
87 FieldElement r = x.square();
88 r *= x;
89 r = r.square();
90 r *= x;
91 FieldElement rl = r;
92 r.square_n(3);
93 r *= rl;
94 r.square_n(1);
95 r *= x;
96 const auto a7 = r;
97 r.square_n(1);
98 r *= x;
99 rl = r;
100 r.square_n(8);
101 r *= rl;
102 rl = r;
103 r.square_n(16);
104 r *= rl;
105 rl = r;
106 r.square_n(32);
107 r *= rl;
108 rl = r;
109 r.square_n(64);
110 r *= rl;
111 rl = r;
112 r.square_n(128);
113 r *= rl;
114 rl = r;
115 r.square_n(256);
116 r *= rl;
117 r.square_n(7);
118 r *= a7;
119 r.square_n(2);
120
121 return r;
122 }
123
124 static Scalar scalar_invert(const Scalar& x) {
125 // Generated using https://github.com/mmcloughlin/addchain
126
127 auto t2 = x.square();
128 auto t13 = t2 * x;
129 auto t4 = t13 * x;
130 auto z = t13 * t4;
131 auto t5 = x * z;
132 auto t16 = t13 * t5;
133 auto t10 = t16 * t2;
134 auto t18 = t10 * t2;
135 auto t1 = t18 * t2;
136 auto t12 = t1 * t2;
137 auto t15 = t12 * t4;
138 auto t0 = t15 * t2;
139 auto t3 = t0 * t2;
140 auto t6 = t2 * t3;
141 auto t11 = t5 * t6;
142 auto t14 = t11 * t4;
143 auto t9 = t14 * t4;
144 auto t17 = t2 * t9;
145 auto t7 = t17 * t4;
146 t4 *= t7;
147 auto t8 = t2 * t4;
148 t5 = t2 * t8;
149 t2 *= t5;
150 auto t19 = t2;
151 t19.square_n(3);
152 t15 *= t19;
153 t19 = t15.square();
154 auto t20 = t19;
155 t20.square_n(8);
156 t20 *= t15;
157 t20.square_n(10);
158 t19 *= t20;
159 t20 = t19;
160 t20.square_n(8);
161 t20 *= t15;
162 t20.square_n(28);
163 t19 *= t20;
164 t20 = t19;
165 t20.square_n(63);
166 t19 *= t20;
167 t20 = t19;
168 t20.square_n(8);
169 t20 *= t15;
170 t20.square_n(127);
171 t19 *= t20;
172 t19 *= x;
173 t19.square_n(7);
174 t19 *= t11;
175 t19.square_n(5);
176 t19 *= t13;
177 t19.square_n(8);
178 t19 *= t10;
179 t19.square_n(8);
180 t19 *= t18;
181 t19.square_n(11);
182 t19 *= t5;
183 t19.square_n(4);
184 t18 *= t19;
185 t18.square_n(8);
186 t17 *= t18;
187 t17.square_n(6);
188 t17 *= t11;
189 t17.square_n(5);
190 t17 *= t12;
191 t17.square_n(5);
192 t16 *= t17;
193 t16.square_n(10);
194 t15 *= t16;
195 t15.square_n(4);
196 t15 *= t13;
197 t15.square_n(15);
198 t14 *= t15;
199 t14.square_n(9);
200 t14 *= t2;
201 t14.square_n(2);
202 t13 *= t14;
203 t13.square_n(9);
204 t12 *= t13;
205 t12.square_n(7);
206 t11 *= t12;
207 t11.square_n(4);
208 t10 *= t11;
209 t10.square_n(12);
210 t10 *= t5;
211 t10.square_n(6);
212 t9 *= t10;
213 t9.square_n(7);
214 t8 *= t9;
215 t8.square_n(8);
216 t8 *= t4;
217 t8.square_n(8);
218 t8 *= t1;
219 t8.square_n(8);
220 t7 *= t8;
221 t7.square_n(5);
222 t7 *= t1;
223 t7.square_n(9);
224 t7 *= t2;
225 t7.square_n(6);
226 t6 *= t7;
227 t6.square_n(7);
228 t5 *= t6;
229 t5.square_n(7);
230 t4 *= t5;
231 t4.square_n(5);
232 t3 *= t4;
233 t3.square_n(4);
234 t3 *= z;
235 t3.square_n(9);
236 t2 *= t3;
237 t2.square_n(7);
238 t1 *= t2;
239 t1.square_n(5);
240 t1 *= z;
241 t1.square_n(9);
242 t0 *= t1;
243 t0.square_n(10);
244 z *= t0;
245
246 return z;
247 }
248};
249
250} // namespace secp521r1
251
252} // namespace
253
254std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp521r1() {
256}
257
258} // namespace Botan::PCurve
static std::shared_ptr< const PrimeOrderCurve > secp521r1()
Definition pcurves.cpp:47
static std::shared_ptr< const PrimeOrderCurve > instance()
int(* final)(unsigned char *, CTX *)
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
Definition mp_core.h:374
void carry(int64_t &h0, int64_t &h1)
constexpr auto word8_add2(W x[8], const W y[8], W carry) -> W
Definition mp_asmi.h:210