diff options
-rw-r--r-- | src/cli/cli_rng.cpp | 44 | ||||
-rw-r--r-- | src/cli/codec.cpp | 204 | ||||
-rw-r--r-- | src/cli/hmac.cpp | 78 | ||||
-rw-r--r-- | src/cli/pk_crypt.cpp | 14 | ||||
-rw-r--r-- | src/cli/utils.cpp | 232 | ||||
-rw-r--r-- | src/lib/codec/base58/base58.cpp | 11 | ||||
-rwxr-xr-x | src/scripts/test_cli.py | 8 |
7 files changed, 351 insertions, 240 deletions
diff --git a/src/cli/cli_rng.cpp b/src/cli/cli_rng.cpp index 78af51314..90b30a820 100644 --- a/src/cli/cli_rng.cpp +++ b/src/cli/cli_rng.cpp @@ -9,6 +9,7 @@ #include <botan/entropy_src.h> #include <botan/cpuid.h> #include <botan/hex.h> +#include <botan/parsing.h> #if defined(BOTAN_HAS_AUTO_SEEDING_RNG) #include <botan/auto_rng.h> @@ -86,4 +87,47 @@ cli_make_rng(const std::string& rng_type, const std::string& hex_drbg_seed) throw CLI_Error_Unsupported("RNG", rng_type); } +class RNG final : public Command + { + public: + RNG() : Command("rng --system --rdrand --auto --entropy --drbg --drbg-seed= *bytes") {} + + std::string group() const override + { + return "misc"; + } + + std::string description() const override + { + return "Sample random bytes from the specified rng"; + } + + void go() override + { + std::string type = get_arg("rng-type"); + + if(type.empty()) + { + for(std::string flag : { "system", "rdrand", "auto", "entropy", "drbg" }) + { + if(flag_set(flag)) + { + type = flag; + break; + } + } + } + + const std::string drbg_seed = get_arg("drbg-seed"); + std::unique_ptr<Botan::RandomNumberGenerator> rng = cli_make_rng(type, drbg_seed); + + for(const std::string& req : get_arg_list("bytes")) + { + output() << Botan::hex_encode(rng->random_vec(Botan::to_u32bit(req))) << "\n"; + } + } + }; + +BOTAN_REGISTER_COMMAND("rng", RNG); + } diff --git a/src/cli/codec.cpp b/src/cli/codec.cpp new file mode 100644 index 000000000..0d3df336d --- /dev/null +++ b/src/cli/codec.cpp @@ -0,0 +1,204 @@ +/* +* (C) 2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "cli.h" + +#if defined(BOTAN_HAS_HEX_CODEC) + #include <botan/hex.h> +#endif + +#if defined(BOTAN_HAS_BASE58_CODEC) + #include <botan/base58.h> +#endif + +#if defined(BOTAN_HAS_BASE64_CODEC) + #include <botan/base64.h> +#endif + +namespace Botan_CLI { + +#if defined(BOTAN_HAS_HEX_CODEC) + +class Hex_Encode final : public Command + { + public: + Hex_Encode() : Command("hex_enc file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Hex encode a given file"; + } + + void go() override + { + auto hex_enc_f = [&](const uint8_t b[], size_t l) { output() << Botan::hex_encode(b, l); }; + this->read_file(get_arg("file"), hex_enc_f, 2); + } + }; + +BOTAN_REGISTER_COMMAND("hex_enc", Hex_Encode); + +class Hex_Decode final : public Command + { + public: + Hex_Decode() : Command("hex_dec file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Hex decode a given file"; + } + + void go() override + { + auto hex_dec_f = [&](const uint8_t b[], size_t l) + { + std::vector<uint8_t> bin = Botan::hex_decode(reinterpret_cast<const char*>(b), l); + output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); + }; + + this->read_file(get_arg("file"), hex_dec_f, 2); + } + }; + +BOTAN_REGISTER_COMMAND("hex_dec", Hex_Decode); + +#endif + +#if defined(BOTAN_HAS_BASE58_CODEC) + +class Base58_Encode final : public Command + { + public: + Base58_Encode() : Command("base58_enc --check file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Encode given file to Base58"; + } + + void go() override + { + auto data = slurp_file(get_arg("file")); + + if(flag_set("check")) + output() << Botan::base58_check_encode(data); + else + output() << Botan::base58_encode(data); + } + }; + +BOTAN_REGISTER_COMMAND("base58_enc", Base58_Encode); + +class Base58_Decode final : public Command + { + public: + Base58_Decode() : Command("base58_dec --check file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Decode Base58 encoded file"; + } + + void go() override + { + auto data = slurp_file_as_str(get_arg("file")); + + std::vector<uint8_t> bin; + + if(flag_set("check")) + bin = Botan::base58_check_decode(data); + else + bin = Botan::base58_decode(data); + + output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); + } + }; + +BOTAN_REGISTER_COMMAND("base58_dec", Base58_Decode); + +#endif // base64 + +#if defined(BOTAN_HAS_BASE64_CODEC) + +class Base64_Encode final : public Command + { + public: + Base64_Encode() : Command("base64_enc file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Encode given file to Base64"; + } + + void go() override + { + auto onData = [&](const uint8_t b[], size_t l) + { + output() << Botan::base64_encode(b, l); + }; + this->read_file(get_arg("file"), onData, 768); + } + }; + +BOTAN_REGISTER_COMMAND("base64_enc", Base64_Encode); + +class Base64_Decode final : public Command + { + public: + Base64_Decode() : Command("base64_dec file") {} + + std::string group() const override + { + return "codec"; + } + + std::string description() const override + { + return "Decode Base64 encoded file"; + } + + void go() override + { + auto write_bin = [&](const uint8_t b[], size_t l) + { + Botan::secure_vector<uint8_t> bin = Botan::base64_decode(reinterpret_cast<const char*>(b), l); + output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); + }; + + this->read_file(get_arg("file"), write_bin, 1024); + } + }; + +BOTAN_REGISTER_COMMAND("base64_dec", Base64_Decode); + +#endif // base64 + +} diff --git a/src/cli/hmac.cpp b/src/cli/hmac.cpp new file mode 100644 index 000000000..5b7345c50 --- /dev/null +++ b/src/cli/hmac.cpp @@ -0,0 +1,78 @@ +/* +* (C) 2009,2010,2014,2015 Jack Lloyd +* (C) 2017 René Korthaus, Rohde & Schwarz Cybersecurity +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "cli.h" + +#include <botan/hex.h> + +#if defined(BOTAN_HAS_MAC) + #include <botan/mac.h> +#endif + +namespace Botan_CLI { + +#if defined(BOTAN_HAS_HMAC) + +class HMAC final : public Command + { + public: + HMAC() : Command("hmac --hash=SHA-256 --buf-size=4096 --no-fsname key *files") {} + + std::string group() const override + { + return "hmac"; + } + + std::string description() const override + { + return "Compute the HMAC tag of given file(s)"; + } + + void go() override + { + const bool no_fsname = flag_set("no-fsname"); + const std::string hash_algo = get_arg("hash"); + std::unique_ptr<Botan::MessageAuthenticationCode> hmac = + Botan::MessageAuthenticationCode::create("HMAC(" + hash_algo + ")"); + + if(!hmac) + { throw CLI_Error_Unsupported("HMAC", hash_algo); } + + hmac->set_key(slurp_file(get_arg("key"))); + + 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 + + for(const std::string& fsname : files) + { + try + { + auto update_hmac = [&](const uint8_t b[], size_t l) { hmac->update(b, l); }; + read_file(fsname, update_hmac, buf_size); + output() << Botan::hex_encode(hmac->final()); + + if(no_fsname == false) + output() << " " << fsname; + + output() << "\n"; + } + catch(CLI_IO_Error& e) + { + error_output() << e.what() << "\n"; + } + } + } + }; + +BOTAN_REGISTER_COMMAND("hmac", HMAC); + +#endif // hmac + +} diff --git a/src/cli/pk_crypt.cpp b/src/cli/pk_crypt.cpp index 9b7f50746..4888a742f 100644 --- a/src/cli/pk_crypt.cpp +++ b/src/cli/pk_crypt.cpp @@ -189,13 +189,19 @@ class PK_Decrypt final : public Command return set_return_code(1); } - Botan::PK_Decryptor_EME dec(*key, rng(), "OAEP(" + oaep_hash + ")"); - - const Botan::secure_vector<uint8_t> file_key = dec.decrypt(encrypted_key); - std::unique_ptr<Botan::AEAD_Mode> aead = Botan::AEAD_Mode::create_or_throw(aead_algo, Botan::DECRYPTION); + const size_t expected_keylen = aead->key_spec().maximum_keylength(); + + Botan::PK_Decryptor_EME dec(*key, rng(), "OAEP(" + oaep_hash + ")"); + + const Botan::secure_vector<uint8_t> file_key = + dec.decrypt_or_random(encrypted_key.data(), + encrypted_key.size(), + expected_keylen, + rng()); + aead->set_key(file_key); aead->set_associated_data_vec(encrypted_key); aead->start(nonce); diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp index c9075e2f8..2de6b0ccb 100644 --- a/src/cli/utils.cpp +++ b/src/cli/utils.cpp @@ -8,23 +8,11 @@ #include "cli.h" #include <botan/version.h> -#include <botan/rng.h> #include <botan/cpuid.h> -#include <botan/hex.h> -#include <botan/parsing.h> #include <botan/internal/stl_util.h> #include <sstream> -#include <iterator> #include <iomanip> -#if defined(BOTAN_HAS_MAC) - #include <botan/mac.h> -#endif - -#if defined(BOTAN_HAS_BASE64_CODEC) - #include <botan/base64.h> -#endif - #if defined(BOTAN_HAS_HTTP_UTIL) #include <botan/http_util.h> #endif @@ -261,49 +249,6 @@ class Print_Cpuid final : public Command BOTAN_REGISTER_COMMAND("cpuid", Print_Cpuid); -class RNG final : public Command - { - public: - RNG() : Command("rng --system --rdrand --auto --entropy --drbg --drbg-seed= *bytes") {} - - std::string group() const override - { - return "misc"; - } - - std::string description() const override - { - return "Sample random bytes from the specified rng"; - } - - void go() override - { - std::string type = get_arg("rng-type"); - - if(type.empty()) - { - for(std::string flag : { "system", "rdrand", "auto", "entropy", "drbg" }) - { - if(flag_set(flag)) - { - type = flag; - break; - } - } - } - - const std::string drbg_seed = get_arg("drbg-seed"); - std::unique_ptr<Botan::RandomNumberGenerator> rng = cli_make_rng(type, drbg_seed); - - for(const std::string& req : get_arg_list("bytes")) - { - output() << Botan::hex_encode(rng->random_vec(Botan::to_u32bit(req))) << "\n"; - } - } - }; - -BOTAN_REGISTER_COMMAND("rng", RNG); - #if defined(BOTAN_HAS_HTTP_UTIL) class HTTP_Get final : public Command @@ -335,181 +280,4 @@ BOTAN_REGISTER_COMMAND("http_get", HTTP_Get); #endif // http_util -#if defined(BOTAN_HAS_HEX_CODEC) - -class Hex_Encode final : public Command - { - public: - Hex_Encode() : Command("hex_enc file") {} - - std::string group() const override - { - return "codec"; - } - - std::string description() const override - { - return "Hex encode a given file"; - } - - void go() override - { - auto hex_enc_f = [&](const uint8_t b[], size_t l) { output() << Botan::hex_encode(b, l); }; - this->read_file(get_arg("file"), hex_enc_f, 2); - } - }; - -BOTAN_REGISTER_COMMAND("hex_enc", Hex_Encode); - -class Hex_Decode final : public Command - { - public: - Hex_Decode() : Command("hex_dec file") {} - - std::string group() const override - { - return "codec"; - } - - std::string description() const override - { - return "Hex decode a given file"; - } - - void go() override - { - auto hex_dec_f = [&](const uint8_t b[], size_t l) - { - std::vector<uint8_t> bin = Botan::hex_decode(reinterpret_cast<const char*>(b), l); - output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); - }; - - this->read_file(get_arg("file"), hex_dec_f, 2); - } - }; - -BOTAN_REGISTER_COMMAND("hex_dec", Hex_Decode); - -#endif - -#if defined(BOTAN_HAS_BASE64_CODEC) - -class Base64_Encode final : public Command - { - public: - Base64_Encode() : Command("base64_enc file") {} - - std::string group() const override - { - return "codec"; - } - - std::string description() const override - { - return "Encode given file to Base64"; - } - - void go() override - { - auto onData = [&](const uint8_t b[], size_t l) - { - output() << Botan::base64_encode(b, l); - }; - this->read_file(get_arg("file"), onData, 768); - } - }; - -BOTAN_REGISTER_COMMAND("base64_enc", Base64_Encode); - -class Base64_Decode final : public Command - { - public: - Base64_Decode() : Command("base64_dec file") {} - - std::string group() const override - { - return "codec"; - } - - std::string description() const override - { - return "Decode Base64 encoded file"; - } - - void go() override - { - auto write_bin = [&](const uint8_t b[], size_t l) - { - Botan::secure_vector<uint8_t> bin = Botan::base64_decode(reinterpret_cast<const char*>(b), l); - output().write(reinterpret_cast<const char*>(bin.data()), bin.size()); - }; - - this->read_file(get_arg("file"), write_bin, 1024); - } - }; - -BOTAN_REGISTER_COMMAND("base64_dec", Base64_Decode); - -#endif // base64 - -#if defined(BOTAN_HAS_HMAC) - -class HMAC final : public Command - { - public: - HMAC() : Command("hmac --hash=SHA-256 --buf-size=4096 --no-fsname key *files") {} - - std::string group() const override - { - return "hmac"; - } - - std::string description() const override - { - return "Compute the HMAC tag of given file(s)"; - } - - void go() override - { - const bool no_fsname = flag_set("no-fsname"); - const std::string hash_algo = get_arg("hash"); - std::unique_ptr<Botan::MessageAuthenticationCode> hmac = - Botan::MessageAuthenticationCode::create("HMAC(" + hash_algo + ")"); - - if(!hmac) - { throw CLI_Error_Unsupported("HMAC", hash_algo); } - - hmac->set_key(slurp_file(get_arg("key"))); - - 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 - - for(const std::string& fsname : files) - { - try - { - auto update_hmac = [&](const uint8_t b[], size_t l) { hmac->update(b, l); }; - read_file(fsname, update_hmac, buf_size); - output() << Botan::hex_encode(hmac->final()); - - if(no_fsname == false) - output() << " " << fsname; - - output() << "\n"; - } - catch(CLI_IO_Error& e) - { - error_output() << e.what() << "\n"; - } - } - } - }; - -BOTAN_REGISTER_COMMAND("hmac", HMAC); - -#endif // hmac - } diff --git a/src/lib/codec/base58/base58.cpp b/src/lib/codec/base58/base58.cpp index ba974f96a..5aa9441d3 100644 --- a/src/lib/codec/base58/base58.cpp +++ b/src/lib/codec/base58/base58.cpp @@ -27,9 +27,7 @@ uint32_t sha256_d_checksum(const uint8_t input[], size_t input_length) sha256->update(checksum); sha256->final(checksum); - checksum.resize(4); - uint32_t c = load_be<uint32_t>(checksum.data(), 0); - return c; + return load_be<uint32_t>(checksum.data(), 0); } class Character_Table @@ -140,7 +138,12 @@ std::vector<uint8_t> base58_decode(const char input[], size_t input_length) for(size_t i = leading_zeros; i != input_length; ++i) { - size_t idx = base58.code_for(input[i]); + const char c = input[i]; + + if(c == ' ' || c == '\n') + continue; + + const size_t idx = base58.code_for(c); if(idx == 0x80) throw Decoding_Error("Invalid base58"); diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py index f63b9dad9..d09ecf611 100755 --- a/src/scripts/test_cli.py +++ b/src/scripts/test_cli.py @@ -150,6 +150,13 @@ def cli_base64_tests(): test_cli("base64_enc", "-", "YmVlcyE=", "bees!") test_cli("base64_dec", "-", "bees!", "YmVlcyE=") +def cli_base58_tests(): + test_cli("base58_enc", "-", "C6sRAr4", "bees!") + test_cli("base58_dec", "-", "bees!", "C6sRAr4") + + test_cli("base58_enc", ["--check", "-"], "Cjv15cdjaBc", "F00F") + test_cli("base58_dec", ["--check", "-"], "F00F", "Cjv15cdjaBc") + def cli_hex_tests(): test_cli("hex_enc", "-", "6265657321", "bees!") test_cli("hex_dec", "-", "bees!", "6265657321") @@ -750,6 +757,7 @@ def main(args=None): test_fns = [ cli_asn1_tests, cli_asn1_tests, + cli_base58_tests, cli_base64_tests, cli_bcrypt_tests, cli_cc_enc_tests, |