diff options
-rw-r--r-- | src/tests/unit_tls.cpp | 577 |
1 files changed, 326 insertions, 251 deletions
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index 621a803c8..919c3c950 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -219,24 +219,27 @@ 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(Botan::TLS::Callbacks( - queue_inserter(s2c_traffic), - queue_inserter(server_recv), + // TLS::Server object constructed by new constructor using virtual callback interface. + std::unique_ptr<Botan::TLS::Server> server( + new Botan::TLS::Server(Botan::TLS::Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + print_alert, + handshake_complete), + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + false)); + + // TLS::Client object constructed by new constructor using virtual callback interface. + std::unique_ptr<Botan::TLS::Client> client( + new Botan::TLS::Client(Botan::TLS::Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), print_alert, handshake_complete), - server_sessions, - creds, - policy, - rng, - next_protocol_chooser, - false); - - Botan::TLS::Callbacks client_callbacks(queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete); - Botan::TLS::Client client(client_callbacks, client_sessions, creds, policy, @@ -244,143 +247,177 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, Botan::TLS::Client::Properties( 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; + // TLS::Server object constructed by legacy constructor. + server = std::unique_ptr<Botan::TLS::Server>( + new Botan::TLS::Server(queue_inserter(s2c_traffic), + queue_inserter(server_recv), + print_alert, + handshake_complete, + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + false)); + + // TLS::Client object constructed by legacy constructor. + std::unique_ptr<Botan::TLS::Client> client( + new Botan::TLS::Client(queue_inserter(c2s_traffic), + queue_inserter(client_recv), + print_alert, + handshake_complete, + client_sessions, + creds, + 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()); - - size_t total_consumed = needed; + result.test_eq("server->protocol", server->next_protocol(), "test/3"); - 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); + } + + continue; + } - if(corrupt_client_data) + 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); - size_t total_consumed = 0; + if(corrupt_client_data) + { + input = Test::mutate_vec(input, true); + size_t needed = client->received_data(input.data(), input.size()); - while(needed > 0 && result.test_lt("Never requesting more than max protocol len", needed, 18*1024)) + size_t total_consumed = 0; + + 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(); + } } } } @@ -449,23 +486,27 @@ 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::Callbacks server_callbacks(queue_inserter(s2c_traffic), - queue_inserter(server_recv), - print_alert, - handshake_complete); - Botan::TLS::Server server(server_callbacks, - server_sessions, - creds, - policy, - rng, - next_protocol_chooser, - true); - - Botan::TLS::Callbacks client_callbacks(queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete); - Botan::TLS::Client client(client_callbacks, + // TLS::Server object constructed by new constructor using virtual callback interface. + std::unique_ptr<Botan::TLS::Server> server( + new Botan::TLS::Server(Botan::TLS::Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + print_alert, + handshake_complete), + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + true)); + + // TLS::Client object constructed by new constructor using virtual callback interface. + std::unique_ptr<Botan::TLS::Client> client( + new Botan::TLS::Client(Botan::TLS::Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), + print_alert, + handshake_complete), client_sessions, creds, policy, @@ -473,162 +514,196 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, Botan::TLS::Client::Properties( 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; + // TLS::Server object constructed by legacy constructor. + server = std::unique_ptr<Botan::TLS::Server>( + new Botan::TLS::Server(queue_inserter(s2c_traffic), + queue_inserter(server_recv), + print_alert, + handshake_complete, + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + true)); + + // TLS::Client object constructed by legacy constructor. + std::unique_ptr<Botan::TLS::Client> client( + new Botan::TLS::Client(queue_inserter(c2s_traffic), + queue_inserter(client_recv), + print_alert, + handshake_complete, + client_sessions, + creds, + 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()); + // 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)); - 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"); - } + // TODO send multiple parts + 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()); - 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(); + } } } } |