diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build-data/makefile.in | 17 | ||||
-rw-r--r-- | src/build-data/os/openbsd.txt | 2 | ||||
-rw-r--r-- | src/cli/pubkey.cpp | 10 | ||||
-rw-r--r-- | src/lib/asn1/asn1_time.cpp | 21 | ||||
-rw-r--r-- | src/lib/asn1/asn1_time.h | 2 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/curve_gfp.cpp | 14 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/curve_gfp.h | 7 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/point_gfp.cpp | 49 | ||||
-rw-r--r-- | src/lib/pubkey/xmss/xmss_tools.cpp | 16 | ||||
-rw-r--r-- | src/tests/data/asn1_time.vec | 37 | ||||
-rw-r--r-- | src/tests/test_asn1.cpp | 45 |
11 files changed, 182 insertions, 38 deletions
diff --git a/src/build-data/makefile.in b/src/build-data/makefile.in index 2039ade4e..5b408c016 100644 --- a/src/build-data/makefile.in +++ b/src/build-data/makefile.in @@ -14,6 +14,7 @@ SO_OBJ_FLAGS = %{shared_flags} LDFLAGS = %{ldflags} EXE_LINK_CMD = %{exe_link_cmd} +POST_LINK_CMD = %{post_link_cmd} LIB_LINKS_TO = %{link_to} EXE_LINKS_TO = %{link_to_botan} $(LIB_LINKS_TO) @@ -65,11 +66,11 @@ TESTOBJS = %{join test_objs} $(CLI): $(LIBRARIES) $(CLIOBJS) $(EXE_LINK_CMD) $(LDFLAGS) $(CLIOBJS) $(EXE_LINKS_TO) %{output_to_exe}$@ - %{post_link_cmd} + $(POST_LINK_CMD) $(TEST): $(LIBRARIES) $(TESTOBJS) $(EXE_LINK_CMD) $(LDFLAGS) $(TESTOBJS) $(EXE_LINKS_TO) %{output_to_exe}$@ - %{post_link_cmd} + $(POST_LINK_CMD) %{if build_fuzzers} @@ -94,20 +95,14 @@ fuzzer_corpus_zip: fuzzer_corpus %{endif} -%{if build_unix_shared_lib} +%{if build_shared_lib} %{out_dir}/%{shared_lib_name}: $(LIBOBJS) %{lib_link_cmd} $(LDFLAGS) $(LIBOBJS) $(LIB_LINKS_TO) %{output_to_exe}$@ +%{endif} +%{if symlink_shared_lib} cd %{out_dir} && ln -fs %{shared_lib_name} %{soname_base} cd %{out_dir} && ln -fs %{shared_lib_name} %{soname_patch} - -%{endif} - -%{if build_msvc_shared_lib} - -%{out_dir}/%{shared_lib_name}: $(LIBOBJS) - %{lib_link_cmd} $(LDFLAGS) $(LIBOBJS) $(LIB_LINKS_TO) %{output_to_exe}$@ - %{endif} # Build Commands diff --git a/src/build-data/os/openbsd.txt b/src/build-data/os/openbsd.txt index 5ba148e66..ad35da15b 100644 --- a/src/build-data/os/openbsd.txt +++ b/src/build-data/os/openbsd.txt @@ -1,6 +1,6 @@ soname_pattern_base "lib{libname}.so" -soname_pattern_abi "lib{libname}.so.{abi_rev}" +soname_pattern_abi "lib{libname}.so.{abi_rev}.{version_minor}" soname_pattern_patch "lib{libname}.so.{abi_rev}.{version_minor}" <target_features> diff --git a/src/cli/pubkey.cpp b/src/cli/pubkey.cpp index 3af91b722..60119ca13 100644 --- a/src/cli/pubkey.cpp +++ b/src/cli/pubkey.cpp @@ -259,14 +259,14 @@ class PKCS8_Tool final : public Command std::unique_ptr<Botan::Private_Key> key; std::string pass_in = get_arg("pass-in"); - if (pass_in.empty()) - { + if(pass_in.empty()) + { key.reset(Botan::PKCS8::load_key(get_arg("key"), rng())); - } + } else - { + { key.reset(Botan::PKCS8::load_key(get_arg("key"), rng(), pass_in)); - } + } const std::chrono::milliseconds pbe_millis(get_arg_sz("pbe-millis")); const std::string pbe = get_arg("pbe"); diff --git a/src/lib/asn1/asn1_time.cpp b/src/lib/asn1/asn1_time.cpp index e64fd57c7..863a064f0 100644 --- a/src/lib/asn1/asn1_time.cpp +++ b/src/lib/asn1/asn1_time.cpp @@ -213,7 +213,7 @@ void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag) } if(!passes_sanity_check()) - throw Invalid_Argument("Time did not pass sanity check: " + t_spec); + throw Invalid_Argument("Time " + t_spec + " does not seem to be valid"); } /* @@ -221,13 +221,26 @@ void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag) */ bool X509_Time::passes_sanity_check() const { - if(m_year < 1950 || m_year > 2100) + if(m_year < 1950 || m_year > 2200) return false; if(m_month == 0 || m_month > 12) return false; - if(m_day == 0 || m_day > 31) + + const uint32_t days_in_month[12] = { 31, 28+1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + if(m_day == 0 || m_day > days_in_month[m_month-1]) return false; - if(m_hour >= 24 || m_minute > 60 || m_second > 60) + + if(m_month == 2 && m_day == 29) + { + if(m_year % 4 != 0) + return false; // not a leap year + + if(m_year % 100 == 0 && m_year % 400 != 0) + return false; + } + + if(m_hour >= 24 || m_minute >= 60 || m_second > 60) return false; if (m_tag == UTC_TIME) diff --git a/src/lib/asn1/asn1_time.h b/src/lib/asn1/asn1_time.h index 73bf2747f..717c58a7d 100644 --- a/src/lib/asn1/asn1_time.h +++ b/src/lib/asn1/asn1_time.h @@ -72,6 +72,8 @@ bool BOTAN_PUBLIC_API(2,0) operator>=(const X509_Time&, const X509_Time&); bool BOTAN_PUBLIC_API(2,0) operator<(const X509_Time&, const X509_Time&); bool BOTAN_PUBLIC_API(2,0) operator>(const X509_Time&, const X509_Time&); +typedef X509_Time ASN1_Time; + } #endif diff --git a/src/lib/pubkey/ec_group/curve_gfp.cpp b/src/lib/pubkey/ec_group/curve_gfp.cpp index 8953edba4..9f614ac61 100644 --- a/src/lib/pubkey/ec_group/curve_gfp.cpp +++ b/src/lib/pubkey/ec_group/curve_gfp.cpp @@ -34,8 +34,14 @@ class CurveGFp_Montgomery final : public CurveGFp_Repr m_r3 = mod_p.multiply(m_r, m_r2); m_a_r = mod_p.multiply(m_r, m_a); m_b_r = mod_p.multiply(m_r, m_b); + + m_a_is_zero = m_a.is_zero(); + m_a_is_minus_3 = (m_a + 3 == m_p); } + bool a_is_zero() const override { return m_a_is_zero; } + bool a_is_minus_3() const override { return m_a_is_minus_3; } + const BigInt& get_a() const override { return m_a; } const BigInt& get_b() const override { return m_b; } @@ -78,6 +84,9 @@ class CurveGFp_Montgomery final : public CurveGFp_Repr // Montgomery parameters BigInt m_r, m_r2, m_r3; word m_p_dash; + + bool m_a_is_zero; + bool m_a_is_minus_3; }; BigInt CurveGFp_Montgomery::invert_element(const BigInt& x, secure_vector<word>& ws) const @@ -190,8 +199,12 @@ class CurveGFp_NIST : public CurveGFp_Repr CurveGFp_NIST(size_t p_bits, const BigInt& a, const BigInt& b) : m_a(a), m_b(b), m_p_words((p_bits + BOTAN_MP_WORD_BITS - 1) / BOTAN_MP_WORD_BITS) { + // All Solinas prime curves are assumed a == -3 } + bool a_is_zero() const override { return false; } + bool a_is_minus_3() const override { return true; } + const BigInt& get_a() const override { return m_a; } const BigInt& get_b() const override { return m_b; } @@ -233,7 +246,6 @@ class CurveGFp_NIST : public CurveGFp_Repr size_t m_p_words; // cache of m_p.sig_words() }; - BigInt CurveGFp_NIST::invert_element(const BigInt& x, secure_vector<word>& ws) const { BOTAN_UNUSED(ws); diff --git a/src/lib/pubkey/ec_group/curve_gfp.h b/src/lib/pubkey/ec_group/curve_gfp.h index 8a83a9c41..3a17c6678 100644 --- a/src/lib/pubkey/ec_group/curve_gfp.h +++ b/src/lib/pubkey/ec_group/curve_gfp.h @@ -30,6 +30,10 @@ class BOTAN_UNSTABLE_API CurveGFp_Repr virtual bool is_one(const BigInt& x) const = 0; + virtual bool a_is_zero() const = 0; + + virtual bool a_is_minus_3() const = 0; + /* * Returns to_curve_rep(get_a()) */ @@ -116,6 +120,9 @@ class BOTAN_UNSTABLE_API CurveGFp final const BigInt& get_b_rep() const { return m_repr->get_b_rep(); } + bool a_is_minus_3() const { return m_repr->a_is_minus_3(); } + bool a_is_zero() const { return m_repr->a_is_zero(); } + bool is_one(const BigInt& x) const { return m_repr->is_one(x); } BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const diff --git a/src/lib/pubkey/ec_group/point_gfp.cpp b/src/lib/pubkey/ec_group/point_gfp.cpp index acbda95d4..860459252 100644 --- a/src/lib/pubkey/ec_group/point_gfp.cpp +++ b/src/lib/pubkey/ec_group/point_gfp.cpp @@ -316,14 +316,47 @@ void PointGFp::mult2(std::vector<BigInt>& ws_bn) T1 <<= 2; // * 4 T1.reduce_below(p, T3.get_word_vector()); - m_curve.sqr(T3, m_coord_z, ws); // z^2 - m_curve.sqr(T4, T3, ws); // z^4 - m_curve.mul(T3, m_curve.get_a_rep(), T4, ws); - - m_curve.sqr(T4, m_coord_x, ws); - T4 *= 3; - T4 += T3; - T4.reduce_below(p, T3.get_word_vector()); + if(m_curve.a_is_zero()) + { + // if a == 0 then 3*x^2 + a*z^4 is just 3*x^2 + m_curve.sqr(T4, m_coord_x, ws); // x^2 + T4 *= 3; // 3*x^2 + T4.reduce_below(p, T3.get_word_vector()); + } + else if(m_curve.a_is_minus_3()) + { + /* + if a == -3 then + 3*x^2 + a*z^4 == 3*x^2 - 3*z^4 == 3*(x^2-z^4) == 3*(x-z^2)*(x+z^2) + */ + m_curve.sqr(T3, m_coord_z, ws); // z^2 + + // (x-z^2) + T2 = m_coord_x; + T2 -= T3; + if(T2.is_negative()) + T2 += p; + + // (x+z^2) + T3 += m_coord_x; + T3.reduce_below(p, T4.get_word_vector()); + + m_curve.mul(T4, T2, T3, ws); // (x-z^2)*(x+z^2) + + T4 *= 3; // 3*(x-z^2)*(x+z^2) + T4.reduce_below(p, T3.get_word_vector()); + } + else + { + m_curve.sqr(T3, m_coord_z, ws); // z^2 + m_curve.sqr(T4, T3, ws); // z^4 + m_curve.mul(T3, m_curve.get_a_rep(), T4, ws); // a*z^4 + + m_curve.sqr(T4, m_coord_x, ws); // x^2 + T4 *= 3; // 3*x^2 + T4 += T3; // 3*x^2 + a*z^4 + T4.reduce_below(p, T3.get_word_vector()); + } m_curve.sqr(T2, T4, ws); T2 -= T1; diff --git a/src/lib/pubkey/xmss/xmss_tools.cpp b/src/lib/pubkey/xmss/xmss_tools.cpp index f4f762aeb..f9bd4892e 100644 --- a/src/lib/pubkey/xmss/xmss_tools.cpp +++ b/src/lib/pubkey/xmss/xmss_tools.cpp @@ -19,26 +19,28 @@ size_t XMSS_Tools::max_threads() size_t XMSS_Tools::bench_threads() { - if(std::thread::hardware_concurrency() <= 1) + const size_t hardware_concurrency = std::thread::hardware_concurrency(); + + if(hardware_concurrency <= 1) { return 1; } const size_t BENCH_ITERATIONS = 1000; std::vector<std::thread> threads; - threads.reserve(std::thread::hardware_concurrency()); + threads.reserve(hardware_concurrency); std::vector<std::chrono::nanoseconds> durations; - std::vector<size_t> concurrency { std::thread::hardware_concurrency(), - std::thread::hardware_concurrency() / 2 }; + std::vector<size_t> concurrency { hardware_concurrency, + hardware_concurrency / 2 }; for(const auto& cc : concurrency) { - std::vector<XMSS_Hash> hash(std::thread::hardware_concurrency(), + std::vector<XMSS_Hash> hash(hardware_concurrency, XMSS_Hash("SHA-256")); const std::vector<uint8_t> buffer(hash[0].output_length()); std::vector<secure_vector<uint8_t>> data( - std::thread::hardware_concurrency(), + hardware_concurrency, secure_vector<uint8_t>(hash[0].output_length())); auto start = std::chrono::high_resolution_clock::now(); for(size_t i = 0; i < cc; ++i) @@ -46,7 +48,7 @@ size_t XMSS_Tools::bench_threads() auto& hs = hash[i]; auto& d = data[i]; - const size_t n_iters = BENCH_ITERATIONS * (std::thread::hardware_concurrency() / cc); + const size_t n_iters = BENCH_ITERATIONS * (hardware_concurrency / cc); threads.emplace_back(std::thread([n_iters, &hs, &d]() { for(size_t n = 0; n < n_iters; n++) diff --git a/src/tests/data/asn1_time.vec b/src/tests/data/asn1_time.vec new file mode 100644 index 000000000..b1b33f279 --- /dev/null +++ b/src/tests/data/asn1_time.vec @@ -0,0 +1,37 @@ + +[UTC] + +Tspec = 500131053030Z + +[UTC.invalid] + +Tspec = 201801310590Z + +[Generalized] + +Tspec = 19500101000000Z +Tspec = 19500131053030Z +Tspec = 20000229000000Z +Tspec = 20180131000000Z +Tspec = 20180131053030Z +Tspec = 20200229000000Z +Tspec = 20201231235960Z +Tspec = 21000101000060Z +Tspec = 21000101005900Z +Tspec = 21000101230000Z +Tspec = 22001231235960Z + +[Generalized.invalid] + +Tspec = 20000001000000Z +Tspec = 20000100000000Z + +Tspec = 19490131053030Z +Tspec = 20180132000000Z +Tspec = 20180229000000Z +Tspec = 21000101000061Z +Tspec = 21000101006000Z +Tspec = 21000101240000Z +Tspec = 21000101990000Z +Tspec = 21000229000000Z +Tspec = 22010131053030Z diff --git a/src/tests/test_asn1.cpp b/src/tests/test_asn1.cpp index ae9c1dafb..d025fe9f5 100644 --- a/src/tests/test_asn1.cpp +++ b/src/tests/test_asn1.cpp @@ -11,8 +11,8 @@ #include <botan/ber_dec.h> #include <botan/asn1_str.h> #include <botan/asn1_print.h> + #include <botan/asn1_time.h> #endif -#include <fstream> namespace Botan_Tests { @@ -291,6 +291,49 @@ class ASN1_Tests final : public Test BOTAN_REGISTER_TEST("asn1", ASN1_Tests); +class ASN1_Time_Parsing_Tests final : public Text_Based_Test + { + public: + ASN1_Time_Parsing_Tests() : + Text_Based_Test("asn1_time.vec", "Tspec") {} + + Test::Result run_one_test(const std::string& tag_str, const VarMap& vars) override + { + Test::Result result("ASN.1 date parsing"); + + const std::string tspec = get_req_str(vars, "Tspec"); + + if(tag_str != "UTC" && + tag_str != "UTC.invalid" && + tag_str != "Generalized" && + tag_str != "Generalized.invalid") + { + throw Test_Error("Invalid tag value in ASN1 date parsing test"); + } + + const Botan::ASN1_Tag tag = + (tag_str == "UTC" || tag_str == "UTC.invalid") ? Botan::UTC_TIME : Botan::GENERALIZED_TIME; + + const bool valid = tag_str.find(".invalid") == std::string::npos; + + if(valid) + { + Botan::ASN1_Time time(tspec, tag); + result.test_success("Accepted valid time"); + } + else + { + result.test_throws("Invalid time rejected", [=]() { + Botan::ASN1_Time time(tspec, tag); + }); + } + + return result; + } + }; + +BOTAN_REGISTER_TEST("asn1_time", ASN1_Time_Parsing_Tests); + class ASN1_Printer_Tests final : public Test { public: |