From 6b31d793706f8422e06b5148e366644074a48b5d Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 26 Jul 2015 00:44:16 +0300 Subject: examples: merge to block utils --- utils/README.md | 7 +++ utils/aes_block_common.hpp | 136 +++++++++++++++++++++++++++++++++++++++++++- utils/aes_decrypt_block.cpp | 49 +++++++++++----- utils/aes_encrypt_block.cpp | 48 +++++++++++----- 4 files changed, 213 insertions(+), 27 deletions(-) (limited to 'utils') diff --git a/utils/README.md b/utils/README.md index 61204c6..8403ee0 100644 --- a/utils/README.md +++ b/utils/README.md @@ -15,6 +15,13 @@ On older CPUs, you can run the utilities ## Block encryption +The block encryption utilities can produce verbose human-readable output, +including round keys, intermediate initialization vector values, etc. +This is primarily intended for debugging purposes. +Enable verbose output by passing the `--verbose` flag to the utilities. +Please note that verbose output can only be produced when *not* using "boxes" +(the `--boxes` flag). + ### aes_encrypt_block.exe Encrypts 16-byte blocks using AES-128/192/256 in the specified mode of diff --git a/utils/aes_block_common.hpp b/utils/aes_block_common.hpp index 327efad..a61217d 100644 --- a/utils/aes_block_common.hpp +++ b/utils/aes_block_common.hpp @@ -69,6 +69,7 @@ namespace : m_program_name(program_name) , m_options("Options") , m_boxes(false) + , m_verbose(false) { } bool parse_options(int argc, char** argv) @@ -79,7 +80,8 @@ namespace ("help,h", "show this message and exit") ("box,b", po::bool_switch(&m_boxes)->default_value(false), "use the \"boxes\" interface") ("mode,m", po::value(&m_mode)->required(), "set mode of operation") - ("algorithm,a", po::value(&m_algorithm)->required(), "set algorithm"); + ("algorithm,a", po::value(&m_algorithm)->required(), "set algorithm") + ("verbose,v", po::bool_switch(&m_verbose)->default_value(false), "enable verbose output"); po::options_description hidden_options; hidden_options.add_options() @@ -130,6 +132,11 @@ namespace return { std::make_move_iterator(m_args.begin()), std::make_move_iterator(m_args.end()) }; } + bool verbose() const + { + return m_verbose; + } + private: const std::string m_program_name; boost::program_options::options_description m_options; @@ -138,5 +145,132 @@ namespace aesni::Algorithm m_algorithm; bool m_boxes; std::vector m_args; + bool m_verbose; + }; +} + +namespace +{ + void dump_block(const char* name, const aesni::aes::Block& block) + { + std::cout << name << ": " << aesni::aes::to_string(block) << "\n" << aesni::aes::to_matrix_string(block) << "\n"; + } + + void dump_plaintext(const aesni::aes::Block& block) + { + dump_block("Plaintext", block); + } + + template + void dump_key(const KeyT& key) + { + std::cout << "Key: " << aesni::aes::to_string(key) << "\n\n"; + } + + void dump_ciphertext(const aesni::aes::Block& ciphertext) + { + dump_block("Ciphertext", ciphertext); + } + + void dump_iv(const aesni::aes::Block& iv) + { + dump_block("Initialization vector", iv); + } + + void dump_next_iv(const aesni::aes::Block& next_iv) + { + dump_block("Next initialization vector", next_iv); + } + + template + void dump_round_keys(const char* name, const RoundKeysT& round_keys) + { + std::cout << name << ":\n"; + for (std::size_t i = 0; i < aesni::aes::get_number_of_rounds(round_keys); ++i) + std::cout << "\t[" << i << "]: " << aesni::aes::to_string(round_keys.keys[i]) << "\n"; + std::cout << "\n"; + } + + template + void dump_encryption_keys(const RoundKeysT& round_keys) + { + dump_round_keys("Encryption round keys", round_keys); + } + + template + void dump_decryption_keys(const RoundKeysT& round_keys) + { + dump_round_keys("Decryption round keys", round_keys); + } + + template + struct Dumper; + + template + struct Dumper + { + static void dump_round_keys(const aesni::aes::Encrypt& encrypt) + { + dump_encryption_keys(encrypt.encryption_keys); + dump_decryption_keys(encrypt.decryption_keys); + } + + static void dump_next_iv(const aesni::aes::Encrypt&) + { } + }; + + template + struct Dumper + { + static void dump_round_keys(const aesni::aes::Encrypt& encrypt) + { + dump_encryption_keys(encrypt.encryption_keys); + dump_decryption_keys(encrypt.decryption_keys); + } + + static void dump_next_iv(const aesni::aes::Encrypt&) + { } + }; + + template + struct Dumper + { + static void dump_round_keys(const aesni::aes::Encrypt& encrypt) + { + dump_encryption_keys(encrypt.encryption_keys); + } + + static void dump_next_iv(const aesni::aes::Encrypt& encrypt) + { + ::dump_next_iv(encrypt.iv); + } + }; + + template + struct Dumper + { + static void dump_round_keys(const aesni::aes::Encrypt& encrypt) + { + dump_encryption_keys(encrypt.encryption_keys); + } + + static void dump_next_iv(const aesni::aes::Encrypt& encrypt) + { + ::dump_next_iv(encrypt.iv); + } + }; + + template + struct Dumper + { + static void dump_round_keys(const aesni::aes::Encrypt& encrypt) + { + dump_encryption_keys(encrypt.encryption_keys); + } + + static void dump_next_iv(const aesni::aes::Encrypt& encrypt) + { + ::dump_next_iv(encrypt.iv); + } }; } diff --git a/utils/aes_decrypt_block.cpp b/utils/aes_decrypt_block.cpp index 778aecb..bab5f50 100644 --- a/utils/aes_decrypt_block.cpp +++ b/utils/aes_decrypt_block.cpp @@ -22,7 +22,8 @@ namespace template bool decrypt_with_mode( const std::string& key_str, - std::deque& ciphertexts) + std::deque& ciphertexts, + bool verbose = false) { typename aesni::aes::Types::BlockT iv; @@ -33,20 +34,40 @@ namespace aesni::aes::from_string(iv, ciphertexts.front()); ciphertexts.pop_front(); + + if (verbose) + dump_iv(iv); } typename aesni::aes::Types::KeyT key; aesni::aes::from_string(key, key_str); + if (verbose) + dump_key(key); + aesni::aes::Encrypt encrypt(key, iv); + if (verbose) + Dumper::dump_round_keys(encrypt); + while (!ciphertexts.empty()) { typename aesni::aes::Types::BlockT ciphertext; aesni::aes::from_string(ciphertext, ciphertexts.front()); ciphertexts.pop_front(); - std::cout << aesni::aes::to_string(encrypt.decrypt(ciphertext)) << "\n"; + const auto plaintext = encrypt.decrypt(ciphertext); + + if (verbose) + { + dump_ciphertext(ciphertext); + dump_plaintext(plaintext); + Dumper::dump_next_iv(encrypt); + } + else + { + std::cout << aesni::aes::to_string(plaintext) << "\n"; + } } return true; @@ -56,24 +77,25 @@ namespace bool decrypt_with_algorithm( aesni::Mode mode, const std::string& key_str, - std::deque& ciphertexts) + std::deque& ciphertexts, + bool verbose = false) { switch (mode) { case AESNI_ECB: - return decrypt_with_mode(key_str, ciphertexts); + return decrypt_with_mode(key_str, ciphertexts, verbose); case AESNI_CBC: - return decrypt_with_mode(key_str, ciphertexts); + return decrypt_with_mode(key_str, ciphertexts, verbose); case AESNI_CFB: - return decrypt_with_mode(key_str, ciphertexts); + return decrypt_with_mode(key_str, ciphertexts, verbose); case AESNI_OFB: - return decrypt_with_mode(key_str, ciphertexts); + return decrypt_with_mode(key_str, ciphertexts, verbose); case AESNI_CTR: - return decrypt_with_mode(key_str, ciphertexts); + return decrypt_with_mode(key_str, ciphertexts, verbose); default: return false; @@ -84,18 +106,19 @@ namespace aesni::Algorithm algorithm, aesni::Mode mode, const std::string& key_str, - std::deque ciphertexts) + std::deque ciphertexts, + bool verbose = false) { switch (algorithm) { case AESNI_AES128: - return decrypt_with_algorithm(mode, key_str, ciphertexts); + return decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); case AESNI_AES192: - return decrypt_with_algorithm(mode, key_str, ciphertexts); + return decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); case AESNI_AES256: - return decrypt_with_algorithm(mode, key_str, ciphertexts); + return decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); default: return false; @@ -205,7 +228,7 @@ int main(int argc, char** argv) const auto success = cmd_parser.use_boxes() ? decrypt_using_boxes(algorithm, mode, key, ciphertexts) - : decrypt(algorithm, mode, key, ciphertexts); + : decrypt(algorithm, mode, key, ciphertexts, cmd_parser.verbose()); if (!success) { diff --git a/utils/aes_encrypt_block.cpp b/utils/aes_encrypt_block.cpp index 89e935b..b814e99 100644 --- a/utils/aes_encrypt_block.cpp +++ b/utils/aes_encrypt_block.cpp @@ -22,7 +22,8 @@ namespace template bool encrypt_with_mode( const std::string& key_str, - std::deque& plaintexts) + std::deque& plaintexts, + bool verbose = false) { typename aesni::aes::Types::BlockT iv; @@ -33,20 +34,39 @@ namespace aesni::aes::from_string(iv, plaintexts.front()); plaintexts.pop_front(); + + if (verbose) + dump_iv(iv); } typename aesni::aes::Types::KeyT key; aesni::aes::from_string(key, key_str); + if (verbose) + dump_key(key); + aesni::aes::Encrypt encrypt(key, iv); + if (verbose) + Dumper::dump_round_keys(encrypt); + while (!plaintexts.empty()) { typename aesni::aes::Types::BlockT plaintext; aesni::aes::from_string(plaintext, plaintexts.front()); plaintexts.pop_front(); + const auto ciphertext = encrypt.encrypt(plaintext); - std::cout << aesni::aes::to_string(encrypt.encrypt(plaintext)) << "\n"; + if (verbose) + { + dump_plaintext(plaintext); + dump_ciphertext(ciphertext); + Dumper::dump_next_iv(encrypt); + } + else + { + std::cout << aesni::aes::to_string(ciphertext) << "\n"; + } } return true; @@ -56,24 +76,25 @@ namespace bool encrypt_with_algorithm( aesni::Mode mode, const std::string& key_str, - std::deque& plaintexts) + std::deque& plaintexts, + bool verbose = false) { switch (mode) { case AESNI_ECB: - return encrypt_with_mode(key_str, plaintexts); + return encrypt_with_mode(key_str, plaintexts, verbose); case AESNI_CBC: - return encrypt_with_mode(key_str, plaintexts); + return encrypt_with_mode(key_str, plaintexts, verbose); case AESNI_CFB: - return encrypt_with_mode(key_str, plaintexts); + return encrypt_with_mode(key_str, plaintexts, verbose); case AESNI_OFB: - return encrypt_with_mode(key_str, plaintexts); + return encrypt_with_mode(key_str, plaintexts, verbose); case AESNI_CTR: - return encrypt_with_mode(key_str, plaintexts); + return encrypt_with_mode(key_str, plaintexts, verbose); default: return false; @@ -84,18 +105,19 @@ namespace aesni::Algorithm algorithm, aesni::Mode mode, const std::string& key_str, - std::deque plaintexts) + std::deque plaintexts, + bool verbose = false) { switch (algorithm) { case AESNI_AES128: - return encrypt_with_algorithm(mode, key_str, plaintexts); + return encrypt_with_algorithm(mode, key_str, plaintexts, verbose); case AESNI_AES192: - return encrypt_with_algorithm(mode, key_str, plaintexts); + return encrypt_with_algorithm(mode, key_str, plaintexts, verbose); case AESNI_AES256: - return encrypt_with_algorithm(mode, key_str, plaintexts); + return encrypt_with_algorithm(mode, key_str, plaintexts, verbose); default: return false; @@ -205,7 +227,7 @@ int main(int argc, char** argv) const auto success = cmd_parser.use_boxes() ? encrypt_using_boxes(algorithm, mode, key, plaintexts) - : encrypt(algorithm, mode, key, plaintexts); + : encrypt(algorithm, mode, key, plaintexts, cmd_parser.verbose()); if (!success) { -- cgit v1.2.3