aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--utils/README.md7
-rw-r--r--utils/aes_block_common.hpp136
-rw-r--r--utils/aes_decrypt_block.cpp49
-rw-r--r--utils/aes_encrypt_block.cpp48
4 files changed, 213 insertions, 27 deletions
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<aesni::Mode>(&m_mode)->required(), "set mode of operation")
- ("algorithm,a", po::value<aesni::Algorithm>(&m_algorithm)->required(), "set algorithm");
+ ("algorithm,a", po::value<aesni::Algorithm>(&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<std::string> 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 <typename KeyT>
+ 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 <typename RoundKeysT>
+ 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 <typename RoundKeysT>
+ void dump_encryption_keys(const RoundKeysT& round_keys)
+ {
+ dump_round_keys("Encryption round keys", round_keys);
+ }
+
+ template <typename RoundKeysT>
+ void dump_decryption_keys(const RoundKeysT& round_keys)
+ {
+ dump_round_keys("Decryption round keys", round_keys);
+ }
+
+ template <aesni::Algorithm algo, aesni::Mode mode>
+ struct Dumper;
+
+ template <aesni::Algorithm algo>
+ struct Dumper<algo, AESNI_ECB>
+ {
+ static void dump_round_keys(const aesni::aes::Encrypt<algo, AESNI_ECB>& encrypt)
+ {
+ dump_encryption_keys(encrypt.encryption_keys);
+ dump_decryption_keys(encrypt.decryption_keys);
+ }
+
+ static void dump_next_iv(const aesni::aes::Encrypt<algo, AESNI_ECB>&)
+ { }
+ };
+
+ template <aesni::Algorithm algo>
+ struct Dumper<algo, AESNI_CBC>
+ {
+ static void dump_round_keys(const aesni::aes::Encrypt<algo, AESNI_CBC>& encrypt)
+ {
+ dump_encryption_keys(encrypt.encryption_keys);
+ dump_decryption_keys(encrypt.decryption_keys);
+ }
+
+ static void dump_next_iv(const aesni::aes::Encrypt<algo, AESNI_CBC>&)
+ { }
+ };
+
+ template <aesni::Algorithm algo>
+ struct Dumper<algo, AESNI_CFB>
+ {
+ static void dump_round_keys(const aesni::aes::Encrypt<algo, AESNI_CFB>& encrypt)
+ {
+ dump_encryption_keys(encrypt.encryption_keys);
+ }
+
+ static void dump_next_iv(const aesni::aes::Encrypt<algo, AESNI_CFB>& encrypt)
+ {
+ ::dump_next_iv(encrypt.iv);
+ }
+ };
+
+ template <aesni::Algorithm algo>
+ struct Dumper<algo, AESNI_OFB>
+ {
+ static void dump_round_keys(const aesni::aes::Encrypt<algo, AESNI_OFB>& encrypt)
+ {
+ dump_encryption_keys(encrypt.encryption_keys);
+ }
+
+ static void dump_next_iv(const aesni::aes::Encrypt<algo, AESNI_OFB>& encrypt)
+ {
+ ::dump_next_iv(encrypt.iv);
+ }
+ };
+
+ template <aesni::Algorithm algo>
+ struct Dumper<algo, AESNI_CTR>
+ {
+ static void dump_round_keys(const aesni::aes::Encrypt<algo, AESNI_CTR>& encrypt)
+ {
+ dump_encryption_keys(encrypt.encryption_keys);
+ }
+
+ static void dump_next_iv(const aesni::aes::Encrypt<algo, AESNI_CTR>& 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 <aesni::Algorithm algorithm, aesni::Mode mode>
bool decrypt_with_mode(
const std::string& key_str,
- std::deque<std::string>& ciphertexts)
+ std::deque<std::string>& ciphertexts,
+ bool verbose = false)
{
typename aesni::aes::Types<algorithm>::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<algorithm>::KeyT key;
aesni::aes::from_string(key, key_str);
+ if (verbose)
+ dump_key(key);
+
aesni::aes::Encrypt<algorithm, mode> encrypt(key, iv);
+ if (verbose)
+ Dumper<algorithm, mode>::dump_round_keys(encrypt);
+
while (!ciphertexts.empty())
{
typename aesni::aes::Types<algorithm>::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<algorithm, mode>::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<std::string>& ciphertexts)
+ std::deque<std::string>& ciphertexts,
+ bool verbose = false)
{
switch (mode)
{
case AESNI_ECB:
- return decrypt_with_mode<algorithm, AESNI_ECB>(key_str, ciphertexts);
+ return decrypt_with_mode<algorithm, AESNI_ECB>(key_str, ciphertexts, verbose);
case AESNI_CBC:
- return decrypt_with_mode<algorithm, AESNI_CBC>(key_str, ciphertexts);
+ return decrypt_with_mode<algorithm, AESNI_CBC>(key_str, ciphertexts, verbose);
case AESNI_CFB:
- return decrypt_with_mode<algorithm, AESNI_CFB>(key_str, ciphertexts);
+ return decrypt_with_mode<algorithm, AESNI_CFB>(key_str, ciphertexts, verbose);
case AESNI_OFB:
- return decrypt_with_mode<algorithm, AESNI_OFB>(key_str, ciphertexts);
+ return decrypt_with_mode<algorithm, AESNI_OFB>(key_str, ciphertexts, verbose);
case AESNI_CTR:
- return decrypt_with_mode<algorithm, AESNI_CTR>(key_str, ciphertexts);
+ return decrypt_with_mode<algorithm, AESNI_CTR>(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<std::string> ciphertexts)
+ std::deque<std::string> ciphertexts,
+ bool verbose = false)
{
switch (algorithm)
{
case AESNI_AES128:
- return decrypt_with_algorithm<AESNI_AES128>(mode, key_str, ciphertexts);
+ return decrypt_with_algorithm<AESNI_AES128>(mode, key_str, ciphertexts, verbose);
case AESNI_AES192:
- return decrypt_with_algorithm<AESNI_AES192>(mode, key_str, ciphertexts);
+ return decrypt_with_algorithm<AESNI_AES192>(mode, key_str, ciphertexts, verbose);
case AESNI_AES256:
- return decrypt_with_algorithm<AESNI_AES256>(mode, key_str, ciphertexts);
+ return decrypt_with_algorithm<AESNI_AES256>(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 <aesni::Algorithm algorithm, aesni::Mode mode>
bool encrypt_with_mode(
const std::string& key_str,
- std::deque<std::string>& plaintexts)
+ std::deque<std::string>& plaintexts,
+ bool verbose = false)
{
typename aesni::aes::Types<algorithm>::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<algorithm>::KeyT key;
aesni::aes::from_string(key, key_str);
+ if (verbose)
+ dump_key(key);
+
aesni::aes::Encrypt<algorithm, mode> encrypt(key, iv);
+ if (verbose)
+ Dumper<algorithm, mode>::dump_round_keys(encrypt);
+
while (!plaintexts.empty())
{
typename aesni::aes::Types<algorithm>::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<algorithm, mode>::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<std::string>& plaintexts)
+ std::deque<std::string>& plaintexts,
+ bool verbose = false)
{
switch (mode)
{
case AESNI_ECB:
- return encrypt_with_mode<algorithm, AESNI_ECB>(key_str, plaintexts);
+ return encrypt_with_mode<algorithm, AESNI_ECB>(key_str, plaintexts, verbose);
case AESNI_CBC:
- return encrypt_with_mode<algorithm, AESNI_CBC>(key_str, plaintexts);
+ return encrypt_with_mode<algorithm, AESNI_CBC>(key_str, plaintexts, verbose);
case AESNI_CFB:
- return encrypt_with_mode<algorithm, AESNI_CFB>(key_str, plaintexts);
+ return encrypt_with_mode<algorithm, AESNI_CFB>(key_str, plaintexts, verbose);
case AESNI_OFB:
- return encrypt_with_mode<algorithm, AESNI_OFB>(key_str, plaintexts);
+ return encrypt_with_mode<algorithm, AESNI_OFB>(key_str, plaintexts, verbose);
case AESNI_CTR:
- return encrypt_with_mode<algorithm, AESNI_CTR>(key_str, plaintexts);
+ return encrypt_with_mode<algorithm, AESNI_CTR>(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<std::string> plaintexts)
+ std::deque<std::string> plaintexts,
+ bool verbose = false)
{
switch (algorithm)
{
case AESNI_AES128:
- return encrypt_with_algorithm<AESNI_AES128>(mode, key_str, plaintexts);
+ return encrypt_with_algorithm<AESNI_AES128>(mode, key_str, plaintexts, verbose);
case AESNI_AES192:
- return encrypt_with_algorithm<AESNI_AES192>(mode, key_str, plaintexts);
+ return encrypt_with_algorithm<AESNI_AES192>(mode, key_str, plaintexts, verbose);
case AESNI_AES256:
- return encrypt_with_algorithm<AESNI_AES256>(mode, key_str, plaintexts);
+ return encrypt_with_algorithm<AESNI_AES256>(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)
{