/* * (C) 2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #define BOTAN_NO_DEPRECATED_WARNINGS #include "tests.h" #if defined(BOTAN_HAS_DL_GROUP) #include #include #endif namespace Botan_Tests { #if defined(BOTAN_HAS_DL_GROUP) namespace { class DL_Group_Tests final : public Test { public: std::vector run() override { std::vector results; Botan::RandomNumberGenerator& rng = Test::rng(); results.push_back(test_dl_encoding()); results.push_back(test_dl_named(rng)); results.push_back(test_dl_generate(rng)); results.push_back(test_dl_errors()); return results; } private: Test::Result test_dl_errors() { Test::Result result("DL_Group errors"); result.test_throws("Uninitialized", "DL_Group uninitialized", []() { Botan::DL_Group dl; dl.get_p(); }); if(Test::options().undefined_behavior_allowed()) { result.test_throws("Bad generator param", "DL_Group unknown PrimeType", []() { auto invalid_type = static_cast(9); Botan::DL_Group dl(Test::rng(), invalid_type, 1024); }); } return result; } Test::Result test_dl_encoding() { Test::Result result("DL_Group encoding"); const Botan::DL_Group orig("modp/ietf/1024"); const std::string pem1 = orig.PEM_encode(Botan::DL_Group::ANSI_X9_42); const std::string pem2 = orig.PEM_encode(Botan::DL_Group::ANSI_X9_57); const std::string pem3 = orig.PEM_encode(Botan::DL_Group::PKCS_3); Botan::DL_Group group1(pem1); result.test_eq("Same p in X9.42 decoding", group1.get_p(), orig.get_p()); result.test_eq("Same q in X9.42 decoding", group1.get_q(), orig.get_q()); result.test_eq("Same g in X9.42 decoding", group1.get_g(), orig.get_g()); result.test_eq("PEM encodings match", group1.PEM_encode(Botan::DL_Group::ANSI_X9_42), Botan::DL_Group::PEM_for_named_group("modp/ietf/1024")); Botan::DL_Group group2(pem2); result.test_eq("Same p in X9.57 decoding", group2.get_p(), orig.get_p()); result.test_eq("Same q in X9.57 decoding", group2.get_q(), orig.get_q()); result.test_eq("Same g in X9.57 decoding", group2.get_g(), orig.get_g()); Botan::DL_Group group3(pem3); result.test_eq("Same p in X9.57 decoding", group3.get_p(), orig.get_p()); // no q in PKCS #3 format result.test_eq("Same g in X9.57 decoding", group3.get_g(), orig.get_g()); return result; } Test::Result test_dl_generate(Botan::RandomNumberGenerator& rng) { Test::Result result("DL_Group generate"); result.start_timer(); Botan::DL_Group dh1050(rng, Botan::DL_Group::Prime_Subgroup, 1050, 175); result.test_eq("DH p size", dh1050.get_p().bits(), 1050); result.test_eq("DH q size", dh1050.get_q().bits(), 175); result.test_lte("DH g size", dh1050.get_g().bits(), 1050); result.test_eq("DH group verifies", dh1050.verify_group(rng, true), true); Botan::DL_Group dh_implicit_q(rng, Botan::DL_Group::Prime_Subgroup, 1040); result.test_eq("DH p size", dh_implicit_q.get_p().bits(), 1040); result.test_eq("DH q size", dh_implicit_q.get_q().bits(), Botan::dl_exponent_size(1040)); result.test_eq("DH group verifies", dh_implicit_q.verify_group(rng, true), true); if(Test::run_long_tests()) { Botan::DL_Group dh_strong(rng, Botan::DL_Group::Strong, 1025); result.test_eq("DH p size", dh_strong.get_p().bits(), 1025); result.test_eq("DH q size", dh_strong.get_q().bits(), 1024); result.test_eq("DH group verifies", dh_strong.verify_group(rng, true), true); } #if defined(BOTAN_HAS_SHA1) Botan::DL_Group dsa1024(rng, Botan::DL_Group::DSA_Kosherizer, 1024); result.test_eq("DSA p size", dsa1024.get_p().bits(), 1024); result.test_eq("DSA q size", dsa1024.get_q().bits(), 160); result.test_lte("DSA g size", dsa1024.get_g().bits(), 1024); result.test_eq("DSA group verifies", dsa1024.verify_group(rng, true), true); const std::vector short_seed(16); const std::vector invalid_seed(20); const std::vector working_seed = Botan::hex_decode("0000000000000000000000000000000000000021"); result.test_throws("DSA seed does not generate group", "DL_Group: The seed given does not generate a DSA group", [&rng,&invalid_seed]() { Botan::DL_Group dsa(rng, invalid_seed, 1024, 160); }); result.test_throws("DSA seed is too short", "Generating a DSA parameter set with a 160 bit long q requires a seed at least as many bits long", [&rng,&short_seed]() { Botan::DL_Group dsa(rng, short_seed, 1024, 160); }); // From FIPS 186-3 test data const std::vector seed = Botan::hex_decode("1F5DA0AF598EEADEE6E6665BF880E63D8B609BA2"); result.test_throws("invalid params", [&]() { Botan::DL_Group invalid(rng, seed, 1024, 224); }); result.test_throws("invalid params", [&]() { Botan::DL_Group invalid(rng, seed, 3072, 224); }); result.test_throws("invalid params", [&]() { Botan::DL_Group invalid(rng, seed, 2048, 256); }); Botan::DL_Group dsa_from_seed(rng, seed, 1024, 160); result.test_eq("DSA q from seed", dsa_from_seed.get_q(), Botan::BigInt("0xAB1A788BCE3C557A965A5BFA6908FAA665FDEB7D")); // Modulo just to avoid embedding entire 1024-bit P in src file result.test_eq("DSA p from seed", static_cast(dsa_from_seed.get_p() % 4294967291), size_t(2513712339)); result.test_eq("DSA group from seed verifies", dsa_from_seed.verify_group(rng, true), true); #endif result.end_timer(); return result; } Test::Result test_dl_named(Botan::RandomNumberGenerator& rng) { const std::vector dl_named = { "modp/ietf/1024", "modp/ietf/1536", "modp/ietf/2048", "modp/ietf/3072", "modp/ietf/4096", "modp/ietf/6144", "modp/ietf/8192", "modp/srp/1024", "modp/srp/1536", "modp/srp/2048", "modp/srp/3072", "modp/srp/4096", "modp/srp/6144", "modp/srp/8192", "dsa/jce/1024", "dsa/botan/2048", "dsa/botan/3072", "ffdhe/ietf/2048", "ffdhe/ietf/3072", "ffdhe/ietf/4096", "ffdhe/ietf/6144", "ffdhe/ietf/8192", }; Test::Result result("DL_Group named"); result.start_timer(); for(std::string name : dl_named) { // Confirm we can load every group we expect Botan::DL_Group group(name); result.test_ne("DL_Group p is set", group.get_p(), 0); result.test_ne("DL_Group g is set", group.get_g(), 0); const size_t strength = group.estimated_strength(); // 8192 bit ~~ 2**202 strength result.confirm("Plausible strength", strength >= 80 && strength < 210); if(name.find("modp/srp/") == std::string::npos) { result.test_ne("DL_Group q is set", group.get_q(), 0); } else { result.test_eq("DL_Group q is not set for SRP groups", group.get_q(), 0); } if(group.p_bits() < 2048 || Test::run_long_tests()) { result.test_eq(name + " verifies", group.verify_group(rng, false), true); } } result.end_timer(); return result; } }; BOTAN_REGISTER_TEST("dl_group", DL_Group_Tests); } #endif }