diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build-data/buildh.in | 17 | ||||
-rw-r--r-- | src/cli/timing_tests.cpp | 454 | ||||
-rw-r--r-- | src/lib/asn1/x509_dn.cpp | 1 | ||||
-rw-r--r-- | src/lib/math/ec_gfp/point_gfp.cpp | 50 | ||||
-rw-r--r-- | src/lib/pk_pad/iso9796/iso9796.cpp | 40 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/curve25519.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/pbes2/pbes2.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/rsa/rsa.cpp | 1 | ||||
-rw-r--r-- | src/lib/pubkey/x509_key.cpp | 2 | ||||
-rw-r--r-- | src/lib/x509/x509_ext.cpp | 2 | ||||
-rw-r--r-- | src/lib/x509/x509_obj.cpp | 1 | ||||
-rw-r--r-- | src/lib/x509/x509cert.cpp | 1 | ||||
-rw-r--r-- | src/tests/test_ocsp.cpp | 3 | ||||
-rw-r--r-- | src/tests/test_pubkey.cpp | 12 |
14 files changed, 499 insertions, 89 deletions
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index de2b5c8b5..1c389fe02 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -80,21 +80,14 @@ #define BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO 1 /* -* If enabled the ECC implementation will use Montgomery ladder -* instead of a fixed window implementation. +* If enabled the ECC implementation will use scalar blinding with order.bits()/2 +* bit long masks. */ -#define BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER 0 - -/* -* Set number of bits used to generate mask for blinding the scalar of -* a point multiplication. Set to zero to disable this side-channel -* countermeasure. -*/ -#define BOTAN_POINTGFP_SCALAR_BLINDING_BITS 20 +#define BOTAN_POINTGFP_USE_SCALAR_BLINDING 1 /* * Set number of bits used to generate mask for blinding the -* representation of an ECC point. Set to zero to diable this +* representation of an ECC point. Set to zero to disable this * side-channel countermeasure. */ #define BOTAN_POINTGFP_RANDOMIZE_BLINDING_BITS 80 @@ -104,7 +97,7 @@ * its inverse, of a form appropriate to the algorithm being blinded), and * then choosing new blinding operands by successive squaring of both * values. This is much faster than computing a new starting point but -* introduces some possible coorelation +* introduces some possible corelation * * To avoid possible leakage problems in long-running processes, the blinder * periodically reinitializes the sequence. This value specifies how often diff --git a/src/cli/timing_tests.cpp b/src/cli/timing_tests.cpp new file mode 100644 index 000000000..7177cdc25 --- /dev/null +++ b/src/cli/timing_tests.cpp @@ -0,0 +1,454 @@ +/* +* Timing Analysis Tests +* +* These tests are not for performance, but verifying that two inputs are not handled +* in a way that is vulnerable to simple timing attacks. +* +* Produces output which can be analyzed with the Mona reporting library +* git clone https://github.com/seecurity/mona-timing-report.git +* +* (C) 2016 Juraj Somorovsky - [email protected] +* (C) 2017 Neverhub +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "cli.h" +#include <botan/hex.h> +#include <sstream> +#include <botan/internal/os_utils.h> + +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> +#endif + +#if defined(BOTAN_HAS_AUTO_SEEDED_RNG) + #include <botan/auto_rng.h> +#endif + +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_RAW) + #include <botan/pubkey.h> + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_TLS_CBC) + #include <botan/internal/tls_cbc.h> + #include <botan/tls_exceptn.h> +#endif + +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> + #include <botan/reducer.h> + #include <botan/numthry.h> +#endif + +namespace Botan_CLI { + +typedef uint64_t ticks; + +class Timing_Test + { + public: + Timing_Test() {} + virtual ~Timing_Test() {} + + std::vector<std::vector<ticks>> + execute_evaluation(const std::vector<std::string>& inputs, + size_t warmup_runs, + size_t measurement_runs); + + virtual std::vector<uint8_t> prepare_input(std::string input) = 0; + + virtual ticks measure_critical_function(std::vector<uint8_t> input) = 0; + + protected: + static ticks get_ticks() + { + // Returns CPU counter or best approximation (monotonic clock of some kind) + return Botan::OS::get_high_resolution_clock(); + } + + static Botan::RandomNumberGenerator& timing_test_rng() + { +#if defined(BOTAN_HAS_SYSTEM_RNG) + return Botan::system_rng(); +#elif defined(BOTAN_HAS_AUTO_SEEDED_RNG) + static AutoSeeded_RNG static_timing_test_rng(Botan::Entropy_Sources::global_sources(), 0); + return static_timing_test_rng; +#else + // we could just use SHA-256 in OFB mode for these purposes + throw CLI_Error("Timing tests require a PRNG"); +#endif + } + + }; + +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_PKCS1v15) && defined(BOTAN_HAS_EME_RAW) + +class Bleichenbacker_Timing_Test : public Timing_Test + { + public: + Bleichenbacker_Timing_Test(size_t keysize) : + m_privkey(Timing_Test::timing_test_rng(), keysize), + m_pubkey(m_privkey), + m_enc(m_pubkey, Timing_Test::timing_test_rng(), "Raw"), + m_dec(m_privkey, Timing_Test::timing_test_rng(), "PKCS1v15") + { + } + + std::vector<uint8_t> prepare_input(std::string input) override + { + const std::vector<uint8_t> input_vector = Botan::hex_decode(input); + const std::vector<uint8_t> encrypted = m_enc.encrypt(input_vector, Timing_Test::timing_test_rng()); + return encrypted; + } + + ticks measure_critical_function(std::vector<uint8_t> input) override + { + const ticks start = get_ticks(); + m_dec.decrypt_or_random(input.data(), m_ctext_length, m_expected_content_size, Timing_Test::timing_test_rng()); + const ticks end = get_ticks(); + return (end - start); + } + + private: + const size_t m_expected_content_size = 48; + const size_t m_ctext_length = 256; + Botan::RSA_PrivateKey m_privkey; + Botan::RSA_PublicKey m_pubkey; + Botan::PK_Encryptor_EME m_enc; + Botan::PK_Decryptor_EME m_dec; + }; + +#endif + +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_OAEP) && defined(BOTAN_HAS_EME_RAW) + +/* +* Test Manger OAEP side channel +* +* "A Chosen Ciphertext Attack on RSA Optimal Asymmetric Encryption +* Padding (OAEP) as Standardized in PKCS #1 v2.0" James Manger +* http://archiv.infsec.ethz.ch/education/fs08/secsem/Manger01.pdf +*/ +class Manger_Timing_Test : public Timing_Test + { + public: + Manger_Timing_Test(size_t keysize) : + m_privkey(Timing_Test::timing_test_rng(), keysize), + m_pubkey(m_privkey), + m_enc(m_pubkey, Timing_Test::timing_test_rng(), m_encrypt_padding), + m_dec(m_privkey, Timing_Test::timing_test_rng(), m_decrypt_padding) + {} + + std::vector<uint8_t> prepare_input(std::string input) override + { + const std::vector<uint8_t> input_vector = Botan::hex_decode(input); + const std::vector<uint8_t> encrypted = m_enc.encrypt(input_vector, Timing_Test::timing_test_rng()); + return encrypted; + } + + ticks measure_critical_function(std::vector<uint8_t> input) override + { + ticks start = get_ticks(); + try + { + m_dec.decrypt(input.data(), m_ctext_length); + } + catch (Botan::Decoding_Error e) + { + } + ticks end = get_ticks(); + + return (end - start); + } + + private: + const std::string m_encrypt_padding = "Raw"; + const std::string m_decrypt_padding = "EME1(SHA-256)"; + const size_t m_ctext_length = 256; + Botan::RSA_PrivateKey m_privkey; + Botan::RSA_PublicKey m_pubkey; + Botan::PK_Encryptor_EME m_enc; + Botan::PK_Decryptor_EME m_dec; + }; + +#endif + +#if defined(BOTAN_HAS_TLS_CBC) + +/* +* Test handling of countermeasure to the Lucky13 attack +*/ +class Lucky13_Timing_Test : public Timing_Test + { + public: + Lucky13_Timing_Test(const std::string& mac_name, + size_t mac_keylen) : + m_mac_algo(mac_name), + m_mac_keylen (mac_keylen), + m_dec("AES-128", 16, m_mac_algo, m_mac_keylen, true, false) + {} + + std::vector<uint8_t> prepare_input(std::string input) override; + ticks measure_critical_function(std::vector<uint8_t> input) override; + + private: + const std::string m_mac_algo; + const size_t m_mac_keylen; + Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption m_dec; + }; + +std::vector<uint8_t> Lucky13_Timing_Test::prepare_input(std::string input) + { + const std::vector<uint8_t> input_vector = Botan::hex_decode(input); + const std::vector<uint8_t> key(16); + const std::vector<uint8_t> iv(16); + + std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode("AES-128/CBC/NoPadding", Botan::ENCRYPTION)); + enc->set_key(key); + enc->start(iv); + Botan::secure_vector<uint8_t> buf(input_vector.begin(), input_vector.end()); + enc->finish(buf); + + return unlock(buf); + } + +ticks Lucky13_Timing_Test::measure_critical_function(std::vector<uint8_t> input) + { + Botan::secure_vector<uint8_t> data(input.begin(), input.end()); + Botan::secure_vector<uint8_t> aad(13); + const Botan::secure_vector<uint8_t> iv(16); + Botan::secure_vector<uint8_t> key(16 + m_mac_keylen); + + m_dec.set_key(unlock(key)); + m_dec.set_ad(unlock(aad)); + m_dec.start(unlock(iv)); + + ticks start = get_ticks(); + try + { + m_dec.finish(data); + } + catch(Botan::TLS::TLS_Exception& e) + { + } + ticks end = get_ticks(); + return (end - start); + } + +#endif + +#if defined(BOTAN_HAS_ECDSA) + +class ECDSA_Timing_Test : public Timing_Test + { + public: + ECDSA_Timing_Test(std::string ecgroup); + + std::vector<uint8_t> prepare_input(std::string input) override; + ticks measure_critical_function(std::vector<uint8_t> input) override; + + private: + const Botan::ECDSA_PrivateKey m_privkey; + const Botan::BigInt m_order; + Botan::Blinded_Point_Multiply m_base_point; + const Botan::BigInt m_x; + const Botan::Modular_Reducer m_mod_order; + }; + +ECDSA_Timing_Test::ECDSA_Timing_Test(std::string ecgroup) : + m_privkey(Timing_Test::timing_test_rng(), Botan::EC_Group(ecgroup)), + m_order(m_privkey.domain().get_order()), + m_base_point(m_privkey.domain().get_base_point(), m_order), + m_x(m_privkey.private_value()), + m_mod_order(m_order) + { + } + +std::vector<uint8_t> ECDSA_Timing_Test::prepare_input(std::string input) + { + const std::vector<uint8_t> input_vector = Botan::hex_decode(input); + return input_vector; + } + +ticks ECDSA_Timing_Test::measure_critical_function(std::vector<uint8_t> input) + { + const Botan::BigInt k(input.data(), input.size()); + const Botan::BigInt msg(Timing_Test::timing_test_rng(), m_order.bits()); + + ticks start = get_ticks(); + + //The following ECDSA operations involve and should not leak any information about k. + const Botan::PointGFp k_times_P = m_base_point.blinded_multiply(k, Timing_Test::timing_test_rng()); + const Botan::BigInt r = m_mod_order.reduce(k_times_P.get_affine_x()); + const Botan::BigInt s = m_mod_order.multiply(inverse_mod(k, m_order), mul_add(m_x, r, msg)); + + ticks end = get_ticks(); + + return (end - start); + } + +#endif + +std::vector<std::vector<ticks>> Timing_Test::execute_evaluation(const std::vector<std::string>& raw_inputs, size_t warmup_runs, size_t measurement_runs) + { + std::vector<std::vector<ticks>> all_results(raw_inputs.size()); + std::vector<std::vector<uint8_t>> inputs(raw_inputs.size()); + + for(size_t i = 0; i != all_results.size(); ++i) + all_results[i].reserve(measurement_runs); + + for(size_t i = 0; i != inputs.size(); ++i) + inputs[i] = prepare_input(raw_inputs[i]); + + // arbitrary upper bounds of 1 and 10 million resp + if(warmup_runs > 1000000 || measurement_runs > 100000000) + throw CLI_Error("Requested execution counts too large, rejecting"); + + size_t total_runs = 0; + while(total_runs < (warmup_runs + measurement_runs)) + { + std::vector<ticks> results(inputs.size()); + + for(size_t i = 0; i != inputs.size(); ++i) + { + results[i] = measure_critical_function(inputs[i]); + } + + total_runs++; + + if(total_runs >= warmup_runs) + { + for(size_t i = 0; i != results.size(); ++i) + all_results[i].push_back(results[i]); + } + } + + return all_results; + } + +class Timing_Test_Command : public Command + { + public: + Timing_Test_Command() : Command("timing_test test_type --test-data-file= --test-data-dir=src/extra_tests/timing/timing-tests/data/ --warmup-runs=1000 --measurement-runs=10000") + {} + + virtual void go() + { + const std::string test_type = get_arg("test_type"); + const size_t warmup_runs = get_arg_sz("warmup-runs"); + const size_t measurement_runs = get_arg_sz("measurement-runs"); + + std::unique_ptr<Timing_Test> test = lookup_timing_test(test_type); + + if(!test) + { + throw CLI_Error("Unknown or unavailable test type '" + test_type + "'"); + } + + std::string filename = get_arg_or("test-data-file", ""); + + if(filename.empty()) + { + const std::string test_data_dir = get_arg("test-data-dir"); + filename = test_data_dir + "/" + test_type + ".vec"; + } + + std::vector<std::string> lines; + + { + std::ifstream infile(filename); + if(infile.good() == false) + throw CLI_Error("Error reading test data from '" + filename + "'"); + std::string line; + while (std::getline(infile, line)) + { + if (line.size() > 0 && line.at(0) != '#') + { + lines.push_back(line); + } + } + } + + std::vector<std::vector<ticks>> results = + test->execute_evaluation(lines, warmup_runs, measurement_runs); + + size_t unique_id = 0; + std::ostringstream oss; + for(size_t secret_id = 0; secret_id != results.size(); ++secret_id) + { + for(size_t i = 0; i != results[secret_id].size(); ++i) + { + oss << unique_id++ << ";" << secret_id << ";" << results[secret_id][i] << "\n"; + } + } + + output() << oss.str(); + } + private: + std::unique_ptr<Timing_Test> lookup_timing_test(const std::string& test_type); + + virtual std::string help_text() const + { + // TODO check feature macros + return (Command::help_text() + + "\ntest_type can take on values " + + "bleichenbacher " + + "manger " + "ecdsa " + + "lucky13sha1sec3 " + + "lucky13sha256sec3 " + + "lucky13sec4sha1 " + + "lucky13sec4sha256 " + + "lucky13sec4sha384 " + ); + } + }; + +BOTAN_REGISTER_COMMAND("timing_test", Timing_Test_Command); + +std::unique_ptr<Timing_Test> Timing_Test_Command::lookup_timing_test(const std::string& test_type) + { +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_PKCS1v15) && defined(BOTAN_HAS_EME_RAW) + if(test_type == "bleichenbacher") + { + return std::unique_ptr<Timing_Test>(new Bleichenbacker_Timing_Test(2048)); + } +#endif + +#if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_OAEP) && defined(BOTAN_HAS_EME_RAW) + if(test_type == "manger") + { + return std::unique_ptr<Timing_Test>(new Manger_Timing_Test(2048)); + } +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(test_type == "ecdsa") + { + return std::unique_ptr<Timing_Test>(new ECDSA_Timing_Test("secp384r1")); + } +#endif + +#if defined(BOTAN_HAS_TLS_CBC) + if(test_type == "lucky13sha1sec3" || test_type == "lucky13sha1sec4") + { + return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-1", 20)); + } + if(test_type == "lucky13sha256sec3" || test_type == "lucky13sha256sec4") + { + return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-256", 32)); + } + if(test_type == "lucky13sha384") + { + return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-384", 48)); + } +#endif + + return nullptr; + } + + +} diff --git a/src/lib/asn1/x509_dn.cpp b/src/lib/asn1/x509_dn.cpp index e5cd2b8cc..a7ceeef4c 100644 --- a/src/lib/asn1/x509_dn.cpp +++ b/src/lib/asn1/x509_dn.cpp @@ -269,7 +269,6 @@ void X509_DN::decode_from(BER_Decoder& source) rdn.start_cons(SEQUENCE) .decode(oid) .decode(str) - .verify_end() .end_cons(); add_attribute(oid, str.value()); diff --git a/src/lib/math/ec_gfp/point_gfp.cpp b/src/lib/math/ec_gfp/point_gfp.cpp index bb446566e..5283b7352 100644 --- a/src/lib/math/ec_gfp/point_gfp.cpp +++ b/src/lib/math/ec_gfp/point_gfp.cpp @@ -314,8 +314,6 @@ Blinded_Point_Multiply::Blinded_Point_Multiply(const PointGFp& base, const BigIn const CurveGFp& curve = base.get_curve(); -#if BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER - const PointGFp inv = -base; m_U.resize(6*m_h + 3); @@ -332,17 +330,6 @@ Blinded_Point_Multiply::Blinded_Point_Multiply(const PointGFp& base, const BigIn m_U[3*m_h+1-i] = m_U[3*m_h+2-i]; m_U[3*m_h+1-i].add(inv, m_ws); } -#else - m_U.resize(1 << m_h); - m_U[0] = PointGFp::zero_of(curve); - m_U[1] = base; - - for(size_t i = 2; i < m_U.size(); ++i) - { - m_U[i] = m_U[i-1]; - m_U[i].add(base, m_ws); - } -#endif } PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, @@ -351,9 +338,9 @@ PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, if(scalar_in.is_negative()) throw Invalid_Argument("Blinded_Point_Multiply scalar must be positive"); -#if BOTAN_POINTGFP_SCALAR_BLINDING_BITS > 0 +#if BOTAN_POINTGFP_USE_SCALAR_BLINDING // Choose a small mask m and use k' = k + m*order (Coron's 1st countermeasure) - const BigInt mask(rng, BOTAN_POINTGFP_SCALAR_BLINDING_BITS, false); + const BigInt mask(rng, (m_order.bits()+1)/2, false); const BigInt scalar = scalar_in + m_order * mask; #else const BigInt& scalar = scalar_in; @@ -365,7 +352,6 @@ PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, for(size_t i = 0; i != m_U.size(); ++i) m_U[i].randomize_repr(rng); -#if BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER PointGFp R = m_U.at(3*m_h + 2); // base point int32_t alpha = 0; @@ -395,38 +381,6 @@ PointGFp Blinded_Point_Multiply::blinded_multiply(const BigInt& scalar_in, const int32_t k0 = scalar.get_bit(0); R.add(m_U[3*m_h + 1 - alpha - (k0 ^ 1)], m_ws); -#else - - // N-bit windowing exponentiation: - - size_t windows = round_up(scalar_bits, m_h) / m_h; - - PointGFp R = m_U[0]; - - if(windows > 0) - { - windows--; - const uint32_t nibble = scalar.get_substring(windows*m_h, m_h); - R.add(m_U[nibble], m_ws); - - /* - Randomize after adding the first nibble as before the addition R - is zero, and we cannot effectively randomize the point - representation of the zero point. - */ - R.randomize_repr(rng); - - while(windows) - { - for(size_t i = 0; i != m_h; ++i) - R.mult2(m_ws); - - const uint32_t inner_nibble = scalar.get_substring((windows-1)*m_h, m_h); - R.add(m_U[inner_nibble], m_ws); - windows--; - } - } -#endif //BOTAN_ASSERT(R.on_the_curve(), "Output is on the curve"); diff --git a/src/lib/pk_pad/iso9796/iso9796.cpp b/src/lib/pk_pad/iso9796/iso9796.cpp index f123a7e15..f56689389 100644 --- a/src/lib/pk_pad/iso9796/iso9796.cpp +++ b/src/lib/pk_pad/iso9796/iso9796.cpp @@ -9,6 +9,7 @@ #include <botan/mgf1.h> #include <botan/internal/bit_ops.h> #include <botan/hash_id.h> +#include <botan/internal/ct_utils.h> namespace Botan { @@ -125,7 +126,8 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, } secure_vector<uint8_t> coded = const_coded; - + + CT::poison(coded.data(), coded.size()); //remove mask uint8_t* DB = coded.data(); const size_t DB_size = coded.size() - HASH_SIZE - tLength; @@ -137,19 +139,26 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, DB[0] &= 0x7F; //recover msg1 and salt - size_t msg1_offset = 0; - for(size_t j = 0; j != DB_size; ++j) + size_t msg1_offset = 1; + uint8_t waiting_for_delim = 0xFF; + uint8_t bad_input = 0; + for(size_t j = 0; j < DB_size; ++j) { - if(DB[j] == 0x01) - { - msg1_offset = j + 1; - break; - } - } - if(msg1_offset == 0) - { - return false; + const uint8_t one_m = CT::is_equal<uint8_t>(DB[j], 0x01); + const uint8_t zero_m = CT::is_zero(DB[j]); + const uint8_t add_m = waiting_for_delim & zero_m; + + bad_input |= waiting_for_delim & ~(zero_m | one_m); + msg1_offset += CT::select<uint8_t>(add_m, 1, 0); + + waiting_for_delim &= zero_m; } + + //invalid, if delimiter 0x01 was not found or msg1_offset is too big + bad_input |= waiting_for_delim; + bad_input |= CT::is_less(coded.size(), tLength + HASH_SIZE + msg1_offset + SALT_SIZE); + //in case that msg1_offset is too big, just continue with offset = 0. + msg1_offset = CT::select<size_t>(bad_input, 0, msg1_offset); secure_vector<uint8_t> msg1(coded.begin() + msg1_offset, coded.end() - tLength - HASH_SIZE - SALT_SIZE); secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(), @@ -186,9 +195,12 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded, hash->update(msg2); hash->update(salt); secure_vector<uint8_t> H2 = hash->final(); - + //check if H3 == H2 - return same_mem(H3.data(), H2.data(), HASH_SIZE); + bad_input |= CT::is_equal<uint8_t>(same_mem(H3.data(), H2.data(), HASH_SIZE), false); + CT::unpoison(coded.data(), coded.size()); + + return (bad_input == 0); } } diff --git a/src/lib/pubkey/curve25519/curve25519.cpp b/src/lib/pubkey/curve25519/curve25519.cpp index 4908bf46f..070b8e841 100644 --- a/src/lib/pubkey/curve25519/curve25519.cpp +++ b/src/lib/pubkey/curve25519/curve25519.cpp @@ -52,7 +52,6 @@ Curve25519_PublicKey::Curve25519_PublicKey(const AlgorithmIdentifier&, BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode(m_public, OCTET_STRING) - .verify_end() .end_cons(); size_check(m_public.size(), "public key"); @@ -81,7 +80,6 @@ Curve25519_PrivateKey::Curve25519_PrivateKey(const AlgorithmIdentifier&, .start_cons(SEQUENCE) .decode(m_public, OCTET_STRING) .decode(m_private, OCTET_STRING) - .verify_end() .end_cons(); size_check(m_public.size(), "public key"); diff --git a/src/lib/pubkey/pbes2/pbes2.cpp b/src/lib/pubkey/pbes2/pbes2.cpp index 3f1000170..01bab76bb 100644 --- a/src/lib/pubkey/pbes2/pbes2.cpp +++ b/src/lib/pubkey/pbes2/pbes2.cpp @@ -116,7 +116,6 @@ pbes2_decrypt(const secure_vector<uint8_t>& key_bits, .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) - .verify_end() .end_cons(); AlgorithmIdentifier prf_algo; @@ -136,7 +135,6 @@ pbes2_decrypt(const secure_vector<uint8_t>& key_bits, .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED, AlgorithmIdentifier("HMAC(SHA-160)", AlgorithmIdentifier::USE_NULL_PARAM)) - .verify_end() .end_cons(); const std::string cipher = OIDS::lookup(enc_algo.oid); diff --git a/src/lib/pubkey/rsa/rsa.cpp b/src/lib/pubkey/rsa/rsa.cpp index 1a287473a..d8deccab3 100644 --- a/src/lib/pubkey/rsa/rsa.cpp +++ b/src/lib/pubkey/rsa/rsa.cpp @@ -58,7 +58,6 @@ RSA_PublicKey::RSA_PublicKey(const AlgorithmIdentifier&, .start_cons(SEQUENCE) .decode(m_n) .decode(m_e) - .verify_end() .end_cons(); } diff --git a/src/lib/pubkey/x509_key.cpp b/src/lib/pubkey/x509_key.cpp index 700020901..6fadeb70d 100644 --- a/src/lib/pubkey/x509_key.cpp +++ b/src/lib/pubkey/x509_key.cpp @@ -46,7 +46,6 @@ Public_Key* load_key(DataSource& source) .start_cons(SEQUENCE) .decode(alg_id) .decode(key_bits, BIT_STRING) - .verify_end() .end_cons(); } else @@ -59,7 +58,6 @@ Public_Key* load_key(DataSource& source) .start_cons(SEQUENCE) .decode(alg_id) .decode(key_bits, BIT_STRING) - .verify_end() .end_cons(); } diff --git a/src/lib/x509/x509_ext.cpp b/src/lib/x509/x509_ext.cpp index 199ca6bcc..965c8efcf 100644 --- a/src/lib/x509/x509_ext.cpp +++ b/src/lib/x509/x509_ext.cpp @@ -219,7 +219,6 @@ void Extensions::decode_from(BER_Decoder& from_source) .decode(oid) .decode_optional(critical, BOOLEAN, UNIVERSAL, false) .decode(value, OCTET_STRING) - .verify_end() .end_cons(); m_extensions_raw.emplace(oid, std::make_pair(value, critical)); @@ -300,7 +299,6 @@ void Basic_Constraints::decode_inner(const std::vector<uint8_t>& in) .start_cons(SEQUENCE) .decode_optional(m_is_ca, BOOLEAN, UNIVERSAL, false) .decode_optional(m_path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT) - .verify_end() .end_cons(); if(m_is_ca == false) diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp index cc97c1f15..43e92d322 100644 --- a/src/lib/x509/x509_obj.cpp +++ b/src/lib/x509/x509_obj.cpp @@ -105,7 +105,6 @@ void X509_Object::decode_from(BER_Decoder& from) .end_cons() .decode(m_sig_algo) .decode(m_sig, BIT_STRING) - .verify_end() .end_cons(); } diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp index e53034dce..b6e15a3e0 100644 --- a/src/lib/x509/x509cert.cpp +++ b/src/lib/x509/x509cert.cpp @@ -95,7 +95,6 @@ void X509_Certificate::force_decode() .start_cons(SEQUENCE) .decode(start) .decode(end) - .verify_end() .end_cons() .decode(dn_subject); diff --git a/src/tests/test_ocsp.cpp b/src/tests/test_ocsp.cpp index 41faa5edf..3fc1ad765 100644 --- a/src/tests/test_ocsp.cpp +++ b/src/tests/test_ocsp.cpp @@ -148,6 +148,7 @@ class OCSP_Tests : public Test { Test::Result result("OCSP online check"); + // Expired end-entity certificate: std::shared_ptr<const Botan::X509_Certificate> ee = load_test_X509_cert("ocsp/randombit.pem"); std::shared_ptr<const Botan::X509_Certificate> ca = load_test_X509_cert("ocsp/letsencrypt.pem"); std::shared_ptr<const Botan::X509_Certificate> trust_root = load_test_X509_cert("ocsp/identrust.pem"); @@ -168,7 +169,7 @@ class OCSP_Tests : public Test { if(result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1)) { - result.confirm("Status good", ocsp_status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD)); + result.confirm("Status expired", ocsp_status[0].count(Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED)); } if(result.test_eq("Expected size of ocsp_status[1]", ocsp_status[1].size(), 1)) { diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 712fa8df4..9a8c5d2e7 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -42,10 +42,18 @@ void check_invalid_signatures(Test::Result& result, { const std::vector<uint8_t> bad_sig = Test::mutate_vec(signature); - if(!result.test_eq("incorrect signature invalid", - verifier.verify_message(message, bad_sig), false)) + try + { + if(!result.test_eq("incorrect signature invalid", + verifier.verify_message(message, bad_sig), false)) + { + result.test_note("Accepted invalid signature " + Botan::hex_encode(bad_sig)); + } + } + catch(std::exception& e) { result.test_note("Accepted invalid signature " + Botan::hex_encode(bad_sig)); + result.test_failure("Modified signature rejected with exception", e.what()); } } } |