diff options
author | lloyd <[email protected]> | 2013-12-31 19:01:37 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-12-31 19:01:37 +0000 |
commit | c0ce45696f6d00e7496634c233410d264d0e9d42 (patch) | |
tree | 35392692a6cc59b00ed6d4b7d71c5619889f034e | |
parent | 7ec00d6a7bfe94f628a6c5118f3a0e8ed7938f99 (diff) |
Make eax_test example (which reads LTC's EAX test file) an actual
test. Update to new AEAD api. Currently requires boost_regex (for
tests only), done via hardcoding in makefile template.
-rw-r--r-- | checks/eax.cpp (renamed from doc/examples/eax_test.cpp) | 128 | ||||
-rw-r--r-- | checks/eax.vec (renamed from doc/examples/eax_vecs.txt) | 0 | ||||
-rw-r--r-- | checks/tests.h | 1 | ||||
-rw-r--r-- | checks/validate.cpp | 1 | ||||
-rw-r--r-- | doc/examples/row_encryptor.cpp | 171 | ||||
-rw-r--r-- | src/build-data/makefile/unix_shr.in | 2 |
6 files changed, 57 insertions, 246 deletions
diff --git a/doc/examples/eax_test.cpp b/checks/eax.cpp index 228ece286..e44adaa6a 100644 --- a/doc/examples/eax_test.cpp +++ b/checks/eax.cpp @@ -4,13 +4,15 @@ * Distributed under the terms of the Botan license */ +#include "tests.h" #include <fstream> #include <iostream> #include <sstream> #include <boost/regex.hpp> -#include <botan/botan.h> #include <botan/eax.h> +#include <botan/hex.h> +#include <botan/lookup.h> using namespace Botan; @@ -42,81 +44,61 @@ std::string seq(unsigned n) return s; } -void eax_test(const std::string& algo, - const std::string& key_str, - const std::string& nonce_str, - const std::string& header_str, - const std::string& tag_str, - const std::string& plaintext_str, - const std::string& ciphertext) +size_t eax_test(const std::string& algo, + const std::string& key_str, + const std::string& nonce_str, + const std::string& header_str, + const std::string& tag_str, + const std::string& plaintext_str, + const std::string& ciphertext) { - /* - printf("EAX(algo=%s key=%s nonce=%s header=%s tag=%s pt=%s ct=%s)\n", - algo.c_str(), key_str.c_str(), nonce_str.c_str(), header_str.c_str(), tag_str.c_str(), - plaintext_str.c_str(), ciphertext.c_str()); - */ + size_t fail = 0; - SymmetricKey key(key_str); - InitializationVector iv(nonce_str); - - EAX_Encryption* enc; - - Pipe pipe(new Hex_Decoder, - enc = new EAX_Encryption(get_block_cipher(algo)), - new Hex_Encoder); - - enc->set_key(key); - enc->set_iv(iv); - - OctetString header(header_str); - - enc->set_header(header.begin(), header.length()); + try + { + EAX_Encryption enc(get_block_cipher(algo)); + EAX_Decryption dec(get_block_cipher(algo)); - pipe.start_msg(); - pipe.write(plaintext_str); - pipe.end_msg(); + enc.set_key(hex_decode(key_str)); + dec.set_key(hex_decode(key_str)); - std::string out = pipe.read_all_as_string(); + enc.set_associated_data_vec(hex_decode(header_str)); + dec.set_associated_data_vec(hex_decode(header_str)); - if(out != ciphertext + tag_str) - { - printf("BAD enc %s '%s' != '%s%s'\n", algo.c_str(), - out.c_str(), ciphertext.c_str(), tag_str.c_str()); - } - else - printf("OK enc %s\n", algo.c_str()); + secure_vector<byte> text = hex_decode_locked(plaintext_str); + enc.start_vec(hex_decode(nonce_str)); + enc.finish(text); - try - { - EAX_Decryption* dec; - Pipe pipe2(new Hex_Decoder, - dec = new EAX_Decryption(get_block_cipher(algo)), - new Hex_Encoder); + const std::string produced = hex_encode(text); - dec->set_key(key); - dec->set_iv(iv); + if(produced != ciphertext + tag_str) + { + std::cout << "EAX " << algo << " " << produced << " != expected " << ciphertext << tag_str << "\n"; + ++fail; + } - dec->set_header(header.begin(), header.length()); + text.clear(); + text = hex_decode_locked(ciphertext); + text += hex_decode_locked(tag_str); - pipe2.start_msg(); - pipe2.write(ciphertext); - pipe2.write(tag_str); - pipe2.end_msg(); + dec.start_vec(hex_decode(nonce_str)); + dec.finish(text); - std::string out2 = pipe2.read_all_as_string(); + const std::string decrypted = hex_encode(text); - if(out2 != plaintext_str) + if(decrypted != plaintext_str) { - printf("BAD decrypt %s '%s'\n", algo.c_str(), out2.c_str()); + std::cout << "EAX " << algo << " " << decrypted << " != expected " << plaintext_str << "\n"; + ++fail; } - else - printf("OK decrypt %s\n", algo.c_str()); } catch(std::exception& e) { - printf("%s\n", e.what()); + std::cout << "Exception during EAX test " << e.what() << "\n"; + ++fail; } + return fail; } std::pair<std::string, int> translate_algo(const std::string& in) @@ -181,11 +163,14 @@ std::string rep(const std::string& s_in, unsigned n) return s_out; } -void run_tests(std::istream& in) +size_t eax_tests(std::istream& in) { std::string algo; std::string key; + size_t fails = 0; + size_t tests = 0; + while(in.good()) { std::string line; @@ -219,31 +204,26 @@ void run_tests(std::istream& in) std::string header = seq(n); std::string nonce = seq(n); - eax_test(algo, key, nonce, header, tag, - plaintext, ciphertext); + tests += 1; + + fails += eax_test(algo, key, nonce, header, tag, + plaintext, ciphertext); key = rep(tag, key.size()); // repeat as needed } } } + test_report("EAX", tests, fails); + return fails; } } -int main() +size_t test_eax() { - std::ifstream in("eax_vecs.txt"); - - Botan::LibraryInitializer init; - - if(!in) - { - std::cerr << "Couldn't read input file\n"; - return 1; - } - - run_tests(in); - + // Uses a set of tests created for libtomcrypt + std::ifstream in("checks/eax.vec"); + return eax_tests(in); } diff --git a/doc/examples/eax_vecs.txt b/checks/eax.vec index 95cd7c1ab..95cd7c1ab 100644 --- a/doc/examples/eax_vecs.txt +++ b/checks/eax.vec diff --git a/checks/tests.h b/checks/tests.h index db92a5d3d..e1f59c501 100644 --- a/checks/tests.h +++ b/checks/tests.h @@ -37,6 +37,7 @@ size_t test_transform(); // One off tests size_t test_ocb(); +size_t test_eax(); size_t test_keywrap(); size_t test_bcrypt(); size_t test_passhash9(); diff --git a/checks/validate.cpp b/checks/validate.cpp index cb15325ef..bcb949a79 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -188,6 +188,7 @@ u32bit do_validation_tests(const std::string& filename, std::vector<test_fn> all_tests; all_tests.push_back(test_aead); all_tests.push_back(test_ocb); + all_tests.push_back(test_eax); all_tests.push_back(test_pbkdf); all_tests.push_back(test_kdf); diff --git a/doc/examples/row_encryptor.cpp b/doc/examples/row_encryptor.cpp deleted file mode 100644 index b512025b6..000000000 --- a/doc/examples/row_encryptor.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <string> -#include <memory> -#include <sstream> -#include <iostream> -#include <stdexcept> - -#include <botan/botan.h> -#include <botan/filters.h> -#include <botan/eax.h> - -using namespace Botan; - -/* -* Encrypt and decrypt small rows -*/ -class Row_Encryptor - { - public: - Row_Encryptor(const std::string& passphrase, - RandomNumberGenerator& rng); - - Row_Encryptor(const std::string& passphrase, - const std::vector<byte>& salt); - - std::string encrypt(const std::string& input, - const std::vector<byte>& salt); - - std::string decrypt(const std::string& input, - const std::vector<byte>& salt); - - std::vector<byte> get_pbkdf_salt() const { return pbkdf_salt; } - private: - void init(const std::string& passphrase); - - Row_Encryptor(const Row_Encryptor&) {} - Row_Encryptor& operator=(const Row_Encryptor&) { return (*this); } - - std::vector<byte> pbkdf_salt; - Pipe enc_pipe, dec_pipe; - EAX_Encryption* eax_enc; // owned by enc_pipe - EAX_Decryption* eax_dec; // owned by dec_pipe; - }; - -Row_Encryptor::Row_Encryptor(const std::string& passphrase, - RandomNumberGenerator& rng) - { - pbkdf_salt.resize(10); // 80 bits - rng.randomize(&pbkdf_salt[0], pbkdf_salt.size()); - init(passphrase); - } - -Row_Encryptor::Row_Encryptor(const std::string& passphrase, - const std::vector<byte>& salt) - { - pbkdf_salt = salt; - init(passphrase); - } - -void Row_Encryptor::init(const std::string& passphrase) - { - std::auto_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-160)")); - - secure_vector<byte> key = pbkdf->derive_key(32, passphrase, - &pbkdf_salt[0], pbkdf_salt.size(), - 10000).bits_of(); - - /* - Save pointers to the EAX objects so we can change the IV as needed - */ - - Algorithm_Factory& af = global_state().algorithm_factory(); - - const BlockCipher* proto = af.prototype_block_cipher("Serpent"); - - if(!proto) - throw std::runtime_error("Could not get a Serpent proto object"); - - enc_pipe.append(eax_enc = new EAX_Encryption(proto->clone())); - dec_pipe.append(eax_dec = new EAX_Decryption(proto->clone())); - - eax_enc->set_key(key); - eax_dec->set_key(key); - } - -std::string Row_Encryptor::encrypt(const std::string& input, - const std::vector<byte>& salt) - { - eax_enc->set_iv(salt); - enc_pipe.process_msg(input); - return enc_pipe.read_all_as_string(Pipe::LAST_MESSAGE); - } - -std::string Row_Encryptor::decrypt(const std::string& input, - const std::vector<byte>& salt) - { - eax_dec->set_iv(salt); - dec_pipe.process_msg(input); - return dec_pipe.read_all_as_string(Pipe::LAST_MESSAGE); - } - -/* -* Test code follows: -*/ - -int main() - { - Botan::LibraryInitializer init; - - AutoSeeded_RNG rng; - - const std::string secret_passphrase = "secret passphrase"; - - Row_Encryptor encryptor("secret passphrase", rng); - - std::vector<std::string> original_inputs; - - for(u32bit i = 0; i != 50000; ++i) - { - std::ostringstream out; - - u32bit output_bytes = rng.next_byte(); - - for(u32bit j = 0; j != output_bytes; ++j) - out << std::hex << (int)rng.next_byte(); - - original_inputs.push_back(out.str()); - } - - std::vector<std::string> encrypted_values; - std::vector<byte> salt(4); - - for(u32bit i = 0; i != original_inputs.size(); ++i) - { - std::string input = original_inputs[i]; - - for(u32bit j = 0; j != 4; ++j) - salt[j] = (i >> 8) & 0xFF; - - encrypted_values.push_back(encryptor.encrypt(input, salt)); - } - - for(u32bit i = 0; i != encrypted_values.size(); ++i) - { - std::string ciphertext = encrypted_values[i]; - - // NOTE: same salt value as previous loop (index value) - for(u32bit j = 0; j != 4; ++j) - salt[j] = (i >> 8) & 0xFF; - - std::string output = encryptor.decrypt(ciphertext, salt); - - if(output != original_inputs[i]) - std::cout << "BOOM " << i << "\n"; - } - - Row_Encryptor test_pbkdf_salt_copy(secret_passphrase, - encryptor.get_pbkdf_salt()); - - zeroise(salt); - std::string test = test_pbkdf_salt_copy.decrypt(encrypted_values[0], salt); - if(test != original_inputs[0]) - std::cout << "PBKDF salt copy failed to decrypt properly\n"; - - return 0; - } diff --git a/src/build-data/makefile/unix_shr.in b/src/build-data/makefile/unix_shr.in index c412a94fd..610367dc5 100644 --- a/src/build-data/makefile/unix_shr.in +++ b/src/build-data/makefile/unix_shr.in @@ -71,7 +71,7 @@ CHECKOBJS = %{check_objs} # Link Commands $(CHECK): $(LIBRARIES) $(CHECKOBJS) - $(CXX) $(LDFLAGS) $(CHECKOBJS) $(SHARED_LIB) $(LINK_TO) -o $(CHECK) + $(CXX) $(LDFLAGS) $(CHECKOBJS) $(SHARED_LIB) $(LINK_TO) -lboost_regex -o $(CHECK) $(STATIC_LIB): $(LIBOBJS) $(RM) $(STATIC_LIB) |