9#include <botan/curve_gfp.h>
11#include <botan/numthry.h>
12#include <botan/reducer.h>
13#include <botan/internal/curve_nistp.h>
14#include <botan/internal/monty.h>
15#include <botan/internal/mp_core.h>
21class CurveGFp_Montgomery
final :
public CurveGFp_Repr {
23 CurveGFp_Montgomery(
const BigInt& p,
const BigInt& a,
const BigInt&
b) :
28 m_p_words(m_p.sig_words()),
30 Modular_Reducer mod_p(m_p);
33 m_r = mod_p.reduce(m_r);
35 m_r2 = mod_p.square(m_r);
36 m_r3 = mod_p.multiply(m_r, m_r2);
37 m_a_r = mod_p.multiply(m_r, m_a);
38 m_b_r = mod_p.multiply(m_r, m_b);
40 m_a_is_zero = m_a.is_zero();
41 m_a_is_minus_3 = (m_a + 3 == m_p);
44 bool a_is_zero()
const override {
return m_a_is_zero; }
46 bool a_is_minus_3()
const override {
return m_a_is_minus_3; }
48 const BigInt& get_a()
const override {
return m_a; }
50 const BigInt& get_b()
const override {
return m_b; }
52 const BigInt& get_p()
const override {
return m_p; }
54 const BigInt& get_a_rep()
const override {
return m_a_r; }
56 const BigInt& get_b_rep()
const override {
return m_b_r; }
58 const BigInt& get_1_rep()
const override {
return m_r; }
60 bool is_one(
const BigInt& x)
const override {
return x == m_r; }
62 size_t get_p_bits()
const override {
return m_p_bits; }
64 size_t get_ws_size()
const override {
return 2 * m_p_words; }
73 BigInt& z,
const word x_words[],
size_t x_size,
const BigInt& y,
secure_vector<word>& ws)
const override;
75 void curve_sqr_words(BigInt& z,
const word x_words[],
size_t x_size,
secure_vector<word>& ws)
const override;
85 BigInt m_r, m_r2, m_r3;
96 curve_mul(res, inv, m_r3, ws);
102 curve_mul(x, tx, m_r2, ws);
106 if(ws.size() < get_ws_size()) {
107 ws.resize(get_ws_size());
110 const size_t output_size = 2 * m_p_words;
111 if(z.size() < output_size) {
112 z.grow_to(output_size);
118void CurveGFp_Montgomery::curve_mul_words(
119 BigInt& z,
const word x_w[],
size_t x_size,
const BigInt& y,
secure_vector<word>& ws)
const {
122 if(ws.size() < get_ws_size()) {
123 ws.resize(get_ws_size());
126 const size_t output_size = 2 * m_p_words;
127 if(z.size() < output_size) {
128 z.grow_to(output_size);
135 std::min(m_p_words, x_size),
138 std::min(m_p_words, y.size()),
145void CurveGFp_Montgomery::curve_sqr_words(BigInt& z,
const word x[],
size_t x_size,
secure_vector<word>& ws)
const {
146 if(ws.size() < get_ws_size()) {
147 ws.resize(get_ws_size());
150 const size_t output_size = 2 * m_p_words;
151 if(z.size() < output_size) {
152 z.grow_to(output_size);
155 bigint_sqr(z.mutable_data(), z.size(), x, x_size, std::min(m_p_words, x_size), ws.data(), ws.size());
160class CurveGFp_NIST :
public CurveGFp_Repr {
162 CurveGFp_NIST(
size_t p_bits,
const BigInt& a,
const BigInt& b) :
171 bool a_is_zero()
const override {
return false; }
173 bool a_is_minus_3()
const override {
return true; }
175 const BigInt& get_a()
const override {
return m_a; }
177 const BigInt& get_b()
const override {
return m_b; }
179 const BigInt& get_1_rep()
const override {
return m_1; }
181 size_t get_p_bits()
const override {
return m_p_bits; }
183 size_t get_ws_size()
const override {
return 2 * m_p_words; }
185 const BigInt& get_a_rep()
const override {
return m_a; }
187 const BigInt& get_b_rep()
const override {
return m_b; }
189 bool is_one(
const BigInt& x)
const override {
return x == 1; }
191 void to_curve_rep(BigInt& x, secure_vector<word>& ws)
const override { redc_mod_p(x, ws); }
193 void from_curve_rep(BigInt& x, secure_vector<word>& ws)
const override { redc_mod_p(x, ws); }
195 virtual void redc_mod_p(BigInt& z, secure_vector<word>& ws)
const = 0;
197 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
199 void curve_mul_words(
200 BigInt& z,
const word x_words[],
size_t x_size,
const BigInt& y, secure_vector<word>& ws)
const override;
202 void curve_mul_tmp(BigInt& x,
const BigInt& y, BigInt& tmp, secure_vector<word>& ws)
const {
203 curve_mul(tmp, x, y, ws);
207 void curve_sqr_tmp(BigInt& x, BigInt& tmp, secure_vector<word>& ws)
const {
208 curve_sqr(tmp, x, ws);
212 void curve_sqr_words(BigInt& z,
const word x_words[],
size_t x_size, secure_vector<word>& ws)
const override;
227void CurveGFp_NIST::curve_mul_words(
228 BigInt& z,
const word x_w[],
size_t x_size,
const BigInt& y,
secure_vector<word>& ws)
const {
231 if(ws.size() < get_ws_size()) {
232 ws.resize(get_ws_size());
235 const size_t output_size = 2 * m_p_words;
236 if(z.size() < output_size) {
237 z.grow_to(output_size);
244 std::min(m_p_words, x_size),
247 std::min(m_p_words, y.size()),
251 this->redc_mod_p(z, ws);
254void CurveGFp_NIST::curve_sqr_words(BigInt& z,
const word x[],
size_t x_size,
secure_vector<word>& ws)
const {
255 if(ws.size() < get_ws_size()) {
256 ws.resize(get_ws_size());
259 const size_t output_size = 2 * m_p_words;
260 if(z.size() < output_size) {
261 z.grow_to(output_size);
264 bigint_sqr(z.mutable_data(), output_size, x, x_size, std::min(m_p_words, x_size), ws.data(), ws.size());
266 this->redc_mod_p(z, ws);
272class CurveGFp_P192
final :
public CurveGFp_NIST {
274 CurveGFp_P192(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(192, a,
b) {}
276 const BigInt& get_p()
const override {
return prime_p192(); }
279 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p192(x, ws); }
285class CurveGFp_P224
final :
public CurveGFp_NIST {
287 CurveGFp_P224(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(224, a,
b) {}
289 const BigInt& get_p()
const override {
return prime_p224(); }
292 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p224(x, ws); }
298class CurveGFp_P256
final :
public CurveGFp_NIST {
300 CurveGFp_P256(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(256, a,
b) {}
302 const BigInt& get_p()
const override {
return prime_p256(); }
305 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p256(x, ws); }
307 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
311 BigInt r, p2, p4, p8, p16, p32, tmp;
315 curve_mul(p2, r, x, ws);
316 curve_sqr(r, p2, ws);
317 curve_sqr_tmp(r, tmp, ws);
319 curve_mul(p4, r, p2, ws);
321 curve_sqr(r, p4, ws);
322 for(
size_t i = 0; i != 3; ++i) {
323 curve_sqr_tmp(r, tmp, ws);
325 curve_mul(p8, r, p4, ws);
327 curve_sqr(r, p8, ws);
328 for(
size_t i = 0; i != 7; ++i) {
329 curve_sqr_tmp(r, tmp, ws);
331 curve_mul(p16, r, p8, ws);
333 curve_sqr(r, p16, ws);
334 for(
size_t i = 0; i != 15; ++i) {
335 curve_sqr_tmp(r, tmp, ws);
337 curve_mul(p32, r, p16, ws);
339 curve_sqr(r, p32, ws);
340 for(
size_t i = 0; i != 31; ++i) {
341 curve_sqr_tmp(r, tmp, ws);
343 curve_mul_tmp(r, x, tmp, ws);
345 for(
size_t i = 0; i != 32 * 4; ++i) {
346 curve_sqr_tmp(r, tmp, ws);
348 curve_mul_tmp(r, p32, tmp, ws);
350 for(
size_t i = 0; i != 32; ++i) {
351 curve_sqr_tmp(r, tmp, ws);
353 curve_mul_tmp(r, p32, tmp, ws);
355 for(
size_t i = 0; i != 16; ++i) {
356 curve_sqr_tmp(r, tmp, ws);
358 curve_mul_tmp(r, p16, tmp, ws);
359 for(
size_t i = 0; i != 8; ++i) {
360 curve_sqr_tmp(r, tmp, ws);
362 curve_mul_tmp(r, p8, tmp, ws);
364 for(
size_t i = 0; i != 4; ++i) {
365 curve_sqr_tmp(r, tmp, ws);
367 curve_mul_tmp(r, p4, tmp, ws);
369 for(
size_t i = 0; i != 2; ++i) {
370 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);
377 curve_mul_tmp(r, x, tmp, ws);
385class CurveGFp_P384
final :
public CurveGFp_NIST {
387 CurveGFp_P384(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(384, a,
b) {}
389 const BigInt& get_p()
const override {
return prime_p384(); }
392 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p384(x, ws); }
394 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
400 BigInt r, x2, x3, x15, x30, tmp, rl;
403 curve_sqr_tmp(r, tmp, ws);
404 curve_mul_tmp(r, x, tmp, ws);
407 curve_sqr_tmp(r, tmp, ws);
408 curve_mul_tmp(r, x, tmp, ws);
412 for(
size_t i = 0; i != 3; ++i) {
413 curve_sqr_tmp(r, tmp, ws);
415 curve_mul_tmp(r, x3, tmp, ws);
418 for(
size_t i = 0; i != 6; ++i) {
419 curve_sqr_tmp(r, tmp, ws);
421 curve_mul_tmp(r, rl, tmp, ws);
423 for(
size_t i = 0; i != 3; ++i) {
424 curve_sqr_tmp(r, tmp, ws);
426 curve_mul_tmp(r, x3, tmp, ws);
429 for(
size_t i = 0; i != 15; ++i) {
430 curve_sqr_tmp(r, tmp, ws);
432 curve_mul_tmp(r, x15, tmp, ws);
435 for(
size_t i = 0; i != 30; ++i) {
436 curve_sqr_tmp(r, tmp, ws);
438 curve_mul_tmp(r, x30, tmp, ws);
441 for(
size_t i = 0; i != 60; ++i) {
442 curve_sqr_tmp(r, tmp, ws);
444 curve_mul_tmp(r, rl, tmp, ws);
447 for(
size_t i = 0; i != 120; ++i) {
448 curve_sqr_tmp(r, tmp, ws);
450 curve_mul_tmp(r, rl, tmp, ws);
452 for(
size_t i = 0; i != 15; ++i) {
453 curve_sqr_tmp(r, tmp, ws);
455 curve_mul_tmp(r, x15, tmp, ws);
457 for(
size_t i = 0; i != 31; ++i) {
458 curve_sqr_tmp(r, tmp, ws);
460 curve_mul_tmp(r, x30, tmp, ws);
462 for(
size_t i = 0; i != 2; ++i) {
463 curve_sqr_tmp(r, tmp, ws);
465 curve_mul_tmp(r, x2, tmp, ws);
467 for(
size_t i = 0; i != 94; ++i) {
468 curve_sqr_tmp(r, tmp, ws);
470 curve_mul_tmp(r, x30, tmp, ws);
472 for(
size_t i = 0; i != 2; ++i) {
473 curve_sqr_tmp(r, tmp, ws);
476 curve_mul_tmp(r, x, tmp, ws);
484class CurveGFp_P521
final :
public CurveGFp_NIST {
486 CurveGFp_P521(
const BigInt& a,
const BigInt& b) : CurveGFp_NIST(521, a,
b) {}
488 const BigInt& get_p()
const override {
return prime_p521(); }
491 void redc_mod_p(BigInt& x, secure_vector<word>& ws)
const override {
redc_p521(x, ws); }
493 BigInt invert_element(
const BigInt& x, secure_vector<word>& ws)
const override;
505 curve_mul_tmp(r, x, tmp, ws);
507 curve_sqr_tmp(r, tmp, ws);
508 curve_mul_tmp(r, x, tmp, ws);
512 for(
size_t i = 0; i != 3; ++i) {
513 curve_sqr_tmp(r, tmp, ws);
515 curve_mul_tmp(r, rl, tmp, ws);
517 curve_sqr_tmp(r, tmp, ws);
518 curve_mul_tmp(r, x, tmp, ws);
521 curve_sqr_tmp(r, tmp, ws);
522 curve_mul_tmp(r, x, tmp, ws);
525 for(
size_t i = 0; i != 8; ++i) {
526 curve_sqr_tmp(r, tmp, ws);
528 curve_mul_tmp(r, rl, tmp, ws);
531 for(
size_t i = 0; i != 16; ++i) {
532 curve_sqr_tmp(r, tmp, ws);
534 curve_mul_tmp(r, rl, tmp, ws);
537 for(
size_t i = 0; i != 32; ++i) {
538 curve_sqr_tmp(r, tmp, ws);
540 curve_mul_tmp(r, rl, tmp, ws);
543 for(
size_t i = 0; i != 64; ++i) {
544 curve_sqr_tmp(r, tmp, ws);
546 curve_mul_tmp(r, rl, tmp, ws);
549 for(
size_t i = 0; i != 128; ++i) {
550 curve_sqr_tmp(r, tmp, ws);
552 curve_mul_tmp(r, rl, tmp, ws);
555 for(
size_t i = 0; i != 256; ++i) {
556 curve_sqr_tmp(r, tmp, ws);
558 curve_mul_tmp(r, rl, tmp, ws);
560 for(
size_t i = 0; i != 7; ++i) {
561 curve_sqr_tmp(r, tmp, ws);
563 curve_mul_tmp(r, a7, tmp, ws);
565 for(
size_t i = 0; i != 2; ++i) {
566 curve_sqr_tmp(r, tmp, ws);
568 curve_mul_tmp(r, x, tmp, ws);
575std::shared_ptr<CurveGFp_Repr> CurveGFp::choose_repr(
const BigInt& p,
const BigInt& a,
const BigInt&
b) {
577 return std::make_shared<CurveGFp_P192>(a,
b);
580 return std::make_shared<CurveGFp_P224>(a,
b);
583 return std::make_shared<CurveGFp_P256>(a,
b);
586 return std::make_shared<CurveGFp_P384>(a,
b);
589 return std::make_shared<CurveGFp_P521>(a,
b);
592 return std::make_shared<CurveGFp_Montgomery>(p, a,
b);
#define BOTAN_DEBUG_ASSERT(expr)
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)
constexpr auto monty_inverse(W a) -> W
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()
BOTAN_TEST_API const BigInt & prime_p224()
BOTAN_TEST_API void redc_p384(BigInt &x, secure_vector< word > &ws)
std::vector< T, secure_allocator< T > > secure_vector
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)