9#include <botan/curve_gfp.h>
10#include <botan/internal/curve_nistp.h>
11#include <botan/numthry.h>
12#include <botan/reducer.h>
13#include <botan/internal/mp_core.h>
14#include <botan/internal/monty.h>
20class CurveGFp_Montgomery
final :
public CurveGFp_Repr
23 CurveGFp_Montgomery(
const BigInt& p,
const BigInt& a,
const BigInt& b) :
24 m_p(p), m_a(a), m_b(b),
25 m_p_words(m_p.sig_words()),
28 Modular_Reducer mod_p(m_p);
31 m_r = mod_p.reduce(m_r);
33 m_r2 = mod_p.square(m_r);
34 m_r3 = mod_p.multiply(m_r, m_r2);
35 m_a_r = mod_p.multiply(m_r, m_a);
36 m_b_r = mod_p.multiply(m_r, m_b);
38 m_a_is_zero = m_a.is_zero();
39 m_a_is_minus_3 = (m_a + 3 == m_p);
42 bool a_is_zero()
const override {
return m_a_is_zero; }
43 bool a_is_minus_3()
const override {
return m_a_is_minus_3; }
45 const BigInt& get_a()
const override {
return m_a; }
47 const BigInt& get_b()
const override {
return m_b; }
49 const BigInt& get_p()
const override {
return m_p; }
51 const BigInt& get_a_rep()
const override {
return m_a_r; }
53 const BigInt& get_b_rep()
const override {
return m_b_r; }
55 const BigInt& get_1_rep()
const override {
return m_r; }
57 bool is_one(
const BigInt& x)
const override {
return x == m_r; }
59 size_t get_p_words()
const override {
return m_p_words; }
61 size_t get_ws_size()
const override {
return 2*m_p_words; }
63 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
65 void to_curve_rep(BigInt& x, secure_vector<word>& ws)
const override;
67 void from_curve_rep(BigInt& x, secure_vector<word>& ws)
const override;
69 void curve_mul_words(BigInt& z,
73 secure_vector<word>& ws)
const override;
75 void curve_sqr_words(BigInt& z,
78 secure_vector<word>& ws)
const override;
87 BigInt m_r, m_r2, m_r3;
94BigInt CurveGFp_Montgomery::invert_element(
const BigInt& x, secure_vector<word>& ws)
const
99 curve_mul(res, inv, m_r3, ws);
103void CurveGFp_Montgomery::to_curve_rep(BigInt& x, secure_vector<word>& ws)
const
106 curve_mul(x, tx, m_r2, ws);
109void CurveGFp_Montgomery::from_curve_rep(BigInt& z, secure_vector<word>& ws)
const
111 if(ws.size() < get_ws_size())
112 ws.resize(get_ws_size());
114 const size_t output_size = 2*m_p_words;
115 if(z.size() < output_size)
116 z.grow_to(output_size);
119 m_p.
data(), m_p_words, m_p_dash,
120 ws.data(), ws.size());
123void CurveGFp_Montgomery::curve_mul_words(BigInt& z,
127 secure_vector<word>& ws)
const
131 if(ws.size() < get_ws_size())
132 ws.resize(get_ws_size());
134 const size_t output_size = 2*m_p_words;
135 if(z.size() < output_size)
136 z.grow_to(output_size);
139 x_w, x_size, std::min(m_p_words, x_size),
140 y.data(),
y.size(), std::min(m_p_words,
y.size()),
141 ws.data(), ws.size());
144 m_p.
data(), m_p_words, m_p_dash,
145 ws.data(), ws.size());
148void CurveGFp_Montgomery::curve_sqr_words(BigInt& z,
151 secure_vector<word>& ws)
const
153 if(ws.size() < get_ws_size())
154 ws.resize(get_ws_size());
156 const size_t output_size = 2*m_p_words;
157 if(z.size() < output_size)
158 z.grow_to(output_size);
161 x, x_size, std::min(m_p_words, x_size),
162 ws.data(), ws.size());
165 m_p.
data(), m_p_words, m_p_dash,
166 ws.data(), ws.size());
169class CurveGFp_NIST :
public CurveGFp_Repr
172 CurveGFp_NIST(
size_t p_bits,
const BigInt& a,
const BigInt& b) :
178 bool a_is_zero()
const override {
return false; }
179 bool a_is_minus_3()
const override {
return true; }
181 const BigInt& get_a()
const override {
return m_a; }
183 const BigInt& get_b()
const override {
return m_b; }
185 const BigInt& get_1_rep()
const override {
return m_1; }
187 size_t get_p_words()
const override {
return m_p_words; }
189 size_t get_ws_size()
const override {
return 2*m_p_words; }
191 const BigInt& get_a_rep()
const override {
return m_a; }
193 const BigInt& get_b_rep()
const override {
return m_b; }
195 bool is_one(
const BigInt& x)
const override {
return x == 1; }
197 void to_curve_rep(BigInt& x, secure_vector<word>& ws)
const override
198 { redc_mod_p(x, ws); }
200 void from_curve_rep(BigInt& x, secure_vector<word>& ws)
const override
201 { redc_mod_p(x, ws); }
203 virtual void redc_mod_p(BigInt& z, secure_vector<word>& ws)
const = 0;
205 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
207 void curve_mul_words(BigInt& z,
208 const word x_words[],
211 secure_vector<word>& ws)
const override;
213 void curve_mul_tmp(BigInt& x,
const BigInt&
y, BigInt& tmp, secure_vector<word>& ws)
const
215 curve_mul(tmp, x,
y, ws);
219 void curve_sqr_tmp(BigInt& x, BigInt& tmp, secure_vector<word>& ws)
const
221 curve_sqr(tmp, x, ws);
225 void curve_sqr_words(BigInt& z,
226 const word x_words[],
228 secure_vector<word>& ws)
const override;
236BigInt CurveGFp_NIST::invert_element(
const BigInt& x, secure_vector<word>& ws)
const
242void CurveGFp_NIST::curve_mul_words(BigInt& z,
246 secure_vector<word>& ws)
const
250 if(ws.size() < get_ws_size())
251 ws.resize(get_ws_size());
253 const size_t output_size = 2*m_p_words;
254 if(z.size() < output_size)
255 z.grow_to(output_size);
258 x_w, x_size, std::min(m_p_words, x_size),
259 y.data(),
y.size(), std::min(m_p_words,
y.size()),
260 ws.data(), ws.size());
262 this->redc_mod_p(z, ws);
265void CurveGFp_NIST::curve_sqr_words(BigInt& z,
const word x[],
size_t x_size,
266 secure_vector<word>& ws)
const
268 if(ws.size() < get_ws_size())
269 ws.resize(get_ws_size());
271 const size_t output_size = 2*m_p_words;
272 if(z.size() < output_size)
273 z.grow_to(output_size);
276 x, x_size, std::min(m_p_words, x_size),
277 ws.data(), ws.size());
279 this->redc_mod_p(z, ws);
285class CurveGFp_P192
final :
public CurveGFp_NIST
288 CurveGFp_P192(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(192, a, b) {}
289 const BigInt& get_p()
const override {
return prime_p192(); }
291 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p192(x, ws); }
297class CurveGFp_P224
final :
public CurveGFp_NIST
300 CurveGFp_P224(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(224, a, b) {}
301 const BigInt& get_p()
const override {
return prime_p224(); }
303 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p224(x, ws); }
309class CurveGFp_P256
final :
public CurveGFp_NIST
312 CurveGFp_P256(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(256, a, b) {}
313 const BigInt& get_p()
const override {
return prime_p256(); }
315 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p256(x, ws); }
316 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
319BigInt CurveGFp_P256::invert_element(
const BigInt& x, secure_vector<word>& ws)
const
321 BigInt r, p2, p4, p8, p16, p32, tmp;
325 curve_mul(p2, r, x, ws);
326 curve_sqr(r, p2, ws);
327 curve_sqr_tmp(r, tmp, ws);
329 curve_mul(p4, r, p2, ws);
331 curve_sqr(r, p4, ws);
332 for(
size_t i = 0; i != 3; ++i)
333 curve_sqr_tmp(r, tmp, ws);
334 curve_mul(p8, r, p4, ws);
336 curve_sqr(r, p8, ws);
337 for(
size_t i = 0; i != 7; ++i)
338 curve_sqr_tmp(r, tmp, ws);
339 curve_mul(p16, r, p8, ws);
341 curve_sqr(r, p16, ws);
342 for(
size_t i = 0; i != 15; ++i)
343 curve_sqr_tmp(r, tmp, ws);
344 curve_mul(p32, r, p16, ws);
346 curve_sqr(r, p32, ws);
347 for(
size_t i = 0; i != 31; ++i)
348 curve_sqr_tmp(r, tmp, ws);
349 curve_mul_tmp(r, x, tmp, ws);
351 for(
size_t i = 0; i != 32*4; ++i)
352 curve_sqr_tmp(r, tmp, ws);
353 curve_mul_tmp(r, p32, tmp, ws);
355 for(
size_t i = 0; i != 32; ++i)
356 curve_sqr_tmp(r, tmp, ws);
357 curve_mul_tmp(r, p32, tmp, ws);
359 for(
size_t i = 0; i != 16; ++i)
360 curve_sqr_tmp(r, tmp, ws);
361 curve_mul_tmp(r, p16, tmp, ws);
362 for(
size_t i = 0; i != 8; ++i)
363 curve_sqr_tmp(r, tmp, ws);
364 curve_mul_tmp(r, p8, tmp, ws);
366 for(
size_t i = 0; i != 4; ++i)
367 curve_sqr_tmp(r, tmp, ws);
368 curve_mul_tmp(r, p4, tmp, ws);
370 for(
size_t i = 0; i != 2; ++i)
371 curve_sqr_tmp(r, tmp, ws);
372 curve_mul_tmp(r, p2, tmp, ws);
374 for(
size_t i = 0; i != 2; ++i)
375 curve_sqr_tmp(r, tmp, ws);
376 curve_mul_tmp(r, x, tmp, ws);
384class CurveGFp_P384
final :
public CurveGFp_NIST
387 CurveGFp_P384(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(384, a, b) {}
388 const BigInt& get_p()
const override {
return prime_p384(); }
390 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p384(x, ws); }
391 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
394BigInt CurveGFp_P384::invert_element(
const BigInt& x, secure_vector<word>& ws)
const
398 BigInt r, x2, x3, x15, x30, tmp, rl;
401 curve_sqr_tmp(r, tmp, ws);
402 curve_mul_tmp(r, x, tmp, ws);
405 curve_sqr_tmp(r, tmp, ws);
406 curve_mul_tmp(r, x, tmp, ws);
410 for(
size_t i = 0; i != 3; ++i)
411 curve_sqr_tmp(r, tmp, ws);
412 curve_mul_tmp(r, x3, tmp, ws);
415 for(
size_t i = 0; i != 6; ++i)
416 curve_sqr_tmp(r, tmp, ws);
417 curve_mul_tmp(r, rl, tmp, ws);
419 for(
size_t i = 0; i != 3; ++i)
420 curve_sqr_tmp(r, tmp, ws);
421 curve_mul_tmp(r, x3, tmp, ws);
424 for(
size_t i = 0; i != 15; ++i)
425 curve_sqr_tmp(r, tmp, ws);
426 curve_mul_tmp(r, x15, tmp, ws);
429 for(
size_t i = 0; i != 30; ++i)
430 curve_sqr_tmp(r, tmp, ws);
431 curve_mul_tmp(r, x30, tmp, ws);
434 for(
size_t i = 0; i != 60; ++i)
435 curve_sqr_tmp(r, tmp, ws);
436 curve_mul_tmp(r, rl, tmp, ws);
439 for(
size_t i = 0; i != 120; ++i)
440 curve_sqr_tmp(r, tmp, ws);
441 curve_mul_tmp(r, rl, tmp, ws);
443 for(
size_t i = 0; i != 15; ++i)
444 curve_sqr_tmp(r, tmp, ws);
445 curve_mul_tmp(r, x15, tmp, ws);
447 for(
size_t i = 0; i != 31; ++i)
448 curve_sqr_tmp(r, tmp, ws);
449 curve_mul_tmp(r, x30, tmp, ws);
451 for(
size_t i = 0; i != 2; ++i)
452 curve_sqr_tmp(r, tmp, ws);
453 curve_mul_tmp(r, x2, tmp, ws);
455 for(
size_t i = 0; i != 94; ++i)
456 curve_sqr_tmp(r, tmp, ws);
457 curve_mul_tmp(r, x30, tmp, ws);
459 for(
size_t i = 0; i != 2; ++i)
460 curve_sqr_tmp(r, tmp, ws);
462 curve_mul_tmp(r, x, tmp, ws);
470class CurveGFp_P521
final :
public CurveGFp_NIST
473 CurveGFp_P521(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(521, a, b) {}
474 const BigInt& get_p()
const override {
return prime_p521(); }
476 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p521(x, ws); }
477 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
480BigInt CurveGFp_P521::invert_element(
const BigInt& x, secure_vector<word>& ws)
const
490 curve_mul_tmp(r, x, tmp, ws);
492 curve_sqr_tmp(r, tmp, ws);
493 curve_mul_tmp(r, x, tmp, ws);
497 for(
size_t i = 0; i != 3; ++i)
498 curve_sqr_tmp(r, tmp, ws);
499 curve_mul_tmp(r, rl, tmp, ws);
501 curve_sqr_tmp(r, tmp, ws);
502 curve_mul_tmp(r, x, tmp, ws);
505 curve_sqr_tmp(r, tmp, ws);
506 curve_mul_tmp(r, x, tmp, ws);
509 for(
size_t i = 0; i != 8; ++i)
510 curve_sqr_tmp(r, tmp, ws);
511 curve_mul_tmp(r, rl, tmp, ws);
514 for(
size_t i = 0; i != 16; ++i)
515 curve_sqr_tmp(r, tmp, ws);
516 curve_mul_tmp(r, rl, tmp, ws);
519 for(
size_t i = 0; i != 32; ++i)
520 curve_sqr_tmp(r, tmp, ws);
521 curve_mul_tmp(r, rl, tmp, ws);
524 for(
size_t i = 0; i != 64; ++i)
525 curve_sqr_tmp(r, tmp, ws);
526 curve_mul_tmp(r, rl, tmp, ws);
529 for(
size_t i = 0; i != 128; ++i)
530 curve_sqr_tmp(r, tmp, ws);
531 curve_mul_tmp(r, rl, tmp, ws);
534 for(
size_t i = 0; i != 256; ++i)
535 curve_sqr_tmp(r, tmp, ws);
536 curve_mul_tmp(r, rl, tmp, ws);
538 for(
size_t i = 0; i != 7; ++i)
539 curve_sqr_tmp(r, tmp, ws);
540 curve_mul_tmp(r, a7, tmp, ws);
542 for(
size_t i = 0; i != 2; ++i)
543 curve_sqr_tmp(r, tmp, ws);
544 curve_mul_tmp(r, x, tmp, ws);
551std::shared_ptr<CurveGFp_Repr>
552CurveGFp::choose_repr(
const BigInt& p,
const BigInt& a,
const BigInt& b)
555 return std::make_shared<CurveGFp_P192>(a, b);
557 return std::make_shared<CurveGFp_P224>(a, b);
559 return std::make_shared<CurveGFp_P256>(a, b);
561 return std::make_shared<CurveGFp_P384>(a, b);
563 return std::make_shared<CurveGFp_P521>(a, b);
565 return std::make_shared<CurveGFp_Montgomery>(p, a, b);
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_UNUSED(...)
const word * data() const
int(* final)(unsigned char *, CTX *)
#define BOTAN_MP_WORD_BITS
BOTAN_TEST_API void redc_p521(BigInt &x, secure_vector< word > &ws)
void bigint_monty_redc(word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size)
BOTAN_TEST_API void redc_p192(BigInt &x, secure_vector< word > &ws)
BOTAN_TEST_API void redc_p256(BigInt &x, secure_vector< word > &ws)
void bigint_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, word workspace[], size_t ws_size)
BOTAN_TEST_API void redc_p224(BigInt &x, secure_vector< word > &ws)
void bigint_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, word workspace[], size_t ws_size)
BOTAN_TEST_API const BigInt & prime_p384()
word monty_inverse(word a)
BOTAN_TEST_API const BigInt & prime_p224()
BOTAN_TEST_API void redc_p384(BigInt &x, secure_vector< word > &ws)
BOTAN_TEST_API const BigInt & prime_p256()
BOTAN_TEST_API const BigInt & prime_p192()
BOTAN_TEST_API const BigInt & prime_p521()
BigInt inverse_mod(const BigInt &n, const BigInt &mod)