diff options
-rw-r--r-- | checks/ec_tests.cpp | 214 | ||||
-rw-r--r-- | checks/pk_bench.cpp | 6 | ||||
-rw-r--r-- | doc/credits.txt | 5 | ||||
-rw-r--r-- | doc/license.txt | 1 | ||||
-rw-r--r-- | doc/log.txt | 5 | ||||
-rw-r--r-- | src/math/bigint/bigint.h | 6 | ||||
-rw-r--r-- | src/math/bigint/mp_core.h | 10 | ||||
-rw-r--r-- | src/math/numbertheory/curve_gfp.h | 49 | ||||
-rw-r--r-- | src/math/numbertheory/point_gfp.cpp | 258 | ||||
-rw-r--r-- | src/math/numbertheory/point_gfp.h | 53 | ||||
-rw-r--r-- | src/pubkey/pubkey.cpp | 11 | ||||
-rw-r--r-- | src/pubkey/pubkey.h | 12 |
12 files changed, 345 insertions, 285 deletions
diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp index 485639e76..d86645dbc 100644 --- a/checks/ec_tests.cpp +++ b/checks/ec_tests.cpp @@ -6,19 +6,12 @@ #include <botan/build.h> -#include "validate.h" - -#if !defined(BOTAN_HAS_ECDSA) - -void do_ec_tests(RandomNumberGenerator&) { return; } - -#else - #include <botan/bigint.h> #include <botan/numthry.h> #include <botan/curve_gfp.h> #include <botan/point_gfp.h> #include <botan/ecdsa.h> +#include <botan/oids.h> using namespace Botan; @@ -26,7 +19,7 @@ using namespace Botan; #include <assert.h> #include "getopt.h" - +#include "validate.h" #include "common.h" #define CHECK_MESSAGE(expr, print) try { if(!(expr)) std::cout << print << "\n"; } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << "\n"; } @@ -34,6 +27,12 @@ using namespace Botan; namespace { +std::ostream& operator<<(std::ostream& out, const PointGFp& point) + { + out << "(" << point.get_affine_x() << " " << point.get_affine_y() << ")"; + return out; + } + PointGFp create_random_point(RandomNumberGenerator& rng, const CurveGFp& curve) { @@ -63,8 +62,6 @@ void test_point_turn_on_sp_red_mul() std::cout << "." << std::flush; // setting up expected values - std::string test_str("test"); - BigInt test_bi(3); BigInt exp_Qx(std::string("466448783855397898016055842232266600516272889280")); BigInt exp_Qy(std::string("1110706324081757720403272427311003102474457754220")); BigInt exp_Qz(1); @@ -87,13 +84,13 @@ void test_point_turn_on_sp_red_mul() BigInt d("459183204582304"); PointGFp r1 = d * p_G; - CHECK(r1.get_affine_x() != BigInt("0")); + CHECK(r1.get_affine_x() != 0); PointGFp p_G2(p_G); PointGFp r2 = d * p_G2; CHECK_MESSAGE(r1 == r2, "error with point mul after extra turn on sp red mul"); - CHECK(r1.get_affine_x() != BigInt("0")); + CHECK(r1.get_affine_x() != 0); PointGFp p_r1 = r1; PointGFp p_r2 = r2; @@ -101,15 +98,15 @@ void test_point_turn_on_sp_red_mul() p_r1 *= 2; p_r2 *= 2; CHECK_MESSAGE(p_r1.get_affine_x() == p_r2.get_affine_x(), "error with mult2 after extra turn on sp red mul"); - CHECK(p_r1.get_affine_x() != BigInt("0")); - CHECK(p_r2.get_affine_x() != BigInt("0")); + CHECK(p_r1.get_affine_x() != 0); + CHECK(p_r2.get_affine_x() != 0); r1 *= 2; r2 *= 2; CHECK_MESSAGE(r1 == r2, "error with mult2 after extra turn on sp red mul"); CHECK_MESSAGE(r1.get_affine_x() == r2.get_affine_x(), "error with mult2 after extra turn on sp red mul"); - CHECK(r1.get_affine_x() != BigInt("0")); + CHECK(r1.get_affine_x() != 0); r1 += p_G; r2 += p_G2; @@ -129,10 +126,6 @@ void test_coordinates() { std::cout << "." << std::flush; - //Setting up expected values - BigInt exp_x(std::string("1340569834321789103897171369812910390864714275730")); - BigInt exp_y(std::string("1270827321510686389126940426305655825361326281787")); - BigInt exp_z(std::string("407040228325808215747982915914693784055965283940")); BigInt exp_affine_x(std::string("16984103820118642236896513183038186009872590470")); BigInt exp_affine_y(std::string("1373093393927139016463695321221277758035357890939")); @@ -156,13 +149,6 @@ void test_coordinates() PointGFp point_exp(secp160r1, exp_affine_x, exp_affine_y); point_exp.check_invariants(); - if(p1.get_x() != exp_x) - std::cout << p1.get_x() << " != " << exp_x << "\n"; - if(p1.get_y() != exp_y) - std::cout << p1.get_y() << " != " << exp_y << "\n"; - if(p1.get_z() != exp_z) - std::cout << p1.get_z() << " != " << exp_z << "\n"; - CHECK_MESSAGE( p1.get_affine_x() == exp_affine_x, " p1_x = " << p1.get_affine_x() << "\n" << "exp_x = " << exp_affine_x << "\n"); CHECK_MESSAGE( p1.get_affine_y() == exp_affine_y, " p1_y = " << p1.get_affine_y() << "\n" << "exp_y = " << exp_affine_y << "\n"); } @@ -184,7 +170,6 @@ void test_point_transformation () { std::cout << "." << std::flush; - // get a vailid point EC_Domain_Params dom_pars(OID("1.3.132.0.8")); PointGFp p = dom_pars.get_base_point(); @@ -192,60 +177,33 @@ void test_point_transformation () // get a copy PointGFp q = p; - //turn on montg. - CHECK_MESSAGE( p.get_x() == q.get_x(), "projective_x changed while turning on montg.!"); - CHECK_MESSAGE( p.get_y() == q.get_y(), "projective_y changed while turning on montg.!"); - CHECK_MESSAGE( p.get_z() == q.get_z(), "projective_z changed while turning on montg.!"); - CHECK_MESSAGE( p.get_affine_x() == q.get_affine_x(), "affine_x changed while turning on montg.!"); - CHECK_MESSAGE( p.get_affine_y() == q.get_affine_y(), "affine_y changed while turning on montg.!"); + CHECK_MESSAGE( p.get_affine_x() == q.get_affine_x(), "affine_x changed during copy"); + CHECK_MESSAGE( p.get_affine_y() == q.get_affine_y(), "affine_y changed during copy"); } void test_point_mult () { std::cout << "." << std::flush; - // setting up expected values - std::string test_str("test"); - BigInt test_bi(3); - BigInt exp_Qx(std::string("466448783855397898016055842232266600516272889280")); - BigInt exp_Qy(std::string("1110706324081757720403272427311003102474457754220")); - BigInt exp_Qz(1); + EC_Domain_Params secp160r1(OIDS::lookup("secp160r1")); + + const CurveGFp& curve = secp160r1.get_curve(); - // performing calculation to test - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - SecureVector<byte> sv_p_secp = decode_hex(p_secp); - SecureVector<byte> sv_a_secp = decode_hex(a_secp); - SecureVector<byte> sv_b_secp = decode_hex(b_secp); SecureVector<byte> sv_G_secp_comp = decode_hex(G_secp_comp); - BigInt bi_p_secp = BigInt::decode(sv_p_secp.begin(), sv_p_secp.size()); - BigInt bi_a_secp = BigInt::decode(sv_a_secp.begin(), sv_a_secp.size()); - BigInt bi_b_secp = BigInt::decode(sv_b_secp.begin(), sv_b_secp.size()); - CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1); + PointGFp p_G = OS2ECP(sv_G_secp_comp, curve); - SecureVector<byte> sv_G_dec = EC2OSP(p_G,0x01); - std::string str_d_U = "aa374ffc3ce144e6b073307972cb6d57b2a4e982"; - SecureVector<byte> sv_d_U = decode_hex(str_d_U); - BigInt d_U = BigInt::decode(sv_d_U.begin(), sv_d_U.size()); + BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982"); PointGFp Q_U = d_U * p_G; - CHECK( Q_U.get_x() == exp_Qx); - CHECK( Q_U.get_y() == exp_Qy); - CHECK( Q_U.get_z() == exp_Qz); + + CHECK(Q_U.get_affine_x() == BigInt("466448783855397898016055842232266600516272889280")); + CHECK(Q_U.get_affine_y() == BigInt("1110706324081757720403272427311003102474457754220")); } void test_point_negative() { std::cout << "." << std::flush; - //Setting up expected values - BigInt exp_p1_x(std::string("1340569834321789103897171369812910390864714275730")); - BigInt exp_p1_y(std::string("1270827321510686389126940426305655825361326281787")); - BigInt exp_p1_neg_x(std::string("1340569834321789103897171369812910390864714275730")); - BigInt exp_p1_neg_y(std::string("190674315820216529076744406410627194292458777540")); - // performing calculation to test std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; @@ -263,17 +221,13 @@ void test_point_negative() PointGFp p1 = p_G *= 2; - CHECK( p1.get_x() == exp_p1_x); - CHECK( p1.get_y() == exp_p1_y); - //cout << "p1.y_proj = " << p1.get_y() << "\n"; + CHECK(p1.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); + CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); + PointGFp p1_neg = p1.negate(); - //cout << "p1_neg.y_proj = " << p1_neg.get_y() << "\n"; - //p1.negate(); - BigInt calc_y_value = p1_neg.get_y(); - BigInt calc_z_value = p1_neg.get_z(); - CHECK( p1_neg.get_x() == exp_p1_neg_x); - CHECK_MESSAGE( calc_y_value == exp_p1_neg_y, "calc_y_value = " << calc_y_value << "\nexp_p1_neg_v = " << exp_p1_neg_y); - //CHECK_MESSAGE( calc_z_value == exp_p1_neg_y, "calc_y_value = " << calc_y_value << "\nexp_p1_neg_v = " << exp_p1_neg_y); + + CHECK(p1_neg.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); + CHECK(p1_neg.get_affine_y() == BigInt("88408243403763901739989511495005261618427168388")); } void test_zeropoint() @@ -288,11 +242,10 @@ void test_zeropoint() BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730"); - BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787"); - BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940"); + PointGFp p1(secp160r1, + BigInt("16984103820118642236896513183038186009872590470"), + BigInt("1373093393927139016463695321221277758035357890939")); - PointGFp p1(secp160r1, bi_p1_xval, bi_p1_yval, bi_p1_zval); p1.check_invariants(); p1 -= p1; @@ -330,8 +283,6 @@ void test_calc_with_zeropoint() { std::cout << "." << std::flush; - - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; SecureVector<byte> sv_G_secp_comp = decode_hex ( G_secp_comp ); BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); @@ -339,11 +290,9 @@ void test_calc_with_zeropoint() BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730"); - BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787"); - BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940"); - - PointGFp p(curve, bi_p1_xval, bi_p1_yval, bi_p1_zval); + PointGFp p(curve, + BigInt("16984103820118642236896513183038186009872590470"), + BigInt("1373093393927139016463695321221277758035357890939")); p.check_invariants(); CHECK_MESSAGE( !p.is_zero(), "created is zeropoint, shouldn't be!"); @@ -365,11 +314,6 @@ void test_add_point() { std::cout << "." << std::flush; - //Setting up expected values - BigInt exp_add_x(std::string("1435263815649099438763411093143066583800699119469")); - BigInt exp_add_y(std::string("1300090790154238148372364036549849084558669436512")); - BigInt exp_add_z(std::string("562006223742588575209908669014372619804457947208")); - // precalculation std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; @@ -388,9 +332,12 @@ void test_add_point() PointGFp p0 = p_G; PointGFp p1 = p_G *= 2; - PointGFp expected(secp160r1, exp_add_x, exp_add_y, exp_add_z); - p1 += p0; + + PointGFp expected(secp160r1, + BigInt("704859595002530890444080436569091156047721708633"), + BigInt("1147993098458695153857594941635310323215433166682")); + CHECK(p1 == expected); } @@ -423,7 +370,10 @@ void test_sub_point() p1 -= p0; - PointGFp expected(secp160r1, exp_sub_x, exp_sub_y, exp_sub_z); + PointGFp expected(secp160r1, + BigInt("425826231723888350446541592701409065913635568770"), + BigInt("203520114162904107873991457957346892027982641970")); + CHECK(p1 == expected); } @@ -453,7 +403,7 @@ void test_mult_point() PointGFp p0 = p_G; PointGFp p1 = p_G *= 2; - p1 *= p0.get_x(); + p1 *= p0.get_affine_x(); PointGFp expected(secp160r1, exp_mult_x, exp_mult_y); @@ -464,28 +414,6 @@ void test_basic_operations() { std::cout << "." << std::flush; - - // set up expected values - BigInt exp_p1_x(std::string("1340569834321789103897171369812910390864714275730")); - BigInt exp_p1_y(std::string("1270827321510686389126940426305655825361326281787")); - BigInt exp_p1_z(std::string("407040228325808215747982915914693784055965283940")); - - BigInt exp_p0_x(std::string("425826231723888350446541592701409065913635568770")); - BigInt exp_p0_y(std::string("203520114162904107873991457957346892027982641970")); - BigInt exp_p0_z(std::string("1")); - - BigInt exp_plus_x(std::string("1435263815649099438763411093143066583800699119469")); - BigInt exp_plus_y(std::string("1300090790154238148372364036549849084558669436512")); - BigInt exp_plus_z(std::string("562006223742588575209908669014372619804457947208")); - - BigInt exp_minus_x(std::string("112913490230515010376958384252467223283065196552")); - BigInt exp_minus_y(std::string("143464803917389475471159193867377888720776527730")); - BigInt exp_minus_z(std::string("562006223742588575209908669014372619804457947208")); - - BigInt exp_mult_x(std::string("43638877777452195295055270548491599621118743290")); - BigInt exp_mult_y(std::string("56841378500012376527163928510402662349220202981")); - BigInt exp_mult_z(std::string("1")); - // precalculation std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; @@ -503,37 +431,43 @@ void test_basic_operations() PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 ); PointGFp p0 = p_G; - PointGFp p1 = p_G *= 2; - // check that all points have correct values - CHECK( p1.get_x() == exp_p1_x); - CHECK( p1.get_y() == exp_p1_y); - CHECK( p1.get_z() == exp_p1_z); + PointGFp expected(secp160r1, + BigInt("425826231723888350446541592701409065913635568770"), + BigInt("203520114162904107873991457957346892027982641970")); - PointGFp expected(secp160r1, exp_p0_x, exp_p0_y, exp_p0_z); CHECK(p0 == expected); + PointGFp p1 = p_G *= 2; + + CHECK(p1.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); + CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); + PointGFp simplePlus= p1 + p0; - PointGFp exp_simplePlus(secp160r1, exp_plus_x, exp_plus_y, exp_plus_z); - CHECK(simplePlus == exp_simplePlus); + PointGFp exp_simplePlus(secp160r1, + BigInt("704859595002530890444080436569091156047721708633"), + BigInt("1147993098458695153857594941635310323215433166682")); + if(simplePlus != exp_simplePlus) + std::cout << simplePlus << " != " << exp_simplePlus << "\n"; PointGFp simpleMinus= p1 - p0; - PointGFp exp_simpleMinus(secp160r1, exp_minus_x, exp_minus_y, exp_minus_z); + PointGFp exp_simpleMinus(secp160r1, + BigInt("425826231723888350446541592701409065913635568770"), + BigInt("203520114162904107873991457957346892027982641970")); + CHECK(simpleMinus == exp_simpleMinus); PointGFp simpleMult= p1 * 123456789; - CHECK( simpleMult.get_x() == exp_mult_x); - CHECK( simpleMult.get_y() == exp_mult_y); - CHECK( simpleMult.get_z() == exp_mult_z); + + CHECK(simpleMult.get_affine_x() == BigInt("43638877777452195295055270548491599621118743290")); + CHECK(simpleMult.get_affine_y() == BigInt("56841378500012376527163928510402662349220202981")); // check that all initial points hasn't changed - CHECK( p1.get_x() == exp_p1_x); - CHECK( p1.get_y() == exp_p1_y); - CHECK( p1.get_z() == exp_p1_z); + CHECK(p1.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); + CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); - CHECK( p0.get_x() == exp_p0_x); - CHECK( p0.get_y() == exp_p0_y); - CHECK( p0.get_z() == exp_p0_z); + CHECK(p0.get_affine_x() == BigInt("425826231723888350446541592701409065913635568770")); + CHECK(p0.get_affine_y() == BigInt("203520114162904107873991457957346892027982641970")); } void test_enc_dec_compressed_160() @@ -760,11 +694,9 @@ void test_more_zeropoint() BigInt bi_b("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); CurveGFp curve(bi_p, bi_a, bi_b); - BigInt bi_p1_xval ("1340569834321789103897171369812910390864714275730"); - BigInt bi_p1_yval ("1270827321510686389126940426305655825361326281787"); - BigInt bi_p1_zval ("407040228325808215747982915914693784055965283940"); - - PointGFp p1(curve, bi_p1_xval, bi_p1_yval, bi_p1_zval); + PointGFp p1(curve, + BigInt("16984103820118642236896513183038186009872590470"), + BigInt("1373093393927139016463695321221277758035357890939")); p1.check_invariants(); PointGFp minus_p1 = -p1; @@ -881,5 +813,3 @@ void do_ec_tests(RandomNumberGenerator& rng) std::cout << std::endl; } -#endif - diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index a09d3a090..6893917fd 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -296,7 +296,9 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, const char* domains[] = { "1.3.132.0.6", // secp112r1 "1.3.132.0.28", // secp128r1 "1.3.132.0.30", // secp160r2 + "1.2.840.10045.3.1.1", // secp192r1 "1.3.132.0.33", // secp224r1 + "1.2.840.10045.3.1.7", // secp256r1 "1.3.132.0.34", // secp384r1 "1.3.132.0.35", // secp512r1 NULL }; @@ -310,7 +312,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, u32bit hashbits = pbits; - if(hashbits < 160) + if(hashbits <= 192) hashbits = 160; if(hashbits == 521) hashbits = 512; @@ -328,7 +330,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, ECDSA_PrivateKey key(rng, params); keygen_timer.stop(); - PK_Signer sig(key, padding); + PK_Signer sig(key, padding, IEEE_1363, DISABLE_FAULT_PROTECTION); PK_Verifier ver(key, padding); benchmark_sig_ver(ver, sig, verify_timer, diff --git a/doc/credits.txt b/doc/credits.txt index 67b318842..63ceae483 100644 --- a/doc/credits.txt +++ b/doc/credits.txt @@ -20,6 +20,9 @@ N: Martin Doering D: GF(p) arithmetic +N: Olivier de Gaalon +D: SQLite encryption codec (src/wrap/sqlite) + N: Matthew Gregan D: Binary file I/O support, allocator fixes @@ -64,7 +67,7 @@ D: GP(p) arithmetic N: Vaclav Ovsik -D: Perl XS module +D: Perl XS module (src/wrap/perl-xs) N: Luca Piccarreta diff --git a/doc/license.txt b/doc/license.txt index 599bf7f63..6d9143ee1 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -3,6 +3,7 @@ Botan (http://botan.randombit.net/) is distributed under these terms: Copyright (C) 1999-2010 Jack Lloyd 2001 Peter J Jones 2004-2007 Justin Karneges + 2004 Vaclav Ovsik 2005 Matthew Gregan 2005-2006 Matt Johnston 2006 Luca Piccarreta diff --git a/doc/log.txt b/doc/log.txt index 042fe6f17..3a37e3a5e 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -1,5 +1,10 @@ * 1.9.5-dev, ????-??-?? + - Numerous ECC optimizations + - Allow PK_Signer's fault protection checks to be toggled off + - Remove all runtime options + - Fix crash in MemoryRegion if Allocator::get failed + - Fix small compilation problem on FreeBSD * 1.9.4, 2010-03-09 - Add the Ajisai SSLv3/TLSv1.0 implementation diff --git a/src/math/bigint/bigint.h b/src/math/bigint/bigint.h index 2612850c3..3756da51f 100644 --- a/src/math/bigint/bigint.h +++ b/src/math/bigint/bigint.h @@ -462,11 +462,11 @@ class BOTAN_DLL BigInt BigInt(RandomNumberGenerator& rng, u32bit bits); /** - * Create BigInt from unsigned 32 bit integer value and an - * also specify the sign of the value + * Create BigInt of specified size, all zeros + * @param sign the sign * @param n integer value */ - BigInt(Sign, u32bit n); + BigInt(Sign sign, u32bit n); /** * Create a number of the specified type and size diff --git a/src/math/bigint/mp_core.h b/src/math/bigint/mp_core.h index ea27a77a7..a2a89186d 100644 --- a/src/math/bigint/mp_core.h +++ b/src/math/bigint/mp_core.h @@ -86,12 +86,12 @@ void bigint_comba_sqr16(word[64], const word[32]); /* * High Level Multiplication/Squaring Interfaces */ -void bigint_mul(word[], u32bit, word[], - const word[], u32bit, u32bit, - const word[], u32bit, u32bit); +void bigint_mul(word z[], u32bit z_size, word workspace[], + const word x[], u32bit x_size, u32bit x_sw, + const word y[], u32bit y_size, u32bit y_sw); -void bigint_sqr(word[], u32bit, word[], - const word[], u32bit, u32bit); +void bigint_sqr(word z[], u32bit z_size, word workspace[], + const word x[], u32bit x_size, u32bit x_sw); } diff --git a/src/math/numbertheory/curve_gfp.h b/src/math/numbertheory/curve_gfp.h index de6bed099..a7be8987c 100644 --- a/src/math/numbertheory/curve_gfp.h +++ b/src/math/numbertheory/curve_gfp.h @@ -34,29 +34,59 @@ class BOTAN_DLL CurveGFp * @param b second coefficient */ CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) : - p(p), a(a), b(b), reducer_p(p) {} + p(p), a(a), b(b), reducer_p(p) + { + r = 1; + r <<= p.sig_words() * BOTAN_MP_WORD_BITS; + + r_inv = inverse_mod(r, p); + + p_dash = (((r * r_inv) - 1) / p).word_at(0); + + a_r = reducer_p.multiply(a, r); + } // CurveGFp(const CurveGFp& other) = default; // CurveGFp& operator=(const CurveGFp& other) = default; /** * Get coefficient a - * @result coefficient a + * @return coefficient a */ const BigInt& get_a() const { return a; } /** * Get coefficient b - * @result coefficient b + * @return coefficient b */ const BigInt& get_b() const { return b; } /** * Get prime modulus of the field of the curve - * @result prime modulus of the field of the curve + * @return prime modulus of the field of the curve */ const BigInt& get_p() const { return p; } + /** + * @return Montgomery parameter r + */ + const BigInt& get_r() const { return r; } + + /** + * @return Montgomery parameter r^-1 + */ + const BigInt& get_r_inv() const { return r_inv; } + + /** + * @return a * r mod p + */ + const BigInt& get_a_r() const { return a_r; } + + /** + * @return Montgomery parameter p-dash + */ + word get_p_dash() const { return p_dash; } + const Modular_Reducer& mod_p() const { return reducer_p; } /** @@ -68,6 +98,11 @@ class BOTAN_DLL CurveGFp std::swap(a, other.a); std::swap(b, other.b); std::swap(p, other.p); + std::swap(reducer_p, other.reducer_p); + + std::swap(r, other.r); + std::swap(r_inv, other.r_inv); + std::swap(p_dash, other.p_dash); } bool operator==(const CurveGFp& other) const @@ -76,7 +111,13 @@ class BOTAN_DLL CurveGFp } private: + // Curve parameters BigInt p, a, b; + + // Montgomery parameters + BigInt r, r_inv, a_r; + word p_dash; + Modular_Reducer reducer_p; }; diff --git a/src/math/numbertheory/point_gfp.cpp b/src/math/numbertheory/point_gfp.cpp index db422c8aa..15a979d89 100644 --- a/src/math/numbertheory/point_gfp.cpp +++ b/src/math/numbertheory/point_gfp.cpp @@ -9,86 +9,121 @@ #include <botan/point_gfp.h> #include <botan/numthry.h> +#include <botan/mp_core.h> namespace Botan { -namespace { +PointGFp::PointGFp(const CurveGFp& curve) : + curve(curve), + coord_x(0), + coord_y(curve.get_r()), + coord_z(0) + { + } -BigInt decompress_point(bool yMod2, - const BigInt& x, - const CurveGFp& curve) +PointGFp::PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y) : + curve(curve) { - BigInt xpow3 = x * x * x; + const Modular_Reducer& mod_p = curve.mod_p(); - BigInt g = curve.get_a() * x; - g += xpow3; - g += curve.get_b(); - g = g % curve.get_p(); + coord_x = mod_p.multiply(curve.get_r(), x); + coord_y = mod_p.multiply(curve.get_r(), y); + coord_z = mod_p.reduce(curve.get_r()); + } - BigInt z = ressol(g, curve.get_p()); +BigInt PointGFp::monty_mult(const BigInt& a, const BigInt& b, + MemoryRegion<word>& workspace) + { + if(a.is_zero() || b.is_zero()) + return 0; - if(z < 0) - throw Illegal_Point("error during decompression"); + const BigInt& p = curve.get_p(); + const u32bit p_size = (workspace.size() - 1) / 2; - if(z.get_bit(0) != yMod2) - z = curve.get_p() - z; + const word p_dash = curve.get_p_dash(); - return z; - } + workspace.clear(); -} + bigint_simple_mul(workspace, + a.data(), a.sig_words(), + b.data(), b.sig_words()); -// arithmetic operators -PointGFp& PointGFp::operator+=(const PointGFp& rhs) - { - if(rhs.is_zero()) - return *this; + bigint_monty_redc(workspace, workspace.size(), + p.data(), p_size, p_dash); + + BigInt result; + result.grow_to(p_size); + copy_mem(result.get_reg().begin(), &workspace[p_size], p_size); + return result; + } + +void PointGFp::add(const PointGFp& rhs, MemoryRegion<word>& ws) + { if(is_zero()) { - *this = rhs; - return *this; + coord_x = rhs.coord_x; + coord_y = rhs.coord_y; + coord_z = rhs.coord_z; + return; } + else if(rhs.is_zero()) + return; const Modular_Reducer& mod_p = curve.mod_p(); - BigInt rhs_z2 = mod_p.square(rhs.coord_z); - BigInt U1 = mod_p.multiply(coord_x, rhs_z2); - BigInt S1 = mod_p.multiply(coord_y, mod_p.multiply(rhs.coord_z, rhs_z2)); + BigInt rhs_z2 = monty_mult(rhs.coord_z, rhs.coord_z, ws); + BigInt U1 = monty_mult(coord_x, rhs_z2, ws); + BigInt S1 = monty_mult(coord_y, monty_mult(rhs.coord_z, rhs_z2, ws), ws); - BigInt lhs_z2 = mod_p.square(coord_z); - BigInt U2 = mod_p.multiply(rhs.coord_x, lhs_z2); - BigInt S2 = mod_p.multiply(rhs.coord_y, mod_p.multiply(coord_z, lhs_z2)); + BigInt lhs_z2 = monty_mult(coord_z, coord_z, ws); + BigInt U2 = monty_mult(rhs.coord_x, lhs_z2, ws); + BigInt S2 = monty_mult(rhs.coord_y, monty_mult(coord_z, lhs_z2, ws), ws); BigInt H = mod_p.reduce(U2 - U1); + BigInt r = mod_p.reduce(S2 - S1); if(H.is_zero()) { if(r.is_zero()) { - mult2(); - return *this; + mult2(ws); + return; } *this = PointGFp(curve); // setting myself to zero - return *this; + return; } - U2 = mod_p.square(H); + U2 = monty_mult(H, H, ws); + + S2 = monty_mult(U2, H, ws); - S2 = mod_p.multiply(U2, H); + U2 = monty_mult(U1, U2, ws); - U2 = mod_p.multiply(U1, U2); + BigInt x = mod_p.reduce(monty_mult(r, r, ws) - S2 - U2*2); - BigInt x = mod_p.reduce(mod_p.square(r) - S2 - mod_p.multiply(2, U2)); - BigInt y = mod_p.reduce(mod_p.multiply(r, (U2-x)) - mod_p.multiply(S1, S2)); - BigInt z = mod_p.multiply(mod_p.multiply(coord_z, rhs.coord_z), H); + U2 -= x; + if(U2.is_negative()) + U2 += curve.get_p(); + + BigInt y = monty_mult(r, U2, ws) - monty_mult(S1, S2, ws); + if(y.is_negative()) + y += curve.get_p(); + + BigInt z = monty_mult(monty_mult(coord_z, rhs.coord_z, ws), H, ws); coord_x = x; coord_y = y; coord_z = z; + } +// arithmetic operators +PointGFp& PointGFp::operator+=(const PointGFp& rhs) + { + SecureVector<word> ws(2 * curve.get_p().sig_words() + 1); + add(rhs, ws); return *this; } @@ -106,6 +141,8 @@ PointGFp& PointGFp::operator-=(const PointGFp& rhs) PointGFp& PointGFp::operator*=(const BigInt& scalar) { + SecureVector<word> ws(2 * curve.get_p().sig_words() + 1); + if(scalar.abs() <= 2) // special cases for small values { u32bit value = scalar.abs().to_u32bit(); @@ -119,7 +156,7 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar) } else if(value == 2) { - this->mult2(); + this->mult2(ws); if(scalar.is_negative()) this->negate(); } @@ -133,31 +170,31 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar) if(scalar.is_negative()) P.negate(); - for(int i = scalar.bits() - 1; i >= 0; --i) - { - H.mult2(); - if(scalar.get_bit(i)) - H += P; - } + u32bit scalar_bits = scalar.bits(); + + PointGFp P2 = P * 2; + PointGFp P3 = P2 + P; - if(!H.is_zero()) // cannot convert if H == O + for(u32bit i = 0; i < scalar_bits - 1; i += 2) { - /** - * Convert H to an equivalent point with z == 1, thus x and y - * correspond to their affine coordinates - */ - if(H.coord_z != 1) - { - const Modular_Reducer& mod_p = curve.mod_p(); + u32bit nibble = scalar.get_substring(scalar_bits - i - 2, 2); - BigInt z_inv = inverse_mod(H.coord_z, curve.get_p()); + H.mult2(ws); + H.mult2(ws); - BigInt z_inv_2 = mod_p.square(z_inv); + if(nibble == 3) + H.add(P3, ws); + else if(nibble == 2) + H.add(P2, ws); + else if(nibble == 1) + H.add(P, ws); + } - H.coord_x = mod_p.multiply(H.coord_x, z_inv_2); - H.coord_y = mod_p.multiply(H.coord_y, mod_p.multiply(z_inv, z_inv_2)); - H.coord_z = 1; - } + if(scalar_bits % 2) + { + H.mult2(ws); + if(scalar.get_bit(0)) + H.add(P, ws); } *this = H; @@ -165,7 +202,7 @@ PointGFp& PointGFp::operator*=(const BigInt& scalar) } // *this *= 2 -void PointGFp::mult2() +void PointGFp::mult2(MemoryRegion<word>& ws) { if(is_zero()) return; @@ -177,22 +214,32 @@ void PointGFp::mult2() const Modular_Reducer& mod_p = curve.mod_p(); - BigInt y_2 = mod_p.square(coord_y); + BigInt y_2 = monty_mult(coord_y, coord_y, ws); + + BigInt S = mod_p.reduce(4 * monty_mult(coord_x, y_2, ws)); + + BigInt z4 = monty_mult(coord_z, coord_z, ws); + z4 = monty_mult(z4, z4, ws); - BigInt S = mod_p.multiply(4, mod_p.multiply(coord_x, y_2)); + BigInt a_z4 = monty_mult(curve.get_a_r(), z4, ws); - BigInt a_z4 = mod_p.multiply(curve.get_a(), - mod_p.square(mod_p.square(coord_z))); + BigInt M = mod_p.reduce(a_z4 + 3 * monty_mult(coord_x, coord_x, ws)); - BigInt M = mod_p.reduce(a_z4 + 3 * mod_p.square(coord_x)); + BigInt x = mod_p.reduce(monty_mult(M, M, ws) - 2*S); - BigInt x = mod_p.reduce(mod_p.square(M) - mod_p.multiply(2, S)); + BigInt U = mod_p.reduce(monty_mult(y_2, y_2, ws) << 3); - BigInt U = mod_p.multiply(8, mod_p.square(y_2)); + S -= x; + while(S.is_negative()) + S += curve.get_p(); - BigInt y = mod_p.reduce(mod_p.multiply(M, S - x) - U); + BigInt y = monty_mult(M, S, ws) - U; + if(y.is_negative()) + y += curve.get_p(); - BigInt z = mod_p.multiply(2, mod_p.multiply(coord_y, coord_z)); + BigInt z = 2 * monty_mult(coord_y, coord_z, ws); + if(z >= curve.get_p()) + z -= curve.get_p(); coord_x = x; coord_y = y; @@ -206,8 +253,11 @@ BigInt PointGFp::get_affine_x() const const Modular_Reducer& mod_p = curve.mod_p(); - BigInt z2 = mod_p.square(coord_z); - return mod_p.multiply(coord_x, inverse_mod(z2, curve.get_p())); + BigInt x = mod_p.multiply(curve.get_r_inv(), coord_x); + BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z); + + BigInt z2 = mod_p.square(z); + return mod_p.multiply(x, inverse_mod(z2, curve.get_p())); } BigInt PointGFp::get_affine_y() const @@ -217,8 +267,11 @@ BigInt PointGFp::get_affine_y() const const Modular_Reducer& mod_p = curve.mod_p(); - BigInt z3 = mod_p.cube(coord_z); - return mod_p.multiply(coord_y, inverse_mod(z3, curve.get_p())); + BigInt y = mod_p.multiply(curve.get_r_inv(), coord_y); + BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z); + + BigInt z3 = mod_p.cube(z); + return mod_p.multiply(y, inverse_mod(z3, curve.get_p())); } void PointGFp::check_invariants() const @@ -235,21 +288,25 @@ void PointGFp::check_invariants() const const Modular_Reducer& mod_p = curve.mod_p(); - BigInt y2 = mod_p.square(coord_y); - BigInt x3 = mod_p.cube(coord_x); + BigInt x = mod_p.multiply(curve.get_r_inv(), coord_x); + BigInt y = mod_p.multiply(curve.get_r_inv(), coord_y); + BigInt z = mod_p.multiply(curve.get_r_inv(), coord_z); + + BigInt y2 = mod_p.square(y); + BigInt x3 = mod_p.cube(x); - BigInt ax = mod_p.multiply(coord_x, curve.get_a()); + BigInt ax = mod_p.multiply(x, curve.get_a()); - if(coord_z == 1) + if(z == 1) { if(mod_p.reduce(x3 + ax + curve.get_b()) != y2) throw Illegal_Point("Invalid ECP point: y^2 != x^3 + a*x + b"); } - BigInt z2 = mod_p.square(coord_z); - BigInt z3 = mod_p.multiply(coord_z, z2); + BigInt z2 = mod_p.square(z); + BigInt z3 = mod_p.multiply(z, z2); - BigInt ax_z4 = mod_p.multiply(mod_p.multiply(z3, coord_z), ax); + BigInt ax_z4 = mod_p.multiply(mod_p.multiply(z3, z), ax); BigInt b_z6 = mod_p.multiply(curve.get_b(), mod_p.square(z3)); @@ -268,10 +325,15 @@ void PointGFp::swap(PointGFp& other) bool PointGFp::operator==(const PointGFp& other) const { - return (coord_x == other.coord_x && - coord_y == other.coord_y && - coord_z == other.coord_z && - get_curve() == other.get_curve()); + if(get_curve() != other.get_curve()) + return false; + + // If this is zero, only equal if other is also zero + if(is_zero()) + return other.is_zero(); + + return (get_affine_x() == other.get_affine_x() && + get_affine_y() == other.get_affine_y()); } // encoding and decoding @@ -326,6 +388,32 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format) throw Invalid_Argument("illegal point encoding format specification"); } +namespace { + +BigInt decompress_point(bool yMod2, + const BigInt& x, + const CurveGFp& curve) + { + BigInt xpow3 = x * x * x; + + BigInt g = curve.get_a() * x; + g += xpow3; + g += curve.get_b(); + g = g % curve.get_p(); + + BigInt z = ressol(g, curve.get_p()); + + if(z < 0) + throw Illegal_Point("error during decompression"); + + if(z.get_bit(0) != yMod2) + z = curve.get_p() - z; + + return z; + } + +} + PointGFp OS2ECP(const byte data[], u32bit data_len, const CurveGFp& curve) { diff --git a/src/math/numbertheory/point_gfp.h b/src/math/numbertheory/point_gfp.h index 2f31421fc..eaebccf49 100644 --- a/src/math/numbertheory/point_gfp.h +++ b/src/math/numbertheory/point_gfp.h @@ -46,32 +46,18 @@ class BOTAN_DLL PointGFp PointGFp() {} /** - * Construct the point O + * Construct the zero point * @param curve The base curve */ - PointGFp(const CurveGFp& curve) : - curve(curve), coord_x(0), coord_y(1), coord_z(0) {} + PointGFp(const CurveGFp& curve); /** - * Construct a point given its affine coordinates + * Construct a point from its affine coordinates * @param curve the base curve * @param x affine x coordinate * @param y affine y coordinate */ - PointGFp(const CurveGFp& curve, - const BigInt& x, const BigInt& y) : - curve(curve), coord_x(x), coord_y(y), coord_z(1) {} - - /** - * Construct a point given its jacobian projective coordinates - * @param curve the base curve - * @param x jacobian projective x coordinate - * @param y jacobian projective y coordinate - * @param z jacobian projective z coordinate - */ - PointGFp(const CurveGFp& curve, - const BigInt& x, const BigInt& y, const BigInt& z) : - curve(curve), coord_x(x), coord_y(y), coord_z(z) {} + PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y); //PointGFp(const PointGFp& other) = default; //PointGFp& operator=(const PointGFp& other) = default; @@ -129,24 +115,6 @@ class BOTAN_DLL PointGFp BigInt get_affine_y() const; /** - * get the jacobian projective x coordinate - * @result jacobian projective x coordinate - */ - const BigInt& get_x() const { return coord_x; } - - /** - * get the jacobian projective y coordinate - * @result jacobian projective y coordinate - */ - const BigInt& get_y() const { return coord_y; } - - /** - * get the jacobian projective z coordinate - * @result jacobian projective z coordinate - */ - const BigInt& get_z() const { return coord_z; } - - /** * Is this the point at infinity? * @result true, if this point is at infinity, false otherwise. */ @@ -173,9 +141,20 @@ class BOTAN_DLL PointGFp bool operator==(const PointGFp& other) const; private: /** + * Montgomery multiplication/reduction + */ + BigInt monty_mult(const BigInt& x, const BigInt& y, + MemoryRegion<word>& workspace); + + /** + * Point addition + */ + void add(const PointGFp& other, MemoryRegion<word>& workspace); + + /** * Point doubling */ - void mult2(); + void mult2(MemoryRegion<word>& workspace); CurveGFp curve; BigInt coord_x, coord_y, coord_z; diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp index 751f20583..abdf4ee55 100644 --- a/src/pubkey/pubkey.cpp +++ b/src/pubkey/pubkey.cpp @@ -117,7 +117,8 @@ SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[], */ PK_Signer::PK_Signer(const Private_Key& key, const std::string& emsa_name, - Signature_Format format) + Signature_Format format, + Fault_Protection prot) { Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); @@ -129,14 +130,14 @@ PK_Signer::PK_Signer(const Private_Key& key, if(!op) op = engine->get_signature_op(key); - if(!verify_op) + if(!verify_op && prot == ENABLE_FAULT_PROTECTION) verify_op = engine->get_verify_op(key); - if(op && verify_op) + if(op && (verify_op || prot == DISABLE_FAULT_PROTECTION)) break; } - if(!op || !verify_op) + if(!op || (!verify_op && prot == ENABLE_FAULT_PROTECTION)) throw Lookup_Error("PK_Signer: No working engine for " + key.algo_name()); @@ -202,7 +203,7 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) SecureVector<byte> plain_sig = op->sign(encoded, encoded.size(), rng); - if(!self_test_signature(encoded, plain_sig)) + if(verify_op && !self_test_signature(encoded, plain_sig)) throw Internal_Error("PK_Signer consistency check failed"); if(op->message_parts() == 1 || sig_format == IEEE_1363) diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h index c31aed67b..eeb4d5841 100644 --- a/src/pubkey/pubkey.h +++ b/src/pubkey/pubkey.h @@ -24,6 +24,14 @@ namespace Botan { enum Signature_Format { IEEE_1363, DER_SEQUENCE }; /** +* Enum marking if protection against fault attacks should be used +*/ +enum Fault_Protection { + ENABLE_FAULT_PROTECTION, + DISABLE_FAULT_PROTECTION +}; + +/** * Public Key Encryptor */ class BOTAN_DLL PK_Encryptor @@ -174,10 +182,12 @@ class BOTAN_DLL PK_Signer * @param emsa the EMSA to use * An example would be "EMSA1(SHA-224)". * @param format the signature format to use + * @param prot says if fault protection should be enabled */ PK_Signer(const Private_Key& key, const std::string& emsa, - Signature_Format format = IEEE_1363); + Signature_Format format = IEEE_1363, + Fault_Protection prot = ENABLE_FAULT_PROTECTION); ~PK_Signer() { delete op; delete verify_op; delete emsa; } private: |