aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build-data/makefile.in17
-rw-r--r--src/build-data/os/openbsd.txt2
-rw-r--r--src/cli/pubkey.cpp10
-rw-r--r--src/lib/asn1/asn1_time.cpp21
-rw-r--r--src/lib/asn1/asn1_time.h2
-rw-r--r--src/lib/pubkey/ec_group/curve_gfp.cpp14
-rw-r--r--src/lib/pubkey/ec_group/curve_gfp.h7
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.cpp49
-rw-r--r--src/lib/pubkey/xmss/xmss_tools.cpp16
-rw-r--r--src/tests/data/asn1_time.vec37
-rw-r--r--src/tests/test_asn1.cpp45
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: