aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-10-06 16:33:22 +0000
committerlloyd <[email protected]>2009-10-06 16:33:22 +0000
commit7c71072fe090b9925715614861471b7e51a70a56 (patch)
treec78231d3a822594a518a4a863b8eb23628baf778
parentf6546e0ffc4d9fda308e8e043446d1940f533140 (diff)
Add cipher mode selftesting in selftest.cpp
Convert hardcoded startup selftests to use the new selftest framework
-rw-r--r--src/selftest/info.txt7
-rw-r--r--src/selftest/selftest.cpp339
-rw-r--r--src/selftest/selftest.h3
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);