diff options
author | lloyd <[email protected]> | 2009-10-06 16:33:22 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-10-06 16:33:22 +0000 |
commit | 7c71072fe090b9925715614861471b7e51a70a56 (patch) | |
tree | c78231d3a822594a518a4a863b8eb23628baf778 | |
parent | f6546e0ffc4d9fda308e8e043446d1940f533140 (diff) |
Add cipher mode selftesting in selftest.cpp
Convert hardcoded startup selftests to use the new selftest framework
-rw-r--r-- | src/selftest/info.txt | 7 | ||||
-rw-r--r-- | src/selftest/selftest.cpp | 339 | ||||
-rw-r--r-- | src/selftest/selftest.h | 3 |
3 files changed, 198 insertions, 151 deletions
diff --git a/src/selftest/info.txt b/src/selftest/info.txt index 323a610a6..c4b61bb99 100644 --- a/src/selftest/info.txt +++ b/src/selftest/info.txt @@ -11,11 +11,6 @@ selftest.h <requires> algo_factory -cbc -cfb -ctr -ecb filters -hmac -ofb +def_engine </requires> diff --git a/src/selftest/selftest.cpp b/src/selftest/selftest.cpp index 6fd6b7fcd..c8c1b5f75 100644 --- a/src/selftest/selftest.cpp +++ b/src/selftest/selftest.cpp @@ -7,14 +7,11 @@ #include <botan/selftest.h> #include <botan/filters.h> -#include <botan/ecb.h> -#include <botan/cbc.h> -#include <botan/cfb.h> -#include <botan/ofb.h> -#include <botan/ctr.h> -#include <botan/hmac.h> +#include <botan/def_eng.h> #include <botan/stl_util.h> +#include <stdio.h> + namespace Botan { namespace { @@ -32,63 +29,19 @@ bool test_filter_kat(Filter* filter, return (output == pipe.read_all_as_string()); } -void do_kat(const std::string& in, const std::string& out, - const std::string& algo_name, Filter* filter) - { - if(!test_filter_kat(filter, in, out)) - throw Self_Test_Failure(algo_name + " startup test"); - } - -/* -* Perform a KAT for a cipher -*/ -void cipher_kat(const BlockCipher* proto, - const std::string& key_str, - const std::string& iv_str, - const std::string& in, - const std::string& ecb_out, - const std::string& cbc_out, - const std::string& cfb_out, - const std::string& ofb_out, - const std::string& ctr_out) - { - SymmetricKey key(key_str); - InitializationVector iv(iv_str); - - std::string name = proto->name(); - - do_kat(in, ecb_out, name + "/ECB", - new ECB_Encryption(proto->clone(), new Null_Padding, key)); - do_kat(ecb_out, in, name + "/ECB", - new ECB_Decryption(proto->clone(), new Null_Padding, key)); - - do_kat(in, cbc_out, name + "/CBC", - new CBC_Encryption(proto->clone(), new Null_Padding, key, iv)); - do_kat(cbc_out, in, name + "/CBC", - new CBC_Decryption(proto->clone(), new Null_Padding, key, iv)); - - do_kat(in, cfb_out, name + "/CFB", - new CFB_Encryption(proto->clone(), key, iv)); - do_kat(cfb_out, in, name + "/CFB", - new CFB_Decryption(proto->clone(), key, iv)); - - do_kat(in, ofb_out, name + "/OFB", new OFB(proto->clone(), key, iv)); - - do_kat(in, ctr_out, name + "/CTR-BE", - new CTR_BE(proto->clone(), key, iv)); - } - } /* * Run a set of KATs */ std::map<std::string, bool> -algorithm_kat(const std::string& name, +algorithm_kat(const SCAN_Name& algo_name, const std::map<std::string, std::string>& vars, Algorithm_Factory& af) { - std::vector<std::string> providers = af.providers_of(name); + const std::string& algo = algo_name.algo_name_and_args(); + + std::vector<std::string> providers = af.providers_of(algo); std::map<std::string, bool> all_results; if(providers.empty()) // no providers, nothing to do @@ -97,44 +50,159 @@ algorithm_kat(const std::string& name, const std::string input = search_map(vars, std::string("input")); const std::string output = search_map(vars, std::string("output")); const std::string key = search_map(vars, std::string("key")); + const std::string iv = search_map(vars, std::string("iv")); for(u32bit i = 0; i != providers.size(); ++i) { const std::string provider = providers[i]; if(const HashFunction* proto = - af.prototype_hash_function(name, provider)) + af.prototype_hash_function(algo, provider)) { - all_results[provider] = test_filter_kat(new Hash_Filter(proto->clone()), - input, output); + Filter* filt = new Hash_Filter(proto->clone()); + all_results[provider] = test_filter_kat(filt, input, output); } else if(const MessageAuthenticationCode* proto = - af.prototype_mac(name, provider)) + af.prototype_mac(algo, provider)) { - all_results[provider] = test_filter_kat(new MAC_Filter(proto->clone(), key), - input, output); + Keyed_Filter* filt = new MAC_Filter(proto->clone(), key); + all_results[provider] = test_filter_kat(filt, input, output); } - -#if 0 - if(const BlockCipher* proto = - af.prototype_block_cipher(name, provider)) + else if(const StreamCipher* proto = + af.prototype_stream_cipher(algo, provider)) { - std::auto_ptr<BlockCipher> block_cipher(proto->clone()); - all_results[provider] = test_block_cipher(block_cipher.get()); + Keyed_Filter* filt = new StreamCipher_Filter(proto->clone()); + filt->set_key(key); + filt->set_iv(iv); + + all_results[provider] = test_filter_kat(filt, input, output); } - else if(const StreamCipher* proto = - af.prototype_stream_cipher(name, provider)) + else if(const BlockCipher* proto = + af.prototype_block_cipher(algo, provider)) { - std::auto_ptr<StreamCipher> stream_cipher(proto->clone()); - all_results[provider] = test_stream_cipher(stream_cipher.get()); + Keyed_Filter* enc = get_cipher_mode(proto, ENCRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + Keyed_Filter* dec = get_cipher_mode(proto, DECRYPTION, + algo_name.cipher_mode(), + algo_name.cipher_mode_pad()); + + if(!enc || !dec) + { + delete enc; + delete dec; + continue; + } + + enc->set_key(key); + enc->set_iv(iv); + + dec->set_key(key); + dec->set_iv(iv); + + bool enc_ok = test_filter_kat(enc, input, output); + bool dec_ok = test_filter_kat(dec, output, input); + + all_results[provider] = enc_ok && dec_ok; } - else -#endif } return all_results; } +namespace { + + +void do_kat(const std::string& in, const std::string& out, + const std::string& algo_name, Filter* filter) + { + if(!test_filter_kat(filter, in, out)) + throw Self_Test_Failure(algo_name + " startup test"); + } + + +void verify_results(const std::string& algo, + const std::map<std::string, bool>& results) + { + for(std::map<std::string, bool>::const_iterator i = results.begin(); + i != results.end(); ++i) + { + if(!i->second) + throw Self_Test_Failure(algo + " self-test failed, provider "+ + i->first); + } + } + +void hash_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + + verify_results(name, algorithm_kat(name, vars, af)); + } + +void mac_test(Algorithm_Factory& af, + const std::string& name, + const std::string& in, + const std::string& out, + const std::string& key) + { + std::map<std::string, std::string> vars; + vars["input"] = in; + vars["output"] = out; + vars["key"] = key; + + verify_results(name, algorithm_kat(name, vars, af)); + } + +/* +* Perform a KAT for a cipher +*/ +void cipher_kat(Algorithm_Factory& af, + const std::string& algo, + const std::string& key_str, + const std::string& iv_str, + const std::string& in, + const std::string& ecb_out, + const std::string& cbc_out, + const std::string& cfb_out, + const std::string& ofb_out, + const std::string& ctr_out) + { + SymmetricKey key(key_str); + InitializationVector iv(iv_str); + + std::map<std::string, std::string> vars; + vars["key"] = key_str; + vars["iv"] = iv_str; + vars["input"] = in; + + std::map<std::string, bool> results; + + vars["output"] = ecb_out; + verify_results(algo + "/ECB", algorithm_kat(algo + "/ECB", vars, af)); + + vars["output"] = cbc_out; + verify_results(algo + "/CBC", + algorithm_kat(algo + "/CBC/NoPadding", vars, af)); + + vars["output"] = cfb_out; + verify_results(algo + "/CFB", algorithm_kat(algo + "/CFB", vars, af)); + + vars["output"] = ofb_out; + verify_results(algo + "/OFB", algorithm_kat(algo + "/OFB", vars, af)); + + vars["output"] = ctr_out; + verify_results(algo + "/CTR", algorithm_kat(algo + "/CTR-BE", vars, af)); + } + +} + /* * Perform Self Tests */ @@ -142,9 +210,7 @@ bool passes_self_tests(Algorithm_Factory& af) { try { - if(const BlockCipher* proto = af.prototype_block_cipher("DES")) - { - cipher_kat(proto, + cipher_kat(af, "DES", "0123456789ABCDEF", "1234567890ABCDEF", "4E6F77206973207468652074696D6520666F7220616C6C20", "3FA40E8A984D48156A271787AB8883F9893D51EC4B563B53", @@ -152,11 +218,8 @@ bool passes_self_tests(Algorithm_Factory& af) "F3096249C7F46E51A69E839B1A92F78403467133898EA622", "F3096249C7F46E5135F24A242EEB3D3F3D6D5BE3255AF8C3", "F3096249C7F46E51163A8CA0FFC94C27FA2F80F480B86F75"); - } - if(const BlockCipher* proto = af.prototype_block_cipher("TripleDES")) - { - cipher_kat(proto, + cipher_kat(af, "TripleDES", "385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E", "C141B5FCCD28DC8A", "6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68", @@ -165,75 +228,63 @@ bool passes_self_tests(Algorithm_Factory& af) "E26BA806A59B0330DE40CA38E77A3E494BE2B212F6DD624B", "E26BA806A59B03307DE2BCC25A08BA40A8BA335F5D604C62", "E26BA806A59B03303C62C2EFF32D3ACDD5D5F35EBCC53371"); - } - - if(const BlockCipher* proto = af.prototype_block_cipher("AES")) - { - cipher_kat(proto, - "2B7E151628AED2A6ABF7158809CF4F3C", - "000102030405060708090A0B0C0D0E0F", - "6BC1BEE22E409F96E93D7E117393172A" - "AE2D8A571E03AC9C9EB76FAC45AF8E51", - "3AD77BB40D7A3660A89ECAF32466EF97" - "F5D3D58503B9699DE785895A96FDBAAF", - "7649ABAC8119B246CEE98E9B12E9197D" - "5086CB9B507219EE95DB113A917678B2", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "C8A64537A0B3A93FCDE3CDAD9F1CE58B", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "7789508D16918F03F53C52DAC54ED825", - "3B3FD92EB72DAD20333449F8E83CFB4A" - "010C041999E03F36448624483E582D0E"); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-1")) - { - do_kat("", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", "A9993E364706816ABA3E25717850C26C9CD0D89D", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + + cipher_kat(af, "AES-128", + "2B7E151628AED2A6ABF7158809CF4F3C", + "000102030405060708090A0B0C0D0E0F", + "6BC1BEE22E409F96E93D7E117393172A" + "AE2D8A571E03AC9C9EB76FAC45AF8E51", + "3AD77BB40D7A3660A89ECAF32466EF97" + "F5D3D58503B9699DE785895A96FDBAAF", + "7649ABAC8119B246CEE98E9B12E9197D" + "5086CB9B507219EE95DB113A917678B2", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "C8A64537A0B3A93FCDE3CDAD9F1CE58B", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "7789508D16918F03F53C52DAC54ED825", + "3B3FD92EB72DAD20333449F8E83CFB4A" + "010C041999E03F36448624483E582D0E"); + + hash_test(af, "SHA-1", + "", "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"); + + hash_test(af, "SHA-1", + "616263", "A9993E364706816ABA3E25717850C26C9CD0D89D"); + + hash_test(af, "SHA-1", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", - "84983E441C3BD26EBAAE4AA1F95129E5E54670F1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "B617318655057264E28BC0B6FB378C8EF146BE00", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } - - if(const HashFunction* proto = af.prototype_hash_function("SHA-256")) - { - do_kat("", - "E3B0C44298FC1C149AFBF4C8996FB924" - "27AE41E4649B934CA495991B7852B855", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("616263", - "BA7816BF8F01CFEA414140DE5DAE2223" - "B00361A396177A9CB410FF61F20015AD", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("6162636462636465636465666465666765666768666768696768696A" + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); + + mac_test(af, "HMAC(SHA-1)", + "4869205468657265", + "B617318655057264E28BC0B6FB378C8EF146BE00", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); + + hash_test(af, "SHA-256", + "", + "E3B0C44298FC1C149AFBF4C8996FB924" + "27AE41E4649B934CA495991B7852B855"); + + hash_test(af, "SHA-256", + "616263", + "BA7816BF8F01CFEA414140DE5DAE2223" + "B00361A396177A9CB410FF61F20015AD"); + + hash_test(af, "SHA-256", + "6162636462636465636465666465666765666768666768696768696A" "68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F7071", "248D6A61D20638B8E5C026930C3E6039" - "A33CE45964FF2167F6ECEDD419DB06C1", - proto->name(), new Hash_Filter(proto->clone())); - - do_kat("4869205468657265", - "198A607EB44BFBC69903A0F1CF2BBDC5" - "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", - "HMAC(" + proto->name() + ")", - new MAC_Filter(new HMAC(proto->clone()), - SymmetricKey("0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" - "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"))); - } + "A33CE45964FF2167F6ECEDD419DB06C1"); + + mac_test(af, "HMAC(SHA-256)", + "4869205468657265", + "198A607EB44BFBC69903A0F1CF2BBDC5" + "BA0AA3F3D9AE3C1C7A3B1696A0B68CF7", + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B" + "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); } - catch(std::exception) + catch(Self_Test_Failure) { return false; } diff --git a/src/selftest/selftest.h b/src/selftest/selftest.h index b5fc9f80a..4cb6e23d7 100644 --- a/src/selftest/selftest.h +++ b/src/selftest/selftest.h @@ -9,6 +9,7 @@ #define BOTAN_SELF_TESTS_H__ #include <botan/algo_factory.h> +#include <botan/scan_name.h> #include <map> #include <string> @@ -20,7 +21,7 @@ namespace Botan { BOTAN_DLL bool passes_self_tests(Algorithm_Factory& af); BOTAN_DLL std::map<std::string, bool> -algorithm_kat(const std::string& name, +algorithm_kat(const SCAN_Name& algo_name, const std::map<std::string, std::string>& vars, Algorithm_Factory& af); |