From 9e4c7395029bb672d208c9c5cb2936ba397cbf20 Mon Sep 17 00:00:00 2001 From: lloyd Date: Thu, 5 Dec 2013 02:09:41 +0000 Subject: Add SIV --- checks/aead.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++ checks/aead.vec | 12 +++++++++ checks/hkdf.cpp | 44 +++++------------------------- checks/tests.cpp | 43 +++++++++++++++++++---------- checks/validate.cpp | 1 + checks/validate.h | 7 +++++ 6 files changed, 133 insertions(+), 52 deletions(-) create mode 100644 checks/aead.cpp create mode 100644 checks/aead.vec (limited to 'checks') diff --git a/checks/aead.cpp b/checks/aead.cpp new file mode 100644 index 000000000..3cb0fb986 --- /dev/null +++ b/checks/aead.cpp @@ -0,0 +1,78 @@ +#include "validate.h" + +#include +#include +#include +#include +#include + +using namespace Botan; + +namespace { + +secure_vector aead(const std::string& algo, + Cipher_Dir dir, + const secure_vector& pt, + const secure_vector& nonce, + const secure_vector& ad, + const secure_vector& key) + { + std::unique_ptr aead(get_aead(algo, dir)); + + aead->set_key(&key[0], key.size()); + aead->start_vec(nonce); + aead->set_associated_data_vec(ad); + + secure_vector ct = pt; + aead->finish(ct); + + return ct; + } + +bool aead_test(const std::string& algo, + const std::string& pt, + const std::string& ct, + const std::string& nonce_hex, + const std::string& ad_hex, + const std::string& key_hex) + { + auto nonce = hex_decode_locked(nonce_hex); + auto ad = hex_decode_locked(ad_hex); + auto key = hex_decode_locked(key_hex); + + const std::string ct2 = hex_encode(aead(algo, + ENCRYPTION, + hex_decode_locked(pt), + nonce, + ad, + key)); + + if(ct != ct2) + std::cout << algo << " got ct " << ct2 << " expected " << ct << "\n"; + + const std::string pt2 = hex_encode(aead(algo, + DECRYPTION, + hex_decode_locked(ct), + nonce, + ad, + key)); + + if(pt != pt2) + std::cout << algo << " got pt " << pt2 << " expected " << pt << "\n"; + + return (ct == ct2) && (pt == pt2); + } + +} + +void test_aead() + { + std::ifstream vec("checks/aead.vec"); + + run_tests_bb(vec, "AEAD", "Ciphertext", true, + [](std::map m) + { + return aead_test(m["AEAD"], m["Plaintext"], m["Ciphertext"], + m["Nonce"], m["AD"], m["Key"]); + }); + } diff --git a/checks/aead.vec b/checks/aead.vec new file mode 100644 index 000000000..4d9f39556 --- /dev/null +++ b/checks/aead.vec @@ -0,0 +1,12 @@ +AEAD = AES-128/SIV +Plaintext = 112233445566778899AABBCCDDEE +Key = FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF +AD = 101112131415161718191A1B1C1D1E1F2021222324252627 +Ciphertext = 85632D07C6E8F37F950ACD320A2ECC9340C02B9690C4DC04DAEF7F6AFE5C + +AEAD = AES-128/SIV +Plaintext = 7468697320697320736F6D6520706C61696E7465787420746F20656E6372797074207573696E67205349562D414553 +Key = 7F7E7D7C7B7A79787776757473727170404142434445464748494A4B4C4D4E4F +AD = 00112233445566778899AABBCCDDEEFFDEADDADADEADDADAFFEEDDCCBBAA99887766554433221100 +Nonce = 09F911029D74E35BD84156C5635688C1 +Ciphertext = E21A9D0FE3BD3ED189C71F29B24C39E1E40B9BAB82D428D0A9B392F13EA14C9B4433F393595A8E031F032350F50D2B21825B3EE64958103BD8445C3F48E5CF diff --git a/checks/hkdf.cpp b/checks/hkdf.cpp index ce93458d7..e63ff55fa 100644 --- a/checks/hkdf.cpp +++ b/checks/hkdf.cpp @@ -33,7 +33,7 @@ secure_vector hkdf(const std::string& algo, return key; } -void hkdf_test(const std::string& algo, +bool hkdf_test(const std::string& algo, const std::string& ikm, const std::string& salt, const std::string& info, @@ -50,40 +50,8 @@ void hkdf_test(const std::string& algo, if(got != okm) std::cout << "HKDF got " << got << " expected " << okm << std::endl; - } - -void run_tests(std::istream& src, - bool clear_between_cb, - const std::string& trigger_key, - std::function)> cb) - { - std::map vars; - - while(src.good()) - { - std::string line; - std::getline(src, line); - - if(line == "") - continue; - - // FIXME: strip # comments - - // FIXME: Do this right - - const std::string key = line.substr(0, line.find_first_of(' ')); - const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos); - - vars[key] = val; - - if(key == trigger_key) - { - cb(vars); - if(clear_between_cb) - vars.clear(); - } - } + return (got == okm); } } @@ -93,10 +61,10 @@ void test_hkdf() // From RFC 5869 std::ifstream vec("checks/hkdf.vec"); - run_tests(vec, true, "OKM", - [](std::map m) + run_tests_bb(vec, "HKDF", "OKM", true, + [](std::map m) -> bool { - hkdf_test(m["Hash"], m["IKM"], m["salt"], m["info"], - m["OKM"], to_u32bit(m["L"])); + return hkdf_test(m["Hash"], m["IKM"], m["salt"], m["info"], + m["OKM"], to_u32bit(m["L"])); }); } diff --git a/checks/tests.cpp b/checks/tests.cpp index 2c6321415..fdaccd805 100644 --- a/checks/tests.cpp +++ b/checks/tests.cpp @@ -1,11 +1,11 @@ #include "validate.h" #include -void run_tests(std::istream& src, - const std::string& name_key, - const std::string& output_key, - bool clear_between_cb, - std::function)> cb) +void run_tests_bb(std::istream& src, + const std::string& name_key, + const std::string& output_key, + bool clear_between_cb, + std::function)> cb) { std::map vars; size_t test_cnt = 0; @@ -20,9 +20,8 @@ void run_tests(std::istream& src, if(line == "") continue; - // FIXME: strip # comments - - // FIXME: Do this right + if(line[0] == '#') + continue; const std::string key = line.substr(0, line.find_first_of(' ')); const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos); @@ -32,14 +31,10 @@ void run_tests(std::istream& src, if(key == output_key) { ++test_cnt; - const std::string got = cb(vars); + bool passed = cb(vars); - if(got != val) - { + if(!passed) ++test_fail; - std::cout << name_key << " #" << test_cnt - << " got " << got << " expected " << val << std::endl; - } if(clear_between_cb) vars.clear(); @@ -51,3 +46,23 @@ void run_tests(std::istream& src, << test_fail << " failed\n"; } +void run_tests(std::istream& src, + const std::string& name_key, + const std::string& output_key, + bool clear_between_cb, + std::function)> cb) + { + run_tests_bb(src, name_key, output_key, clear_between_cb, + [name_key,output_key,cb](std::map vars) + { + const std::string got = cb(vars); + if(got != vars[output_key]) + { + std::cout << name_key << " got " << got + << " expected " << vars[output_key] << std::endl; + return false; + } + return true; + }); + } + diff --git a/checks/validate.cpp b/checks/validate.cpp index 606f3a2c3..48932f0e4 100644 --- a/checks/validate.cpp +++ b/checks/validate.cpp @@ -422,6 +422,7 @@ u32bit do_validation_tests(const std::string& filename, test_hkdf(); test_pbkdf(); test_kdf(); + test_aead(); } return errors; diff --git a/checks/validate.h b/checks/validate.h index e1a8acfd5..48830619b 100644 --- a/checks/validate.h +++ b/checks/validate.h @@ -38,6 +38,13 @@ void test_ocb(); void test_hkdf(); void test_pbkdf(); void test_kdf(); +void test_aead(); + +void run_tests_bb(std::istream& src, + const std::string& name_key, + const std::string& output_key, + bool clear_between_cb, + std::function)> cb); void run_tests(std::istream& src, const std::string& name_key, -- cgit v1.2.3