aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/unit_tls.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
committerJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
commitdfab07a7bc00dc00f98ab86c70d536306073f34f (patch)
treed3dbb140764f259c932171d6f229d033dee685ca /src/tests/unit_tls.cpp
parente29024608fca1b811aa72a7aafd930a42740b968 (diff)
parent1b9cf39063194fe91dc8e5d78f73d7251c5d16fc (diff)
Merge master into this branch, resolving conflicts with #457/#576
which recently landed on master.
Diffstat (limited to 'src/tests/unit_tls.cpp')
-rw-r--r--src/tests/unit_tls.cpp586
1 files changed, 346 insertions, 240 deletions
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index 1dbc20273..33c6c245e 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -1,5 +1,6 @@
/*
* (C) 2014,2015 Jack Lloyd
+* 2016 Matthias Gierlings
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -161,7 +162,11 @@ std::function<void (const byte[], size_t)> queue_inserter(std::vector<byte>& q)
return [&](const byte buf[], size_t sz) { q.insert(q.end(), buf, buf + sz); };
}
-void print_alert(Botan::TLS::Alert, const byte[], size_t)
+void print_alert(Botan::TLS::Alert)
+ {
+ }
+
+void alert_cb_with_data(Botan::TLS::Alert, const byte[], size_t)
{
}
@@ -219,164 +224,216 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version,
{
std::vector<byte> c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent;
- Botan::TLS::Server server(queue_inserter(s2c_traffic),
- queue_inserter(server_recv),
- print_alert,
- handshake_complete,
+ std::unique_ptr<Botan::TLS::Callbacks> server_cb(new Botan::TLS::Compat_Callbacks(
+ queue_inserter(s2c_traffic),
+ queue_inserter(server_recv),
+ std::function<void (Botan::TLS::Alert, const byte[], size_t)>(alert_cb_with_data),
+ handshake_complete,
+ nullptr,
+ next_protocol_chooser));
+
+ // TLS::Server object constructed by new constructor using virtual callback interface.
+ std::unique_ptr<Botan::TLS::Server> server(
+ new Botan::TLS::Server(*server_cb,
server_sessions,
creds,
server_policy,
rng,
- next_protocol_chooser,
- false);
+ false));
+
+ std::unique_ptr<Botan::TLS::Callbacks> client_cb(new Botan::TLS::Compat_Callbacks(
+ queue_inserter(c2s_traffic),
+ queue_inserter(client_recv),
+ std::function<void (Botan::TLS::Alert, const byte[], size_t)>(alert_cb_with_data),
+ handshake_complete));
- Botan::TLS::Client client(queue_inserter(c2s_traffic),
- queue_inserter(client_recv),
- print_alert,
- handshake_complete,
+ // TLS::Client object constructed by new constructor using virtual callback interface.
+ std::unique_ptr<Botan::TLS::Client> client(
+ new Botan::TLS::Client(*client_cb,
client_sessions,
creds,
client_policy,
rng,
Botan::TLS::Server_Information("server.example.com"),
offer_version,
- protocols_offered);
+ protocols_offered));
size_t rounds = 0;
- while(true)
+ // Test TLS using both new and legacy constructors.
+ for(size_t ctor_sel = 0; ctor_sel < 2; ctor_sel++)
{
- ++rounds;
-
- if(rounds > 25)
+ if(ctor_sel == 1)
{
- if(r <= 2)
- result.test_failure("Still here after many rounds, deadlock?");
- break;
+ c2s_traffic.clear();
+ s2c_traffic.clear();
+ server_recv.clear();
+ client_recv.clear();
+ client_sent.clear();
+ server_sent.clear();
+
+ // TLS::Server object constructed by legacy constructor.
+ server.reset(
+ new Botan::TLS::Server(queue_inserter(s2c_traffic),
+ queue_inserter(server_recv),
+ alert_cb_with_data,
+ handshake_complete,
+ server_sessions,
+ creds,
+ server_policy,
+ rng,
+ next_protocol_chooser,
+ false));
+
+ // TLS::Client object constructed by legacy constructor.
+ client.reset(
+ new Botan::TLS::Client(queue_inserter(c2s_traffic),
+ queue_inserter(client_recv),
+ alert_cb_with_data,
+ handshake_complete,
+ client_sessions,
+ creds,
+ server_policy,
+ rng,
+ Botan::TLS::Server_Information("server.example.com"),
+ offer_version,
+ protocols_offered));
}
- if(handshake_done && (client.is_closed() || server.is_closed()))
- break;
-
- if(client.is_active() && client_sent.empty())
+ while(true)
{
- // Choose a len between 1 and 511
- const size_t c_len = 1 + rng.next_byte() + rng.next_byte();
- client_sent = unlock(rng.random_vec(c_len));
+ ++rounds;
- // TODO send in several records
- client.send(client_sent);
- }
+ if(rounds > 25)
+ {
+ if(r <= 2)
+ result.test_failure("Still here after many rounds, deadlock?");
+ break;
+ }
- if(server.is_active() && server_sent.empty())
- {
- result.test_eq("server protocol", server.next_protocol(), "test/3");
+ if(handshake_done && (client->is_closed() || server->is_closed()))
+ break;
- const size_t s_len = 1 + rng.next_byte() + rng.next_byte();
- server_sent = unlock(rng.random_vec(s_len));
- server.send(server_sent);
- }
+ 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();
+ client_sent = unlock(rng.random_vec(c_len));
- const bool corrupt_client_data = (r == 3);
- const bool corrupt_server_data = (r == 4);
+ // TODO send in several records
+ client->send(client_sent);
+ }
- if(c2s_traffic.size() > 0)
- {
- /*
- * Use this as a temp value to hold the queues as otherwise they
- * might end up appending more in response to messages during the
- * handshake.
- */
- std::vector<byte> input;
- std::swap(c2s_traffic, input);
-
- if(corrupt_server_data)
+ if(server->is_active() && server_sent.empty())
{
- input = Test::mutate_vec(input, true);
- size_t needed = server.received_data(input.data(), input.size());
+ result.test_eq("server->protocol", server->next_protocol(), "test/3");
- size_t total_consumed = needed;
-
- while(needed > 0 &&
- result.test_lt("Never requesting more than max protocol len", needed, 18*1024) &&
- result.test_lt("Total requested is readonable", total_consumed, 128*1024))
- {
- input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
- needed = server.received_data(input.data(), input.size());
- total_consumed += needed;
- }
+ const size_t s_len = 1 + rng.next_byte() + rng.next_byte();
+ server_sent = unlock(rng.random_vec(s_len));
+ server->send(server_sent);
}
- else
+
+ const bool corrupt_client_data = (r == 3);
+ const bool corrupt_server_data = (r == 4);
+
+ if(c2s_traffic.size() > 0)
{
- size_t needed = server.received_data(input.data(), input.size());
- result.test_eq("full packet received", needed, 0);
- }
+ /*
+ * Use this as a temp value to hold the queues as otherwise they
+ * might end up appending more in response to messages during the
+ * handshake.
+ */
+ std::vector<byte> input;
+ std::swap(c2s_traffic, input);
+
+ if(corrupt_server_data)
+ {
+ input = Test::mutate_vec(input, true);
+ size_t needed = server->received_data(input.data(), input.size());
- continue;
- }
+ size_t total_consumed = needed;
- if(s2c_traffic.size() > 0)
- {
- std::vector<byte> input;
- std::swap(s2c_traffic, input);
+ while(needed > 0 &&
+ result.test_lt("Never requesting more than max protocol len", needed, 18*1024) &&
+ result.test_lt("Total requested is readonable", total_consumed, 128*1024))
+ {
+ input.resize(needed);
+ Test::rng().randomize(input.data(), input.size());
+ needed = server->received_data(input.data(), input.size());
+ total_consumed += needed;
+ }
+ }
+ else
+ {
+ size_t needed = server->received_data(input.data(), input.size());
+ result.test_eq("full packet received", needed, 0);
+ }
- if(corrupt_client_data)
+ continue;
+ }
+
+ if(s2c_traffic.size() > 0)
{
- input = Test::mutate_vec(input, true);
- size_t needed = client.received_data(input.data(), input.size());
+ std::vector<byte> input;
+ std::swap(s2c_traffic, input);
+
+ if(corrupt_client_data)
+ {
+ input = Test::mutate_vec(input, true);
+ size_t needed = client->received_data(input.data(), input.size());
- size_t total_consumed = 0;
+ size_t total_consumed = 0;
- while(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024))
+ 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());
+ needed = client->received_data(input.data(), input.size());
+ total_consumed += needed;
+ }
+ }
+ else
{
- input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
- needed = client.received_data(input.data(), input.size());
- total_consumed += needed;
+ size_t needed = client->received_data(input.data(), input.size());
+ result.test_eq("full packet received", needed, 0);
}
+
+ continue;
}
- else
+
+ if(client_recv.size())
{
- size_t needed = client.received_data(input.data(), input.size());
- result.test_eq("full packet received", needed, 0);
+ result.test_eq("client recv", client_recv, server_sent);
}
- continue;
- }
-
- if(client_recv.size())
- {
- result.test_eq("client recv", client_recv, server_sent);
- }
-
- if(server_recv.size())
- {
- result.test_eq("server recv", server_recv, client_sent);
- }
+ if(server_recv.size())
+ {
+ result.test_eq("server->recv", server_recv, client_sent);
+ }
- if(r > 2)
- {
- if(client_recv.size() && server_recv.size())
+ if(r > 2)
{
- result.test_failure("Negotiated in the face of data corruption " + std::to_string(r));
+ if(client_recv.size() && server_recv.size())
+ {
+ result.test_failure("Negotiated in the face of data corruption " + std::to_string(r));
+ }
}
- }
- if(client.is_closed() && server.is_closed())
- break;
+ if(client->is_closed() && server->is_closed())
+ break;
- if(server_recv.size() && client_recv.size())
- {
- Botan::SymmetricKey client_key = client.key_material_export("label", "context", 32);
- Botan::SymmetricKey server_key = server.key_material_export("label", "context", 32);
+ if(server_recv.size() && client_recv.size())
+ {
+ Botan::SymmetricKey client_key = client->key_material_export("label", "context", 32);
+ Botan::SymmetricKey server_key = server->key_material_export("label", "context", 32);
- result.test_eq("TLS key material export", client_key.bits_of(), server_key.bits_of());
+ result.test_eq("TLS key material export", client_key.bits_of(), server_key.bits_of());
- if(r % 2 == 0)
- client.close();
- else
- server.close();
+ if(r % 2 == 0)
+ client->close();
+ else
+ server->close();
+ }
}
}
}
@@ -453,183 +510,232 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version,
{
std::vector<byte> c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent;
- Botan::TLS::Server server(queue_inserter(s2c_traffic),
- queue_inserter(server_recv),
- print_alert,
- handshake_complete,
+ std::unique_ptr<Botan::TLS::Callbacks> server_cb(new Botan::TLS::Compat_Callbacks(
+ queue_inserter(s2c_traffic),
+ queue_inserter(server_recv),
+ std::function<void (Botan::TLS::Alert)>(print_alert),
+ handshake_complete,
+ nullptr,
+ next_protocol_chooser));
+
+ std::unique_ptr<Botan::TLS::Callbacks> client_cb(new Botan::TLS::Compat_Callbacks(
+ queue_inserter(c2s_traffic),
+ queue_inserter(client_recv),
+ std::function<void (Botan::TLS::Alert)>(print_alert),
+ handshake_complete));
+
+ // TLS::Server object constructed by new constructor using virtual callback interface.
+ std::unique_ptr<Botan::TLS::Server> server(
+ new Botan::TLS::Server(*server_cb,
server_sessions,
creds,
server_policy,
rng,
- next_protocol_chooser,
- true);
+ true));
- Botan::TLS::Client client(queue_inserter(c2s_traffic),
- queue_inserter(client_recv),
- print_alert,
- handshake_complete,
+ // TLS::Client object constructed by new constructor using virtual callback interface.
+ std::unique_ptr<Botan::TLS::Client> client(
+ new Botan::TLS::Client(*client_cb,
client_sessions,
creds,
client_policy,
rng,
Botan::TLS::Server_Information("server.example.com"),
offer_version,
- protocols_offered);
+ protocols_offered));
size_t rounds = 0;
- while(true)
+ // Test DTLS using both new and legacy constructors.
+ for(size_t ctor_sel = 0; ctor_sel < 2; ctor_sel++)
{
- // TODO: client and server should be in different threads
- std::this_thread::sleep_for(std::chrono::milliseconds(rng.next_byte() % 2));
- ++rounds;
-
- if(rounds > 100)
+ if(ctor_sel == 1)
{
- result.test_failure("Still here after many rounds");
- break;
+ c2s_traffic.clear();
+ s2c_traffic.clear();
+ server_recv.clear();
+ client_recv.clear();
+ client_sent.clear();
+ server_sent.clear();
+ // TLS::Server object constructed by legacy constructor.
+ server.reset(
+ new Botan::TLS::Server(queue_inserter(s2c_traffic),
+ queue_inserter(server_recv),
+ alert_cb_with_data,
+ handshake_complete,
+ server_sessions,
+ creds,
+ server_policy,
+ rng,
+ next_protocol_chooser,
+ true));
+
+ // TLS::Client object constructed by legacy constructor.
+ client.reset(
+ new Botan::TLS::Client(queue_inserter(c2s_traffic),
+ queue_inserter(client_recv),
+ alert_cb_with_data,
+ handshake_complete,
+ client_sessions,
+ creds,
+ client_policy,
+ rng,
+ Botan::TLS::Server_Information("server.example.com"),
+ offer_version,
+ protocols_offered));
}
- if(handshake_done && (client.is_closed() || server.is_closed()))
- break;
-
- if(client.is_active() && client_sent.empty())
+ while(true)
{
- // Choose a len between 1 and 511 and send random chunks:
- const size_t c_len = 1 + rng.next_byte() + rng.next_byte();
- client_sent = unlock(rng.random_vec(c_len));
+ // TODO: client and server should be in different threads
+ std::this_thread::sleep_for(std::chrono::milliseconds(rng.next_byte() % 2));
+ ++rounds;
- // TODO send multiple parts
- client.send(client_sent);
- }
-
- if(server.is_active() && server_sent.empty())
- {
- result.test_eq("server ALPN", server.next_protocol(), "test/3");
-
- const size_t s_len = 1 + rng.next_byte() + rng.next_byte();
- server_sent = unlock(rng.random_vec(s_len));
- server.send(server_sent);
- }
+ if(rounds > 100)
+ {
+ result.test_failure("Still here after many rounds");
+ break;
+ }
- const bool corrupt_client_data = (r == 3 && rng.next_byte() % 3 <= 1 && rounds < 10);
- const bool corrupt_server_data = (r == 4 && rng.next_byte() % 3 <= 1 && rounds < 10);
+ if(handshake_done && (client->is_closed() || server->is_closed()))
+ break;
- if(c2s_traffic.size() > 0)
- {
- /*
- * Use this as a temp value to hold the queues as otherwise they
- * might end up appending more in response to messages during the
- * handshake.
- */
- std::vector<byte> input;
- std::swap(c2s_traffic, input);
-
- if(corrupt_server_data)
+ if(client->is_active() && client_sent.empty())
{
- try
- {
- input = Test::mutate_vec(input, true);
- size_t needed = server.received_data(input.data(), input.size());
-
- 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());
- needed = client.received_data(input.data(), input.size());
- }
- }
- catch(std::exception&)
- {
- result.test_note("corruption caused server exception");
- }
+ // Choose a len between 1 and 511, todo use random chunks
+ const size_t c_len = 1 + rng.next_byte() + rng.next_byte();
+ client_sent = unlock(rng.random_vec(c_len));
+ client->send(client_sent);
}
- else
+
+ if(server->is_active() && server_sent.empty())
{
- try
- {
- size_t needed = server.received_data(input.data(), input.size());
- result.test_eq("full packet received", needed, 0);
- }
- catch(std::exception& e)
- {
- result.test_failure("server error", e.what());
- }
- }
+ result.test_eq("server ALPN", server->next_protocol(), "test/3");
- continue;
- }
+ const size_t s_len = 1 + rng.next_byte() + rng.next_byte();
+ server_sent = unlock(rng.random_vec(s_len));
+ server->send(server_sent);
+ }
- if(s2c_traffic.size() > 0)
- {
- std::vector<byte> input;
- std::swap(s2c_traffic, input);
+ const bool corrupt_client_data = (r == 3 && rng.next_byte() % 3 <= 1 && rounds < 10);
+ const bool corrupt_server_data = (r == 4 && rng.next_byte() % 3 <= 1 && rounds < 10);
- if(corrupt_client_data)
+ if(c2s_traffic.size() > 0)
{
- try
+ /*
+ * Use this as a temp value to hold the queues as otherwise they
+ * might end up appending more in response to messages during the
+ * handshake.
+ */
+ std::vector<byte> input;
+ std::swap(c2s_traffic, input);
+
+ if(corrupt_server_data)
{
- input = Test::mutate_vec(input, true);
- size_t needed = client.received_data(input.data(), input.size());
-
- if(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024))
+ try
{
- input.resize(needed);
- Test::rng().randomize(input.data(), input.size());
- needed = client.received_data(input.data(), input.size());
+ input = Test::mutate_vec(input, true);
+ size_t needed = server->received_data(input.data(), input.size());
+
+ 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());
+ client->received_data(input.data(), input.size());
+ }
+ }
+ catch(std::exception&)
+ {
+ result.test_note("corruption caused server exception");
}
}
- catch(std::exception&)
+ else
{
- result.test_note("corruption caused client exception");
+ try
+ {
+ size_t needed = server->received_data(input.data(), input.size());
+ result.test_eq("full packet received", needed, 0);
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure("server error", e.what());
+ }
}
+
+ continue;
}
- else
+
+ if(s2c_traffic.size() > 0)
{
- try
+ std::vector<byte> input;
+ std::swap(s2c_traffic, input);
+
+ if(corrupt_client_data)
{
- size_t needed = client.received_data(input.data(), input.size());
- result.test_eq("full packet received", needed, 0);
+ try
+ {
+ input = Test::mutate_vec(input, true);
+ size_t needed = client->received_data(input.data(), input.size());
+
+ 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());
+ client->received_data(input.data(), input.size());
+ }
+ }
+ catch(std::exception&)
+ {
+ result.test_note("corruption caused client exception");
+ }
}
- catch(std::exception& e)
+ else
{
- result.test_failure("client error", e.what());
+ try
+ {
+ size_t needed = client->received_data(input.data(), input.size());
+ result.test_eq("full packet received", needed, 0);
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure("client error", e.what());
+ }
}
- }
- continue;
- }
+ continue;
+ }
- // If we corrupted a DTLS application message, resend it:
- if(client.is_active() && corrupt_client_data && server_recv.empty())
- client.send(client_sent);
- if(server.is_active() && corrupt_server_data && client_recv.empty())
- server.send(server_sent);
+ // If we corrupted a DTLS application message, resend it:
+ if(client->is_active() && corrupt_client_data && server_recv.empty())
+ client->send(client_sent);
+ if(server->is_active() && corrupt_server_data && client_recv.empty())
+ server->send(server_sent);
- if(client_recv.size())
- {
- result.test_eq("client recv", client_recv, server_sent);
- }
+ if(client_recv.size())
+ {
+ result.test_eq("client recv", client_recv, server_sent);
+ }
- if(server_recv.size())
- {
- result.test_eq("server recv", server_recv, client_sent);
- }
+ if(server_recv.size())
+ {
+ result.test_eq("server recv", server_recv, client_sent);
+ }
- if(client.is_closed() && server.is_closed())
- break;
+ if(client->is_closed() && server->is_closed())
+ break;
- if(server_recv.size() && client_recv.size())
- {
- Botan::SymmetricKey client_key = client.key_material_export("label", "context", 32);
- Botan::SymmetricKey server_key = server.key_material_export("label", "context", 32);
+ if(server_recv.size() && client_recv.size())
+ {
+ Botan::SymmetricKey client_key = client->key_material_export("label", "context", 32);
+ Botan::SymmetricKey server_key = server->key_material_export("label", "context", 32);
- result.test_eq("key material export", client_key.bits_of(), server_key.bits_of());
+ result.test_eq("key material export", client_key.bits_of(), server_key.bits_of());
- if(r % 2 == 0)
- client.close();
- else
- server.close();
+ if(r % 2 == 0)
+ client->close();
+ else
+ server->close();
+ }
}
}
}