aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/unit_tls.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-09-19 10:02:41 -0400
committerJack Lloyd <[email protected]>2016-10-07 15:56:32 -0400
commit13c9dce65807785f9d0d0f33b94803f9807a009b (patch)
tree168b9efe0b40303a362993621d4f73acc38e6d2e /src/tests/unit_tls.cpp
parent36220cebaae551f3e7c22e2abd8a8ce848e56892 (diff)
TLS: Split CBC+HMAC modes to standalone AEAD_Mode
Now record layer only deals with an AEAD, and the weird complications of CBC modes mostly hidden in tls_cbc.cpp
Diffstat (limited to 'src/tests/unit_tls.cpp')
-rw-r--r--src/tests/unit_tls.cpp283
1 files changed, 167 insertions, 116 deletions
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index 5ae24ba81..f869f426b 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -118,9 +118,10 @@ class Credentials_Manager_Test : public Botan::Credentials_Manager
bool m_provides_client_certs;
};
-Botan::Credentials_Manager* create_creds(bool client_type)
+Botan::Credentials_Manager* create_creds(Botan::RandomNumberGenerator& rng,
+ bool with_client_certs = false)
{
- std::unique_ptr<Botan::Private_Key> ca_key(new Botan::RSA_PrivateKey(Test::rng(), 1024));
+ std::unique_ptr<Botan::Private_Key> ca_key(new Botan::RSA_PrivateKey(rng, 1024));
Botan::X509_Cert_Options ca_opts;
ca_opts.common_name = "Test CA";
@@ -131,9 +132,9 @@ Botan::Credentials_Manager* create_creds(bool client_type)
Botan::X509::create_self_signed_cert(ca_opts,
*ca_key,
"SHA-256",
- Test::rng());
+ rng);
- Botan::Private_Key* server_key = new Botan::RSA_PrivateKey(Test::rng(), 1024);
+ Botan::Private_Key* server_key = new Botan::RSA_PrivateKey(rng, 1024);
Botan::X509_Cert_Options server_opts;
server_opts.common_name = "server.example.com";
@@ -142,7 +143,7 @@ Botan::Credentials_Manager* create_creds(bool client_type)
Botan::PKCS10_Request req = Botan::X509::create_cert_req(server_opts,
*server_key,
"SHA-256",
- Test::rng());
+ rng);
Botan::X509_CA ca(ca_cert, *ca_key, "SHA-256");
@@ -152,12 +153,12 @@ Botan::Credentials_Manager* create_creds(bool client_type)
Botan::X509_Time end_time(now + years(1));
Botan::X509_Certificate server_cert = ca.sign_request(req,
- Test::rng(),
+ rng,
start_time,
end_time);
Credentials_Manager_Test* cmt (new Credentials_Manager_Test(server_cert, ca_cert, server_key));
- cmt->m_provides_client_certs = client_type;
+ cmt->m_provides_client_certs = with_client_certs;
return cmt;
}
@@ -176,11 +177,10 @@ void alert_cb_with_data(Botan::TLS::Alert, const byte[], size_t)
Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
Botan::Credentials_Manager& creds,
- Botan::TLS::Policy& client_policy,
- Botan::TLS::Policy& server_policy )
+ const Botan::TLS::Policy& client_policy,
+ const Botan::TLS::Policy& server_policy,
+ Botan::RandomNumberGenerator& rng)
{
- Botan::RandomNumberGenerator& rng = Test::rng();
-
Botan::TLS::Session_Manager_In_Memory server_sessions(rng);
Botan::TLS::Session_Manager_In_Memory client_sessions(rng);
@@ -197,9 +197,12 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
auto handshake_complete = [&](const Botan::TLS::Session& session) -> bool {
handshake_done = true;
- result.test_note("Session established " + session.version().to_string() + " " +
- session.ciphersuite().to_string() + " " +
- Botan::hex_encode(session.session_id()));
+ const std::string session_report =
+ "Session established " + session.version().to_string() + " " +
+ session.ciphersuite().to_string() + " " +
+ Botan::hex_encode(session.session_id());
+
+ result.test_note(session_report);
if(session.version() != offer_version)
{
@@ -311,7 +314,9 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
if(rounds > 25)
{
if(r <= 2)
+ {
result.test_failure("Still here after many rounds, deadlock?");
+ }
break;
}
@@ -320,21 +325,39 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
if(client->is_active() && client_sent.empty())
{
- // Choose a len between 1 and 511
- const size_t c_len = 1 + rng.next_byte() + rng.next_byte();
+ // Choose random application data to send
+ const size_t c_len = 1 + (static_cast<size_t>(rng.next_byte()) << 4) ^ rng.next_byte();
client_sent = unlock(rng.random_vec(c_len));
- // TODO send in several records
- client->send(client_sent);
+ size_t sent_so_far = 0;
+ while(sent_so_far != client_sent.size())
+ {
+ const size_t left = client_sent.size() - sent_so_far;
+ const size_t rnd12 = (rng.next_byte() << 4) ^ rng.next_byte();
+ const size_t sending = std::min(left, rnd12);
+
+ client->send(&client_sent[sent_so_far], sending);
+ sent_so_far += sending;
+ }
}
if(server->is_active() && server_sent.empty())
{
result.test_eq("server->protocol", server->next_protocol(), "test/3");
- const size_t s_len = 1 + rng.next_byte() + rng.next_byte();
+ const size_t s_len = 1 + (static_cast<size_t>(rng.next_byte()) << 4) ^ rng.next_byte();
server_sent = unlock(rng.random_vec(s_len));
- server->send(server_sent);
+
+ size_t sent_so_far = 0;
+ while(sent_so_far != server_sent.size())
+ {
+ const size_t left = server_sent.size() - sent_so_far;
+ const size_t rnd12 = (rng.next_byte() << 4) ^ rng.next_byte();
+ const size_t sending = std::min(left, rnd12);
+
+ server->send(&server_sent[sent_so_far], sending);
+ sent_so_far += sending;
+ }
}
const bool corrupt_client_data = (r == 3);
@@ -362,7 +385,7 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
result.test_lt("Total requested is readonable", total_consumed, 128*1024))
{
input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
+ rng.randomize(input.data(), input.size());
needed = server->received_data(input.data(), input.size());
total_consumed += needed;
}
@@ -391,7 +414,7 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
while(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024))
{
input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
+ rng.randomize(input.data(), input.size());
needed = client->received_data(input.data(), input.size());
total_consumed += needed;
}
@@ -461,20 +484,20 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
Botan::Credentials_Manager& creds,
- Botan::TLS::Policy& policy )
+ const Botan::TLS::Policy& policy,
+ Botan::RandomNumberGenerator& rng)
{
- return test_tls_handshake(offer_version, creds, policy, policy);
+ return test_tls_handshake(offer_version, creds, policy, policy, rng);
}
Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
Botan::Credentials_Manager& creds,
- Botan::TLS::Policy& client_policy,
- Botan::TLS::Policy& server_policy )
+ const Botan::TLS::Policy& client_policy,
+ const Botan::TLS::Policy& server_policy,
+ Botan::RandomNumberGenerator& rng)
{
BOTAN_ASSERT(offer_version.is_datagram_protocol(), "Test is for datagram version");
- Botan::RandomNumberGenerator& rng = Test::rng();
-
Botan::TLS::Session_Manager_In_Memory server_sessions(rng);
Botan::TLS::Session_Manager_In_Memory client_sessions(rng);
@@ -592,7 +615,7 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
while(true)
{
// TODO: client and server should be in different threads
- std::this_thread::sleep_for(std::chrono::milliseconds(rng.next_byte() % 2));
+ std::this_thread::sleep_for(std::chrono::microseconds(rng.next_byte() % 128));
++rounds;
if(rounds > 100)
@@ -644,7 +667,7 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
if(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024))
{
input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
+ rng.randomize(input.data(), input.size());
client->received_data(input.data(), input.size());
}
}
@@ -684,7 +707,7 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
if(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024))
{
input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
+ rng.randomize(input.data(), input.size());
client->received_data(input.data(), input.size());
}
}
@@ -761,10 +784,11 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
}
Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
- Botan::Credentials_Manager& creds,
- Botan::TLS::Policy& policy)
+ Botan::Credentials_Manager& creds,
+ const Botan::TLS::Policy& policy,
+ Botan::RandomNumberGenerator& rng)
{
- return test_dtls_handshake(offer_version, creds, policy, policy);
+ return test_dtls_handshake(offer_version, creds, policy, policy, rng);
}
class Test_Policy : public Botan::TLS::Text_Policy
@@ -781,104 +805,131 @@ class Test_Policy : public Botan::TLS::Text_Policy
};
+
class TLS_Unit_Tests : public Test
{
+ private:
+ void test_with_policy(std::vector<Test::Result>& results,
+ const std::vector<Botan::TLS::Protocol_Version>& versions,
+ Botan::Credentials_Manager& creds,
+ const Botan::TLS::Policy& policy)
+ {
+ Botan::RandomNumberGenerator& rng = Test::rng();
+
+ for(auto&& version : versions)
+ {
+ if(version.is_datagram_protocol())
+ results.push_back(test_dtls_handshake(version, creds, policy, rng));
+ else
+ results.push_back(test_tls_handshake(version, creds, policy, rng));
+ }
+ }
+
+ void test_all_versions(std::vector<Test::Result>& results,
+ Botan::Credentials_Manager& creds,
+ const std::string& kex_policy,
+ const std::string& cipher_policy,
+ const std::string& mac_policy,
+ const std::string& etm_policy)
+ {
+ Test_Policy policy;
+ policy.set("ciphers", cipher_policy);
+ policy.set("macs", mac_policy);
+ policy.set("key_exchange_methods", kex_policy);
+ policy.set("negotiate_encrypt_then_mac", etm_policy);
+
+ std::vector<Botan::TLS::Protocol_Version> versions = {
+ Botan::TLS::Protocol_Version::TLS_V10,
+ Botan::TLS::Protocol_Version::TLS_V11,
+ Botan::TLS::Protocol_Version::TLS_V12,
+ Botan::TLS::Protocol_Version::DTLS_V10,
+ Botan::TLS::Protocol_Version::DTLS_V12
+ };
+
+ return test_with_policy(results, versions, creds, policy);
+ }
+
+ void test_modern_versions(std::vector<Test::Result>& results,
+ Botan::Credentials_Manager& creds,
+ const std::string& kex_policy,
+ const std::string& cipher_policy,
+ const std::string& mac_policy = "AEAD",
+ const std::map<std::string, std::string>& extra_policies = {})
+ {
+ Test_Policy policy;
+ policy.set("ciphers", cipher_policy);
+ policy.set("macs", mac_policy);
+ policy.set("key_exchange_methods", kex_policy);
+
+ for(auto&& kv : extra_policies)
+ policy.set(kv.first, kv.second);
+
+ std::vector<Botan::TLS::Protocol_Version> versions = {
+ Botan::TLS::Protocol_Version::TLS_V12,
+ Botan::TLS::Protocol_Version::DTLS_V12
+ };
+
+ return test_with_policy(results, versions, creds, policy);
+ }
+
public:
std::vector<Test::Result> run() override
{
- std::unique_ptr<Botan::Credentials_Manager> basic_creds(create_creds(false));
- std::unique_ptr<Botan::Credentials_Manager> basic_creds_with_client_cert(create_creds(true));
+ Botan::RandomNumberGenerator& rng = Test::rng();
+
+ std::unique_ptr<Botan::Credentials_Manager> creds(create_creds(rng));
std::vector<Test::Result> results;
- Test_Policy policy;
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V10, *basic_creds, policy));
-
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V11, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V10, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- policy.set("key_exchange_methods", "RSA");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V10, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V11, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V10, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- policy.set("key_exchange_methods", "DH");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V10, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V11, *basic_creds, policy));
-
- policy.set("key_exchange_methods", "ECDH");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V10, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- policy.set("ciphers", "AES-128");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V10, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V11, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V10, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds_with_client_cert, policy));
+ for(std::string etm_setting : { "true", "false" })
+ {
+ test_all_versions(results, *creds, "RSA", "AES-128", "SHA-256 SHA-1", etm_setting);
+ test_all_versions(results, *creds, "ECDH", "AES-128", "SHA-256 SHA-1", etm_setting);
+
+ test_all_versions(results, *creds, "RSA", "AES-256", "SHA-1", etm_setting);
+ test_all_versions(results, *creds, "ECDH", "AES-256", "SHA-1", etm_setting);
+
+#if defined(BOTAN_HAS_CAMELLIA)
+ test_all_versions(results, *creds, "RSA", "Camellia-128", "SHA-256", etm_setting);
+ test_all_versions(results, *creds, "ECDH", "Camellia-256", "SHA-256 SHA-384", etm_setting);
+#endif
+
+#if defined(BOTAN_HAS_DES)
+ test_all_versions(results, *creds, "RSA", "3DES", "SHA-1", etm_setting);
+ test_all_versions(results, *creds, "ECDH", "3DES", "SHA-1", etm_setting);
+#endif
+
+#if defined(BOTAN_HAS_SEED)
+ test_all_versions(results, *creds, "RSA", "SEED", "SHA-1", etm_setting);
+#endif
+ }
+
+ test_modern_versions(results, *creds, "DH", "AES-128", "SHA-256");
+ test_modern_versions(results, *creds, "RSA", "AES-128/GCM");
+ test_modern_versions(results, *creds, "ECDH", "AES-128/GCM");
+ test_modern_versions(results, *creds, "ECDH", "AES-128/GCM", "AEAD",
+ { { "use_ecc_point_compression", "true" } });
+
+ std::unique_ptr<Botan::Credentials_Manager> creds_with_client_cert(create_creds(rng, true));
+ test_modern_versions(results, *creds_with_client_cert, "ECDH", "AES-256/GCM");
#if defined(BOTAN_HAS_AEAD_OCB)
- policy.set("ciphers", "AES-128/OCB(12)");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
+ test_modern_versions(results, *creds, "ECDH", "AES-128/OCB(12)");
#endif
#if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
- policy.set("ciphers", "ChaCha20Poly1305");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
+ test_modern_versions(results, *creds, "ECDH", "ChaCha20Poly1305");
#endif
- policy.set("ciphers", "AES-128/GCM");
- policy.set("key_exchange_methods", "PSK");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
+ test_modern_versions(results, *creds, "PSK", "AES-128/GCM");
+
+#if defined(BOTAN_HAS_CCM)
+ test_modern_versions(results, *creds, "PSK", "AES-128/CCM");
+ test_modern_versions(results, *creds, "PSK", "AES-128/CCM(8)");
+#endif
// For whatever reason no (EC)DHE_PSK GCM ciphersuites are defined
- policy.set("ciphers", "AES-128");
- policy.set("key_exchange_methods", "ECDHE_PSK");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- policy.set("key_exchange_methods", "DHE_PSK");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- policy.set("negotiate_encrypt_then_mac", "false");
- policy.set("key_exchange_methods", "ECDH");
- policy.set("ciphers", "AES-128");
- Test_Policy server_policy;
- server_policy.set("key_exchange_methods", "ECDH");
- server_policy.set("ciphers", "AES-128");
- server_policy.set("negotiate_encrypt_then_mac", "true");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V10, *basic_creds, policy, server_policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V11, *basic_creds, policy, server_policy));
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy, server_policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V10, *basic_creds, policy, server_policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy, server_policy));
-
- policy.set("negotiate_encrypt_then_mac", "true");
- policy.set("ciphers", "AES-128/GCM");
- server_policy.set("ciphers", "AES-128/GCM");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy, server_policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy, server_policy));
-
- policy.set("use_ecc_point_compression", "true");
- policy.set("key_exchange_methods", "ECDH");
- policy.set("ciphers", "AES-128");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy));
-
- server_policy.set("use_ecc_point_compression", "true");
- server_policy.set("key_exchange_methods", "ECDH");
- server_policy.set("ciphers", "AES-128");
- results.push_back(test_tls_handshake(Botan::TLS::Protocol_Version::TLS_V12, *basic_creds, policy, server_policy));
- results.push_back(test_dtls_handshake(Botan::TLS::Protocol_Version::DTLS_V12, *basic_creds, policy, server_policy));
+ test_modern_versions(results, *creds, "ECDHE_PSK", "AES-128", "SHA-256");
+ test_modern_versions(results, *creds, "DHE_PSK", "AES-128", "SHA-1");
return results;
}