diff options
author | Jack Lloyd <[email protected]> | 2015-11-11 05:43:01 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-11-11 05:43:01 -0500 |
commit | cf05aea092fad448c2f4a8e8b66159237096ba8e (patch) | |
tree | 00631bcc84809a1eeac5dd32dd92c62143ef831b /src/tests/unit_ecc.cpp | |
parent | 6bb38ae2fa0e1be46b3a3256ac03f435b16a57ea (diff) |
Update and consolidate the test framework.
The tests previously had used 4 to 6 different schemes internally (the vec file
reader framework, Catch, the old InSiTo Boost.Test tests, the PK/BigInt tests
which escaped the rewrite in 1.11.7, plus a number of one-offs). Converge on a
design that works everywhere, and update all the things.
Fix also a few bugs found by the test changes: SHA-512-256 name incorrect,
OpenSSL RC4 name incorrect, signature of FFI function botan_pubkey_destroy
was wrong.
Diffstat (limited to 'src/tests/unit_ecc.cpp')
-rw-r--r-- | src/tests/unit_ecc.cpp | 1218 |
1 files changed, 550 insertions, 668 deletions
diff --git a/src/tests/unit_ecc.cpp b/src/tests/unit_ecc.cpp index bd813b37e..90d966a39 100644 --- a/src/tests/unit_ecc.cpp +++ b/src/tests/unit_ecc.cpp @@ -1,5 +1,5 @@ /* -* (C) 2009 Jack Lloyd +* (C) 2009,2015 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -7,152 +7,265 @@ #include "tests.h" #if defined(BOTAN_HAS_ECC_GROUP) + #include <botan/bigint.h> + #include <botan/numthry.h> + #include <botan/curve_gfp.h> + #include <botan/curve_nistp.h> + #include <botan/point_gfp.h> + #include <botan/ec_group.h> + #include <botan/reducer.h> + #include <botan/oids.h> + #include <botan/hex.h> +#endif + +namespace Botan_Tests { -#include <iostream> -#include <memory> -#include <botan/bigint.h> -#include <botan/hex.h> -#include <botan/numthry.h> -#include <botan/curve_gfp.h> -#include <botan/point_gfp.h> -#include <botan/ec_group.h> -#include <botan/reducer.h> -#include <botan/oids.h> - -using namespace Botan; +namespace { -#define CHECK_MESSAGE(expr, print) try { if(!(expr)) { ++fails; std::cout << "FAILURE: " << print << std::endl; }} catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << std::endl; } -#define CHECK(expr) try { if(!(expr)) { ++fails; std::cout << "FAILURE: " << #expr << std::endl; } } catch(std::exception& e) { std::cout << __FUNCTION__ << ": " << e.what() << std::endl; } +#if defined(BOTAN_HAS_ECC_GROUP) -namespace { +const std::vector<std::string> ec_groups = { + "brainpool160r1", + "brainpool192r1", + "brainpool224r1", + "brainpool256r1", + "brainpool320r1", + "brainpool384r1", + "brainpool512r1", + "gost_256A", + "secp112r1", + "secp112r2", + "secp128r1", + "secp128r2", + "secp160k1", + "secp160r1", + "secp160r2", + "secp192k1", + "secp192r1", + "secp224k1", + "secp224r1", + "secp256k1", + "secp256r1", + "secp384r1", + "secp521r1", + "x962_p192v2", + "x962_p192v3", + "x962_p239v1", + "x962_p239v2", + "x962_p239v3" + }; -std::ostream& operator<<(std::ostream& out, const PointGFp& point) +Botan::BigInt test_integer(Botan::RandomNumberGenerator& rng, size_t bits, BigInt max) { - out << "(" << point.get_affine_x() << " " << point.get_affine_y() << ")"; - return out; + /* + Produces integers with long runs of ones and zeros, for testing for + carry handling problems. + */ + Botan::BigInt x = 0; + + auto flip_prob = [](size_t i) { + if(i % 64 == 0) + return .5; + if(i % 32 == 0) + return .4; + if(i % 8 == 0) + return .05; + return .01; + }; + + bool active = rng.next_byte() % 2; + for(size_t i = 0; i != bits; ++i) + { + x <<= 1; + x += static_cast<int>(active); + + const double prob = flip_prob(i); + const double sample = double(rng.next_byte() % 100) / 100.0; // biased + + if(sample < prob) + active = !active; + } + + if(max > 0) + { + while(x >= max) + { + const size_t b = x.bits() - 1; + BOTAN_ASSERT(x.get_bit(b) == true, "Set"); + x.clear_bit(b); + } + } + + return x; } -PointGFp create_random_point(RandomNumberGenerator& rng, - const CurveGFp& curve) +Botan::PointGFp create_random_point(Botan::RandomNumberGenerator& rng, + const Botan::CurveGFp& curve) { - const BigInt& p = curve.get_p(); + const Botan::BigInt& p = curve.get_p(); - Modular_Reducer mod_p(p); + Botan::Modular_Reducer mod_p(p); while(true) { - const BigInt x = BigInt::random_integer(rng, 1, p); - const BigInt x3 = mod_p.multiply(x, mod_p.square(x)); - const BigInt ax = mod_p.multiply(curve.get_a(), x); - const BigInt y = mod_p.reduce(x3 + ax + curve.get_b()); - const BigInt sqrt_y = ressol(y, p); + const Botan::BigInt x = Botan::BigInt::random_integer(rng, 1, p); + const Botan::BigInt x3 = mod_p.multiply(x, mod_p.square(x)); + const Botan::BigInt ax = mod_p.multiply(curve.get_a(), x); + const Botan::BigInt y = mod_p.reduce(x3 + ax + curve.get_b()); + const Botan::BigInt sqrt_y = ressol(y, p); if(sqrt_y > 1) { BOTAN_ASSERT_EQUAL(mod_p.square(sqrt_y), y, "Square root is correct"); - PointGFp point(curve, x, sqrt_y); + Botan::PointGFp point(curve, x, sqrt_y); return point; } } } -size_t test_point_turn_on_sp_red_mul() +class ECC_Randomized_Tests : public Test { - size_t fails = 0; - - // setting up expected values - BigInt exp_Qx(std::string("466448783855397898016055842232266600516272889280")); - BigInt exp_Qy(std::string("1110706324081757720403272427311003102474457754220")); - BigInt exp_Qz(1); - - // 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"; - std::vector<byte> sv_p_secp = hex_decode(p_secp); - std::vector<byte> sv_a_secp = hex_decode(a_secp); - std::vector<byte> sv_b_secp = hex_decode(b_secp); - std::vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); - BigInt bi_p_secp = BigInt::decode(sv_p_secp.data(), sv_p_secp.size()); - BigInt bi_a_secp = BigInt::decode(sv_a_secp.data(), sv_a_secp.size()); - BigInt bi_b_secp = BigInt::decode(sv_b_secp.data(), sv_b_secp.size()); - CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP(sv_G_secp_comp, secp160r1); - - BigInt d("459183204582304"); - - PointGFp r1 = d * p_G; - 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() != 0); - - PointGFp p_r1 = r1; - PointGFp p_r2 = r2; - - 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() != 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() != 0); - r1 += p_G; - r2 += p_G2; - - CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul"); - - r1 += p_G; - r2 += p_G2; - - CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul for both operands"); - r1 += p_G; - r2 += p_G2; - - CHECK_MESSAGE(r1 == r2, "error with op+= after extra turn on sp red mul for both operands"); - return fails; + public: + std::vector<Test::Result> run() override; + }; + +std::vector<Test::Result> ECC_Randomized_Tests::run() + { + std::vector<Test::Result> results; + for(auto&& group_name : ec_groups) + { + Test::Result result("ECC randomized " + group_name); + + Botan::EC_Group group(group_name); + + const Botan::PointGFp& base_point = group.get_base_point(); + const Botan::BigInt& group_order = group.get_order(); + + const Botan::PointGFp inf = base_point * group_order; + result.test_eq("infinite order correct", inf.is_zero(), true); + result.test_eq("infinity on the curve", inf.on_the_curve(), true); + + try + { + for(size_t i = 0; i <= Test::soak_level(); ++i) + { + const size_t h = 1 + (Test::rng().next_byte() % 8); + Botan::Blinded_Point_Multiply blind(base_point, group_order, h); + + const Botan::BigInt a = Botan::BigInt::random_integer(Test::rng(), 2, group_order); + const Botan::BigInt b = Botan::BigInt::random_integer(Test::rng(), 2, group_order); + const Botan::BigInt c = a + b; + + const Botan::PointGFp P = base_point * a; + const Botan::PointGFp Q = base_point * b; + const Botan::PointGFp R = base_point * c; + + const Botan::PointGFp P1 = blind.blinded_multiply(a, Test::rng()); + const Botan::PointGFp Q1 = blind.blinded_multiply(b, Test::rng()); + const Botan::PointGFp R1 = blind.blinded_multiply(c, Test::rng()); + + const Botan::PointGFp A1 = P + Q; + const Botan::PointGFp A2 = Q + P; + + result.test_eq("p + q", A1, R); + result.test_eq("q + p", A2, R); + + result.test_eq("p on the curve", P.on_the_curve(), true); + result.test_eq("q on the curve", Q.on_the_curve(), true); + result.test_eq("r on the curve", R.on_the_curve(), true); + result.test_eq("a1 on the curve", A1.on_the_curve(), true); + result.test_eq("a2 on the curve", A2.on_the_curve(), true); + + result.test_eq("P1", P1, P); + result.test_eq("Q1", Q1, Q); + result.test_eq("R1", R1, R); + } + } + catch(std::exception& e) + { + result.test_failure(group_name.c_str(), e.what()); + } + results.push_back(result); + } + + return results; } -size_t test_coordinates() +BOTAN_REGISTER_TEST("ecc_randomized", ECC_Randomized_Tests); + +class NIST_Curve_Reduction_Tests : public Test { - size_t fails = 0; + public: + typedef std::function<void (Botan::BigInt&, Botan::secure_vector<Botan::word>&)> reducer_fn; + std::vector<Test::Result> run() + { + std::vector<Test::Result> results; + +#if defined(BOTAN_HAS_NIST_PRIME_REDUCERS_W32) + results.push_back(random_redc_test("P-192", Botan::prime_p192(), Botan::redc_p192)); + results.push_back(random_redc_test("P-224", Botan::prime_p224(), Botan::redc_p224)); + results.push_back(random_redc_test("P-256", Botan::prime_p256(), Botan::redc_p256)); + results.push_back(random_redc_test("P-384", Botan::prime_p384(), Botan::redc_p384)); +#endif + results.push_back(random_redc_test("P-521", Botan::prime_p521(), Botan::redc_p521)); + return results; + } + + Test::Result random_redc_test(const std::string& prime_name, + const Botan::BigInt& p, + reducer_fn redc_fn) + { + const Botan::BigInt p2 = p*p; + const size_t p_bits = p.bits(); + + Botan::Modular_Reducer p_redc(p); + Botan::secure_vector<Botan::word> ws; + + Test::Result result("NIST " + prime_name + " reduction"); + + for(size_t i = 0; i <= 10 * Test::soak_level(); ++i) + { + const Botan::BigInt x = test_integer(Test::rng(), 2*p_bits, p2); + + // TODO: time and report all three approaches + const Botan::BigInt v1 = x % p; + const Botan::BigInt v2 = p_redc.reduce(x); - BigInt exp_affine_x(std::string("16984103820118642236896513183038186009872590470")); - BigInt exp_affine_y(std::string("1373093393927139016463695321221277758035357890939")); + Botan::BigInt v3 = x; + redc_fn(v3, ws); + + if(!result.test_eq("reference redc", v1, v2) || + !result.test_eq("specialized redc", v2, v3)) + { + result.test_note("failing input" + Botan::hex_encode(Botan::BigInt::encode(x))); + } + } + + return result; + } + }; + +BOTAN_REGISTER_TEST("nist_redc", NIST_Curve_Reduction_Tests); + +Test::Result test_coordinates() + { + Test::Result result("ECC Unit"); + + const Botan::BigInt exp_affine_x("16984103820118642236896513183038186009872590470"); + const Botan::BigInt exp_affine_y("1373093393927139016463695321221277758035357890939"); // precalculation - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p0 = p_G; - PointGFp p1 = p_G * 2; - PointGFp point_exp(secp160r1, exp_affine_x, exp_affine_y); - if(!point_exp.on_the_curve()) - throw Internal_Error("Point not on the curve"); - - CHECK_MESSAGE(p1.get_affine_x() == exp_affine_x, "p1_x = " << p1.get_affine_x() << "\n" << "exp_x = " << exp_affine_x); - CHECK_MESSAGE(p1.get_affine_y() == exp_affine_y, "p1_y = " << p1.get_affine_y() << "\n" << "exp_y = " << exp_affine_y); - return fails; + const Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); + const Botan::PointGFp p0 = p_G; + const Botan::PointGFp p1 = p_G * 2; + const Botan::PointGFp point_exp(curve, exp_affine_x, exp_affine_y); + result.confirm("Point is on the curve", point_exp.on_the_curve()); + + result.test_eq("Point affine x", p1.get_affine_x(), exp_affine_x); + result.test_eq("Point affine y", p1.get_affine_y(), exp_affine_y); + return result; } @@ -167,353 +280,247 @@ Version 0.3; Section 2.1.2 -------- */ - -size_t test_point_transformation () +Test::Result test_point_transformation () { - size_t fails = 0; + Test::Result result("ECC Unit"); - // get a vailid point - EC_Group dom_pars(OID("1.3.132.0.8")); - PointGFp p = dom_pars.get_base_point(); + // get a valid point + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); + Botan::PointGFp p = dom_pars.get_base_point() * Test::rng().next_byte(); // get a copy - PointGFp q = p; + Botan::PointGFp q = p; - 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"); - return fails; + result.test_eq("affine x after copy", p.get_affine_x(), q.get_affine_x()); + result.test_eq("affine y after copy", p.get_affine_y(), q.get_affine_y()); + return result; } -size_t test_point_mult () +Test::Result test_point_mult () { - size_t fails = 0; - - EC_Group secp160r1(OIDS::lookup("secp160r1")); + Test::Result result("ECC Unit"); - const CurveGFp& curve = secp160r1.get_curve(); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_G_secp_comp = hex_decode(G_secp_comp); - PointGFp p_G = OS2ECP(sv_G_secp_comp, curve); + Botan::BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982"); + Botan::PointGFp Q_U = d_U * p_G; - BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982"); - PointGFp Q_U = d_U * p_G; - - CHECK(Q_U.get_affine_x() == BigInt("466448783855397898016055842232266600516272889280")); - CHECK(Q_U.get_affine_y() == BigInt("1110706324081757720403272427311003102474457754220")); - return fails; + result.test_eq("affine x", Q_U.get_affine_x(), Botan::BigInt("466448783855397898016055842232266600516272889280")); + result.test_eq("affine y", Q_U.get_affine_y(), Botan::BigInt("1110706324081757720403272427311003102474457754220")); + return result; } -size_t test_point_negative() +Test::Result test_point_negative() { - size_t fails = 0; - - // 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"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p1 = p_G *= 2; - - CHECK(p1.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); - CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); - - PointGFp p1_neg = p1.negate(); - - CHECK(p1_neg.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); - CHECK(p1_neg.get_affine_y() == BigInt("88408243403763901739989511495005261618427168388")); - return fails; + Test::Result result("ECC Unit"); + + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); + + const Botan::PointGFp p1 = p_G * 2; + + result.test_eq("affine x", p1.get_affine_x(), Botan::BigInt("16984103820118642236896513183038186009872590470")); + result.test_eq("affine y", p1.get_affine_y(), Botan::BigInt("1373093393927139016463695321221277758035357890939")); + + const Botan::PointGFp p1_neg = -p1; + + result.test_eq("affine x", p1_neg.get_affine_x(), p1.get_affine_x()); + result.test_eq("affine y", p1_neg.get_affine_y(), Botan::BigInt("88408243403763901739989511495005261618427168388")); + return result; } -size_t test_zeropoint() +Test::Result test_zeropoint() { - size_t fails = 0; + Test::Result result("ECC Unit"); - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); - PointGFp p1(secp160r1, - BigInt("16984103820118642236896513183038186009872590470"), - BigInt("1373093393927139016463695321221277758035357890939")); + Botan::PointGFp p1(curve, + Botan::BigInt("16984103820118642236896513183038186009872590470"), + Botan::BigInt("1373093393927139016463695321221277758035357890939")); - if(!p1.on_the_curve()) - throw Internal_Error("Point not on the curve"); + result.confirm("point is on the curve", p1.on_the_curve()); p1 -= p1; - CHECK_MESSAGE( p1.is_zero(), "p - q with q = p is not zero!"); - return fails; + result.confirm("p - q with q = p results in zero", p1.is_zero()); + return result; } -size_t test_zeropoint_enc_dec() +Test::Result test_zeropoint_enc_dec() { - size_t fails = 0; + Test::Result result("ECC Unit"); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); - PointGFp p(curve); - CHECK_MESSAGE( p.is_zero(), "by constructor created zeropoint is no zeropoint!"); + Botan::PointGFp p(curve); + result.confirm("zero point is zero", p.is_zero()); + std::vector<byte> sv_p = unlock(EC2OSP(p, Botan::PointGFp::UNCOMPRESSED)); + result.test_eq("encoded/decode rt works", OS2ECP(sv_p, curve), p); - std::vector<byte> sv_p = unlock(EC2OSP(p, PointGFp::UNCOMPRESSED)); - PointGFp p_encdec = OS2ECP(sv_p, curve); - CHECK_MESSAGE( p == p_encdec, "encoded-decoded (uncompressed) point is not equal the original!"); + sv_p = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED)); + result.test_eq("encoded/decode compressed rt works", OS2ECP(sv_p, curve), p); - sv_p = unlock(EC2OSP(p, PointGFp::UNCOMPRESSED)); - p_encdec = OS2ECP(sv_p, curve); - CHECK_MESSAGE( p == p_encdec, "encoded-decoded (compressed) point is not equal the original!"); - - sv_p = unlock(EC2OSP(p, PointGFp::HYBRID)); - p_encdec = OS2ECP(sv_p, curve); - CHECK_MESSAGE( p == p_encdec, "encoded-decoded (hybrid) point is not equal the original!"); - return fails; + sv_p = unlock(EC2OSP(p, Botan::PointGFp::HYBRID)); + result.test_eq("encoded/decode hybrid rt works", OS2ECP(sv_p, curve), p); + return result; } -size_t test_calc_with_zeropoint() +Test::Result test_calc_with_zeropoint() { - size_t fails = 0; + Test::Result result("ECC Unit"); - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a_secp("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b_secp("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); - PointGFp p(curve, - BigInt("16984103820118642236896513183038186009872590470"), - BigInt("1373093393927139016463695321221277758035357890939")); + Botan::PointGFp p(curve, + Botan::BigInt("16984103820118642236896513183038186009872590470"), + Botan::BigInt("1373093393927139016463695321221277758035357890939")); - if(!p.on_the_curve()) - throw Internal_Error("Point not on the curve"); - CHECK_MESSAGE( !p.is_zero(), "created is zeropoint, shouldn't be!"); + result.confirm("point is on the curve", p.on_the_curve()); + result.confirm("point is not zero", !p.is_zero()); - PointGFp zero(curve); - CHECK_MESSAGE( zero.is_zero(), "by constructor created zeropoint is no zeropoint!"); + Botan::PointGFp zero(curve); + result.confirm("zero point is zero", zero.is_zero()); - PointGFp res = p + zero; - CHECK_MESSAGE( res == p, "point + zeropoint is not equal the point"); + Botan::PointGFp res = p + zero; + result.test_eq("point + 0 equals the point", p, res); res = p - zero; - CHECK_MESSAGE( res == p, "point - zeropoint is not equal the point"); + result.test_eq("point - 0 equals the point", p, res); res = zero * 32432243; - CHECK_MESSAGE( res.is_zero(), "zeropoint * skalar is not a zero-point!"); - return fails; + result.confirm("point * 0 is the zero point", res.is_zero()); + return result; } -size_t test_add_point() +Test::Result test_add_point() { - size_t fails = 0; + Test::Result result("ECC Unit"); // precalculation - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p0 = p_G; - PointGFp p1 = p_G *= 2; + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); + + Botan::PointGFp p0 = p_G; + Botan::PointGFp p1 = p_G * 2; p1 += p0; - PointGFp expected(secp160r1, - BigInt("704859595002530890444080436569091156047721708633"), - BigInt("1147993098458695153857594941635310323215433166682")); + Botan::PointGFp expected(curve, + Botan::BigInt("704859595002530890444080436569091156047721708633"), + Botan::BigInt("1147993098458695153857594941635310323215433166682")); - CHECK(p1 == expected); - return fails; + result.test_eq("point addition", p1, expected); + return result; } -size_t test_sub_point() +Test::Result test_sub_point() { - size_t fails = 0; + Test::Result result("ECC Unit"); - //Setting up expected values - BigInt exp_sub_x(std::string("112913490230515010376958384252467223283065196552")); - BigInt exp_sub_y(std::string("143464803917389475471159193867377888720776527730")); - BigInt exp_sub_z(std::string("562006223742588575209908669014372619804457947208")); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); - // precalculation - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p0 = p_G; - PointGFp p1 = p_G *= 2; + Botan::PointGFp p0 = p_G; + Botan::PointGFp p1 = p_G * 2; p1 -= p0; - PointGFp expected(secp160r1, - BigInt("425826231723888350446541592701409065913635568770"), - BigInt("203520114162904107873991457957346892027982641970")); + Botan::PointGFp expected(curve, + Botan::BigInt("425826231723888350446541592701409065913635568770"), + Botan::BigInt("203520114162904107873991457957346892027982641970")); - CHECK(p1 == expected); - return fails; + result.test_eq("point subtraction", p1, expected); + return result; } -size_t test_mult_point() +Test::Result test_mult_point() { - size_t fails = 0; + Test::Result result("ECC Unit"); - //Setting up expected values - BigInt exp_mult_x(std::string("967697346845926834906555988570157345422864716250")); - BigInt exp_mult_y(std::string("512319768365374654866290830075237814703869061656")); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); - // precalculation - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p0 = p_G; - PointGFp p1 = p_G *= 2; + Botan::PointGFp p0 = p_G; + Botan::PointGFp p1 = p_G * 2; p1 *= p0.get_affine_x(); - PointGFp expected(secp160r1, exp_mult_x, exp_mult_y); + const Botan::BigInt exp_mult_x(std::string("967697346845926834906555988570157345422864716250")); + const Botan::BigInt exp_mult_y(std::string("512319768365374654866290830075237814703869061656")); + Botan::PointGFp expected(curve, exp_mult_x, exp_mult_y); - CHECK(p1 == expected); - return fails; + result.test_eq("point mult", p1, expected); + return result; } -size_t test_basic_operations() +Test::Result test_basic_operations() { - size_t fails = 0; + Test::Result result("ECC Unit"); // precalculation - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffc"; - std::string b_secp = "1c97befc54bd7a8b65acf89f81d4d4adc565fa45"; - std::string G_secp_comp = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), 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 p0 = p_G; + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + const Botan::PointGFp& p_G = secp160r1.get_base_point(); - PointGFp expected(secp160r1, - BigInt("425826231723888350446541592701409065913635568770"), - BigInt("203520114162904107873991457957346892027982641970")); + const Botan::PointGFp p0 = p_G; + const Botan::PointGFp p1 = p_G * 2; - CHECK(p0 == expected); + result.test_eq("p1 affine x", p1.get_affine_x(), Botan::BigInt("16984103820118642236896513183038186009872590470")); + result.test_eq("p1 affine y", p1.get_affine_y(), Botan::BigInt("1373093393927139016463695321221277758035357890939")); - PointGFp p1 = p_G *= 2; + const Botan::PointGFp simplePlus = p1 + p0; + const Botan::PointGFp exp_simplePlus(curve, + Botan::BigInt("704859595002530890444080436569091156047721708633"), + Botan::BigInt("1147993098458695153857594941635310323215433166682")); - CHECK(p1.get_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); - CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); + result.test_eq("point addition", simplePlus, exp_simplePlus); - PointGFp simplePlus= p1 + p0; - PointGFp exp_simplePlus(secp160r1, - BigInt("704859595002530890444080436569091156047721708633"), - BigInt("1147993098458695153857594941635310323215433166682")); - if(simplePlus != exp_simplePlus) - std::cout << simplePlus << " != " << exp_simplePlus << std::endl; + const Botan::PointGFp simpleMinus = p1 - p0; + const Botan::PointGFp exp_simpleMinus(curve, + Botan::BigInt("425826231723888350446541592701409065913635568770"), + Botan::BigInt("203520114162904107873991457957346892027982641970")); - PointGFp simpleMinus= p1 - p0; - PointGFp exp_simpleMinus(secp160r1, - BigInt("425826231723888350446541592701409065913635568770"), - BigInt("203520114162904107873991457957346892027982641970")); + result.test_eq("point subtraction", simpleMinus, exp_simpleMinus); - CHECK(simpleMinus == exp_simpleMinus); + const Botan::PointGFp simpleMult = p1 * 123456789; - PointGFp simpleMult= p1 * 123456789; + result.test_eq("point mult affine x", simpleMult.get_affine_x(), + Botan::BigInt("43638877777452195295055270548491599621118743290")); + result.test_eq("point mult affine y", simpleMult.get_affine_y(), + Botan::BigInt("56841378500012376527163928510402662349220202981")); - 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_affine_x() == BigInt("16984103820118642236896513183038186009872590470")); - CHECK(p1.get_affine_y() == BigInt("1373093393927139016463695321221277758035357890939")); - - CHECK(p0.get_affine_x() == BigInt("425826231723888350446541592701409065913635568770")); - CHECK(p0.get_affine_y() == BigInt("203520114162904107873991457957346892027982641970")); - return fails; + return result; } -size_t test_enc_dec_compressed_160() +Test::Result test_enc_dec_compressed_160() { - size_t fails = 0; + Test::Result result("ECC Unit"); // Test for compressed conversion (02/03) 160bit - std::string p_secp = "ffffffffffffffffffffffffffffffff7fffffff"; - std::string a_secp = "ffffffffffffffffffffffffffffffff7ffffffC"; - std::string b_secp = "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"; - std::string G_secp_comp = "024A96B5688EF573284664698968C38BB913CBFC82"; - std::string G_order_secp_comp = "0100000000000000000001F4C8F927AED3CA752257"; - - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + const std::vector<byte> G_comp = Botan::hex_decode("024A96B5688EF573284664698968C38BB913CBFC82"); - CurveGFp secp160r1(bi_p_secp, bi_a_secp, bi_b_secp); + const Botan::PointGFp p = Botan::OS2ECP(G_comp, curve); - PointGFp p_G = OS2ECP ( sv_G_secp_comp, secp160r1 ); - std::vector<byte> sv_result = unlock(EC2OSP(p_G, PointGFp::COMPRESSED)); + std::vector<byte> sv_result = unlock(Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED)); - CHECK( sv_result == sv_G_secp_comp); - return fails; + result.test_eq("result", sv_result, G_comp); + return result; } -size_t test_enc_dec_compressed_256() +Test::Result test_enc_dec_compressed_256() { - size_t fails = 0; + Test::Result result("ECC Unit"); // Test for compressed conversion (02/03) 256bit std::string p_secp = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"; @@ -522,28 +529,28 @@ size_t test_enc_dec_compressed_256() std::string G_secp_comp = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; std::string G_order_secp_comp = "ffffffff00000000ffffffffffffffffBCE6FAADA7179E84F3B9CAC2FC632551"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_comp = hex_decode ( G_secp_comp ); + std::vector<byte> sv_p_secp = Botan::hex_decode ( p_secp ); + std::vector<byte> sv_a_secp = Botan::hex_decode ( a_secp ); + std::vector<byte> sv_b_secp = Botan::hex_decode ( b_secp ); + std::vector<byte> sv_G_secp_comp = Botan::hex_decode ( G_secp_comp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + Botan::BigInt bi_p_secp = Botan::BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); + Botan::BigInt bi_a_secp = Botan::BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); + Botan::BigInt bi_b_secp = Botan::BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve ); - std::vector<byte> sv_result = unlock(EC2OSP(p_G, PointGFp::COMPRESSED)); + Botan::PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve ); + std::vector<byte> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::COMPRESSED)); - CHECK( sv_result == sv_G_secp_comp); - return fails; + result.test_eq("compressed_256", sv_result, sv_G_secp_comp); + return result; } -size_t test_enc_dec_uncompressed_112() +Test::Result test_enc_dec_uncompressed_112() { - size_t fails = 0; + Test::Result result("ECC Unit"); // Test for uncompressed conversion (04) 112bit @@ -553,27 +560,27 @@ size_t test_enc_dec_uncompressed_112() std::string G_secp_uncomp = "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97"; std::string G_order_secp_uncomp = "36DF0AAFD8B8D7597CA10520D04B"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + std::vector<byte> sv_p_secp = Botan::hex_decode ( p_secp ); + std::vector<byte> sv_a_secp = Botan::hex_decode ( a_secp ); + std::vector<byte> sv_b_secp = Botan::hex_decode ( b_secp ); + std::vector<byte> sv_G_secp_uncomp = Botan::hex_decode ( G_secp_uncomp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + Botan::BigInt bi_p_secp = Botan::BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); + Botan::BigInt bi_a_secp = Botan::BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); + Botan::BigInt bi_b_secp = Botan::BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, curve ); - std::vector<byte> sv_result = unlock(EC2OSP(p_G, PointGFp::UNCOMPRESSED)); + Botan::PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, curve ); + std::vector<byte> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::UNCOMPRESSED)); - CHECK( sv_result == sv_G_secp_uncomp); - return fails; + result.test_eq("uncompressed_112", sv_result, sv_G_secp_uncomp); + return result; } -size_t test_enc_dec_uncompressed_521() +Test::Result test_enc_dec_uncompressed_521() { - size_t fails = 0; + Test::Result result("ECC Unit"); // Test for uncompressed conversion(04) with big values(521 bit) std::string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; @@ -582,30 +589,28 @@ size_t test_enc_dec_uncompressed_521() std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + std::vector<byte> sv_p_secp = Botan::hex_decode ( p_secp ); + std::vector<byte> sv_a_secp = Botan::hex_decode ( a_secp ); + std::vector<byte> sv_b_secp = Botan::hex_decode ( b_secp ); + std::vector<byte> sv_G_secp_uncomp = Botan::hex_decode ( G_secp_uncomp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + Botan::BigInt bi_p_secp = Botan::BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); + Botan::BigInt bi_a_secp = Botan::BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); + Botan::BigInt bi_b_secp = Botan::BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP ( sv_G_secp_uncomp, curve ); + Botan::PointGFp p_G = Botan::OS2ECP ( sv_G_secp_uncomp, curve ); - std::vector<byte> sv_result = unlock(EC2OSP(p_G, PointGFp::UNCOMPRESSED)); - std::string result = hex_encode(sv_result.data(), sv_result.size()); - std::string exp_result = hex_encode(sv_G_secp_uncomp.data(), sv_G_secp_uncomp.size()); + std::vector<byte> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::UNCOMPRESSED)); - CHECK_MESSAGE(sv_result == sv_G_secp_uncomp, "calc. result = " << result << "\nexp. result = " << exp_result); - return fails; + result.test_eq("expected", sv_result, sv_G_secp_uncomp); + return result; } -size_t test_enc_dec_uncompressed_521_prime_too_large() +Test::Result test_enc_dec_uncompressed_521_prime_too_large() { - size_t fails = 0; + Test::Result result("ECC Unit"); // Test for uncompressed conversion(04) with big values(521 bit) std::string p_secp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; // length increased by "ff" @@ -614,344 +619,221 @@ size_t test_enc_dec_uncompressed_521_prime_too_large() std::string G_secp_uncomp = "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2ffA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"; std::string G_order_secp_uncomp = "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"; - std::vector<byte> sv_p_secp = hex_decode ( p_secp ); - std::vector<byte> sv_a_secp = hex_decode ( a_secp ); - std::vector<byte> sv_b_secp = hex_decode ( b_secp ); - std::vector<byte> sv_G_secp_uncomp = hex_decode ( G_secp_uncomp ); + std::vector<byte> sv_p_secp = Botan::hex_decode ( p_secp ); + std::vector<byte> sv_a_secp = Botan::hex_decode ( a_secp ); + std::vector<byte> sv_b_secp = Botan::hex_decode ( b_secp ); + std::vector<byte> sv_G_secp_uncomp = Botan::hex_decode ( G_secp_uncomp ); - BigInt bi_p_secp = BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); - BigInt bi_a_secp = BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); - BigInt bi_b_secp = BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + Botan::BigInt bi_p_secp = Botan::BigInt::decode ( sv_p_secp.data(), sv_p_secp.size() ); + Botan::BigInt bi_a_secp = Botan::BigInt::decode ( sv_a_secp.data(), sv_a_secp.size() ); + Botan::BigInt bi_b_secp = Botan::BigInt::decode ( sv_b_secp.data(), sv_b_secp.size() ); + + Botan::CurveGFp secp521r1 (bi_p_secp, bi_a_secp, bi_b_secp); + std::unique_ptr<Botan::PointGFp> p_G; - CurveGFp secp521r1 (bi_p_secp, bi_a_secp, bi_b_secp); - std::unique_ptr<PointGFp> p_G; - bool exc = false; try { - p_G = std::unique_ptr<PointGFp>(new PointGFp(OS2ECP ( sv_G_secp_uncomp, secp521r1))); - if(!p_G->on_the_curve()) - throw Internal_Error("Point not on the curve"); + p_G = std::unique_ptr<Botan::PointGFp>(new Botan::PointGFp(Botan::OS2ECP ( sv_G_secp_uncomp, secp521r1))); + result.test_failure("point decoding with too large value accepted"); } - catch (std::exception e) + catch(std::exception& e) { - exc = true; + result.test_note("rejected invalid point"); } - CHECK_MESSAGE(exc, "attempt of creation of point on curve with too high prime did not throw an exception"); - return fails; + return result; } -size_t test_gfp_store_restore() +Test::Result test_gfp_store_restore() { - size_t fails = 0; + Test::Result result("ECC Unit"); // generate point - //EC_Group dom_pars = global_config().get_ec_dompar("1.3.132.0.8"); - //EC_Group dom_pars("1.3.132.0.8"); - EC_Group dom_pars(OID("1.3.132.0.8")); - PointGFp p = dom_pars.get_base_point(); + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); + Botan::PointGFp p = dom_pars.get_base_point(); - //store point (to std::string) - std::vector<byte> sv_mes = unlock(EC2OSP(p, PointGFp::COMPRESSED)); - PointGFp new_p = OS2ECP(sv_mes, dom_pars.get_curve()); + std::vector<byte> sv_mes = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED)); + Botan::PointGFp new_p = Botan::OS2ECP(sv_mes, dom_pars.get_curve()); - CHECK_MESSAGE( p == new_p, "original and restored point are different!"); - return fails; + result.test_eq("original and restored points are same", p, new_p); + return result; } // maybe move this test -size_t test_cdc_curve_33() +Test::Result test_cdc_curve_33() { - size_t fails = 0; + Test::Result result("ECC Unit"); std::string G_secp_uncomp = "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7"; - std::vector<byte> sv_G_uncomp = hex_decode ( G_secp_uncomp ); + std::vector<byte> sv_G_uncomp = Botan::hex_decode ( G_secp_uncomp ); - BigInt bi_p_secp = BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809"); - BigInt bi_a_secp("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe"); - BigInt bi_b_secp("0xa9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7"); + Botan::BigInt bi_p_secp = Botan::BigInt("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809"); + Botan::BigInt bi_a_secp("0xa377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe"); + Botan::BigInt bi_b_secp("0xa9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7"); - CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); - PointGFp p_G = OS2ECP ( sv_G_uncomp, curve); - bool exc = false; - try - { - if(!p_G.on_the_curve()) - throw Internal_Error("Point not on the curve"); - } - catch (std::exception) - { - exc = true; - } - CHECK(!exc); - return fails; + Botan::CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); + Botan::PointGFp p_G = Botan::OS2ECP ( sv_G_uncomp, curve); + result.confirm("point is on the curve", p_G.on_the_curve()); + return result; } -size_t test_more_zeropoint() +Test::Result test_more_zeropoint() { - size_t fails = 0; + Test::Result result("ECC Unit"); // by Falko + Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1")); + const Botan::CurveGFp& curve = secp160r1.get_curve(); + std::string G = "024a96b5688ef573284664698968c38bb913cbfc82"; - std::vector<byte> sv_G_secp_comp = hex_decode ( G ); - BigInt bi_p("0xffffffffffffffffffffffffffffffff7fffffff"); - BigInt bi_a("0xffffffffffffffffffffffffffffffff7ffffffc"); - BigInt bi_b("0x1c97befc54bd7a8b65acf89f81d4d4adc565fa45"); - CurveGFp curve(bi_p, bi_a, bi_b); - - PointGFp p1(curve, - BigInt("16984103820118642236896513183038186009872590470"), - BigInt("1373093393927139016463695321221277758035357890939")); - - if(!p1.on_the_curve()) - throw Internal_Error("Point not on the curve"); - PointGFp minus_p1 = -p1; - if(!minus_p1.on_the_curve()) - throw Internal_Error("Point not on the curve"); - PointGFp shouldBeZero = p1 + minus_p1; - if(!shouldBeZero.on_the_curve()) - throw Internal_Error("Point not on the curve"); - - BigInt y1 = p1.get_affine_y(); + std::vector<byte> sv_G_secp_comp = Botan::hex_decode ( G ); + + Botan::PointGFp p1(curve, + Botan::BigInt("16984103820118642236896513183038186009872590470"), + Botan::BigInt("1373093393927139016463695321221277758035357890939")); + + result.confirm("point is on the curve", p1.on_the_curve()); + Botan::PointGFp minus_p1 = -p1; + result.confirm("point is on the curve", minus_p1.on_the_curve()); + Botan::PointGFp shouldBeZero = p1 + minus_p1; + result.confirm("point is on the curve", shouldBeZero.on_the_curve()); + result.confirm("point is zero", shouldBeZero.is_zero()); + + Botan::BigInt y1 = p1.get_affine_y(); y1 = curve.get_p() - y1; - CHECK_MESSAGE(p1.get_affine_x() == minus_p1.get_affine_x(), - "problem with minus_p1 : x"); - CHECK_MESSAGE(minus_p1.get_affine_y() == y1, - "problem with minus_p1 : y"); + result.test_eq("minus point x", minus_p1.get_affine_x(), p1.get_affine_x()); + result.test_eq("minus point y", minus_p1.get_affine_y(), y1); - PointGFp zero(curve); - if(!zero.on_the_curve()) - throw Internal_Error("Point not on the curve"); - CHECK_MESSAGE(p1 + zero == p1, "addition of zero modified point"); + Botan::PointGFp zero(curve); + result.confirm("zero point is on the curve", zero.on_the_curve()); + result.test_eq("addition of zero does nothing", p1, p1 + zero); - CHECK_MESSAGE( shouldBeZero.is_zero(), "p - q with q = p is not zero!"); - return fails; + return result; } -size_t test_mult_by_order() +Test::Result test_mult_by_order() { - size_t fails = 0; + Test::Result result("ECC Unit"); // generate point - EC_Group dom_pars(OID("1.3.132.0.8")); - PointGFp p = dom_pars.get_base_point(); - PointGFp shouldBeZero = p * dom_pars.get_order(); + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); + Botan::PointGFp p = dom_pars.get_base_point(); + Botan::PointGFp shouldBeZero = p * dom_pars.get_order(); - CHECK_MESSAGE(shouldBeZero.is_zero(), "G * order != O"); - return fails; + result.confirm("G * order = 0", shouldBeZero.is_zero()); + return result; } -size_t test_point_swap() +Test::Result test_point_swap() { - size_t fails = 0; - - EC_Group dom_pars(OID("1.3.132.0.8")); + Test::Result result("ECC Unit"); - auto& rng = test_rng(); + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); - PointGFp a(create_random_point(rng, dom_pars.get_curve())); - PointGFp b(create_random_point(rng, dom_pars.get_curve())); - b *= BigInt(rng, 20); + Botan::PointGFp a(create_random_point(Test::rng(), dom_pars.get_curve())); + Botan::PointGFp b(create_random_point(Test::rng(), dom_pars.get_curve())); + b *= Botan::BigInt(Test::rng(), 20); - PointGFp c(a); - PointGFp d(b); + Botan::PointGFp c(a); + Botan::PointGFp d(b); d.swap(c); - CHECK(a == d); - CHECK(b == c); + result.test_eq("swap correct", a, d); + result.test_eq("swap correct", b, c); - return fails; + return result; } /** * This test verifies that the side channel attack resistant multiplication function * yields the same result as the normal (insecure) multiplication via operator*= */ -size_t test_mult_sec_mass() +Test::Result test_mult_sec_mass() { - size_t fails = 0; - - auto& rng = test_rng(); + Test::Result result("ECC Unit"); - EC_Group dom_pars(OID("1.3.132.0.8")); + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); for(int i = 0; i<50; i++) { try { - PointGFp a(create_random_point(rng, dom_pars.get_curve())); - BigInt scal(BigInt(rng, 40)); - PointGFp b = a * scal; - PointGFp c(a); + Botan::PointGFp a(create_random_point(Test::rng(), dom_pars.get_curve())); + Botan::BigInt scal(Botan::BigInt(Test::rng(), 40)); + Botan::PointGFp b = a * scal; + Botan::PointGFp c(a); c *= scal; - CHECK(b == c); + result.test_eq("same result", b, c); } catch(std::exception& e) { - std::cout << "test_mult_sec_mass failed: " << e.what() << std::endl; - ++fails; + result.test_failure("mult_sec_mass", e.what()); } } - return fails; + return result; } -size_t test_curve_cp_ctor() +Test::Result test_curve_cp_ctor() { + Test::Result result("ECC Unit"); + try { - EC_Group dom_pars(OID("1.3.132.0.8")); - CurveGFp curve(dom_pars.get_curve()); + Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8")); + Botan::CurveGFp curve(dom_pars.get_curve()); } - catch(...) + catch(std::exception& e) { - return 1; - + result.test_failure("curve_cp_ctor", e.what()); } - return 0; + return result; } -namespace { - -const std::vector<std::string> ec_groups = { - "brainpool160r1", - "brainpool192r1", - "brainpool224r1", - "brainpool256r1", - "brainpool320r1", - "brainpool384r1", - "brainpool512r1", - "gost_256A", - "secp112r1", - "secp112r2", - "secp128r1", - "secp128r2", - "secp160k1", - "secp160r1", - "secp160r2", - "secp192k1", - "secp192r1", - "secp224k1", - "secp224r1", - "secp256k1", - "secp256r1", - "secp384r1", - "secp521r1", - "x962_p192v2", - "x962_p192v3", - "x962_p239v1", - "x962_p239v2", - "x962_p239v3" - }; - -} - -} - -BOTAN_TEST_CASE(ecc_randomized, "ECC Randomized", { - auto& rng = test_rng(); - size_t fails = 0; - size_t tests = 0; - - for(auto&& group_name : ec_groups) - { - EC_Group group(group_name); - - const PointGFp& base_point = group.get_base_point(); - const BigInt& group_order = group.get_order(); - - const PointGFp inf = base_point * group_order; - BOTAN_CONFIRM(inf.is_zero(), "Group math ok"); - BOTAN_CONFIRM(inf.on_the_curve(), "Infinity still on the curve"); - - try - { - for(size_t i = 0; i != 10; ++i) - { - ++tests; - - const size_t h = 1 + (rng.next_byte() % 8); - Blinded_Point_Multiply blind(base_point, group_order, h); - - const BigInt a = BigInt::random_integer(rng, 2, group_order); - const BigInt b = BigInt::random_integer(rng, 2, group_order); - const BigInt c = a + b; - - const PointGFp P = base_point * a; - const PointGFp Q = base_point * b; - const PointGFp R = base_point * c; - - const PointGFp P1 = blind.blinded_multiply(a, rng); - const PointGFp Q1 = blind.blinded_multiply(b, rng); - const PointGFp R1 = blind.blinded_multiply(c, rng); - - const PointGFp A1 = P + Q; - const PointGFp A2 = Q + P; - - BOTAN_TEST(A1, R, "Addition"); - BOTAN_TEST(A2, R, "Addition"); - BOTAN_CONFIRM(P.on_the_curve(), "On the curve"); - BOTAN_CONFIRM(Q.on_the_curve(), "On the curve"); - BOTAN_CONFIRM(R.on_the_curve(), "On the curve"); - BOTAN_CONFIRM(A1.on_the_curve(), "On the curve"); - BOTAN_CONFIRM(A2.on_the_curve(), "On the curve"); - - BOTAN_TEST(P, P1, "P1"); - BOTAN_TEST(Q, Q1, "Q1"); - BOTAN_TEST(R, R1, "R1"); - } - } - catch(std::exception& e) +class ECC_Unit_Tests : public Test + { + public: + std::vector<Test::Result> run() override { - std::cout << "Testing " << group_name << " failed: " << e.what() << std::endl; - ++fails; + std::vector<Test::Result> results; + + results.push_back(test_coordinates()); + results.push_back(test_point_transformation ()); + results.push_back(test_point_mult ()); + results.push_back(test_point_negative()); + results.push_back(test_zeropoint()); + results.push_back(test_zeropoint_enc_dec()); + results.push_back(test_calc_with_zeropoint()); + results.push_back(test_add_point()); + results.push_back(test_sub_point()); + results.push_back(test_mult_point()); + results.push_back(test_basic_operations()); + results.push_back(test_enc_dec_compressed_160()); + results.push_back(test_enc_dec_compressed_256()); + results.push_back(test_enc_dec_uncompressed_112()); + results.push_back(test_enc_dec_uncompressed_521()); + results.push_back(test_enc_dec_uncompressed_521_prime_too_large()); + results.push_back(test_gfp_store_restore()); + results.push_back(test_cdc_curve_33()); + results.push_back(test_more_zeropoint()); + results.push_back(test_mult_by_order()); + results.push_back(test_point_swap()); + results.push_back(test_mult_sec_mass()); + results.push_back(test_curve_cp_ctor()); + + return results; } - } - }); - + }; -size_t test_ecc_unit() - { - size_t fails = 0; - - fails += test_point_turn_on_sp_red_mul(); - fails += test_coordinates(); - fails += test_point_transformation (); - fails += test_point_mult (); - fails += test_point_negative(); - fails += test_zeropoint(); - fails += test_zeropoint_enc_dec(); - fails += test_calc_with_zeropoint(); - fails += test_add_point(); - fails += test_sub_point(); - fails += test_mult_point(); - fails += test_basic_operations(); - fails += test_enc_dec_compressed_160(); - fails += test_enc_dec_compressed_256(); - fails += test_enc_dec_uncompressed_112(); - fails += test_enc_dec_uncompressed_521(); - fails += test_enc_dec_uncompressed_521_prime_too_large(); - fails += test_gfp_store_restore(); - fails += test_cdc_curve_33(); - fails += test_more_zeropoint(); - fails += test_mult_by_order(); - fails += test_point_swap(); - fails += test_mult_sec_mass(); - fails += test_curve_cp_ctor(); - - test_report("ECC", 0, fails); - - return fails; - } +BOTAN_REGISTER_TEST("ecc_unit", ECC_Unit_Tests); -#else +#endif -SKIP_TEST(ecc_unit); -SKIP_TEST(ecc_randomized); +} -#endif // BOTAN_HAS_ECC_GROUP +} |