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 | |
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')
-rw-r--r-- | src/tests/data/modes/cbc.vec | 7 | ||||
-rw-r--r-- | src/tests/test_modes.cpp | 150 |
2 files changed, 91 insertions, 66 deletions
diff --git a/src/tests/data/modes/cbc.vec b/src/tests/data/modes/cbc.vec index 4767b7e50..30ca53f3e 100644 --- a/src/tests/data/modes/cbc.vec +++ b/src/tests/data/modes/cbc.vec @@ -1217,6 +1217,13 @@ Nonce = 000102030405060708090A0B0C0D0E0F In = 6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710 Out = F58C4C04D6E5F1BA779EABFB5F7BFBD69CFC4E967EDB808D679F777BC6702C7D39F23369A9D9BACFA530E26304231461B2EB05E2C39BE9FCDA6C19078C6A9D1B +# test empty nonce, must be equivalent to zero +[AES-128/CBC/NoPadding] +Key = 2B7E151628AED2A6ABF7158809CF4F3C +Nonce = +In = 6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710 +Out = 3AD77BB40D7A3660A89ECAF32466EF97B148C17F309EE692287AE57CF12ADD49C93D11BFAF08C5DC4D90B37B4DEE002BA7356E1207BB406639E5E5CEB9A9ED93 + # RFC 3962: Advanced Encryption Standard (AES) Encryption for Kerberos 5 [AES-128/CBC/CTS] Key = 636869636b656e207465726979616b69 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; } |