diff options
author | lloyd <[email protected]> | 2009-10-07 18:09:33 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-10-07 18:09:33 +0000 |
commit | c3ee539408849fc317b6ada78148cd5cb5ae6399 (patch) | |
tree | a9ff14b87ffaee7a0f90cdfe918fba87b2541924 /checks/dolook.cpp | |
parent | 0d409578fecf39b6c2dc4926c4d95e353dcfcd78 (diff) |
Use the new selftest framework for testing hashes, MACs, and ciphers.
Remove the Decrypt direction cipher mode tests - now both directions
are always tested for all modes. Also add IVs for Salsa20 (were implicit
all-zeros) since that does not fly anymore in validate.dat
Diffstat (limited to 'checks/dolook.cpp')
-rw-r--r-- | checks/dolook.cpp | 251 |
1 files changed, 200 insertions, 51 deletions
diff --git a/checks/dolook.cpp b/checks/dolook.cpp index 0c20448af..b64c5a5a3 100644 --- a/checks/dolook.cpp +++ b/checks/dolook.cpp @@ -4,6 +4,11 @@ #include <botan/lookup.h> #include <botan/filters.h> #include <botan/libstate.h> +#include <botan/hmac.h> +#include <botan/aes.h> +#include <botan/sha2_32.h> +#include <botan/sha2_64.h> +#include <botan/parsing.h> #ifdef BOTAN_HAS_COMPRESSOR_BZIP2 #include <botan/bzip2.h> @@ -17,84 +22,203 @@ #include <botan/zlib.h> #endif +#if defined(BOTAN_HAS_RANDPOOL) + #include <botan/randpool.h> +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + #include <botan/hmac_rng.h> +#endif + +#if defined(BOTAN_HAS_X931_RNG) + #include <botan/x931_rng.h> + #include <botan/des.h> +#endif + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include <botan/auto_rng.h> +#endif + using namespace Botan; #include "common.h" -Filter* lookup(const std::string& algname, - const std::vector<std::string>& params, - const std::string& section) +/* A weird little hack to fit S2K algorithms into the validation suite + You probably wouldn't ever want to actually use the S2K algorithms like + this, the raw S2K interface is more convenient for actually using them +*/ +class S2K_Filter : public Filter { - std::string key = params[0]; - std::string iv = params[1]; - Filter* filter = 0; - - // The order of the lookup has to change based on how the names are - // formatted and parsed. - filter = lookup_kdf(algname, key, iv); - if(filter) return filter; + public: + void write(const byte in[], u32bit len) + { passphrase += std::string(reinterpret_cast<const char*>(in), len); } + void end_msg() + { + s2k->change_salt(salt, salt.size()); + s2k->set_iterations(iterations); + SymmetricKey x = s2k->derive_key(outlen, passphrase); + send(x.bits_of()); + } + S2K_Filter(S2K* algo, const SymmetricKey& s, u32bit o, u32bit i) + { + s2k = algo; + outlen = o; + iterations = i; + salt = s.bits_of(); - if(section == "Cipher Modes (Decryption)") - filter = lookup_cipher(algname, key, iv, false); - else - filter = lookup_cipher(algname, key, iv, true); - if(filter) return filter; + } + ~S2K_Filter() { delete s2k; } + private: + std::string passphrase; + S2K* s2k; + SecureVector<byte> salt; + u32bit outlen, iterations; + }; - filter = lookup_block(algname, key); - if(filter) return filter; - - filter = lookup_rng(algname, key); - if(filter) return filter; +/* Not too useful generally; just dumps random bits for benchmarking */ +class RNG_Filter : public Filter + { + public: + void write(const byte[], u32bit); - filter = lookup_encoder(algname); - if(filter) return filter; + RNG_Filter(RandomNumberGenerator* r) : rng(r) {} + ~RNG_Filter() { delete rng; } + private: + RandomNumberGenerator* rng; + }; - filter = lookup_hash(algname); - if(filter) return filter; +class KDF_Filter : public Filter + { + public: + void write(const byte in[], u32bit len) + { secret.append(in, len); } + void end_msg() + { + SymmetricKey x = kdf->derive_key(outlen, + secret, secret.size(), + salt, salt.size()); + send(x.bits_of(), x.length()); + } + KDF_Filter(KDF* algo, const SymmetricKey& s, u32bit o) + { + kdf = algo; + outlen = o; + salt = s.bits_of(); + } + ~KDF_Filter() { delete kdf; } + private: + SecureVector<byte> secret; + SecureVector<byte> salt; + KDF* kdf; + u32bit outlen; + }; - filter = lookup_mac(algname, key); - if(filter) return filter; +Filter* lookup_s2k(const std::string& algname, + const std::vector<std::string>& params) + { + S2K* s2k = 0; - filter = lookup_s2k(algname, params); - if(filter) return filter; + try { + s2k = get_s2k(algname); + } + catch(...) { } + if(s2k) + return new S2K_Filter(s2k, params[0], to_u32bit(params[1]), + to_u32bit(params[2])); return 0; } -Filter* lookup_hash(const std::string& algname) +void RNG_Filter::write(const byte[], u32bit length) { - Filter* hash = 0; - - try { - hash = new Hash_Filter(algname); + if(length) + { + SecureVector<byte> out(length); + rng->randomize(out, out.size()); + send(out); } - catch(Algorithm_Not_Found) {} - - return hash; } -Filter* lookup_mac(const std::string& algname, const std::string& key) +Filter* lookup_rng(const std::string& algname, + const std::string& key) { - Filter* mac = 0; - try { - mac = new MAC_Filter(algname, key); + RandomNumberGenerator* prng = 0; + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + if(algname == "AutoSeeded") + prng = new AutoSeeded_RNG; +#endif + +#if defined(BOTAN_HAS_X931_RNG) + if(algname == "X9.31-RNG(TripleDES)") + prng = new ANSI_X931_RNG(new TripleDES, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-128)") + prng = new ANSI_X931_RNG(new AES_128, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-192)") + prng = new ANSI_X931_RNG(new AES_192, + new Fixed_Output_RNG(decode_hex(key))); + else if(algname == "X9.31-RNG(AES-256)") + prng = new ANSI_X931_RNG(new AES_256, + new Fixed_Output_RNG(decode_hex(key))); +#endif + +#if defined(BOTAN_HAS_RANDPOOL) + if(algname == "Randpool") + { + prng = new Randpool(new AES_256, new HMAC(new SHA_256)); + + prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), + key.length()); + } +#endif + +#if defined(BOTAN_HAS_X931_RNG) + // these are used for benchmarking: AES-256/SHA-256 matches library + // defaults, so benchmark reflects real-world performance (maybe) + if(algname == "X9.31-RNG") + { + RandomNumberGenerator* rng = +#if defined(BOTAN_HAS_HMAC_RNG) + new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); +#elif defined(BOTAN_HAS_RANDPOOL) + new Randpool(new AES_256, new HMAC(new SHA_256)); +#endif + + prng = new ANSI_X931_RNG(new AES_256, rng); + + } +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + if(algname == "HMAC_RNG") + { + prng = new HMAC_RNG(new HMAC(new SHA_512), new HMAC(new SHA_256)); } - catch(Algorithm_Not_Found) {} +#endif - return mac; + if(prng) + { + prng->add_entropy(reinterpret_cast<const byte*>(key.c_str()), + key.length()); + return new RNG_Filter(prng); + } + + return 0; } -Filter* lookup_cipher(const std::string& algname, const std::string& key, - const std::string& iv, bool encrypt) +Filter* lookup_kdf(const std::string& algname, const std::string& salt, + const std::string& params) { + KDF* kdf = 0; try { - if(encrypt) - return get_cipher(algname, key, iv, ENCRYPTION); - else - return get_cipher(algname, key, iv, DECRYPTION); + kdf = get_kdf(algname); } - catch(Algorithm_Not_Found) {} - catch(Invalid_Algorithm_Name) {} + catch(...) { return 0; } + + if(kdf) + return new KDF_Filter(kdf, salt, to_u32bit(params)); return 0; } @@ -128,3 +252,28 @@ Filter* lookup_encoder(const std::string& algname) return 0; } + +Filter* lookup(const std::string& algname, + const std::vector<std::string>& params) + { + std::string key = params[0]; + std::string iv = params[1]; + Filter* filter = 0; + + // The order of the lookup has to change based on how the names are + // formatted and parsed. + filter = lookup_kdf(algname, key, iv); + if(filter) return filter; + + filter = lookup_rng(algname, key); + if(filter) return filter; + + filter = lookup_encoder(algname); + if(filter) return filter; + + filter = lookup_s2k(algname, params); + if(filter) return filter; + + return 0; + } + |