diff options
author | Alexander Bluhm <[email protected]> | 2017-04-03 18:00:54 +0200 |
---|---|---|
committer | Alexander Bluhm <[email protected]> | 2017-04-25 15:50:33 +0200 |
commit | a9b91783b734d0cb1b3515f091564d126218275f (patch) | |
tree | 6ea2804824dc3286865cdd368952c3922171a3eb /src/tests/test_modes.cpp | |
parent | 3a560e25b2ab197e54935eb047090446be6c10f5 (diff) |
Implement cipher modes with OpenSSL.
Use the OpenSSL provider to implement AES CBC mode. Also pass down
the provider to the encryption layer if there is no matching OpenSSL
mode. Add a test with empty nonce.
Diffstat (limited to 'src/tests/test_modes.cpp')
-rw-r--r-- | src/tests/test_modes.cpp | 150 |
1 files changed, 84 insertions, 66 deletions
diff --git a/src/tests/test_modes.cpp b/src/tests/test_modes.cpp index 480b15527..63edba5f1 100644 --- a/src/tests/test_modes.cpp +++ b/src/tests/test_modes.cpp @@ -22,6 +22,11 @@ class Cipher_Mode_Tests : public Text_Based_Test Text_Based_Test("modes", "Key,Nonce,In,Out") {} + std::vector<std::string> possible_providers(const std::string& algo) override + { + return provider_filter(Botan::Cipher_Mode::providers(algo)); + } + Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { const std::vector<uint8_t> key = get_req_bin(vars, "Key"); @@ -31,102 +36,115 @@ class Cipher_Mode_Tests : public Text_Based_Test Test::Result result(algo); - std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode(algo, Botan::ENCRYPTION)); - std::unique_ptr<Botan::Cipher_Mode> dec(Botan::get_cipher_mode(algo, Botan::DECRYPTION)); + const std::vector<std::string> providers = possible_providers(algo); - if(!enc || !dec) + if(providers.empty()) { - result.note_missing(algo); + result.note_missing("cipher mode " + algo); return result; } - result.test_is_nonempty("provider", enc->provider()); - result.test_eq("name", enc->name(), algo); - - result.test_eq("mode not authenticated", enc->authenticated(), false); + for(auto&& provider_ask : providers) + { + std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode( + algo, Botan::ENCRYPTION, provider_ask)); + std::unique_ptr<Botan::Cipher_Mode> dec(Botan::get_cipher_mode( + algo, Botan::DECRYPTION, provider_ask)); - // Test to make sure reset() resets what we need it to - enc->set_key(mutate_vec(key)); - Botan::secure_vector<uint8_t> garbage = Test::rng().random_vec(enc->update_granularity()); - enc->start(mutate_vec(nonce)); - enc->update(garbage); + if(!enc || !dec) + { + result.note_missing(algo); + return result; + } - enc->reset(); + result.test_is_nonempty("provider", enc->provider()); + result.test_eq("name", enc->name(), algo); - enc->set_key(key); - enc->start(nonce); + result.test_eq("mode not authenticated", enc->authenticated(), false); - Botan::secure_vector<uint8_t> buf(input.begin(), input.end()); - // TODO: should first update if possible - enc->finish(buf); - result.test_eq("encrypt", buf, expected); + // Test to make sure reset() resets what we need it to + enc->set_key(mutate_vec(key)); + Botan::secure_vector<uint8_t> garbage = Test::rng().random_vec(enc->update_granularity()); + enc->start(mutate_vec(nonce)); + enc->update(garbage); - // additionally test process() if possible - size_t update_granularity = enc->update_granularity(); - size_t input_length = input.size(); - size_t min_final_bytes = enc->minimum_final_size(); - if(input_length > (update_granularity + min_final_bytes)) - { - // reset state first enc->reset(); + enc->set_key(key); enc->start(nonce); - buf.assign(input.begin(), input.end()); - // we can process at max input_length - const size_t max_blocks_to_process = (input_length - min_final_bytes) / update_granularity; - const size_t bytes_to_process = max_blocks_to_process * update_granularity; + Botan::secure_vector<uint8_t> buf(input.begin(), input.end()); + // TODO: should first update if possible + enc->finish(buf); + result.test_eq("encrypt", buf, expected); - const size_t bytes_written = enc->process(buf.data(), bytes_to_process); + // additionally test process() if possible + size_t update_granularity = enc->update_granularity(); + size_t input_length = input.size(); + size_t min_final_bytes = enc->minimum_final_size(); + if(input_length > (update_granularity + min_final_bytes)) + { + // reset state first + enc->reset(); - result.test_eq("correct number of bytes processed", bytes_written, bytes_to_process); + enc->start(nonce); + buf.assign(input.begin(), input.end()); - enc->finish(buf, bytes_to_process); - result.test_eq("encrypt", buf, expected); - } + // we can process at max input_length + const size_t max_blocks_to_process = (input_length - min_final_bytes) / update_granularity; + const size_t bytes_to_process = max_blocks_to_process * update_granularity; - // decryption - buf.assign(expected.begin(), expected.end()); + const size_t bytes_written = enc->process(buf.data(), bytes_to_process); - // Test to make sure reset() resets what we need it to - dec->set_key(mutate_vec(key)); - garbage = Test::rng().random_vec(dec->update_granularity()); - dec->start(mutate_vec(nonce)); - dec->update(garbage); + result.test_eq("correct number of bytes processed", bytes_written, bytes_to_process); - dec->reset(); + enc->finish(buf, bytes_to_process); + result.test_eq("encrypt", buf, expected); + } - dec->set_key(key); - dec->start(nonce); - dec->finish(buf); - result.test_eq("decrypt", buf, input); + // decryption + buf.assign(expected.begin(), expected.end()); + + // Test to make sure reset() resets what we need it to + dec->set_key(mutate_vec(key)); + garbage = Test::rng().random_vec(dec->update_granularity()); + dec->start(mutate_vec(nonce)); + dec->update(garbage); - // additionally test process() if possible - update_granularity = dec->update_granularity(); - input_length = expected.size(); - min_final_bytes = dec->minimum_final_size(); - if(input_length > (update_granularity + min_final_bytes)) - { - // reset state first dec->reset(); + dec->set_key(key); dec->start(nonce); - buf.assign(expected.begin(), expected.end()); + dec->finish(buf); + result.test_eq("decrypt", buf, input); - // we can process at max input_length - const size_t max_blocks_to_process = (input_length - min_final_bytes) / update_granularity; - const size_t bytes_to_process = max_blocks_to_process * update_granularity; + // additionally test process() if possible + update_granularity = dec->update_granularity(); + input_length = expected.size(); + min_final_bytes = dec->minimum_final_size(); + if(input_length > (update_granularity + min_final_bytes)) + { + // reset state first + dec->reset(); - const size_t bytes_written = dec->process(buf.data(), bytes_to_process); + dec->start(nonce); + buf.assign(expected.begin(), expected.end()); - result.test_eq("correct number of bytes processed", bytes_written, bytes_to_process); + // we can process at max input_length + const size_t max_blocks_to_process = (input_length - min_final_bytes) / update_granularity; + const size_t bytes_to_process = max_blocks_to_process * update_granularity; - dec->finish(buf, bytes_to_process); - result.test_eq("decrypt", buf, input); - } + const size_t bytes_written = dec->process(buf.data(), bytes_to_process); + + result.test_eq("correct number of bytes processed", bytes_written, bytes_to_process); - enc->clear(); - dec->clear(); + dec->finish(buf, bytes_to_process); + result.test_eq("decrypt", buf, input); + } + + enc->clear(); + dec->clear(); + } return result; } |