aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
authorAlexander Bluhm <[email protected]>2017-04-03 18:00:54 +0200
committerAlexander Bluhm <[email protected]>2017-04-25 15:50:33 +0200
commita9b91783b734d0cb1b3515f091564d126218275f (patch)
tree6ea2804824dc3286865cdd368952c3922171a3eb /src/tests
parent3a560e25b2ab197e54935eb047090446be6c10f5 (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.vec7
-rw-r--r--src/tests/test_modes.cpp150
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;
}