diff options
Diffstat (limited to 'src/cli')
-rw-r--r-- | src/cli/asn1.cpp | 66 | ||||
-rw-r--r-- | src/cli/cc_enc.cpp | 28 | ||||
-rw-r--r-- | src/cli/cli.h | 68 | ||||
-rw-r--r-- | src/cli/compress.cpp | 28 | ||||
-rw-r--r-- | src/cli/credentials.h | 26 | ||||
-rw-r--r-- | src/cli/main.cpp | 4 | ||||
-rw-r--r-- | src/cli/math.cpp | 18 | ||||
-rw-r--r-- | src/cli/pubkey.cpp | 49 | ||||
-rw-r--r-- | src/cli/speed.cpp | 400 | ||||
-rw-r--r-- | src/cli/timing_tests.cpp | 107 | ||||
-rw-r--r-- | src/cli/tls_client.cpp | 81 | ||||
-rw-r--r-- | src/cli/tls_proxy.cpp | 179 | ||||
-rw-r--r-- | src/cli/tls_server.cpp | 85 | ||||
-rw-r--r-- | src/cli/tls_utils.cpp | 24 | ||||
-rw-r--r-- | src/cli/utils.cpp | 39 | ||||
-rw-r--r-- | src/cli/x509.cpp | 60 |
16 files changed, 775 insertions, 487 deletions
diff --git a/src/cli/asn1.cpp b/src/cli/asn1.cpp index b877a24a1..f24e2c316 100644 --- a/src/cli/asn1.cpp +++ b/src/cli/asn1.cpp @@ -47,7 +47,9 @@ std::string url_encode(const std::vector<uint8_t>& in) { const int c = in[i]; if(::isprint(c)) + { out << static_cast<char>(c); + } else { out << "%" << std::hex << static_cast<int>(c) << std::dec; @@ -56,14 +58,16 @@ std::string url_encode(const std::vector<uint8_t>& in) } if(unprintable >= in.size() / 4) + { return Botan::hex_encode(in); + } return out.str(); } void emit(const std::string& type, size_t level, size_t length, const std::string& value = "") { - const size_t LIMIT = 4*1024; + const size_t LIMIT = 4 * 1024; const size_t BIN_LIMIT = 1024; std::ostringstream out; @@ -72,23 +76,35 @@ void emit(const std::string& type, size_t level, size_t length, const std::strin << ", l=" << std::setw(4) << length << ": "; for(size_t i = INITIAL_LEVEL; i != level; ++i) + { out << ' '; + } out << type; bool should_skip = false; if(value.length() > LIMIT) + { should_skip = true; + } if((type == "OCTET STRING" || type == "BIT STRING") && value.length() > BIN_LIMIT) + { should_skip = true; + } if(value != "" && !should_skip) { - if(out.tellp() % 2 == 0) out << ' '; + if(out.tellp() % 2 == 0) + { + out << ' '; + } - while(out.tellp() < 50) out << ' '; + while(out.tellp() < 50) + { + out << ' '; + } out << value; } @@ -177,12 +193,12 @@ void decode(Botan::BER_Decoder& decoder, size_t level) if(type_tag == Botan::SEQUENCE) { emit("SEQUENCE", level, length); - decode(cons_info, level+1); + decode(cons_info, level + 1); } else if(type_tag == Botan::SET) { emit("SET", level, length); - decode(cons_info, level+1); + decode(cons_info, level + 1); } else { @@ -193,15 +209,21 @@ void decode(Botan::BER_Decoder& decoder, size_t level) name = "cons [" + std::to_string(type_tag) + "]"; if(class_tag & Botan::APPLICATION) + { name += " appl"; + } if(class_tag & Botan::CONTEXT_SPECIFIC) + { name += " context"; + } } else + { name = type_name(type_tag) + " (cons)"; + } emit(name, level, length); - decode(cons_info, level+1); + decode(cons_info, level + 1); } } else if((class_tag & Botan::APPLICATION) || (class_tag & Botan::CONTEXT_SPECIFIC)) @@ -217,12 +239,10 @@ void decode(Botan::BER_Decoder& decoder, size_t level) } catch(...) { - emit("[" + std::to_string(type_tag) + "]", level, length, - url_encode(bits)); + emit("[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); } #else - emit("[" + std::to_string(type_tag) + "]", level, length, - url_encode(bits)); + emit("[" + std::to_string(type_tag) + "]", level, length, url_encode(bits)); #endif } else if(type_tag == Botan::OBJECT_ID) @@ -232,7 +252,9 @@ void decode(Botan::BER_Decoder& decoder, size_t level) std::string out = Botan::OIDS::lookup(oid); if(out != oid.as_string()) + { out += " [" + oid.as_string() + "]"; + } emit(type_name(type_tag), level, length, out); } @@ -241,21 +263,31 @@ void decode(Botan::BER_Decoder& decoder, size_t level) Botan::BigInt number; if(type_tag == Botan::INTEGER) + { data.decode(number); + } else if(type_tag == Botan::ENUMERATED) + { data.decode(number, Botan::ENUMERATED, class_tag); + } std::vector<uint8_t> rep; /* If it's small, it's probably a number, not a hash */ if(number.bits() <= 20) + { rep = Botan::BigInt::encode(number, Botan::BigInt::Decimal); + } else + { rep = Botan::BigInt::encode(number, Botan::BigInt::Hexadecimal); + } std::string str; for(size_t i = 0; i != rep.size(); ++i) + { str += static_cast<char>(rep[i]); + } emit(type_name(type_tag), level, length, str); } @@ -263,8 +295,7 @@ void decode(Botan::BER_Decoder& decoder, size_t level) { bool boolean; data.decode(boolean); - emit(type_name(type_tag), - level, length, (boolean ? "true" : "false")); + emit(type_name(type_tag), level, length, (boolean ? "true" : "false")); } else if(type_tag == Botan::NULL_TAG) { @@ -282,8 +313,7 @@ void decode(Botan::BER_Decoder& decoder, size_t level) } catch(...) { - emit(type_name(type_tag), level, length, - url_encode(decoded_bits)); + emit(type_name(type_tag), level, length, url_encode(decoded_bits)); } } else if(type_tag == Botan::BIT_STRING) @@ -294,19 +324,23 @@ void decode(Botan::BER_Decoder& decoder, size_t level) std::vector<bool> bit_set; for(size_t i = 0; i != decoded_bits.size(); ++i) + { for(size_t j = 0; j != 8; ++j) { - const bool bit = static_cast<bool>((decoded_bits[decoded_bits.size()-i-1] >> (7-j)) & 1); + const bool bit = static_cast<bool>((decoded_bits[decoded_bits.size() - i - 1] >> (7 - j)) & 1); bit_set.push_back(bit); } + } std::string bit_str; for(size_t i = 0; i != bit_set.size(); ++i) { - bool the_bit = bit_set[bit_set.size()-i-1]; + bool the_bit = bit_set[bit_set.size() - i - 1]; if(!the_bit && bit_str.size() == 0) + { continue; + } bit_str += (the_bit ? "1" : "0"); } diff --git a/src/cli/cc_enc.cpp b/src/cli/cc_enc.cpp index 9a3256417..ec160c3ce 100644 --- a/src/cli/cc_enc.cpp +++ b/src/cli/cc_enc.cpp @@ -28,7 +28,9 @@ uint8_t luhn_checksum(uint64_t cc_number) { digit *= 2; if(digit > 9) + { digit -= 9; + } } sum += digit; @@ -75,11 +77,15 @@ uint64_t encrypt_cc_number(uint64_t cc_number, const Botan::BigInt c = Botan::FPE::fe1_encrypt(n, cc_ranked, key, tweak); if(c.bits() > 50) + { throw Botan::Internal_Error("FPE produced a number too large"); + } uint64_t enc_cc = 0; for(size_t i = 0; i != 7; ++i) - enc_cc = (enc_cc << 8) | c.byte_at(6-i); + { + enc_cc = (enc_cc << 8) | c.byte_at(6 - i); + } return cc_derank(enc_cc); } @@ -94,11 +100,15 @@ uint64_t decrypt_cc_number(uint64_t enc_cc, const Botan::BigInt c = Botan::FPE::fe1_decrypt(n, cc_ranked, key, tweak); if(c.bits() > 50) + { throw CLI_Error("FPE produced a number too large"); + } uint64_t dec_cc = 0; for(size_t i = 0; i != 7; ++i) - dec_cc = (dec_cc << 8) | c.byte_at(6-i); + { + dec_cc = (dec_cc << 8) | c.byte_at(6 - i); + } return cc_derank(dec_cc); } @@ -117,12 +127,11 @@ class CC_Encrypt final : public Command std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create("PBKDF2(SHA-256)")); if(!pbkdf) + { throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)"); + } - Botan::secure_vector<uint8_t> key = - pbkdf->pbkdf_iterations(32, pass, - tweak.data(), tweak.size(), - 100000); + Botan::secure_vector<uint8_t> key = pbkdf->pbkdf_iterations(32, pass, tweak.data(), tweak.size(), 100000); output() << encrypt_cc_number(cc_number, key, tweak) << "\n"; } @@ -143,12 +152,11 @@ class CC_Decrypt final : public Command std::unique_ptr<Botan::PBKDF> pbkdf(Botan::PBKDF::create("PBKDF2(SHA-256)")); if(!pbkdf) + { throw CLI_Error_Unsupported("PBKDF", "PBKDF2(SHA-256)"); + } - Botan::secure_vector<uint8_t> key = - pbkdf->pbkdf_iterations(32, pass, - tweak.data(), tweak.size(), - 100000); + Botan::secure_vector<uint8_t> key = pbkdf->pbkdf_iterations(32, pass, tweak.data(), tweak.size(), 100000); output() << decrypt_cc_number(cc_number, key, tweak) << "\n"; } diff --git a/src/cli/cli.h b/src/cli/cli.h index c3dc8d849..a5150d6d7 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -12,11 +12,11 @@ #include <botan/rng.h> #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - #include <botan/auto_rng.h> + #include <botan/auto_rng.h> #endif #if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> + #include <botan/system_rng.h> #endif #include <fstream> @@ -56,15 +56,15 @@ class CLI_Error_Unsupported : public CLI_Error { public: CLI_Error_Unsupported(const std::string& what, - const std::string& who) : - CLI_Error(what + " with '" + who + "' unsupported or not available") {} + const std::string& who) + : CLI_Error(what + " with '" + who + "' unsupported or not available") {} }; struct CLI_Error_Invalid_Spec : public CLI_Error { public: - explicit CLI_Error_Invalid_Spec(const std::string& spec) : - CLI_Error("Invalid command spec '" + spec + "'") {} + explicit CLI_Error_Invalid_Spec(const std::string& spec) + : CLI_Error("Invalid command spec '" + spec + "'") {} }; class Command @@ -124,7 +124,7 @@ class Command parse_spec(); std::vector<std::string> args; - for(auto&& param : params) + for(auto const& param : params) { if(param.find("--") == 0) { @@ -138,12 +138,15 @@ class Command if(m_spec_flags.count(opt_name) == 0) { if(m_spec_opts.count(opt_name)) + { throw CLI_Usage_Error("Invalid usage of option --" + opt_name + " without value"); + } else + { throw CLI_Usage_Error("Unknown flag --" + opt_name); + } } - m_user_flags.insert(opt_name); } else @@ -168,7 +171,7 @@ class Command bool seen_stdin_flag = false; size_t arg_i = 0; - for(auto&& arg : m_spec_args) + for(auto const& arg : m_spec_args) { if(arg_i >= args.size()) { @@ -184,7 +187,9 @@ class Command if(args[arg_i] == "-") { if(seen_stdin_flag) + { throw CLI_Usage_Error("Cannot specifiy '-' (stdin) more than once"); + } seen_stdin_flag = true; } @@ -194,7 +199,9 @@ class Command if(m_spec_rest.empty()) { if(arg_i != args.size()) + { throw CLI_Usage_Error("Too many arguments"); + } } else { @@ -218,7 +225,7 @@ class Command } // Now insert any defaults for options not supplied by the user - for(auto&& opt : m_spec_opts) + for(auto const& opt : m_spec_opts) { if(m_user_args.count(opt.first) == 0) { @@ -252,7 +259,10 @@ class Command return "Usage: " + m_spec; } - const std::string& cmd_spec() const { return m_spec; } + const std::string& cmd_spec() const + { + return m_spec; + } std::string cmd_name() const { @@ -266,14 +276,18 @@ class Command const std::vector<std::string> parts = Botan::split_on(m_spec, ' '); if(parts.size() == 0) + { throw CLI_Error_Invalid_Spec(m_spec); + } for(size_t i = 1; i != parts.size(); ++i) { const std::string s = parts[i]; if(s.empty()) // ?!? (shouldn't happen) + { throw CLI_Error_Invalid_Spec(m_spec); + } if(s.size() > 2 && s[0] == '-' && s[1] == '-') { @@ -287,8 +301,7 @@ class Command } else { - m_spec_opts.insert(std::make_pair(s.substr(2, eq - 2), - s.substr(eq + 1, std::string::npos))); + m_spec_opts.insert(std::make_pair(s.substr(2, eq - 2), s.substr(eq + 1, std::string::npos))); } } else if(s[0] == '*') @@ -307,7 +320,9 @@ class Command { // named argument if(!m_spec_rest.empty()) // rest arg wasn't last + { throw CLI_Error("Invalid command spec " + m_spec); + } m_spec_args.push_back(s); } @@ -318,13 +333,12 @@ class Command m_spec_opts.insert(std::make_pair("output", "")); m_spec_opts.insert(std::make_pair("error-output", "")); - m_spec_opts.insert(std::make_pair("rng-type", #if defined(BOTAN_HAS_SYSTEM_RNG) - "system" + const auto availableRng = "system"; #else - "auto" + const auto availableRng = "auto"; #endif - )); + m_spec_opts.insert(std::make_pair("rng-type", availableRng)); } /* @@ -335,14 +349,18 @@ class Command std::ostream& output() { if(m_output_stream.get()) + { return *m_output_stream; + } return std::cout; } std::ostream& error_output() { if(m_error_output_stream.get()) + { return *m_error_output_stream; + } return std::cerr; } @@ -397,7 +415,9 @@ class Command std::vector<std::string> get_arg_list(const std::string& what) const { if(what != m_spec_rest) + { throw CLI_Error("Unexpected list name '" + what + "'"); + } return m_user_rest; } @@ -409,7 +429,9 @@ class Command { std::vector<uint8_t> buf; auto insert_fn = [&](const uint8_t b[], size_t l) - { buf.insert(buf.end(), b, b + l); }; + { + buf.insert(buf.end(), b, b + l); + }; this->read_file(input_file, insert_fn); return buf; } @@ -418,7 +440,9 @@ class Command { std::string str; auto insert_fn = [&](const uint8_t b[], size_t l) - { str.append(reinterpret_cast<const char*>(b), l); }; + { + str.append(reinterpret_cast<const char*>(b), l); + }; this->read_file(input_file, insert_fn); return str; } @@ -438,7 +462,9 @@ class Command { std::ifstream in(input_file, std::ios::binary); if(!in) + { throw CLI_IO_Error("reading file", input_file); + } do_read_file(in, consumer_fn, buf_size); } } @@ -557,8 +583,8 @@ class Command }; }; -#define BOTAN_REGISTER_COMMAND(name, CLI_Class) \ - namespace { Botan_CLI::Command::Registration \ +#define BOTAN_REGISTER_COMMAND(name, CLI_Class) \ + namespace { Botan_CLI::Command::Registration \ reg_cmd_ ## CLI_Class(name, []() -> Botan_CLI::Command* { return new CLI_Class; }); } \ BOTAN_FORCE_SEMICOLON diff --git a/src/cli/compress.cpp b/src/cli/compress.cpp index d5b2c4736..6ee6398ee 100644 --- a/src/cli/compress.cpp +++ b/src/cli/compress.cpp @@ -7,7 +7,7 @@ #include "cli.h" #if defined(BOTAN_HAS_COMPRESSION) - #include <botan/compression.h> + #include <botan/compression.h> #endif namespace Botan_CLI { @@ -19,15 +19,15 @@ class Compress final : public Command public: Compress() : Command("compress --type=gzip --level=6 --buf-size=8192 file") {} - std::string output_filename(const std::string& input_fsname, - const std::string& comp_type) + std::string output_filename(const std::string& input_fsname, const std::string& comp_type) { - const std::map<std::string, std::string> suffixes = { - { "zlib", "zlib" }, - { "gzip", "gz" }, - { "bzip2", "bz2" }, - { "lzma", "xz" }, - }; + const std::map<std::string, std::string> suffixes = + { + { "zlib", "zlib" }, + { "gzip", "gz" }, + { "bzip2", "bz2" }, + { "lzma", "xz" }, + }; auto suffix_info = suffixes.find(comp_type); if(suffixes.count(comp_type) == 0) @@ -103,10 +103,12 @@ class Decompress final : public Command { auto last_dot = in_file.find_last_of('.'); if(last_dot == std::string::npos || last_dot == 0) + { throw CLI_Error("No extension detected in filename '" + in_file + "'"); + } out_file = in_file.substr(0, last_dot); - suffix = in_file.substr(last_dot+1, std::string::npos); + suffix = in_file.substr(last_dot + 1, std::string::npos); } void go() override @@ -119,18 +121,24 @@ class Decompress final : public Command std::ifstream in(in_file); if(!in.good()) + { throw CLI_IO_Error("reading", in_file); + } std::unique_ptr<Botan::Decompression_Algorithm> decompress; decompress.reset(Botan::make_decompressor(suffix)); if(!decompress) + { throw CLI_Error_Unsupported("Decompression", suffix); + } std::ofstream out(out_file); if(!out.good()) + { throw CLI_IO_Error("writing", out_file); + } Botan::secure_vector<uint8_t> buf; diff --git a/src/cli/credentials.h b/src/cli/credentials.h index 71acdc83d..99733e42b 100644 --- a/src/cli/credentials.h +++ b/src/cli/credentials.h @@ -18,8 +18,12 @@ inline bool value_exists(const std::vector<std::string>& vec, const std::string& val) { for(size_t i = 0; i != vec.size(); ++i) + { if(vec[i] == val) + { return true; + } + } return false; } @@ -64,7 +68,7 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager // TODO: make path configurable const std::vector<std::string> paths = { "/etc/ssl/certs", "/usr/share/ca-certificates" }; - for(auto&& path : paths) + for(auto const& path : paths) { std::shared_ptr<Botan::Certificate_Store> cs(new Botan::Certificate_Store_In_Memory(path)); m_certstores.push_back(cs); @@ -84,10 +88,14 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager // don't ask for client certs if(type == "tls-server") + { return v; + } - for(auto&& cs : m_certstores) + for(auto const& cs : m_certstores) + { v.push_back(cs.get()); + } return v; } @@ -99,13 +107,17 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager { BOTAN_UNUSED(type); - for(auto&& i : m_creds) + for(auto const& i : m_creds) { if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end()) + { continue; + } if(hostname != "" && !i.certs[0].matches_dns_name(hostname)) + { continue; + } return i.certs; } @@ -117,10 +129,12 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager const std::string& /*type*/, const std::string& /*context*/) override { - for(auto&& i : m_creds) + for(auto const& i : m_creds) { if(cert == i.certs[0]) + { return i.key.get(); + } } return nullptr; @@ -129,8 +143,8 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager private: struct Certificate_Info { - std::vector<Botan::X509_Certificate> certs; - std::shared_ptr<Botan::Private_Key> key; + std::vector<Botan::X509_Certificate> certs; + std::shared_ptr<Botan::Private_Key> key; }; std::vector<Certificate_Info> m_creds; diff --git a/src/cli/main.cpp b/src/cli/main.cpp index f63de8fa2..5fbaf085e 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -36,9 +36,7 @@ std::string main_help() int main(int argc, char* argv[]) { - std::cerr << Botan::runtime_version_check(BOTAN_VERSION_MAJOR, - BOTAN_VERSION_MINOR, - BOTAN_VERSION_PATCH); + std::cerr << Botan::runtime_version_check(BOTAN_VERSION_MAJOR, BOTAN_VERSION_MINOR, BOTAN_VERSION_PATCH); const std::string cmd_name = (argc <= 1) ? "help" : argv[1]; diff --git a/src/cli/math.cpp b/src/cli/math.cpp index 4ed58b9f0..ee1c2b1a9 100644 --- a/src/cli/math.cpp +++ b/src/cli/math.cpp @@ -68,9 +68,7 @@ class Factor final : public Command std::sort(factors.begin(), factors.end()); output() << n << ": "; - std::copy(factors.begin(), - factors.end(), - std::ostream_iterator<Botan::BigInt>(output(), " ")); + std::copy(factors.begin(), factors.end(), std::ostream_iterator<Botan::BigInt>(output(), " ")); output() << std::endl; } @@ -92,11 +90,15 @@ class Factor final : public Command Botan::BigInt a_factor = 0; while(a_factor == 0) + { a_factor = rho(n, rng); + } std::vector<Botan::BigInt> rho_factored = factorize(a_factor, rng); for(size_t j = 0; j != rho_factored.size(); j++) + { factors.push_back(rho_factored[j]); + } n /= a_factor; } @@ -111,7 +113,7 @@ class Factor final : public Command */ Botan::BigInt rho(const Botan::BigInt& n, Botan::RandomNumberGenerator& rng) { - Botan::BigInt x = Botan::BigInt::random_integer(rng, 0, n-1); + Botan::BigInt x = Botan::BigInt::random_integer(rng, 0, n - 1); Botan::BigInt y = x; Botan::BigInt d = 0; @@ -123,18 +125,22 @@ class Factor final : public Command i++; if(i == 0) // overflow, bail out + { break; + } x = mod_n.multiply((x + 1), x); d = Botan::gcd(y - x, n); if(d != 1 && d != n) + { return d; + } if(i == k) { y = x; - k = 2*k; + k = 2 * k; } } return 0; @@ -155,7 +161,9 @@ class Factor final : public Command { uint16_t prime = Botan::PRIMES[j]; if(n < prime) + { break; + } Botan::BigInt x = Botan::gcd(n, prime); diff --git a/src/cli/pubkey.cpp b/src/cli/pubkey.cpp index aac493a0e..25f3e2ed5 100644 --- a/src/cli/pubkey.cpp +++ b/src/cli/pubkey.cpp @@ -17,11 +17,11 @@ #include <botan/pubkey.h> #if defined(BOTAN_HAS_DL_GROUP) - #include <botan/dl_group.h> + #include <botan/dl_group.h> #endif #if defined(BOTAN_HAS_ECC_GROUP) - #include <botan/ec_group.h> + #include <botan/ec_group.h> #endif namespace Botan_CLI { @@ -37,7 +37,7 @@ class PK_Keygen final : public Command const std::string params = get_arg("params"); std::unique_ptr<Botan::Private_Key> - key(Botan::create_private_key(algo, rng(), params)); + key(Botan::create_private_key(algo, rng(), params)); if(!key) { @@ -82,11 +82,17 @@ namespace { std::string algo_default_emsa(const std::string& key) { if(key == "RSA") - return "EMSA4"; // PSS + { + return "EMSA4"; + } // PSS else if(key == "ECDSA" || key == "DSA") + { return "EMSA1"; + } else + { return "EMSA1"; + } } } @@ -98,20 +104,27 @@ class PK_Sign final : public Command void go() override { - std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(get_arg("key"), - rng(), - get_arg("passphrase"))); + std::unique_ptr<Botan::Private_Key> key( + Botan::PKCS8::load_key( + get_arg("key"), + rng(), + get_arg("passphrase"))); if(!key) + { throw CLI_Error("Unable to load private key"); + } const std::string sig_padding = get_arg_or("emsa", algo_default_emsa(key->algo_name())) + "(" + get_arg("hash") + ")"; Botan::PK_Signer signer(*key, rng(), sig_padding); - this->read_file(get_arg("file"), - [&signer](const uint8_t b[], size_t l) { signer.update(b, l); }); + auto onData = [&signer](const uint8_t b[], size_t l) + { + signer.update(b, l); + }; + this->read_file(get_arg("file"), onData); output() << Botan::base64_encode(signer.signature(rng())) << "\n"; } @@ -128,14 +141,19 @@ class PK_Verify final : public Command { std::unique_ptr<Botan::Public_Key> key(Botan::X509::load_key(get_arg("pubkey"))); if(!key) + { throw CLI_Error("Unable to load public key"); + } const std::string sig_padding = get_arg_or("emsa", algo_default_emsa(key->algo_name())) + "(" + get_arg("hash") + ")"; Botan::PK_Verifier verifier(*key, sig_padding); - this->read_file(get_arg("file"), - [&verifier](const uint8_t b[], size_t l) { verifier.update(b, l); }); + auto onData = [&verifier](const uint8_t b[], size_t l) + { + verifier.update(b, l); + }; + this->read_file(get_arg("file"), onData); const Botan::secure_vector<uint8_t> signature = Botan::base64_decode(this->slurp_file_as_str(get_arg("signature"))); @@ -227,7 +245,9 @@ class Gen_DL_Group final : public Command output() << grp.PEM_encode(Botan::DL_Group::ANSI_X9_42); } else + { throw CLI_Usage_Error("Invalid DL type '" + type + "'"); + } } }; @@ -243,9 +263,10 @@ class PKCS8_Tool final : public Command void go() override { std::unique_ptr<Botan::Private_Key> key( - Botan::PKCS8::load_key(get_arg("key"), - rng(), - get_arg("pass-in"))); + Botan::PKCS8::load_key( + get_arg("key"), + rng(), + get_arg("pass-in"))); const std::chrono::milliseconds pbe_millis(get_arg_sz("pbe-millis")); const std::string pbe = get_arg("pbe"); diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index 2bffc736e..cf048e0d2 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -26,91 +26,91 @@ //#define INCLUDE_SIMD_PERF #if defined(BOTAN_HAS_SIMD_32) && defined(INCLUDE_SIMD_PERF) - #include <botan/internal/simd_32.h> + #include <botan/internal/simd_32.h> #endif #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - #include <botan/auto_rng.h> + #include <botan/auto_rng.h> #endif #if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> + #include <botan/system_rng.h> #endif #if defined(BOTAN_HAS_HMAC_DRBG) - #include <botan/hmac_drbg.h> + #include <botan/hmac_drbg.h> #endif #if defined(BOTAN_HAS_HMAC_RNG) - #include <botan/hmac_rng.h> + #include <botan/hmac_rng.h> #endif #if defined(BOTAN_HAS_RDRAND_RNG) - #include <botan/rdrand_rng.h> + #include <botan/rdrand_rng.h> #endif #if defined(BOTAN_HAS_FPE_FE1) - #include <botan/fpe_fe1.h> + #include <botan/fpe_fe1.h> #endif #if defined(BOTAN_HAS_COMPRESSION) - #include <botan/compression.h> + #include <botan/compression.h> #endif #if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO) - #include <botan/pkcs8.h> - #include <botan/pubkey.h> - #include <botan/x509_key.h> - #include <botan/workfactor.h> + #include <botan/pkcs8.h> + #include <botan/pubkey.h> + #include <botan/x509_key.h> + #include <botan/workfactor.h> #endif #if defined(BOTAN_HAS_NUMBERTHEORY) - #include <botan/numthry.h> + #include <botan/numthry.h> #endif #if defined(BOTAN_HAS_RSA) - #include <botan/rsa.h> + #include <botan/rsa.h> #endif #if defined(BOTAN_HAS_ECC_GROUP) - #include <botan/ec_group.h> + #include <botan/ec_group.h> #endif #if defined(BOTAN_HAS_ECDSA) - #include <botan/ecdsa.h> + #include <botan/ecdsa.h> #endif #if defined(BOTAN_HAS_ECKCDSA) - #include <botan/eckcdsa.h> + #include <botan/eckcdsa.h> #endif #if defined(BOTAN_HAS_ECGDSA) - #include <botan/ecgdsa.h> + #include <botan/ecgdsa.h> #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh.h> + #include <botan/dh.h> #endif #if defined(BOTAN_HAS_CURVE_25519) - #include <botan/curve25519.h> + #include <botan/curve25519.h> #endif #if defined(BOTAN_HAS_ECDH) - #include <botan/ecdh.h> + #include <botan/ecdh.h> #endif #if defined(BOTAN_HAS_MCELIECE) - #include <botan/mceliece.h> + #include <botan/mceliece.h> #endif #if defined(BOTAN_HAS_XMSS) - #include <botan/xmss.h> + #include <botan/xmss.h> #endif #if defined(BOTAN_HAS_NEWHOPE) && defined(BOTAN_HAS_CHACHA) - #include <botan/newhope.h> - #include <botan/chacha.h> + #include <botan/newhope.h> + #include <botan/chacha.h> #endif namespace Botan_CLI { @@ -123,17 +123,16 @@ class Timer Timer(const std::string& name, uint64_t event_mult = 1, const std::string& doing = "", - const std::string& provider = "") : - m_name(name + (provider.empty() ? provider : " [" + provider + "]")), - m_doing(doing), - m_event_mult(event_mult) - {} + const std::string& provider = "") + : m_name(name + (provider.empty() ? provider : " [" + provider + "]")) + , m_doing(doing) + , m_event_mult(event_mult) {} Timer(const std::string& name, const std::string& provider, const std::string& doing, - uint64_t event_mult = 1) : - Timer(name, event_mult, doing, provider) {} + uint64_t event_mult = 1) + : Timer(name, event_mult, doing, provider) {} static uint64_t get_system_timestamp_ns() { @@ -197,8 +196,15 @@ class Timer struct Timer_Scope { public: - explicit Timer_Scope(Timer& timer) : m_timer(timer) { m_timer.start(); } - ~Timer_Scope() { m_timer.stop(); } + explicit Timer_Scope(Timer& timer) + : m_timer(timer) + { + m_timer.start(); + } + ~Timer_Scope() + { + m_timer.stop(); + } private: Timer& m_timer; }; @@ -219,17 +225,41 @@ class Timer } } - uint64_t value() const { return m_time_used; } - double seconds() const { return milliseconds() / 1000.0; } - double milliseconds() const { return value() / 1000000.0; } + uint64_t value() const + { + return m_time_used; + } + double seconds() const + { + return milliseconds() / 1000.0; + } + double milliseconds() const + { + return value() / 1000000.0; + } - double ms_per_event() const { return milliseconds() / events(); } + double ms_per_event() const + { + return milliseconds() / events(); + } - uint64_t cycles_consumed() const { return m_cpu_cycles_used; } + uint64_t cycles_consumed() const + { + return m_cpu_cycles_used; + } - uint64_t events() const { return m_event_count * m_event_mult; } - const std::string& get_name() const { return m_name; } - const std::string& doing() const { return m_doing; } + uint64_t events() const + { + return m_event_count * m_event_mult; + } + const std::string& get_name() const + { + return m_name; + } + const std::string& doing() const + { + return m_doing; + } static std::string result_string_bps(const Timer& t); static std::string result_string_ops(const Timer& t); @@ -244,7 +274,7 @@ class Timer std::string Timer::result_string_bps(const Timer& timer) { - const size_t MiB = 1024*1024; + const size_t MiB = 1024 * 1024; const double MiB_total = static_cast<double>(timer.events()) / MiB; const double MiB_per_sec = MiB_total / timer.seconds(); @@ -253,10 +283,11 @@ std::string Timer::result_string_bps(const Timer& timer) oss << timer.get_name(); if(!timer.doing().empty()) + { oss << " " << timer.doing(); + } - oss << " " << std::fixed << std::setprecision(3) - << MiB_per_sec << " MiB/sec"; + oss << " " << std::fixed << std::setprecision(3) << MiB_per_sec << " MiB/sec"; if(timer.cycles_consumed() != 0) { @@ -309,7 +340,8 @@ std::vector<std::string> default_benchmark_list() points of the most interesting or widely used algorithms. */ - return { + return + { /* Block ciphers */ "AES-128", "AES-192", @@ -382,7 +414,8 @@ std::vector<std::string> default_benchmark_list() class Speed final : public Command { public: - Speed() : Command("speed --msec=300 --provider= --buf-size=4096 *algos") {} + Speed() + : Command("speed --msec=300 --provider= --buf-size=4096 *algos") {} void go() override { @@ -393,7 +426,9 @@ class Speed final : public Command std::vector<std::string> algos = get_arg_list("algos"); const bool using_defaults = (algos.empty()); if(using_defaults) + { algos = default_benchmark_list(); + } for(auto algo : algos) { @@ -592,7 +627,7 @@ class Speed final : public Command size_t buf_size, bench_fn<T> bench_one) { - for(auto&& prov : T::providers(algo)) + for(auto const& prov : T::providers(algo)) { if(provider.empty() || provider == prov) { @@ -618,19 +653,20 @@ class Speed final : public Command Timer ks_timer(cipher.name(), provider, "key schedule"); const Botan::SymmetricKey key(rng(), cipher.maximum_keylength()); - ks_timer.run([&] { cipher.set_key(key); }); + ks_timer.run([&]() { cipher.set_key(key); }); - encrypt_timer.run_until_elapsed(runtime, [&] { cipher.encrypt(buffer); }); + encrypt_timer.run_until_elapsed(runtime, [&]() { cipher.encrypt(buffer); }); output() << Timer::result_string_bps(encrypt_timer); - decrypt_timer.run_until_elapsed(runtime, [&] { cipher.decrypt(buffer); }); + decrypt_timer.run_until_elapsed(runtime, [&]() { cipher.decrypt(buffer); }); output() << Timer::result_string_bps(decrypt_timer); } - void bench_stream_cipher(Botan::StreamCipher& cipher, - const std::string& provider, - const std::chrono::milliseconds runtime, - size_t buf_size) + void bench_stream_cipher( + Botan::StreamCipher& cipher, + const std::string& provider, + const std::chrono::milliseconds runtime, + size_t buf_size) { Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size); @@ -647,28 +683,30 @@ class Speed final : public Command while(encrypt_timer.under(runtime)) { - encrypt_timer.run([&] { cipher.encipher(buffer); }); + encrypt_timer.run([&]() { cipher.encipher(buffer); }); } output() << Timer::result_string_bps(encrypt_timer); } - void bench_hash(Botan::HashFunction& hash, - const std::string& provider, - const std::chrono::milliseconds runtime, - size_t buf_size) + void bench_hash( + Botan::HashFunction& hash, + const std::string& provider, + const std::chrono::milliseconds runtime, + size_t buf_size) { Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size); Timer timer(hash.name(), provider, "hash", buffer.size()); - timer.run_until_elapsed(runtime, [&] { hash.update(buffer); }); + timer.run_until_elapsed(runtime, [&]() { hash.update(buffer); }); output() << Timer::result_string_bps(timer); } - void bench_mac(Botan::MessageAuthenticationCode& mac, - const std::string& provider, - const std::chrono::milliseconds runtime, - size_t buf_size) + void bench_mac( + Botan::MessageAuthenticationCode& mac, + const std::string& provider, + const std::chrono::milliseconds runtime, + size_t buf_size) { Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size); @@ -676,14 +714,15 @@ class Speed final : public Command mac.set_key(key); Timer timer(mac.name(), provider, "mac", buffer.size()); - timer.run_until_elapsed(runtime, [&] { mac.update(buffer); }); + timer.run_until_elapsed(runtime, [&]() { mac.update(buffer); }); output() << Timer::result_string_bps(timer); } - void bench_cipher_mode(Botan::Cipher_Mode& enc, - Botan::Cipher_Mode& dec, - const std::chrono::milliseconds runtime, - size_t buf_size) + void bench_cipher_mode( + Botan::Cipher_Mode& enc, + Botan::Cipher_Mode& dec, + const std::chrono::milliseconds runtime, + size_t buf_size) { Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size); @@ -694,22 +733,24 @@ class Speed final : public Command const Botan::SymmetricKey key(rng(), enc.key_spec().maximum_keylength()); - ks_timer.run([&] { enc.set_key(key); }); - ks_timer.run([&] { dec.set_key(key); }); + ks_timer.run([&]() { enc.set_key(key); }); + ks_timer.run([&]() { dec.set_key(key); }); Botan::secure_vector<uint8_t> iv = rng().random_vec(enc.default_nonce_length()); while(encrypt_timer.under(runtime) && decrypt_timer.under(runtime)) { // Must run in this order, or AEADs will reject the ciphertext - iv_timer.run([&] { enc.start(iv); }); - encrypt_timer.run([&] { enc.finish(buffer); }); + iv_timer.run([&]() { enc.start(iv); }); + encrypt_timer.run([&]() { enc.finish(buffer); }); - iv_timer.run([&] { dec.start(iv); }); - decrypt_timer.run([&] { dec.finish(buffer); }); + iv_timer.run([&]() { dec.start(iv); }); + decrypt_timer.run([&]() { dec.finish(buffer); }); if(iv.size() > 0) + { iv[0] += 1; + } } output() << Timer::result_string_ops(ks_timer); @@ -718,10 +759,11 @@ class Speed final : public Command output() << Timer::result_string_bps(decrypt_timer); } - void bench_rng(Botan::RandomNumberGenerator& rng, - const std::string& rng_name, - const std::chrono::milliseconds runtime, - size_t buf_size) + void bench_rng( + Botan::RandomNumberGenerator& rng, + const std::string& rng_name, + const std::chrono::milliseconds runtime, + size_t buf_size) { Botan::secure_vector<uint8_t> buffer(buf_size); @@ -730,7 +772,7 @@ class Speed final : public Command #endif Timer timer(rng_name, "", "generate", buffer.size()); - timer.run_until_elapsed(runtime, [&] { rng.randomize(buffer.data(), buffer.size()); }); + timer.run_until_elapsed(runtime, [&]() { rng.randomize(buffer.data(), buffer.size()); }); output() << Timer::result_string_bps(timer); } @@ -750,7 +792,7 @@ class Speed final : public Command Timer sub_op("SIMD_4x32", SIMD_par, "sub"); Timer xor_op("SIMD_4x32", SIMD_par, "xor"); Timer bswap_op("SIMD_4x32", SIMD_par, "bswap"); - Timer transpose_op("SIMD_4x32", SIMD_par/4, "transpose4"); + Timer transpose_op("SIMD_4x32", SIMD_par / 4, "transpose4"); std::chrono::milliseconds msec_part = msec / 5; @@ -761,7 +803,8 @@ class Speed final : public Command { total_time.start(); - load_le_op.run([&] { + load_le_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { // Test that unaligned loads work ok @@ -769,42 +812,48 @@ class Speed final : public Command } }); - load_be_op.run([&] { + load_be_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { simd[i].load_be(rnd + i); } }); - add_op.run([&] { + add_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { - simd[i] += simd[(i+8) % SIMD_par]; + simd[i] += simd[(i + 8) % SIMD_par]; } }); - xor_op.run([&] { + xor_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { - simd[i] ^= simd[(i+8) % SIMD_par]; + simd[i] ^= simd[(i + 8) % SIMD_par]; } }); - transpose_op.run([&] { + transpose_op.run([&]() + { for(size_t i = 0; i != SIMD_par; i += 4) { - Botan::SIMD_4x32::transpose(simd[i], simd[i+1], simd[i+2], simd[i+3]); + Botan::SIMD_4x32::transpose(simd[i], simd[i + 1], simd[i + 2], simd[i + 3]); } }); - sub_op.run([&] { + sub_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { - simd[i] -= simd[(i+8) % SIMD_par]; + simd[i] -= simd[(i + 8) % SIMD_par]; } }); - bswap_op.run([&] { + bswap_op.run([&]() + { for(size_t i = 0; i != SIMD_par; ++i) { simd[i] = simd[i].bswap(); @@ -834,7 +883,7 @@ class Speed final : public Command Botan_Tests::SeedCapturing_RNG rng; Timer timer(src, "", "bytes"); - timer.run([&] { entropy_bits = srcs.poll_just(rng, src); }); + timer.run([&]() { entropy_bits = srcs.poll_just(rng, src); }); #if defined(BOTAN_HAS_COMPRESSION) std::unique_ptr<Botan::Compression_Algorithm> comp(Botan::make_compressor("zlib")); @@ -866,11 +915,12 @@ class Speed final : public Command #if defined(BOTAN_HAS_ECC_GROUP) void bench_ecc_mult(const std::chrono::milliseconds runtime) { - const std::vector<std::string> groups = { + const std::vector<std::string> groups = + { "secp256r1", "brainpool256r1", "secp384r1", "brainpool384r1", "secp521r1", "brainpool512r1" - }; + }; for(std::string group_name : groups) { @@ -888,7 +938,7 @@ class Speed final : public Command const Botan::PointGFp r1 = mult_timer.run([&]() { return base_point * scalar; }); const Botan::PointGFp r2 = blinded_mult_timer.run( - [&]() { return scalar_mult.blinded_multiply(scalar, rng()); }); + [&]() { return scalar_mult.blinded_multiply(scalar, rng()); }); BOTAN_ASSERT_EQUAL(r1, r2, "Same point computed by both methods"); } @@ -913,8 +963,8 @@ class Speed final : public Command const Botan::secure_vector<uint8_t> os_cmp = Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED); const Botan::secure_vector<uint8_t> os_uncmp = Botan::EC2OSP(p, Botan::PointGFp::UNCOMPRESSED); - uncmp_timer.run([&] { OS2ECP(os_uncmp, curve); }); - cmp_timer.run([&] { OS2ECP(os_cmp, curve); }); + uncmp_timer.run([&]() { OS2ECP(os_uncmp, curve); }); + cmp_timer.run([&]() { OS2ECP(os_cmp, curve); }); } output() << Timer::result_string_ops(uncmp_timer); @@ -978,8 +1028,8 @@ class Speed final : public Command while(f_timer.under(runtime)) { - e_timer.run([&] { Botan::power_mod(group.get_g(), random_e, group.get_p()); }); - f_timer.run([&] { Botan::power_mod(group.get_g(), random_f, group.get_p()); }); + e_timer.run([&]() { Botan::power_mod(group.get_g(), random_e, group.get_p()); }); + f_timer.run([&]() { Botan::power_mod(group.get_g(), random_f, group.get_p()); }); } output() << Timer::result_string_ops(e_timer); @@ -1006,19 +1056,23 @@ class Speed final : public Command { const Botan::BigInt x(rng(), p.bits() - 1); - const Botan::BigInt x_inv1 = invmod_timer.run([&]{ + const Botan::BigInt x_inv1 = invmod_timer.run([&] + { return Botan::inverse_mod(x + p, p); }); - const Botan::BigInt x_inv2 = monty_timer.run([&]{ + const Botan::BigInt x_inv2 = monty_timer.run([&] + { return Botan::normalized_montgomery_inverse(x, p); }); - const Botan::BigInt x_inv3 = ct_invmod_timer.run([&]{ + const Botan::BigInt x_inv3 = ct_invmod_timer.run([&] + { return Botan::ct_inverse_mod_odd_modulus(x, p); }); - const Botan::BigInt x_inv4 = powm_timer.run([&]{ + const Botan::BigInt x_inv4 = powm_timer.run([&] + { return powm_p(x); }); @@ -1044,12 +1098,15 @@ class Speed final : public Command while(genprime_timer.under(runtime) && is_prime_timer.under(runtime)) { - const Botan::BigInt p = genprime_timer.run([&] { - return Botan::random_prime(rng(), bits, coprime); }); + const Botan::BigInt p = genprime_timer.run([&] + { + return Botan::random_prime(rng(), bits, coprime); + }); - const bool ok = is_prime_timer.run([&] { + const bool ok = is_prime_timer.run([&] + { return Botan::is_prime(p, rng(), 64, true); - }); + }); if(!ok) { @@ -1060,7 +1117,7 @@ class Speed final : public Command // Now test p+2, p+4, ... which may or may not be prime for(size_t i = 2; i != 64; i += 2) { - is_prime_timer.run([&] { Botan::is_prime(p, rng(), 64, true); }); + is_prime_timer.run([&]() { Botan::is_prime(p, rng(), 64, true); }); } } @@ -1071,11 +1128,12 @@ class Speed final : public Command #endif #if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO) - void bench_pk_enc(const Botan::Private_Key& key, - const std::string& nm, - const std::string& provider, - const std::string& padding, - std::chrono::milliseconds msec) + void bench_pk_enc( + const Botan::Private_Key& key, + const std::string& nm, + const std::string& provider, + const std::string& padding, + std::chrono::milliseconds msec) { std::vector<uint8_t> plaintext, ciphertext; @@ -1091,12 +1149,12 @@ class Speed final : public Command if(ciphertext.empty() || enc_timer.under(msec)) { plaintext = unlock(rng().random_vec(enc.maximum_input_size())); - ciphertext = enc_timer.run([&] { return enc.encrypt(plaintext, rng()); }); + ciphertext = enc_timer.run([&]() { return enc.encrypt(plaintext, rng()); }); } if(dec_timer.under(msec)) { - auto dec_pt = dec_timer.run([&] { return dec.decrypt(ciphertext); }); + auto dec_pt = dec_timer.run([&]() { return dec.decrypt(ciphertext); }); if(dec_pt != plaintext) // sanity check { @@ -1126,8 +1184,8 @@ class Speed final : public Command while(ka_timer.under(msec)) { - Botan::SymmetricKey symkey1 = ka_timer.run([&] { return ka1.derive_key(32, ka2_pub); }); - Botan::SymmetricKey symkey2 = ka_timer.run([&] { return ka2.derive_key(32, ka1_pub); }); + Botan::SymmetricKey symkey1 = ka_timer.run([&]() { return ka1.derive_key(32, ka2_pub); }); + Botan::SymmetricKey symkey2 = ka_timer.run([&]() { return ka2.derive_key(32, ka1_pub); }); if(symkey1 != symkey1) { @@ -1197,7 +1255,7 @@ class Speed final : public Command */ message = unlock(rng().random_vec(48)); - signature = sig_timer.run([&] { return sig.sign_message(message, rng()); }); + signature = sig_timer.run([&]() { return sig.sign_message(message, rng()); }); bad_signature = signature; bad_signature[rng().next_byte() % bad_signature.size()] ^= rng().next_nonzero_byte(); @@ -1205,16 +1263,20 @@ class Speed final : public Command if(ver_timer.under(msec)) { - const bool verified = ver_timer.run([&] { - return ver.verify_message(message, signature); }); + const bool verified = ver_timer.run([&] + { + return ver.verify_message(message, signature); + }); if(!verified) { error_output() << "Correct signature rejected in PK signature bench\n"; } - const bool verified_bad = ver_timer.run([&] { - return ver.verify_message(message, bad_signature); }); + const bool verified_bad = ver_timer.run([&] + { + return ver.verify_message(message, bad_signature); + }); if(verified_bad) { @@ -1238,7 +1300,8 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { return new Botan::RSA_PrivateKey(rng(), keylen); })); @@ -1264,7 +1327,8 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { return new Botan::ECDSA_PrivateKey(rng(), Botan::EC_Group(grp)); })); @@ -1276,7 +1340,7 @@ class Speed final : public Command #if defined(BOTAN_HAS_ECKCDSA) void bench_eckcdsa(const std::string& provider, - std::chrono::milliseconds msec) + std::chrono::milliseconds msec) { for(std::string grp : { "secp256r1", "secp384r1", "secp521r1" }) { @@ -1284,7 +1348,8 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { return new Botan::ECKCDSA_PrivateKey(rng(), Botan::EC_Group(grp)); })); @@ -1296,7 +1361,7 @@ class Speed final : public Command #if defined(BOTAN_HAS_ECGDSA) void bench_ecgdsa(const std::string& provider, - std::chrono::milliseconds msec) + std::chrono::milliseconds msec) { for(std::string grp : { "secp256r1", "secp384r1", "secp521r1" }) { @@ -1304,7 +1369,8 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { return new Botan::ECGDSA_PrivateKey(rng(), Botan::EC_Group(grp)); })); @@ -1325,10 +1391,12 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] + { return new Botan::DH_PrivateKey(rng(), Botan::DL_Group(grp)); })); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] + { return new Botan::DH_PrivateKey(rng(), Botan::DL_Group(grp)); })); @@ -1348,10 +1416,12 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] + { return new Botan::ECDH_PrivateKey(rng(), Botan::EC_Group(grp)); })); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] + { return new Botan::ECDH_PrivateKey(rng(), Botan::EC_Group(grp)); })); @@ -1369,10 +1439,12 @@ class Speed final : public Command Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key1(keygen_timer.run([&] + { return new Botan::Curve25519_PrivateKey(rng()); })); - std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] { + std::unique_ptr<Botan::PK_Key_Agreement_Key> key2(keygen_timer.run([&] + { return new Botan::Curve25519_PrivateKey(rng()); })); @@ -1394,13 +1466,14 @@ class Speed final : public Command SL=256 n=6624 t=115 - 942 KB pubkey 2184 KB privkey */ - const std::vector<std::pair<size_t, size_t>> mce_params = { - { 2480, 45 }, - { 2960, 57 }, - { 3408, 67 }, - { 4624, 95 }, - { 6624, 115 } - }; + const std::vector<std::pair<size_t, size_t>> mce_params = + { + { 2480, 45 }, + { 2960, 57 }, + { 3408, 67 }, + { 4624, 95 }, + { 6624, 115 } + }; for(auto params : mce_params) { @@ -1413,12 +1486,13 @@ class Speed final : public Command } const std::string nm = "McEliece-" + std::to_string(n) + "," + std::to_string(t) + - " (WF=" + std::to_string(Botan::mceliece_work_factor(n, t)) + ")"; + " (WF=" + std::to_string(Botan::mceliece_work_factor(n, t)) + ")"; Timer keygen_timer(nm, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { - return new Botan::McEliece_PrivateKey(rng(), n, t); + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { + return new Botan::McEliece_PrivateKey(rng(), n, t); })); output() << Timer::result_string_ops(keygen_timer); @@ -1428,24 +1502,26 @@ class Speed final : public Command #endif #if defined(BOTAN_HAS_XMSS) - void bench_xmss(const std::string& provider, - std::chrono::milliseconds msec) + void bench_xmss(const std::string& provider, + std::chrono::milliseconds msec) { // H16 and H20 signatures take an hour or more to generate - std::vector<std::string> xmss_params{ + std::vector<std::string> xmss_params + { "XMSS_SHA2-256_W16_H10", "XMSS_SHA2-512_W16_H10", "XMSS_SHAKE128_W16_H10", "XMSS_SHAKE256_W16_H10", - }; + }; for(std::string params : xmss_params) { Timer keygen_timer(params, provider, "keygen"); - std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] { + std::unique_ptr<Botan::Private_Key> key(keygen_timer.run([&] + { return new Botan::XMSS_PrivateKey(Botan::XMSS_Parameters::xmss_id_from_string(params), rng()); - })); + })); output() << Timer::result_string_ops(keygen_timer); bench_pk_sig(*key, params, provider, "", msec); @@ -1467,8 +1543,14 @@ class Speed final : public Command class ChaCha20_RNG : public Botan::RandomNumberGenerator { public: - std::string name() const override { return "ChaCha20_RNG"; } - void clear() override { /* ignored */ } + std::string name() const override + { + return "ChaCha20_RNG"; + } + void clear() override + { + /* ignored */ + } void randomize(uint8_t out[], size_t len) override { @@ -1476,9 +1558,15 @@ class Speed final : public Command m_chacha.cipher1(out, len); } - bool is_seeded() const override { return true; } + bool is_seeded() const override + { + return true; + } - void add_entropy(const uint8_t[], size_t) override { /* ignored */ } + void add_entropy(const uint8_t[], size_t) override + { + /* ignored */ + } ChaCha20_RNG(const Botan::secure_vector<uint8_t>& seed) { diff --git a/src/cli/timing_tests.cpp b/src/cli/timing_tests.cpp index 3adda8482..6ffbbddc2 100644 --- a/src/cli/timing_tests.cpp +++ b/src/cli/timing_tests.cpp @@ -23,27 +23,27 @@ #include <botan/internal/os_utils.h> #if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> + #include <botan/system_rng.h> #endif #if defined(BOTAN_HAS_AUTO_SEEDED_RNG) - #include <botan/auto_rng.h> + #include <botan/auto_rng.h> #endif #if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_RAW) - #include <botan/pubkey.h> - #include <botan/rsa.h> + #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> + #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> + #include <botan/ecdsa.h> + #include <botan/reducer.h> + #include <botan/numthry.h> #endif namespace Botan_CLI { @@ -56,10 +56,10 @@ class Timing_Test Timing_Test() = default; virtual ~Timing_Test() = default; - std::vector<std::vector<ticks>> - execute_evaluation(const std::vector<std::string>& inputs, - size_t warmup_runs, - size_t measurement_runs); + 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; @@ -92,13 +92,11 @@ class Timing_Test 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") - { - } + 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 { @@ -138,12 +136,11 @@ class Bleichenbacker_Timing_Test : public Timing_Test 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) - {} + 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 { @@ -159,7 +156,7 @@ class Manger_Timing_Test : public Timing_Test { m_dec.decrypt(input.data(), m_ctext_length); } - catch (Botan::Decoding_Error e) + catch(Botan::Decoding_Error e) { } ticks end = get_ticks(); @@ -187,12 +184,10 @@ class Manger_Timing_Test : public Timing_Test 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) - {} + 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; @@ -261,14 +256,12 @@ class ECDSA_Timing_Test : public Timing_Test 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) - { - } +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) { @@ -295,20 +288,28 @@ ticks ECDSA_Timing_Test::measure_critical_function(std::vector<uint8_t> input) #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>> 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(auto& result : all_results) + { + result.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)) @@ -325,7 +326,9 @@ std::vector<std::vector<ticks>> Timing_Test::execute_evaluation(const std::vecto if(total_runs >= warmup_runs) { for(size_t i = 0; i != results.size(); ++i) + { all_results[i].push_back(results[i]); + } } } @@ -335,8 +338,9 @@ std::vector<std::vector<ticks>> Timing_Test::execute_evaluation(const std::vecto class Timing_Test_Command : public Command { public: - Timing_Test_Command() : Command("timing_test test_type --test-data-file= --test-data-dir=src/tests/data/timing --warmup-runs=1000 --measurement-runs=10000") - {} + Timing_Test_Command() + : Command("timing_test test_type --test-data-file= --test-data-dir=src/tests/data/timing " + "--warmup-runs=1000 --measurement-runs=10000") {} virtual void go() override { @@ -364,19 +368,20 @@ class Timing_Test_Command : public Command { 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)) + while(std::getline(infile, line)) { - if (line.size() > 0 && line.at(0) != '#') + 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); + std::vector<std::vector<ticks>> results = test->execute_evaluation(lines, warmup_runs, measurement_runs); size_t unique_id = 0; std::ostringstream oss; @@ -406,7 +411,7 @@ class Timing_Test_Command : public Command "lucky13sec4sha1 " + "lucky13sec4sha256 " + "lucky13sec4sha384 " - ); + ); } }; diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp index 3cba471f0..642e60373 100644 --- a/src/cli/tls_client.cpp +++ b/src/cli/tls_client.cpp @@ -15,7 +15,7 @@ #include <botan/hex.h> #if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER) -#include <botan/tls_session_manager_sqlite.h> + #include <botan/tls_session_manager_sqlite.h> #endif #include <string> @@ -32,7 +32,7 @@ #include <fcntl.h> #if !defined(MSG_NOSIGNAL) - #define MSG_NOSIGNAL 0 + #define MSG_NOSIGNAL 0 #endif #include "credentials.h" @@ -42,9 +42,10 @@ namespace Botan_CLI { class TLS_Client final : public Command, public Botan::TLS::Callbacks { public: - TLS_Client() : Command("tls_client host --port=443 --print-certs --policy= " - "--tls1.0 --tls1.1 --tls1.2 " - "--session-db= --session-db-pass= --next-protocols= --type=tcp") {} + TLS_Client() + : Command("tls_client host --port=443 --print-certs --policy= " + "--tls1.0 --tls1.1 --tls1.2 " + "--session-db= --session-db-pass= --next-protocols= --type=tcp") {} void go() override { @@ -97,7 +98,9 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks const std::string next_protos = get_arg("next-protocols"); if(transport != "tcp" && transport != "udp") + { throw CLI_Usage_Error("Invalid transport type '" + transport + "' for TLS"); + } const bool use_tcp = (transport == "tcp"); @@ -121,20 +124,15 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks struct sockaddr_storage addrbuf; std::string hostname; if(!host.empty() && - inet_pton(AF_INET, host.c_str(), &addrbuf) != 1 && - inet_pton(AF_INET6, host.c_str(), &addrbuf) != 1) + inet_pton(AF_INET, host.c_str(), &addrbuf) != 1 && + inet_pton(AF_INET6, host.c_str(), &addrbuf) != 1) { hostname = host; } - Botan::TLS::Client client(*this, - *session_mgr, - creds, - *policy, - rng(), + Botan::TLS::Client client(*this, *session_mgr, creds, *policy, rng(), Botan::TLS::Server_Information(hostname, port), - version, - protocols_to_offer); + version, protocols_to_offer); bool first_active = true; @@ -151,7 +149,9 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks { std::string app = client.application_protocol(); if(app != "") + { output() << "Server choose protocol: " << client.application_protocol() << "\n"; + } first_active = false; } } @@ -162,7 +162,7 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks if(FD_ISSET(m_sockfd, &readfds)) { - uint8_t buf[4*1024] = { 0 }; + uint8_t buf[4 * 1024] = { 0 }; ssize_t got = ::read(m_sockfd, buf, sizeof(buf)); @@ -213,7 +213,9 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks } } else + { client.send(buf, got); + } } if(client.timeout_check()) @@ -231,7 +233,7 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks addrinfo hints = {}; hints.ai_family = AF_UNSPEC; hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM; - addrinfo *res, *rp = nullptr; + addrinfo* res, *rp = nullptr; if(::getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res) != 0) { @@ -277,22 +279,25 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks const Botan::TLS::Policy& policy) override { if(cert_chain.empty()) + { throw std::invalid_argument("Certificate chain was empty"); + } - Botan::Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(), - policy.minimum_signature_strength()); + Botan::Path_Validation_Restrictions restrictions( + policy.require_cert_revocation_info(), + policy.minimum_signature_strength()); auto ocsp_timeout = std::chrono::milliseconds(1000); - Botan::Path_Validation_Result result = - Botan::x509_path_validate(cert_chain, - restrictions, - trusted_roots, - hostname, - usage, - std::chrono::system_clock::now(), - ocsp_timeout, - ocsp); + Botan::Path_Validation_Result result = Botan::x509_path_validate( + cert_chain, + restrictions, + trusted_roots, + hostname, + usage, + std::chrono::system_clock::now(), + ocsp_timeout, + ocsp); std::cout << "Certificate validation status: " << result.result_string() << "\n"; if(result.successful_validation()) @@ -300,20 +305,26 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks auto status = result.all_statuses(); if(status.size() > 0 && status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD)) + { std::cout << "Valid OCSP response for this server\n"; + } } } bool tls_session_established(const Botan::TLS::Session& session) override { output() << "Handshake complete, " << session.version().to_string() - << " using " << session.ciphersuite().to_string() << "\n"; + << " using " << session.ciphersuite().to_string() << "\n"; if(!session.session_id().empty()) + { output() << "Session ID " << Botan::hex_encode(session.session_id()) << "\n"; + } if(!session.session_ticket().empty()) + { output() << "Session ticket " << Botan::hex_encode(session.session_ticket()) << "\n"; + } if(flag_set("print-certs")) { @@ -321,7 +332,7 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks for(size_t i = 0; i != certs.size(); ++i) { - output() << "Certificate " << i+1 << "/" << certs.size() << "\n"; + output() << "Certificate " << i + 1 << "/" << certs.size() << "\n"; output() << certs[i].to_string(); output() << certs[i].PEM_encode(); } @@ -335,7 +346,9 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks int r = send(sockfd, buf, length, MSG_NOSIGNAL); if(r == -1) + { throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); + } } void tls_emit_data(const uint8_t buf[], size_t length) override @@ -349,9 +362,13 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks if(sent == -1) { if(errno == EINTR) + { sent = 0; + } else + { throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); + } } offset += sent; @@ -367,11 +384,13 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks void tls_record_received(uint64_t /*seq_no*/, const uint8_t buf[], size_t buf_size) override { for(size_t i = 0; i != buf_size; ++i) + { output() << buf[i]; + } } - private: - int m_sockfd = -1; + private: + int m_sockfd = -1; }; BOTAN_REGISTER_COMMAND("tls_client", TLS_Client); diff --git a/src/cli/tls_proxy.cpp b/src/cli/tls_proxy.cpp index 5140654de..25ffabdb8 100644 --- a/src/cli/tls_proxy.cpp +++ b/src/cli/tls_proxy.cpp @@ -28,7 +28,7 @@ #include <botan/hex.h> #if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER) - #include <botan/tls_session_manager_sqlite.h> + #include <botan/tls_session_manager_sqlite.h> #endif #include "credentials.h" @@ -67,28 +67,31 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio typedef boost::shared_ptr<tls_proxy_session> pointer; - static pointer create(boost::asio::io_service& io, - Botan::TLS::Session_Manager& session_manager, - Botan::Credentials_Manager& credentials, - Botan::TLS::Policy& policy, - tcp::resolver::iterator endpoints) + static pointer create( + boost::asio::io_service& io, + Botan::TLS::Session_Manager& session_manager, + Botan::Credentials_Manager& credentials, + Botan::TLS::Policy& policy, + tcp::resolver::iterator endpoints) { return pointer( - new tls_proxy_session( - io, - session_manager, - credentials, - policy, - endpoints) - ); + new tls_proxy_session( + io, + session_manager, + credentials, + policy, + endpoints) + ); } - tcp::socket& client_socket() { return m_client_socket; } + tcp::socket& client_socket() + { + return m_client_socket; + } void start() { m_c2p.resize(readbuf_size); - client_read(boost::system::error_code(), 0); // start read loop } @@ -103,22 +106,21 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio } private: - tls_proxy_session(boost::asio::io_service& io, - Botan::TLS::Session_Manager& session_manager, - Botan::Credentials_Manager& credentials, - Botan::TLS::Policy& policy, - tcp::resolver::iterator endpoints) : - m_strand(io), - m_server_endpoints(endpoints), - m_client_socket(io), - m_server_socket(io), - m_tls(*this, - session_manager, - credentials, - policy, - m_rng) - { - } + tls_proxy_session( + boost::asio::io_service& io, + Botan::TLS::Session_Manager& session_manager, + Botan::Credentials_Manager& credentials, + Botan::TLS::Policy& policy, + tcp::resolver::iterator endpoints) + : m_strand(io) + , m_server_endpoints(endpoints) + , m_client_socket(io) + , m_server_socket(io) + , m_tls(*this, + session_manager, + credentials, + policy, + m_rng) {} void client_read(const boost::system::error_code& error, size_t bytes_transferred) @@ -133,7 +135,9 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio try { if(!m_tls.is_active()) + { log_binary_message("From client", &m_c2p[0], bytes_transferred); + } m_tls.received_data(&m_c2p[0], bytes_transferred); } catch(Botan::Exception& e) @@ -145,9 +149,11 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio m_client_socket.async_read_some( boost::asio::buffer(&m_c2p[0], m_c2p.size()), - m_strand.wrap(boost::bind(&tls_proxy_session::client_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + m_strand.wrap( + boost::bind( + &tls_proxy_session::client_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); } void handle_client_write_completion(const boost::system::error_code& error) @@ -190,7 +196,9 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio void tls_emit_data(const uint8_t buf[], size_t buf_len) override { if(buf_len > 0) + { m_p2c_pending.insert(m_p2c_pending.end(), buf, buf + buf_len); + } // no write now active and we still have output pending if(m_p2c.empty() && !m_p2c_pending.empty()) @@ -202,17 +210,20 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio boost::asio::async_write( m_client_socket, boost::asio::buffer(&m_p2c[0], m_p2c.size()), - m_strand.wrap(boost::bind( - &tls_proxy_session::handle_client_write_completion, - shared_from_this(), - boost::asio::placeholders::error))); + m_strand.wrap( + boost::bind( + &tls_proxy_session::handle_client_write_completion, + shared_from_this(), + boost::asio::placeholders::error))); } } void proxy_write_to_server(const uint8_t buf[], size_t buf_len) { if(buf_len > 0) + { m_p2s_pending.insert(m_p2s_pending.end(), buf, buf + buf_len); + } // no write now active and we still have output pending if(m_p2s.empty() && !m_p2s_pending.empty()) @@ -224,10 +235,11 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio boost::asio::async_write( m_server_socket, boost::asio::buffer(&m_p2s[0], m_p2s.size()), - m_strand.wrap(boost::bind( - &tls_proxy_session::handle_server_write_completion, - shared_from_this(), - boost::asio::placeholders::error))); + m_strand.wrap( + boost::bind( + &tls_proxy_session::handle_server_write_completion, + shared_from_this(), + boost::asio::placeholders::error))); } } @@ -261,9 +273,10 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio m_server_socket.async_read_some( boost::asio::buffer(&m_s2p[0], m_s2p.size()), - m_strand.wrap(boost::bind(&tls_proxy_session::server_read, shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + m_strand.wrap( + boost::bind(&tls_proxy_session::server_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); } bool tls_session_established(const Botan::TLS::Session& session) override @@ -273,20 +286,21 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio m_hostname = session.server_info().hostname(); if(m_hostname != "") + { std::cout << "Client requested hostname '" << m_hostname << "'" << std::endl; + } - async_connect(m_server_socket, m_server_endpoints, - [this](boost::system::error_code ec, tcp::resolver::iterator endpoint) - { - if(ec) - { - log_error("Server connection", ec); - return; - } - - server_read(boost::system::error_code(), 0); // start read loop - proxy_write_to_server(nullptr, 0); - }); + auto onConnect = [this](boost::system::error_code ec, tcp::resolver::iterator endpoint) + { + if(ec) + { + log_error("Server connection", ec); + return; + } + server_read(boost::system::error_code(), 0); // start read loop + proxy_write_to_server(nullptr, 0); + }; + async_connect(m_server_socket, m_server_endpoints, onConnect); return true; } @@ -298,7 +312,9 @@ class tls_proxy_session : public boost::enable_shared_from_this<tls_proxy_sessio return; } else + { std::cout << "Alert " << alert.type_string() << std::endl; + } } boost::asio::io_service::strand m_strand; @@ -326,16 +342,17 @@ class tls_proxy_server public: typedef tls_proxy_session session; - tls_proxy_server(boost::asio::io_service& io, unsigned short port, - tcp::resolver::iterator endpoints, - Botan::Credentials_Manager& creds, - Botan::TLS::Policy& policy, - Botan::TLS::Session_Manager& session_mgr) : - m_acceptor(io, tcp::endpoint(tcp::v4(), port)), - m_server_endpoints(endpoints), - m_creds(creds), - m_policy(policy), - m_session_manager(session_mgr) + tls_proxy_server( + boost::asio::io_service& io, unsigned short port, + tcp::resolver::iterator endpoints, + Botan::Credentials_Manager& creds, + Botan::TLS::Policy& policy, + Botan::TLS::Session_Manager& session_mgr) + : m_acceptor(io, tcp::endpoint(tcp::v4(), port)) + , m_server_endpoints(endpoints) + , m_creds(creds) + , m_policy(policy) + , m_session_manager(session_mgr) { session::pointer new_session = make_session(); @@ -345,29 +362,26 @@ class tls_proxy_server &tls_proxy_server::handle_accept, this, new_session, - boost::asio::placeholders::error) - ); + boost::asio::placeholders::error)); } private: session::pointer make_session() { return session::create( - m_acceptor.get_io_service(), - m_session_manager, - m_creds, - m_policy, - m_server_endpoints - ); + m_acceptor.get_io_service(), + m_session_manager, + m_creds, + m_policy, + m_server_endpoints); } void handle_accept(session::pointer new_session, const boost::system::error_code& error) { - if (!error) + if(!error) { new_session->start(); - new_session = make_session(); m_acceptor.async_accept( @@ -376,8 +390,7 @@ class tls_proxy_server &tls_proxy_server::handle_accept, this, new_session, - boost::asio::placeholders::error) - ); + boost::asio::placeholders::error)); } } @@ -395,7 +408,7 @@ class TLS_Proxy final : public Command { public: TLS_Proxy() : Command("tls_proxy listen_port target_host target_port server_cert server_key " - "--threads=0 --session-db= --session-db-pass=") {} + "--threads=0 --session-db= --session-db-pass=") {} void go() override { @@ -439,12 +452,16 @@ class TLS_Proxy final : public Command // run forever... first thread is main calling io.run below for(size_t i = 2; i <= num_threads; ++i) + { threads.push_back(std::make_shared<std::thread>([&io]() { io.run(); })); + } io.run(); - for (size_t i = 0; i < threads.size(); ++i) + for(size_t i = 0; i < threads.size(); ++i) + { threads[i]->join(); + } } }; diff --git a/src/cli/tls_server.cpp b/src/cli/tls_server.cpp index b1a5b0ec6..41e131dce 100644 --- a/src/cli/tls_server.cpp +++ b/src/cli/tls_server.cpp @@ -25,7 +25,7 @@ #include <fcntl.h> #if !defined(MSG_NOSIGNAL) - #define MSG_NOSIGNAL 0 + #define MSG_NOSIGNAL 0 #endif namespace Botan_CLI { @@ -43,7 +43,9 @@ class TLS_Server final : public Command const std::string transport = get_arg("type"); if(transport != "tcp" && transport != "udp") + { throw CLI_Usage_Error("Invalid transport type '" + transport + "' for TLS"); + } const bool is_tcp = (transport == "tcp"); @@ -70,11 +72,14 @@ class TLS_Server final : public Command Basic_Credentials_Manager creds(rng(), server_crt, server_key); - auto protocol_chooser = [](const std::vector<std::string>& protocols) -> std::string { + auto protocol_chooser = [](const std::vector<std::string>& protocols) -> std::string + { for(size_t i = 0; i != protocols.size(); ++i) + { std::cout << "Client offered protocol " << i << " = " << protocols[i] << std::endl; + } return "echo/1.0"; // too bad - }; + }; output() << "Listening for new connections on " << transport << " port " << port << std::endl; @@ -85,62 +90,67 @@ class TLS_Server final : public Command int fd; if(is_tcp) + { fd = ::accept(server_fd, nullptr, nullptr); + } else { struct sockaddr_in from; socklen_t from_len = sizeof(sockaddr_in); - if(::recvfrom(server_fd, nullptr, 0, MSG_PEEK, - reinterpret_cast<struct sockaddr*>(&from), &from_len) != 0) + if(::recvfrom(server_fd, nullptr, 0, MSG_PEEK, reinterpret_cast<struct sockaddr*>(&from), &from_len) != 0) + { throw CLI_Error("Could not peek next packet"); + } if(::connect(server_fd, reinterpret_cast<struct sockaddr*>(&from), from_len) != 0) + { throw CLI_Error("Could not connect UDP socket"); - + } fd = server_fd; } using namespace std::placeholders; auto socket_write = is_tcp ? std::bind(&stream_socket_write, fd, _1, _2) : - std::bind(&dgram_socket_write, fd, _1, _2); + std::bind(&dgram_socket_write, fd, _1, _2); std::string s; std::list<std::string> pending_output; auto proc_fn = [&](const uint8_t input[], size_t input_len) { - for(size_t i = 0; i != input_len; ++i) + for(size_t i = 0; i != input_len; ++i) + { + const char c = static_cast<char>(input[i]); + s += c; + if(c == '\n') { - const char c = static_cast<char>(input[i]); - s += c; - if(c == '\n') - { - pending_output.push_back(s); - s.clear(); - } + pending_output.push_back(s); + s.clear(); } + } }; - Botan::TLS::Server server(socket_write, - proc_fn, - std::bind(&TLS_Server::alert_received, this, _1, _2, _3), - std::bind(&TLS_Server::handshake_complete, this, _1), - session_manager, - creds, - *policy, - rng(), - protocol_chooser, - !is_tcp); + Botan::TLS::Server server( + socket_write, + proc_fn, + std::bind(&TLS_Server::alert_received, this, _1, _2, _3), + std::bind(&TLS_Server::handshake_complete, this, _1), + session_manager, + creds, + *policy, + rng(), + protocol_chooser, + !is_tcp); try { while(!server.is_closed()) { - try + try { - uint8_t buf[4*1024] = { 0 }; + uint8_t buf[4 * 1024] = { 0 }; ssize_t got = ::read(fd, buf, sizeof(buf)); if(got == -1) @@ -164,10 +174,12 @@ class TLS_Server final : public Command server.send(output); if(output == "quit\n") + { server.close(); + } } } - catch(std::exception& e) + catch(std::exception& e) { std::cout << "Connection1 problem: " << e.what() << std::endl; if(is_tcp) @@ -183,7 +195,9 @@ class TLS_Server final : public Command } if(is_tcp) + { ::close(fd); + } } } private: @@ -193,7 +207,9 @@ class TLS_Server final : public Command int fd = ::socket(PF_INET, type, 0); if(fd == -1) + { throw CLI_Error("Unable to acquire socket"); + } sockaddr_in socket_info; ::memset(&socket_info, 0, sizeof(socket_info)); @@ -217,7 +233,6 @@ class TLS_Server final : public Command throw CLI_Error("listen failed"); } } - return fd; } @@ -227,10 +242,14 @@ class TLS_Server final : public Command << " using " << session.ciphersuite().to_string() << std::endl; if(!session.session_id().empty()) + { std::cout << "Session ID " << Botan::hex_encode(session.session_id()) << std::endl; + } if(!session.session_ticket().empty()) + { std::cout << "Session ticket " << Botan::hex_encode(session.session_ticket()) << std::endl; + } return true; } @@ -240,9 +259,13 @@ class TLS_Server final : public Command ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL); if(sent == -1) + { std::cout << "Error writing to socket - " << strerror(errno) << std::endl; + } else if(sent != static_cast<ssize_t>(length)) + { std::cout << "Packet of length " << length << " truncated to " << sent << std::endl; + } } static void stream_socket_write(int sockfd, const uint8_t buf[], size_t length) @@ -254,9 +277,13 @@ class TLS_Server final : public Command if(sent == -1) { if(errno == EINTR) + { sent = 0; + } else + { throw CLI_Error("Socket write failed"); + } } buf += sent; diff --git a/src/cli/tls_utils.cpp b/src/cli/tls_utils.cpp index ef590ff3f..b24af1656 100644 --- a/src/cli/tls_utils.cpp +++ b/src/cli/tls_utils.cpp @@ -18,7 +18,8 @@ class TLS_All_Policy : public Botan::TLS::Policy public: std::vector<std::string> allowed_ciphers() const override { - return std::vector<std::string>{ + return std::vector<std::string> + { "ChaCha20Poly1305", "AES-256/OCB(12)", "AES-128/OCB(12)", @@ -41,8 +42,7 @@ class TLS_All_Policy : public Botan::TLS::Policy std::vector<std::string> allowed_key_exchange_methods() const override { - return { "SRP_SHA", "ECDHE_PSK", "DHE_PSK", "PSK", - "CECPQ1", "ECDH", "DH", "RSA" }; + return { "SRP_SHA", "ECDHE_PSK", "DHE_PSK", "PSK", "CECPQ1", "ECDH", "DH", "RSA" }; } std::vector<std::string> allowed_signature_methods() const override @@ -54,22 +54,35 @@ class TLS_All_Policy : public Botan::TLS::Policy class TLS_Ciphersuites final : public Command { public: - TLS_Ciphersuites() : Command("tls_ciphers --policy=default --version=tls1.2") {} + TLS_Ciphersuites() + : Command("tls_ciphers --policy=default --version=tls1.2") {} static Botan::TLS::Protocol_Version::Version_Code tls_version_from_str(const std::string& str) { if(str == "tls1.2" || str == "TLS1.2" || str == "TLS-1.2") + { return Botan::TLS::Protocol_Version::TLS_V12; + } else if(str == "tls1.1" || str == "TLS1.1" || str == "TLS-1.1") + { return Botan::TLS::Protocol_Version::TLS_V11; + } else if(str == "tls1.0" || str == "TLS1.1" || str == "TLS-1.1") + { return Botan::TLS::Protocol_Version::TLS_V10; + } if(str == "dtls1.2" || str == "DTLS1.2" || str == "DTLS-1.2") + { return Botan::TLS::Protocol_Version::DTLS_V12; + } else if(str == "dtls1.0" || str == "DTLS1.0" || str == "DTLS-1.0") + { return Botan::TLS::Protocol_Version::DTLS_V10; + } else + { throw CLI_Error("Unknown TLS version '" + str + "'"); + } } void go() override @@ -101,8 +114,7 @@ class TLS_Ciphersuites final : public Command std::ifstream policy_file(policy_type); if(!policy_file.good()) { - throw CLI_Error("Error TLS policy '" + policy_type + - "' is neither a file nor a known policy type"); + throw CLI_Error("Error TLS policy '" + policy_type + "' is neither a file nor a known policy type"); } policy.reset(new Botan::TLS::Text_Policy(policy_file)); diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp index d561f4cdf..65923ec47 100644 --- a/src/cli/utils.cpp +++ b/src/cli/utils.cpp @@ -14,31 +14,31 @@ #include <botan/entropy_src.h> #if defined(BOTAN_HAS_BASE64_CODEC) - #include <botan/base64.h> + #include <botan/base64.h> #endif #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - #include <botan/auto_rng.h> + #include <botan/auto_rng.h> #endif #if defined(BOTAN_HAS_SYSTEM_RNG) - #include <botan/system_rng.h> + #include <botan/system_rng.h> #endif #if defined(BOTAN_HAS_RDRAND_RNG) - #include <botan/rdrand_rng.h> + #include <botan/rdrand_rng.h> #endif #if defined(BOTAN_HAS_HTTP_UTIL) - #include <botan/http_util.h> + #include <botan/http_util.h> #endif #if defined(BOTAN_HAS_BCRYPT) - #include <botan/bcrypt.h> + #include <botan/bcrypt.h> #endif #if defined(BOTAN_HAS_HMAC) - #include <botan/hmac.h> + #include <botan/hmac.h> #endif namespace Botan_CLI { @@ -133,13 +133,17 @@ class Hash final : public Command std::unique_ptr<Botan::HashFunction> hash_fn(Botan::HashFunction::create(hash_algo)); if(!hash_fn) + { throw CLI_Error_Unsupported("hashing", hash_algo); + } const size_t buf_size = get_arg_sz("buf-size"); std::vector<std::string> files = get_arg_list("files"); if(files.empty()) - files.push_back("-"); // read stdin if no arguments on command line + { + files.push_back("-"); + } // read stdin if no arguments on command line for(const std::string& fsname : files) { @@ -277,9 +281,11 @@ class Base64_Encode final : public Command void go() override { - this->read_file(get_arg("file"), - [&](const uint8_t b[], size_t l) { output() << Botan::base64_encode(b, l); }, - 768); + auto onData = [&](const uint8_t b[], size_t l) + { + output() << Botan::base64_encode(b, l); + }; + this->read_file(get_arg("file"), onData, 768); } }; @@ -298,9 +304,7 @@ class Base64_Decode final : public Command output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); }; - this->read_file(get_arg("file"), - write_bin, - 1024); + this->read_file(get_arg("file"), write_bin, 1024); } }; @@ -361,10 +365,11 @@ class HMAC final : public Command void go() override { const std::string hash_algo = get_arg("hash"); - std::unique_ptr<Botan::MessageAuthenticationCode> hmac(Botan::MessageAuthenticationCode::create("HMAC(" + hash_algo + ")")); + std::unique_ptr<Botan::MessageAuthenticationCode> hmac(Botan::MessageAuthenticationCode::create("HMAC(" + hash_algo + + ")")); if(!hmac) - throw CLI_Error_Unsupported("HMAC", hash_algo); + { throw CLI_Error_Unsupported("HMAC", hash_algo); } hmac->set_key(slurp_file(get_arg("key"))); @@ -372,7 +377,7 @@ class HMAC final : public Command std::vector<std::string> files = get_arg_list("files"); if(files.empty()) - files.push_back("-"); // read stdin if no arguments on command line + { files.push_back("-"); } // read stdin if no arguments on command line for(const std::string& fsname : files) { diff --git a/src/cli/x509.cpp b/src/cli/x509.cpp index c1c5f6955..e2163b987 100644 --- a/src/cli/x509.cpp +++ b/src/cli/x509.cpp @@ -16,7 +16,7 @@ #include <botan/x509self.h> #if defined(BOTAN_HAS_OCSP) - #include <botan/ocsp.h> + #include <botan/ocsp.h> #endif namespace Botan_CLI { @@ -24,8 +24,9 @@ namespace Botan_CLI { class Sign_Cert final : public Command { public: - Sign_Cert() : Command("sign_cert --ca-key-pass= --hash=SHA-256 " - "--duration=365 ca_cert ca_key pkcs10_req") {} + Sign_Cert() + : Command("sign_cert --ca-key-pass= --hash=SHA-256 " + "--duration=365 ca_cert ca_key pkcs10_req") {} void go() override { @@ -34,18 +35,17 @@ class Sign_Cert final : public Command if(flag_set("ca_key_pass")) { - key.reset(Botan::PKCS8::load_key(get_arg("ca_key"), - rng(), - get_arg("ca_key_pass"))); + key.reset(Botan::PKCS8::load_key(get_arg("ca_key"), rng(), get_arg("ca_key_pass"))); } else { - key.reset(Botan::PKCS8::load_key(get_arg("ca_key"), - rng())); + key.reset(Botan::PKCS8::load_key(get_arg("ca_key"), rng())); } if(!key) + { throw CLI_Error("Failed to load key from " + get_arg("ca_key")); + } Botan::X509_CA ca(ca_cert, *key, get_arg("hash"), rng()); @@ -59,8 +59,7 @@ class Sign_Cert final : public Command Botan::X509_Time end_time(now + days(get_arg_sz("duration"))); - Botan::X509_Certificate new_cert = ca.sign_request(req, rng(), - start_time, end_time); + Botan::X509_Certificate new_cert = ca.sign_request(req, rng(), start_time, end_time); output() << new_cert.PEM_encode(); } @@ -96,7 +95,9 @@ class Cert_Info final : public Command catch(Botan::Exception& e) { if(!in.end_of_data()) + { output() << "X509_Certificate parsing failed " << e.what() << "\n"; + } } } } @@ -128,8 +129,7 @@ class OCSP_Check final : public Command } else { - output() << "OCSP check failed " << - Botan::Path_Validation_Result::status_string(status) << "\n"; + output() << "OCSP check failed " << Botan::Path_Validation_Result::status_string(status) << "\n"; } } }; @@ -148,7 +148,7 @@ class Cert_Verify final : public Command Botan::X509_Certificate subject_cert(get_arg("subject")); Botan::Certificate_Store_In_Memory trusted; - for(auto&& certfile : get_arg_list("ca_certs")) + for(auto const& certfile : get_arg_list("ca_certs")) { trusted.add_certificate(Botan::X509_Certificate(certfile)); } @@ -176,18 +176,18 @@ BOTAN_REGISTER_COMMAND("cert_verify", Cert_Verify); class Gen_Self_Signed final : public Command { public: - Gen_Self_Signed() : Command("gen_self_signed key CN --country= --dns= " - "--organization= --email= --key-pass= --ca --hash=SHA-256") {} + Gen_Self_Signed() + : Command("gen_self_signed key CN --country= --dns= " + "--organization= --email= --key-pass= --ca --hash=SHA-256") {} void go() override { - std::unique_ptr<Botan::Private_Key> key( - Botan::PKCS8::load_key(get_arg("key"), - rng(), - get_arg("key-pass"))); + std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(get_arg("key"), rng(), get_arg("key-pass"))); if(!key) + { throw CLI_Error("Failed to load key from " + get_arg("key")); + } Botan::X509_Cert_Options opts; @@ -198,10 +198,11 @@ class Gen_Self_Signed final : public Command opts.dns = get_arg("dns"); if(flag_set("ca")) + { opts.CA_key(); + } - Botan::X509_Certificate cert = - Botan::X509::create_self_signed_cert(opts, *key, get_arg("hash"), rng()); + Botan::X509_Certificate cert = Botan::X509::create_self_signed_cert(opts, *key, get_arg("hash"), rng()); output() << cert.PEM_encode(); } @@ -212,18 +213,18 @@ BOTAN_REGISTER_COMMAND("gen_self_signed", Gen_Self_Signed); class Generate_PKCS10 final : public Command { public: - Generate_PKCS10() : Command("gen_pkcs10 key CN --country= --organization= " - "--email= --key-pass= --hash=SHA-256") {} + Generate_PKCS10() + : Command("gen_pkcs10 key CN --country= --organization= " + "--email= --key-pass= --hash=SHA-256") {} void go() override { - std::unique_ptr<Botan::Private_Key> key( - Botan::PKCS8::load_key(get_arg("key"), - rng(), - get_arg("key-pass"))); + std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(get_arg("key"), rng(), get_arg("key-pass"))); if(!key) + { throw CLI_Error("Failed to load key from " + get_arg("key")); + } Botan::X509_Cert_Options opts; @@ -232,10 +233,7 @@ class Generate_PKCS10 final : public Command opts.organization = get_arg("organization"); opts.email = get_arg("email"); - Botan::PKCS10_Request req = - Botan::X509::create_cert_req(opts, *key, - get_arg("hash"), - rng()); + Botan::PKCS10_Request req = Botan::X509::create_cert_req(opts, *key, get_arg("hash"), rng()); output() << req.PEM_encode(); } |