1 /*
2 * (C) 2014,2015,2018 Jack Lloyd
3 * 2016 Matthias Gierlings
4 * 2017 René Korthaus, Rohde & Schwarz Cybersecurity
5 * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6 *
7 * Botan is released under the Simplified BSD License (see license.txt)
8 */
9
10 #include "tests.h"
11 #include <vector>
12 #include <memory>
13
14 #if defined(BOTAN_HAS_TLS)
15
16 #include <botan/tls_client.h>
17 #include <botan/tls_server.h>
18 #include <botan/tls_policy.h>
19 #include <botan/tls_extensions.h>
20 #include <botan/internal/tls_reader.h>
21
22 #include <botan/ec_group.h>
23 #include <botan/hex.h>
24 #include <botan/oids.h>
25 #include <botan/pkcs10.h>
26 #include <botan/rsa.h>
27 #include <botan/ecdsa.h>
28 #include <botan/x509_ca.h>
29 #include <botan/x509self.h>
30
31 #if defined(BOTAN_HAS_DSA)
32 #include <botan/dsa.h>
33 #endif
34
35 #if defined(BOTAN_HAS_SRP6)
36 #include <botan/srp6.h>
37 #endif
38
39 #if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
40 #include <botan/tls_session_manager_sqlite.h>
41 #endif
42
43 #endif
44
45 namespace Botan_Tests {
46
47 namespace {
48
49 #if defined(BOTAN_HAS_TLS)
50 class Credentials_Manager_Test final : public Botan::Credentials_Manager
51 {
52 public:
Credentials_Manager_Test(bool with_client_certs,const Botan::X509_Certificate & rsa_cert,Botan::Private_Key * rsa_key,const Botan::X509_Certificate & rsa_ca,const Botan::X509_CRL & rsa_crl,const Botan::X509_Certificate & ecdsa_cert,Botan::Private_Key * ecdsa_key,const Botan::X509_Certificate & ecdsa_ca,const Botan::X509_CRL & ecdsa_crl,const Botan::X509_Certificate * dsa_cert,Botan::Private_Key * dsa_key,const Botan::X509_Certificate * dsa_ca,Botan::X509_CRL * dsa_crl)53 Credentials_Manager_Test(bool with_client_certs,
54 const Botan::X509_Certificate& rsa_cert,
55 Botan::Private_Key* rsa_key,
56 const Botan::X509_Certificate& rsa_ca,
57 const Botan::X509_CRL& rsa_crl,
58 const Botan::X509_Certificate& ecdsa_cert,
59 Botan::Private_Key* ecdsa_key,
60 const Botan::X509_Certificate& ecdsa_ca,
61 const Botan::X509_CRL& ecdsa_crl,
62 const Botan::X509_Certificate* dsa_cert,
63 Botan::Private_Key* dsa_key,
64 const Botan::X509_Certificate* dsa_ca,
65 Botan::X509_CRL* dsa_crl) :
66 m_rsa_cert(rsa_cert),
67 m_rsa_ca(rsa_ca),
68 m_rsa_key(rsa_key),
69 m_ecdsa_cert(ecdsa_cert),
70 m_ecdsa_ca(ecdsa_ca),
71 m_ecdsa_key(ecdsa_key),
72 m_dsa_cert(dsa_cert),
73 m_dsa_ca(dsa_ca),
74 m_dsa_key(dsa_key),
75 m_dsa_crl(dsa_crl)
76 {
77 std::unique_ptr<Botan::Certificate_Store_In_Memory> store(new Botan::Certificate_Store_In_Memory);
78 store->add_certificate(m_rsa_ca);
79 store->add_certificate(m_ecdsa_ca);
80 store->add_crl(rsa_crl);
81 store->add_crl(ecdsa_crl);
82
83 if(m_dsa_ca != nullptr)
84 {
85 store->add_certificate(*m_dsa_ca);
86 }
87 if(m_dsa_crl != nullptr)
88 {
89 store->add_crl(*m_dsa_crl);
90 }
91
92 m_stores.push_back(std::move(store));
93 m_provides_client_certs = with_client_certs;
94 }
95
96 std::vector<Botan::Certificate_Store*>
trusted_certificate_authorities(const std::string &,const std::string &)97 trusted_certificate_authorities(const std::string&,
98 const std::string&) override
99 {
100 std::vector<Botan::Certificate_Store*> v;
101 for(auto const& store : m_stores)
102 {
103 v.push_back(store.get());
104 }
105 return v;
106 }
107
find_cert_chain(const std::vector<std::string> & cert_key_types,const std::vector<Botan::X509_DN> & acceptable_CAs,const std::string & type,const std::string & context)108 std::vector<Botan::X509_Certificate> find_cert_chain(
109 const std::vector<std::string>& cert_key_types,
110 const std::vector<Botan::X509_DN>& acceptable_CAs,
111 const std::string& type,
112 const std::string& context) override
113 {
114 std::vector<Botan::X509_Certificate> chain;
115
116 if(m_acceptable_cas.empty())
117 m_acceptable_cas = acceptable_CAs;
118
119 if(type == "tls-server" || (type == "tls-client" && m_provides_client_certs))
120 {
121 for(auto const& key_type : cert_key_types)
122 {
123 if(key_type == "RSA")
124 {
125 chain.push_back(m_rsa_cert);
126 chain.push_back(m_rsa_ca);
127 break;
128 }
129 else if(key_type == "ECDSA")
130 {
131 chain.push_back(m_ecdsa_cert);
132 chain.push_back(m_ecdsa_ca);
133 break;
134 }
135 #if defined(BOTAN_HAS_DSA)
136 else if(key_type == "DSA")
137 {
138 if(m_dsa_cert == nullptr || m_dsa_ca == nullptr)
139 {
140 throw Test_Error("No DSA certificates set for " + type + "/" + context);
141 }
142 chain.push_back(*m_dsa_cert);
143 chain.push_back(*m_dsa_ca);
144 break;
145 }
146 #else
147 BOTAN_UNUSED(context);
148 #endif
149 }
150 }
151
152 return chain;
153 }
154
private_key_for(const Botan::X509_Certificate & crt,const std::string &,const std::string &)155 Botan::Private_Key* private_key_for(const Botan::X509_Certificate& crt,
156 const std::string&,
157 const std::string&) override
158 {
159 if(crt == m_rsa_cert)
160 {
161 return m_rsa_key.get();
162 }
163 if(crt == m_ecdsa_cert)
164 {
165 return m_ecdsa_key.get();
166 }
167 if(crt == *m_dsa_cert)
168 {
169 return m_dsa_key.get();
170 }
171 return nullptr;
172 }
173
psk(const std::string & type,const std::string & context,const std::string &)174 Botan::SymmetricKey psk(const std::string& type,
175 const std::string& context,
176 const std::string&) override
177 {
178 if(type == "tls-server" && context == "session-ticket")
179 {
180 return Botan::SymmetricKey("AABBCCDDEEFF012345678012345678");
181 }
182
183 if(type == "tls-server" && context == "dtls-cookie-secret")
184 {
185 return Botan::SymmetricKey("4AEA5EAD279CADEB537A594DA0E9DE3A");
186 }
187
188 if(context == "server.example.com" && type == "tls-client")
189 {
190 return Botan::SymmetricKey("20B602D1475F2DF888FCB60D2AE03AFD");
191 }
192
193 if(context == "server.example.com" && type == "tls-server")
194 {
195 return Botan::SymmetricKey("20B602D1475F2DF888FCB60D2AE03AFD");
196 }
197
198 throw Test_Error("No PSK set for " + type + "/" + context);
199 }
200
get_acceptable_cas() const201 const std::vector<Botan::X509_DN>& get_acceptable_cas() const { return m_acceptable_cas; }
202
203 private:
204 Botan::X509_Certificate m_rsa_cert, m_rsa_ca;
205 std::unique_ptr<Botan::Private_Key> m_rsa_key;
206
207 Botan::X509_Certificate m_ecdsa_cert, m_ecdsa_ca;
208 std::unique_ptr<Botan::Private_Key> m_ecdsa_key;
209
210 std::unique_ptr<const Botan::X509_Certificate> m_dsa_cert, m_dsa_ca;
211 std::unique_ptr<Botan::Private_Key> m_dsa_key;
212 std::unique_ptr<Botan::X509_CRL> m_dsa_crl;
213 std::vector<std::unique_ptr<Botan::Certificate_Store>> m_stores;
214 bool m_provides_client_certs;
215 std::vector<Botan::X509_DN> m_acceptable_cas;
216 };
217
218 Botan::Credentials_Manager*
create_creds(Botan::RandomNumberGenerator & rng,bool with_client_certs=false)219 create_creds(Botan::RandomNumberGenerator& rng,
220 bool with_client_certs = false)
221 {
222 // rsa and ecdsa are required for the tls module
223 const Botan::EC_Group ecdsa_params("secp256r1");
224 const size_t rsa_params = 1024;
225
226 std::unique_ptr<Botan::Private_Key> rsa_ca_key(new Botan::RSA_PrivateKey(rng, rsa_params));
227 std::unique_ptr<Botan::Private_Key> rsa_srv_key(new Botan::RSA_PrivateKey(rng, rsa_params));
228
229 std::unique_ptr<Botan::Private_Key> ecdsa_ca_key(new Botan::ECDSA_PrivateKey(rng, ecdsa_params));
230 std::unique_ptr<Botan::Private_Key> ecdsa_srv_key(new Botan::ECDSA_PrivateKey(rng, ecdsa_params));
231
232 Botan::X509_Cert_Options rsa_ca_opts("RSA Test CA/VT");
233 Botan::X509_Cert_Options ecdsa_ca_opts("ECDSA Test CA/VT");
234 rsa_ca_opts.CA_key(1);
235 ecdsa_ca_opts.CA_key(1);
236
237 const Botan::X509_Certificate rsa_ca_cert =
238 Botan::X509::create_self_signed_cert(rsa_ca_opts, *rsa_ca_key, "SHA-256", rng);
239 const Botan::X509_Certificate ecdsa_ca_cert =
240 Botan::X509::create_self_signed_cert(ecdsa_ca_opts, *ecdsa_ca_key, "SHA-256", rng);
241
242 const Botan::X509_Cert_Options server_opts("server.example.com");
243
244 const Botan::PKCS10_Request rsa_req =
245 Botan::X509::create_cert_req(server_opts, *rsa_srv_key, "SHA-256", rng);
246 const Botan::PKCS10_Request ecdsa_req =
247 Botan::X509::create_cert_req(server_opts, *ecdsa_srv_key, "SHA-256", rng);
248
249 Botan::X509_CA rsa_ca(rsa_ca_cert, *rsa_ca_key, "SHA-256", rng);
250 Botan::X509_CA ecdsa_ca(ecdsa_ca_cert, *ecdsa_ca_key, "SHA-256", rng);
251
252 typedef std::chrono::duration<int, std::ratio<31556926>> years;
253 auto now = std::chrono::system_clock::now();
254
255 const Botan::X509_Time start_time(now);
256 const Botan::X509_Time end_time(now + years(1));
257
258 const Botan::X509_Certificate rsa_srv_cert =
259 rsa_ca.sign_request(rsa_req, rng, start_time, end_time);
260 const Botan::X509_Certificate ecdsa_srv_cert =
261 ecdsa_ca.sign_request(ecdsa_req, rng, start_time, end_time);
262
263 Botan::X509_CRL rsa_crl = rsa_ca.new_crl(rng);
264 Botan::X509_CRL ecdsa_crl = ecdsa_ca.new_crl(rng);
265
266 // dsa support is optional
267 std::unique_ptr<Botan::Private_Key> dsa_ca_key;
268 std::unique_ptr<Botan::Private_Key> dsa_srv_key;
269 std::unique_ptr<Botan::X509_CRL> dsa_crl;
270 std::unique_ptr<Botan::X509_Certificate> dsa_srv_cert;
271 std::unique_ptr<Botan::X509_Certificate> dsa_ca_cert;
272
273 #if defined(BOTAN_HAS_DSA)
274 const Botan::DL_Group dsa_params("dsa/jce/1024");
275
276 dsa_ca_key.reset(new Botan::DSA_PrivateKey(rng, dsa_params));
277 dsa_srv_key.reset(new Botan::DSA_PrivateKey(rng, dsa_params));
278
279 Botan::X509_Cert_Options dsa_ca_opts("DSA Test CA/VT");
280 dsa_ca_opts.CA_key(1);
281
282 dsa_ca_cert.reset(new Botan::X509_Certificate(
283 Botan::X509::create_self_signed_cert(dsa_ca_opts, *dsa_ca_key, "SHA-256", rng)));
284
285 const Botan::PKCS10_Request dsa_req =
286 Botan::X509::create_cert_req(server_opts, *dsa_srv_key, "SHA-256", rng);
287
288 Botan::X509_CA dsa_ca(*dsa_ca_cert, *dsa_ca_key, "SHA-256", rng);
289 dsa_srv_cert.reset(new Botan::X509_Certificate(
290 dsa_ca.sign_request(dsa_req, rng, start_time, end_time)));
291
292 dsa_crl.reset(new Botan::X509_CRL(dsa_ca.new_crl(rng)));
293 #endif
294
295 Credentials_Manager_Test* cmt = new Credentials_Manager_Test(
296 with_client_certs,
297 rsa_srv_cert, rsa_srv_key.release(), rsa_ca_cert, rsa_crl,
298 ecdsa_srv_cert, ecdsa_srv_key.release(), ecdsa_ca_cert, ecdsa_crl,
299 dsa_srv_cert.release(), dsa_srv_key.release(), dsa_ca_cert.release(), dsa_crl.release());
300
301 return cmt;
302 }
303
304 #if defined(BOTAN_HAS_SRP6)
305 Botan::Credentials_Manager*
create_srp6_creds(Botan::RandomNumberGenerator & rng)306 create_srp6_creds(Botan::RandomNumberGenerator& rng)
307 {
308 class Credentials_Manager_SRP6 : public Botan::Credentials_Manager
309 {
310 public:
311 Credentials_Manager_SRP6(Botan::RandomNumberGenerator& rng)
312 {
313 m_group_id = "modp/srp/1024";
314 m_username = "srp6_username";
315 m_password = "srp6_password";
316 m_salt.resize(16);
317 rng.randomize(m_salt.data(), m_salt.size());
318
319 m_verifier = Botan::generate_srp6_verifier(m_username,
320 m_password,
321 m_salt,
322 m_group_id,
323 "SHA-1");
324 }
325
326 bool attempt_srp(const std::string& /*type*/,
327 const std::string& /*context*/) override
328 {
329 return true;
330 }
331
332 std::string srp_identifier(const std::string& /*type*/,
333 const std::string& /*context*/) override
334 {
335 return m_username;
336 }
337
338 std::string srp_password(const std::string& /*type*/,
339 const std::string& /*context*/,
340 const std::string& identifier) override
341 {
342 if(identifier == m_username)
343 return m_password;
344 return "";
345 }
346
347 bool srp_verifier(const std::string& /*type*/,
348 const std::string& /*context*/,
349 const std::string& identifier,
350 std::string& group_name,
351 Botan::BigInt& verifier,
352 std::vector<uint8_t>& salt,
353 bool generate_fake_on_unknown) override
354 {
355 // FIXME test generate_fake_on_unknown behavior
356 if(identifier == m_username)
357 {
358 group_name = m_group_id;
359 verifier = m_verifier;
360 salt = m_salt;
361 return true;
362 }
363 else if(generate_fake_on_unknown)
364 {
365 group_name = m_group_id;
366 verifier = m_verifier + 1;
367 salt = m_salt;
368 return true;
369 }
370 else
371 return false;
372 }
373
374 std::string m_username;
375 std::string m_password;
376 std::vector<uint8_t> m_salt;
377 std::string m_group_id;
378 Botan::BigInt m_verifier;
379 };
380
381 return new Credentials_Manager_SRP6(rng);
382 }
383 #endif
384
385
386 class TLS_Handshake_Test final
387 {
388 public:
TLS_Handshake_Test(const std::string & test_descr,Botan::TLS::Protocol_Version offer_version,Botan::Credentials_Manager & creds,const Botan::TLS::Policy & client_policy,const Botan::TLS::Policy & server_policy,Botan::RandomNumberGenerator & rng,Botan::TLS::Session_Manager & client_sessions,Botan::TLS::Session_Manager & server_sessions,bool expect_client_auth)389 TLS_Handshake_Test(const std::string& test_descr,
390 Botan::TLS::Protocol_Version offer_version,
391 Botan::Credentials_Manager& creds,
392 const Botan::TLS::Policy& client_policy,
393 const Botan::TLS::Policy& server_policy,
394 Botan::RandomNumberGenerator& rng,
395 Botan::TLS::Session_Manager& client_sessions,
396 Botan::TLS::Session_Manager& server_sessions,
397 bool expect_client_auth) :
398 m_offer_version(offer_version),
399 m_results(test_descr),
400 m_creds(creds),
401 m_client_policy(client_policy),
402 m_client_sessions(client_sessions),
403 m_rng(rng),
404 m_client_auth(expect_client_auth)
405 {
406 m_server_cb.reset(new Test_Callbacks(m_results, offer_version, m_s2c, m_server_recv));
407 m_client_cb.reset(new Test_Callbacks(m_results, offer_version, m_c2s, m_client_recv));
408
409 m_server.reset(
410 new Botan::TLS::Server(*m_server_cb, server_sessions, m_creds, server_policy, m_rng,
411 offer_version.is_datagram_protocol())
412 );
413
414 }
415
416 void go();
417
results() const418 const Test::Result& results() const { return m_results; }
419 private:
420
421 class Test_Extension : public Botan::TLS::Extension
422 {
423 public:
static_type()424 static Botan::TLS::Handshake_Extension_Type static_type()
425 { return static_cast<Botan::TLS::Handshake_Extension_Type>(666); }
426
type() const427 Botan::TLS::Handshake_Extension_Type type() const override { return static_type(); }
428
serialize(Botan::TLS::Connection_Side) const429 std::vector<uint8_t> serialize(Botan::TLS::Connection_Side) const override { return m_buf; }
430
value() const431 const std::vector<uint8_t>& value() const { return m_buf; }
432
empty() const433 bool empty() const override { return false; }
434
Test_Extension(Botan::TLS::Connection_Side side)435 Test_Extension(Botan::TLS::Connection_Side side)
436 {
437 const uint8_t client_extn[6] = { 'c', 'l', 'i', 'e', 'n', 't' };
438 const uint8_t server_extn[6] = { 's', 'e', 'r', 'v', 'e', 'r' };
439
440 Botan::TLS::append_tls_length_value(m_buf,
441 (side == Botan::TLS::CLIENT) ? client_extn : server_extn,
442 6, 1);
443 }
444 private:
445 std::vector<uint8_t> m_buf;
446 };
447
448 class Test_Callbacks : public Botan::TLS::Callbacks
449 {
450 public:
Test_Callbacks(Test::Result & results,Botan::TLS::Protocol_Version expected_version,std::vector<uint8_t> & outbound,std::vector<uint8_t> & recv_buf)451 Test_Callbacks(Test::Result& results,
452 Botan::TLS::Protocol_Version expected_version,
453 std::vector<uint8_t>& outbound,
454 std::vector<uint8_t>& recv_buf) :
455 m_results(results),
456 m_expected_version(expected_version),
457 m_outbound(outbound),
458 m_recv(recv_buf)
459 {}
460
tls_emit_data(const uint8_t bits[],size_t len)461 void tls_emit_data(const uint8_t bits[], size_t len) override
462 {
463 m_outbound.insert(m_outbound.end(), bits, bits + len);
464 }
465
tls_record_received(uint64_t,const uint8_t bits[],size_t len)466 void tls_record_received(uint64_t /*seq*/, const uint8_t bits[], size_t len) override
467 {
468 m_recv.insert(m_recv.end(), bits, bits + len);
469 }
470
tls_alert(Botan::TLS::Alert)471 void tls_alert(Botan::TLS::Alert /*alert*/) override
472 {
473 // TODO test that it is a no_renegotiation alert
474 // ignore
475 }
476
tls_modify_extensions(Botan::TLS::Extensions & extn,Botan::TLS::Connection_Side which_side)477 void tls_modify_extensions(Botan::TLS::Extensions& extn, Botan::TLS::Connection_Side which_side) override
478 {
479 extn.add(new Test_Extension(which_side));
480
481 // Insert an unsupported signature scheme as highest prio, to ensure we are tolerant of this
482 if(auto sig_algs = extn.get<Botan::TLS::Signature_Algorithms>())
483 {
484 std::vector<Botan::TLS::Signature_Scheme> schemes = sig_algs->supported_schemes();
485 // 0x0301 is RSA PKCS1/SHA-224, which is not supported anymore
486 schemes.insert(schemes.begin(), static_cast<Botan::TLS::Signature_Scheme>(0x0301));
487 // This replaces the previous extension value
488 extn.add(new Botan::TLS::Signature_Algorithms(schemes));
489 }
490 }
491
tls_examine_extensions(const Botan::TLS::Extensions & extn,Botan::TLS::Connection_Side which_side)492 void tls_examine_extensions(const Botan::TLS::Extensions& extn, Botan::TLS::Connection_Side which_side) override
493 {
494 Botan::TLS::Extension* test_extn = extn.get(static_cast<Botan::TLS::Handshake_Extension_Type>(666));
495
496 if(test_extn == nullptr)
497 {
498 m_results.test_failure("Did not receive test extension from peer");
499 }
500 else
501 {
502 Botan::TLS::Unknown_Extension* unknown_ext = dynamic_cast<Botan::TLS::Unknown_Extension*>(test_extn);
503
504 if(unknown_ext)
505 {
506 const std::vector<uint8_t> val = unknown_ext->value();
507
508 if(m_results.test_eq("Expected size for test extn", val.size(), 7))
509 {
510 if(which_side == Botan::TLS::CLIENT)
511 m_results.test_eq("Expected extension value", val, "06636C69656E74");
512 else
513 m_results.test_eq("Expected extension value", val, "06736572766572");
514 }
515 }
516 else
517 {
518 m_results.test_failure("Unknown extension type had unexpected type at runtime");
519 }
520 }
521 }
522
tls_session_established(const Botan::TLS::Session & session)523 bool tls_session_established(const Botan::TLS::Session& session) override
524 {
525 const std::string session_report =
526 "Session established " + session.version().to_string() + " " +
527 session.ciphersuite().to_string() + " " +
528 Botan::hex_encode(session.session_id());
529
530 m_results.test_note(session_report);
531
532 if(session.version() != m_expected_version)
533 {
534 m_results.test_failure("Expected " + m_expected_version.to_string() +
535 " negotiated " + session.version().to_string());
536 }
537
538 return true;
539 }
540
tls_server_choose_app_protocol(const std::vector<std::string> & protos)541 std::string tls_server_choose_app_protocol(const std::vector<std::string>& protos) override
542 {
543 m_results.test_eq("ALPN protocol count", protos.size(), 2);
544 m_results.test_eq("ALPN protocol 1", protos[0], "test/1");
545 m_results.test_eq("ALPN protocol 2", protos[1], "test/2");
546 return "test/3";
547 }
548
tls_decode_group_param(Botan::TLS::Group_Params group_param)549 virtual std::string tls_decode_group_param(Botan::TLS::Group_Params group_param) override
550 {
551 if(static_cast<uint16_t>(group_param) == 0xFEE1)
552 return "secp112r1";
553
554 return Botan::TLS::Callbacks::tls_decode_group_param(group_param);
555 }
556
557 private:
558 Test::Result& m_results;
559 const Botan::TLS::Protocol_Version m_expected_version;
560 std::vector<uint8_t>& m_outbound;
561 std::vector<uint8_t>& m_recv;
562 };
563
564 const Botan::TLS::Protocol_Version m_offer_version;
565 Test::Result m_results;
566
567 Botan::Credentials_Manager& m_creds;
568 const Botan::TLS::Policy& m_client_policy;
569 Botan::TLS::Session_Manager& m_client_sessions;
570 Botan::RandomNumberGenerator& m_rng;
571
572 std::unique_ptr<Test_Callbacks> m_client_cb;
573
574 std::unique_ptr<Test_Callbacks> m_server_cb;
575 std::unique_ptr<Botan::TLS::Server> m_server;
576
577 const bool m_client_auth;
578
579 std::vector<uint8_t> m_c2s, m_s2c, m_client_recv, m_server_recv;
580 };
581
go()582 void TLS_Handshake_Test::go()
583 {
584 m_results.start_timer();
585
586 Botan::RandomNumberGenerator& rng = Test::rng();
587
588 const std::vector<std::string> protocols_offered = { "test/1", "test/2" };
589
590 // Choose random application data to send
591 const size_t c_len = 1 + ((static_cast<size_t>(rng.next_byte()) << 4) ^ rng.next_byte());
592 std::vector<uint8_t> client_msg(c_len);
593 Test::rng().randomize(client_msg.data(), client_msg.size());
594 bool client_has_written = false;
595
596 const size_t s_len = 1 + ((static_cast<size_t>(rng.next_byte()) << 4) ^ rng.next_byte());
597 std::vector<uint8_t> server_msg(s_len);
598 Test::rng().randomize(server_msg.data(), server_msg.size());
599 bool server_has_written = false;
600
601 std::unique_ptr<Botan::TLS::Client> client;
602 client.reset(
603 new Botan::TLS::Client(*m_client_cb, m_client_sessions, m_creds,
604 m_client_policy, m_rng,
605 Botan::TLS::Server_Information("server.example.com"),
606 m_offer_version,
607 protocols_offered));
608
609 size_t rounds = 0;
610
611 bool client_handshake_completed = false;
612 bool server_handshake_completed = false;
613
614 while(true)
615 {
616 ++rounds;
617
618 if(rounds > 25)
619 {
620 m_results.test_failure("Still here after many rounds, deadlock?");
621 break;
622 }
623
624 if(client_handshake_completed == false && client->is_active())
625 client_handshake_completed = true;
626
627 if(server_handshake_completed == false && m_server->is_active())
628 server_handshake_completed = true;
629
630 if(client->is_closed() || m_server->is_closed())
631 {
632 break;
633 }
634
635 if(client->is_active() && client_has_written == false)
636 {
637 m_results.test_eq("client ALPN protocol", client->application_protocol(), "test/3");
638
639 size_t sent_so_far = 0;
640 while(sent_so_far != client_msg.size())
641 {
642 const size_t left = client_msg.size() - sent_so_far;
643 const size_t rnd12 = (rng.next_byte() << 4) ^ rng.next_byte();
644 const size_t sending = std::min(left, rnd12);
645
646 client->send(&client_msg[sent_so_far], sending);
647 sent_so_far += sending;
648 }
649 client->send_warning_alert(Botan::TLS::Alert::NO_RENEGOTIATION);
650 client_has_written = true;
651 }
652
653 if(m_server->is_active() && server_has_written == false)
654 {
655 m_results.test_eq("server ALPN protocol", m_server->application_protocol(), "test/3");
656
657 size_t sent_so_far = 0;
658 while(sent_so_far != server_msg.size())
659 {
660 const size_t left = server_msg.size() - sent_so_far;
661 const size_t rnd12 = (rng.next_byte() << 4) ^ rng.next_byte();
662 const size_t sending = std::min(left, rnd12);
663
664 m_server->send(&server_msg[sent_so_far], sending);
665 sent_so_far += sending;
666 }
667
668 m_server->send_warning_alert(Botan::TLS::Alert::NO_RENEGOTIATION);
669 server_has_written = true;
670 }
671
672 if(m_c2s.size() > 0)
673 {
674 /*
675 * Use this as a temp value to hold the queues as otherwise they
676 * might end up appending more in response to messages during the
677 * handshake.
678 */
679 std::vector<uint8_t> input;
680 std::swap(m_c2s, input);
681
682 size_t needed = m_server->received_data(input.data(), input.size());
683 m_results.test_eq("full packet received", needed, 0);
684
685 continue;
686 }
687
688 if(m_s2c.size() > 0)
689 {
690 std::vector<uint8_t> input;
691 std::swap(m_s2c, input);
692
693 size_t needed = client->received_data(input.data(), input.size());
694 m_results.test_eq("full packet received", needed, 0);
695
696 continue;
697 }
698
699 if(m_client_recv.size())
700 {
701 m_results.test_eq("client recv", m_client_recv, server_msg);
702 }
703
704 if(m_server_recv.size())
705 {
706 m_results.test_eq("server recv", m_server_recv, client_msg);
707 }
708
709 if(client->is_closed() && m_server->is_closed())
710 {
711 break;
712 }
713
714 if(m_server->is_active())
715 {
716 std::vector<Botan::X509_Certificate> certs = m_server->peer_cert_chain();
717 if(m_client_auth)
718 {
719 m_results.test_eq("got client certs", certs.size(), 2);
720
721 Credentials_Manager_Test& test_creds = dynamic_cast<Credentials_Manager_Test&>(m_creds);
722
723 std::vector<Botan::X509_DN> acceptable_CAs = test_creds.get_acceptable_cas();
724
725 m_results.test_gte("client got CA list", acceptable_CAs.size(), 2); // DSA is optional
726
727 for(const Botan::X509_DN& dn : acceptable_CAs)
728 {
729 m_results.test_eq("Expected CA country field",
730 dn.get_first_attribute("C"), "VT");
731 }
732 }
733 else
734 {
735 m_results.test_eq("no client certs", certs.size(), 0);
736 }
737 }
738
739 if(m_server_recv.size() && m_client_recv.size())
740 {
741 Botan::SymmetricKey client_key = client->key_material_export("label", "context", 32);
742 Botan::SymmetricKey server_key = m_server->key_material_export("label", "context", 32);
743
744 m_results.test_eq("TLS key material export", client_key.bits_of(), server_key.bits_of());
745
746 m_results.confirm("Client is active", client->is_active());
747 m_results.confirm("Client is not closed", !client->is_closed());
748 client->close();
749 m_results.confirm("Client is no longer active", !client->is_active());
750 m_results.confirm("Client is closed", client->is_closed());
751 }
752 }
753
754 m_results.end_timer();
755 }
756
757 class Test_Policy final : public Botan::TLS::Text_Policy
758 {
759 public:
Test_Policy()760 Test_Policy() : Text_Policy("") {}
acceptable_protocol_version(Botan::TLS::Protocol_Version) const761 bool acceptable_protocol_version(Botan::TLS::Protocol_Version) const override
762 {
763 return true;
764 }
send_fallback_scsv(Botan::TLS::Protocol_Version) const765 bool send_fallback_scsv(Botan::TLS::Protocol_Version) const override
766 {
767 return false;
768 }
769
dtls_initial_timeout() const770 size_t dtls_initial_timeout() const override
771 {
772 return 1;
773 }
dtls_maximum_timeout() const774 size_t dtls_maximum_timeout() const override
775 {
776 return 8;
777 }
778
minimum_rsa_bits() const779 size_t minimum_rsa_bits() const override
780 {
781 return 1024;
782 }
783
minimum_dsa_group_size() const784 size_t minimum_dsa_group_size() const override
785 {
786 return 1024;
787 }
788
minimum_signature_strength() const789 size_t minimum_signature_strength() const override
790 {
791 return 80;
792 }
793 };
794
795 class TLS_Unit_Tests final : public Test
796 {
797 private:
test_with_policy(const std::string & test_descr,std::vector<Test::Result> & results,Botan::TLS::Session_Manager & client_ses,Botan::TLS::Session_Manager & server_ses,Botan::Credentials_Manager & creds,const std::vector<Botan::TLS::Protocol_Version> & versions,const Botan::TLS::Policy & policy,bool client_auth=false)798 void test_with_policy(const std::string& test_descr,
799 std::vector<Test::Result>& results,
800 Botan::TLS::Session_Manager& client_ses,
801 Botan::TLS::Session_Manager& server_ses,
802 Botan::Credentials_Manager& creds,
803 const std::vector<Botan::TLS::Protocol_Version>& versions,
804 const Botan::TLS::Policy& policy,
805 bool client_auth = false)
806 {
807 Botan::RandomNumberGenerator& rng = Test::rng();
808
809 try
810 {
811 for(auto const& version : versions)
812 {
813 TLS_Handshake_Test test(
814 version.to_string() + " " + test_descr,
815 version, creds, policy, policy, rng, client_ses, server_ses, client_auth);
816 test.go();
817 results.push_back(test.results());
818
819 TLS_Handshake_Test test_resumption(
820 version.to_string() + " " + test_descr,
821 version, creds, policy, policy, rng, client_ses, server_ses, client_auth);
822 test_resumption.go();
823 results.push_back(test_resumption.results());
824 }
825 }
826 catch(std::exception& e)
827 {
828 results.push_back(Test::Result::Failure(test_descr, e.what()));
829 }
830 }
831
test_all_versions(const std::string & test_descr,std::vector<Test::Result> & results,Botan::TLS::Session_Manager & client_ses,Botan::TLS::Session_Manager & server_ses,Botan::Credentials_Manager & creds,const std::string & kex_policy,const std::string & cipher_policy,const std::string & mac_policy,const std::string & etm_policy,bool client_auth=false)832 void test_all_versions(const std::string& test_descr,
833 std::vector<Test::Result>& results,
834 Botan::TLS::Session_Manager& client_ses,
835 Botan::TLS::Session_Manager& server_ses,
836 Botan::Credentials_Manager& creds,
837 const std::string& kex_policy,
838 const std::string& cipher_policy,
839 const std::string& mac_policy,
840 const std::string& etm_policy,
841 bool client_auth = false)
842 {
843 Test_Policy policy;
844 policy.set("ciphers", cipher_policy);
845 policy.set("macs", mac_policy);
846 policy.set("key_exchange_methods", kex_policy);
847 policy.set("negotiate_encrypt_then_mac", etm_policy);
848
849 policy.set("allow_tls10", "true");
850 policy.set("allow_tls11", "true");
851 policy.set("allow_tls12", "true");
852 policy.set("allow_dtls10", "true");
853 policy.set("allow_dtls12", "true");
854
855 if(kex_policy.find("RSA") != std::string::npos || kex_policy.find("SRP") != std::string::npos)
856 {
857 policy.set("signature_methods", "IMPLICIT");
858 }
859
860 std::vector<Botan::TLS::Protocol_Version> versions =
861 {
862 #if defined(BOTAN_HAS_TLS_V10)
863 Botan::TLS::Protocol_Version::TLS_V10,
864 Botan::TLS::Protocol_Version::TLS_V11,
865 Botan::TLS::Protocol_Version::DTLS_V10,
866 #endif
867 Botan::TLS::Protocol_Version::TLS_V12,
868 Botan::TLS::Protocol_Version::DTLS_V12
869 };
870
871 return test_with_policy(test_descr, results, client_ses, server_ses, creds, versions, policy, client_auth);
872 }
873
test_modern_versions(const std::string & test_descr,std::vector<Test::Result> & results,Botan::TLS::Session_Manager & client_ses,Botan::TLS::Session_Manager & server_ses,Botan::Credentials_Manager & creds,const std::string & kex_policy,const std::string & cipher_policy,const std::string & mac_policy="AEAD",bool client_auth=false)874 void test_modern_versions(const std::string& test_descr,
875 std::vector<Test::Result>& results,
876 Botan::TLS::Session_Manager& client_ses,
877 Botan::TLS::Session_Manager& server_ses,
878 Botan::Credentials_Manager& creds,
879 const std::string& kex_policy,
880 const std::string& cipher_policy,
881 const std::string& mac_policy = "AEAD",
882 bool client_auth = false)
883 {
884 std::map<std::string, std::string> no_extra_policies;
885 return test_modern_versions(test_descr, results, client_ses, server_ses, creds,
886 kex_policy, cipher_policy, mac_policy, no_extra_policies, client_auth);
887 }
888
test_modern_versions(const std::string & test_descr,std::vector<Test::Result> & results,Botan::TLS::Session_Manager & client_ses,Botan::TLS::Session_Manager & server_ses,Botan::Credentials_Manager & creds,const std::string & kex_policy,const std::string & cipher_policy,const std::string & mac_policy,const std::map<std::string,std::string> & extra_policies,bool client_auth=false)889 void test_modern_versions(const std::string& test_descr,
890 std::vector<Test::Result>& results,
891 Botan::TLS::Session_Manager& client_ses,
892 Botan::TLS::Session_Manager& server_ses,
893 Botan::Credentials_Manager& creds,
894 const std::string& kex_policy,
895 const std::string& cipher_policy,
896 const std::string& mac_policy,
897 const std::map<std::string, std::string>& extra_policies,
898 bool client_auth = false)
899 {
900 Test_Policy policy;
901 policy.set("ciphers", cipher_policy);
902 policy.set("macs", mac_policy);
903 policy.set("key_exchange_methods", kex_policy);
904 policy.set("allow_tls10", "false");
905 policy.set("allow_tls11", "false");
906 policy.set("allow_tls12", "true");
907 policy.set("allow_dtls10", "false");
908 policy.set("allow_dtls12", "true");
909
910 if(kex_policy.find("RSA") != std::string::npos)
911 {
912 policy.set("signature_methods", "IMPLICIT");
913 }
914
915 for(auto const& kv : extra_policies)
916 {
917 policy.set(kv.first, kv.second);
918 }
919
920 std::vector<Botan::TLS::Protocol_Version> versions =
921 {
922 Botan::TLS::Protocol_Version::TLS_V12,
923 Botan::TLS::Protocol_Version::DTLS_V12
924 };
925
926 return test_with_policy(test_descr, results, client_ses, server_ses, creds, versions, policy, client_auth);
927 }
928
929 public:
run()930 std::vector<Test::Result> run() override
931 {
932 std::vector<Test::Result> results;
933
934 Botan::RandomNumberGenerator& rng = Test::rng();
935
936 std::unique_ptr<Botan::TLS::Session_Manager> client_ses;
937 std::unique_ptr<Botan::TLS::Session_Manager> server_ses;
938
939 #if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
940 client_ses.reset(
941 new Botan::TLS::Session_Manager_SQLite("client pass", rng, ":memory:", 5, std::chrono::seconds(2)));
942 server_ses.reset(
943 new Botan::TLS::Session_Manager_SQLite("server pass", rng, ":memory:", 10, std::chrono::seconds(4)));
944
945 #else
946 client_ses.reset(new Botan::TLS::Session_Manager_In_Memory(rng));
947 server_ses.reset(new Botan::TLS::Session_Manager_In_Memory(rng));
948 #endif
949
950 std::unique_ptr<Botan::Credentials_Manager> creds(create_creds(rng));
951
952 #if defined(BOTAN_HAS_TLS_CBC)
953 for(std::string etm_setting : { "false", "true" })
954 {
955 test_all_versions("AES-128 RSA", results, *client_ses, *server_ses, *creds, "RSA", "AES-128", "SHA-256 SHA-1", etm_setting);
956 test_all_versions("AES-128 ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128", "SHA-256 SHA-1", etm_setting);
957
958 #if defined(BOTAN_HAS_CAMELLIA) && defined(BOTAN_HAS_TLS_CBC)
959 test_all_versions("Camellia-128 RSA", results, *client_ses, *server_ses,
960 *creds, "RSA", "Camellia-128", "SHA-256 SHA-1", etm_setting);
961 test_all_versions("Camellia-256 RSA SHA-2", results, *client_ses, *server_ses,
962 *creds, "RSA", "Camellia-256", "SHA-256 SHA-384 SHA-1", etm_setting);
963 #endif
964
965 #if defined(BOTAN_HAS_DES)
966 test_all_versions("3DES RSA", results, *client_ses, *server_ses, *creds, "RSA", "3DES", "SHA-1", etm_setting);
967 test_all_versions("3DES ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "3DES", "SHA-1", etm_setting);
968 #endif
969
970 #if defined(BOTAN_HAS_SEED)
971 test_all_versions("SEED RSA", results, *client_ses, *server_ses, *creds, "RSA", "SEED", "SHA-1", etm_setting);
972 #endif
973
974 server_ses->remove_all();
975 }
976 client_ses->remove_all();
977
978 test_modern_versions("AES-128 DH", results, *client_ses, *server_ses, *creds, "DH", "AES-128", "SHA-256");
979
980 #if defined(BOTAN_HAS_DSA)
981 if(Test::run_long_tests())
982 {
983 test_modern_versions("AES-128 DSA", results, *client_ses, *server_ses, *creds, "DH", "AES-128", "SHA-256",
984 { { "signature_methods", "DSA" } });
985
986 test_modern_versions("AES-128/GCM DSA", results, *client_ses, *server_ses, *creds, "DH", "AES-128/GCM", "AEAD",
987 { { "signature_methods", "DSA" } });
988 }
989 #endif
990
991 #if defined(BOTAN_HAS_SRP6)
992 std::unique_ptr<Botan::Credentials_Manager> srp6_creds(create_srp6_creds(rng));
993 test_all_versions("SRP6 AES", results, *client_ses, *server_ses, *srp6_creds, "SRP_SHA", "AES-128", "SHA-1", "false");
994 #endif
995
996 #endif
997
998 Botan::TLS::Strict_Policy strict_policy;
999 test_with_policy("Strict policy", results, *client_ses, *server_ses, *creds,
1000 {Botan::TLS::Protocol_Version::TLS_V12}, strict_policy);
1001
1002 Botan::TLS::NSA_Suite_B_128 suiteb_128;
1003 test_with_policy("Suite B", results, *client_ses, *server_ses, *creds,
1004 {Botan::TLS::Protocol_Version::TLS_V12}, suiteb_128);
1005
1006 // Remove server sessions before client, so clients retry with session server doesn't know
1007 server_ses->remove_all();
1008
1009 test_modern_versions("AES-128/GCM RSA", results, *client_ses, *server_ses, *creds, "RSA", "AES-128/GCM");
1010 test_modern_versions("AES-128/GCM ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM");
1011
1012 test_modern_versions("AES-128/GCM ECDH RSA",
1013 results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
1014 { { "signature_methods", "RSA" } });
1015
1016 test_modern_versions("AES-128/GCM ECDH no OCSP",
1017 results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
1018 { { "support_cert_status_message", "false" } });
1019
1020 client_ses->remove_all();
1021
1022 #if defined(BOTAN_HAS_CAMELLIA) && defined(BOTAN_HAS_TLS_CBC)
1023 test_modern_versions("Camellia-256 SHA-2", results, *client_ses, *server_ses, *creds, "RSA", "Camellia-256", "SHA-384 SHA-256");
1024 #endif
1025 #if defined(BOTAN_HAS_CAMELLIA) && defined(BOTAN_HAS_AEAD_GCM)
1026 test_modern_versions("Camellia-128/GCM ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "Camellia-128/GCM", "AEAD");
1027 #endif
1028
1029 #if defined(BOTAN_HAS_ARIA)
1030 test_modern_versions("ARIA ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "ARIA-128/GCM", "AEAD");
1031 #endif
1032
1033 #if defined(BOTAN_HAS_CECPQ1)
1034
1035 #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_AEAD_GCM)
1036 test_modern_versions("AES-256/GCM CECPQ1", results, *client_ses, *server_ses, *creds, "CECPQ1", "AES-256/GCM", "AEAD");
1037 #endif
1038
1039 #if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_AEAD_OCB)
1040 test_modern_versions("AES-256/OCB CECPQ1", results, *client_ses, *server_ses, *creds,
1041 "CECPQ1", "AES-256/OCB(12)", "AEAD");
1042 test_modern_versions("AES-256/OCB CECPQ1 RSA", results, *client_ses, *server_ses, *creds,
1043 "CECPQ1", "AES-256/OCB(12)", "AEAD",
1044 {{ "signature_methods", "RSA" }});
1045 #endif
1046
1047 #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
1048 test_modern_versions("ChaCha20Poly1305 CECPQ1", results, *client_ses, *server_ses, *creds,
1049 "CECPQ1", "ChaCha20Poly1305", "AEAD",
1050 { { "signature_methods", "RSA" }});
1051 #endif
1052
1053 #endif
1054
1055 test_modern_versions("AES-128/GCM point compression", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
1056 { { "use_ecc_point_compression", "true" } });
1057 test_modern_versions("AES-256/GCM p521", results, *client_ses, *server_ses, *creds, "ECDH", "AES-256/GCM", "AEAD",
1058 { { "groups", "secp521r1" } });
1059 test_modern_versions("AES-128/GCM bp256r1", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
1060 { { "groups", "brainpool256r1" } });
1061
1062 #if defined(BOTAN_HAS_CURVE_25519)
1063 test_modern_versions("AES-128/GCM x25519", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD",
1064 { { "groups", "x25519" } });
1065 #endif
1066
1067 test_modern_versions("AES-128/GCM FFDHE-2048",
1068 results, *client_ses, *server_ses, *creds, "DH", "AES-128/GCM", "AEAD",
1069 { { "groups", "ffdhe/ietf/2048" } });
1070
1071 std::unique_ptr<Botan::Credentials_Manager> creds_with_client_cert(create_creds(rng, true));
1072
1073 client_ses->remove_all();
1074 test_modern_versions("AES-256/GCM client certs",
1075 results, *client_ses, *server_ses, *creds_with_client_cert, "ECDH", "AES-256/GCM", "AEAD", true);
1076
1077 #if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
1078 client_ses.reset(new Botan::TLS::Session_Manager_In_Memory(rng));
1079 server_ses.reset(new Botan::TLS::Session_Manager_In_Memory(rng));
1080 #endif
1081
1082 #if defined(BOTAN_HAS_AEAD_OCB)
1083 test_modern_versions("AES-128/OCB ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/OCB(12)");
1084 #endif
1085
1086 server_ses->remove_all();
1087
1088 #if defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
1089 test_modern_versions("ChaCha20Poly1305 ECDH", results, *client_ses, *server_ses, *creds, "ECDH", "ChaCha20Poly1305");
1090 #endif
1091
1092 test_modern_versions("AES-128/GCM PSK", results, *client_ses, *server_ses, *creds, "PSK", "AES-128/GCM");
1093
1094 #if defined(BOTAN_HAS_AEAD_CCM)
1095 test_modern_versions("AES-128/CCM PSK", results, *client_ses, *server_ses, *creds, "PSK", "AES-128/CCM");
1096 test_modern_versions("AES-128/CCM-8 PSK", results, *client_ses, *server_ses, *creds, "PSK", "AES-128/CCM(8)");
1097 #endif
1098
1099 #if defined(BOTAN_HAS_TLS_CBC)
1100 // For whatever reason no (EC)DHE_PSK GCM ciphersuites are defined
1101 test_modern_versions("AES-128 ECDHE_PSK", results, *client_ses, *server_ses, *creds, "ECDHE_PSK", "AES-128", "SHA-256");
1102 test_modern_versions("AES-128 DHE_PSK", results, *client_ses, *server_ses, *creds, "DHE_PSK", "AES-128", "SHA-1");
1103 #endif
1104
1105 // Test with a custom curve
1106
1107 /*
1108 * First register a curve, in this case secp112r1
1109 */
1110 const Botan::BigInt p("0xDB7C2ABF62E35E668076BEAD208B");
1111 const Botan::BigInt a("0xDB7C2ABF62E35E668076BEAD2088");
1112 const Botan::BigInt b("0x659EF8BA043916EEDE8911702B22");
1113
1114 const Botan::BigInt g_x("0x09487239995A5EE76B55F9C2F098");
1115 const Botan::BigInt g_y("0xA89CE5AF8724C0A23E0E0FF77500");
1116 const Botan::BigInt order("0xDB7C2ABF62E35E7628DFAC6561C5");
1117
1118 const Botan::OID oid("1.3.132.0.6");
1119
1120 // Creating this object implicitly registers the curve for future use ...
1121 Botan::EC_Group reg_secp112r1(p, a, b, g_x, g_y, order, 1, oid);
1122
1123 Botan::OIDS::add_oid(oid, "secp112r1");
1124
1125 test_modern_versions("AES-256/GCM secp112r1", results, *client_ses, *server_ses, *creds, "ECDH", "AES-256/GCM", "AEAD",
1126 { { "groups", "0xFEE1" }, { "minimum_ecdh_group_size", "112" } });
1127
1128 return results;
1129 }
1130
1131 };
1132
1133 BOTAN_REGISTER_TEST("tls", "tls", TLS_Unit_Tests);
1134
1135 class DTLS_Reconnection_Test : public Test
1136 {
1137 public:
run()1138 std::vector<Test::Result> run() override
1139 {
1140 class Test_Callbacks : public Botan::TLS::Callbacks
1141 {
1142 public:
1143 Test_Callbacks(Test::Result& results,
1144 std::vector<uint8_t>& outbound,
1145 std::vector<uint8_t>& recv_buf) :
1146 m_results(results),
1147 m_outbound(outbound),
1148 m_recv(recv_buf)
1149 {}
1150
1151 void tls_emit_data(const uint8_t bits[], size_t len) override
1152 {
1153 m_outbound.insert(m_outbound.end(), bits, bits + len);
1154 }
1155
1156 void tls_record_received(uint64_t /*seq*/, const uint8_t bits[], size_t len) override
1157 {
1158 m_recv.insert(m_recv.end(), bits, bits + len);
1159 }
1160
1161 void tls_alert(Botan::TLS::Alert /*alert*/) override
1162 {
1163 // ignore
1164 }
1165
1166 bool tls_session_established(const Botan::TLS::Session& /*session*/) override
1167 {
1168 m_results.test_success("Established a session");
1169 return true;
1170 }
1171
1172 private:
1173 Test::Result& m_results;
1174 std::vector<uint8_t>& m_outbound;
1175 std::vector<uint8_t>& m_recv;
1176 };
1177
1178 class Credentials_PSK : public Botan::Credentials_Manager
1179 {
1180 public:
1181 Botan::SymmetricKey psk(const std::string& type,
1182 const std::string& context,
1183 const std::string&) override
1184 {
1185 if(type == "tls-server" && context == "session-ticket")
1186 {
1187 return Botan::SymmetricKey("AABBCCDDEEFF012345678012345678");
1188 }
1189
1190 if(type == "tls-server" && context == "dtls-cookie-secret")
1191 {
1192 return Botan::SymmetricKey("4AEA5EAD279CADEB537A594DA0E9DE3A");
1193 }
1194
1195 if(context == "localhost" && type == "tls-client")
1196 {
1197 return Botan::SymmetricKey("20B602D1475F2DF888FCB60D2AE03AFD");
1198 }
1199
1200 if(context == "localhost" && type == "tls-server")
1201 {
1202 return Botan::SymmetricKey("20B602D1475F2DF888FCB60D2AE03AFD");
1203 }
1204
1205 throw Test_Error("No PSK set for " + type + "/" + context);
1206 }
1207 };
1208
1209 class Datagram_PSK_Policy : public Botan::TLS::Policy
1210 {
1211 public:
1212 std::vector<std::string> allowed_macs() const override
1213 { return std::vector<std::string>({"AEAD"}); }
1214
1215 std::vector<std::string> allowed_key_exchange_methods() const override
1216 { return {"PSK"}; }
1217
1218 bool allow_tls10() const override { return false; }
1219 bool allow_tls11() const override { return false; }
1220 bool allow_tls12() const override { return false; }
1221 bool allow_dtls10() const override { return false; }
1222 bool allow_dtls12() const override { return true; }
1223
1224 bool allow_dtls_epoch0_restart() const override { return true; }
1225 };
1226
1227 Test::Result result("DTLS reconnection");
1228
1229 Datagram_PSK_Policy server_policy;
1230 Datagram_PSK_Policy client_policy;
1231 Credentials_PSK creds;
1232 Botan::TLS::Session_Manager_In_Memory server_sessions(rng());
1233 //Botan::TLS::Session_Manager_In_Memory client_sessions(rng());
1234 Botan::TLS::Session_Manager_Noop client_sessions;
1235
1236 std::vector<uint8_t> s2c, server_recv;
1237 Test_Callbacks server_callbacks(result, s2c, server_recv);
1238 Botan::TLS::Server server(server_callbacks, server_sessions, creds, server_policy, rng(), true);
1239
1240 std::vector<uint8_t> c1_c2s, client1_recv;
1241 Test_Callbacks client1_callbacks(result, c1_c2s, client1_recv);
1242 Botan::TLS::Client client1(client1_callbacks, client_sessions, creds, client_policy, rng(),
1243 Botan::TLS::Server_Information("localhost"),
1244 Botan::TLS::Protocol_Version::latest_dtls_version());
1245
1246 bool c1_to_server_sent = false;
1247 bool server_to_c1_sent = false;
1248
1249 const std::vector<uint8_t> c1_to_server_magic(16, 0xC1);
1250 const std::vector<uint8_t> server_to_c1_magic(16, 0x42);
1251
1252 size_t c1_rounds = 0;
1253 for(;;)
1254 {
1255 c1_rounds++;
1256
1257 if(c1_rounds > 64)
1258 {
1259 result.test_failure("Still spinning in client1 loop after 64 rounds");
1260 return {result};
1261 }
1262
1263 if(c1_c2s.size() > 0)
1264 {
1265 std::vector<uint8_t> input;
1266 std::swap(c1_c2s, input);
1267 server.received_data(input.data(), input.size());
1268 continue;
1269 }
1270
1271 if(s2c.size() > 0)
1272 {
1273 std::vector<uint8_t> input;
1274 std::swap(s2c, input);
1275 client1.received_data(input.data(), input.size());
1276 continue;
1277 }
1278
1279 if(!c1_to_server_sent && client1.is_active())
1280 {
1281 client1.send(c1_to_server_magic);
1282 c1_to_server_sent = true;
1283 }
1284
1285 if(!server_to_c1_sent && server.is_active())
1286 {
1287 server.send(server_to_c1_magic);
1288 }
1289
1290 if(server_recv.size() > 0 && client1_recv.size() > 0)
1291 {
1292 result.test_eq("Expected message from client1", server_recv, c1_to_server_magic);
1293 result.test_eq("Expected message to client1", client1_recv, server_to_c1_magic);
1294 break;
1295 }
1296 }
1297
1298 // Now client1 "goes away" (goes silent) and new client
1299 // connects to same server context (ie due to reuse of client source port)
1300 // See RFC 6347 section 4.2.8
1301
1302 server_recv.clear();
1303 s2c.clear();
1304
1305 std::vector<uint8_t> c2_c2s, client2_recv;
1306 Test_Callbacks client2_callbacks(result, c2_c2s, client2_recv);
1307 Botan::TLS::Client client2(client2_callbacks, client_sessions, creds, client_policy, rng(),
1308 Botan::TLS::Server_Information("localhost"),
1309 Botan::TLS::Protocol_Version::latest_dtls_version());
1310
1311 bool c2_to_server_sent = false;
1312 bool server_to_c2_sent = false;
1313
1314 const std::vector<uint8_t> c2_to_server_magic(16, 0xC2);
1315 const std::vector<uint8_t> server_to_c2_magic(16, 0x66);
1316
1317 size_t c2_rounds = 0;
1318
1319 for(;;)
1320 {
1321 c2_rounds++;
1322
1323 if(c2_rounds > 64)
1324 {
1325 result.test_failure("Still spinning in client2 loop after 64 rounds");
1326 return {result};
1327 }
1328
1329 if(c2_c2s.size() > 0)
1330 {
1331 std::vector<uint8_t> input;
1332 std::swap(c2_c2s, input);
1333 server.received_data(input.data(), input.size());
1334 continue;
1335 }
1336
1337 if(s2c.size() > 0)
1338 {
1339 std::vector<uint8_t> input;
1340 std::swap(s2c, input);
1341 client2.received_data(input.data(), input.size());
1342 continue;
1343 }
1344
1345 if(!c2_to_server_sent && client2.is_active())
1346 {
1347 client2.send(c2_to_server_magic);
1348 c2_to_server_sent = true;
1349 }
1350
1351 if(!server_to_c2_sent && server.is_active())
1352 {
1353 server.send(server_to_c2_magic);
1354 }
1355
1356 if(server_recv.size() > 0 && client2_recv.size() > 0)
1357 {
1358 result.test_eq("Expected message from client2", server_recv, c2_to_server_magic);
1359 result.test_eq("Expected message to client2", client2_recv, server_to_c2_magic);
1360 break;
1361 }
1362 }
1363
1364 return {result};
1365 }
1366 };
1367
1368 BOTAN_REGISTER_TEST("tls", "tls_dtls_reconnect", DTLS_Reconnection_Test);
1369
1370 #endif
1371
1372 }
1373
1374 }
1375