aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/info.txt90
-rw-r--r--src/tls/msg_cert_req.cpp163
-rw-r--r--src/tls/msg_cert_verify.cpp117
-rw-r--r--src/tls/msg_certificate.cpp88
-rw-r--r--src/tls/msg_client_hello.cpp287
-rw-r--r--src/tls/msg_client_kex.cpp419
-rw-r--r--src/tls/msg_finished.cpp104
-rw-r--r--src/tls/msg_hello_verify.cpp69
-rw-r--r--src/tls/msg_next_protocol.cpp55
-rw-r--r--src/tls/msg_server_hello.cpp142
-rw-r--r--src/tls/msg_server_kex.cpp285
-rw-r--r--src/tls/msg_session_ticket.cpp57
-rw-r--r--src/tls/sessions_sqlite/info.txt6
-rw-r--r--src/tls/sessions_sqlite/tls_session_manager_sqlite.cpp223
-rw-r--r--src/tls/sessions_sqlite/tls_session_manager_sqlite.h80
-rw-r--r--src/tls/tls_alert.cpp123
-rw-r--r--src/tls/tls_alert.h113
-rw-r--r--src/tls/tls_blocking.cpp90
-rw-r--r--src/tls/tls_blocking.h97
-rw-r--r--src/tls/tls_channel.cpp668
-rw-r--r--src/tls/tls_channel.h259
-rw-r--r--src/tls/tls_ciphersuite.cpp236
-rw-r--r--src/tls/tls_ciphersuite.h137
-rw-r--r--src/tls/tls_client.cpp530
-rw-r--r--src/tls/tls_client.h106
-rw-r--r--src/tls/tls_exceptn.h47
-rw-r--r--src/tls/tls_extensions.cpp533
-rw-r--r--src/tls/tls_extensions.h397
-rw-r--r--src/tls/tls_handshake_hash.cpp86
-rw-r--r--src/tls/tls_handshake_hash.h50
-rw-r--r--src/tls/tls_handshake_io.cpp381
-rw-r--r--src/tls/tls_handshake_io.h168
-rw-r--r--src/tls/tls_handshake_msg.h36
-rw-r--r--src/tls/tls_handshake_state.cpp442
-rw-r--r--src/tls/tls_handshake_state.h210
-rw-r--r--src/tls/tls_heartbeats.cpp78
-rw-r--r--src/tls/tls_heartbeats.h43
-rw-r--r--src/tls/tls_magic.h72
-rw-r--r--src/tls/tls_messages.h567
-rw-r--r--src/tls/tls_policy.cpp286
-rw-r--r--src/tls/tls_policy.h194
-rw-r--r--src/tls/tls_reader.h226
-rw-r--r--src/tls/tls_record.cpp622
-rw-r--r--src/tls/tls_record.h135
-rw-r--r--src/tls/tls_seq_numbers.h125
-rw-r--r--src/tls/tls_server.cpp725
-rw-r--r--src/tls/tls_server.h71
-rw-r--r--src/tls/tls_server_info.h91
-rw-r--r--src/tls/tls_session.cpp177
-rw-r--r--src/tls/tls_session.h206
-rw-r--r--src/tls/tls_session_key.cpp86
-rw-r--r--src/tls/tls_session_key.h50
-rw-r--r--src/tls/tls_session_manager.h149
-rw-r--r--src/tls/tls_session_manager_memory.cpp122
-rw-r--r--src/tls/tls_suite_info.cpp463
-rw-r--r--src/tls/tls_version.cpp101
-rw-r--r--src/tls/tls_version.h151
57 files changed, 0 insertions, 11634 deletions
diff --git a/src/tls/info.txt b/src/tls/info.txt
deleted file mode 100644
index adae12cb2..000000000
--- a/src/tls/info.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-define TLS 20131128
-
-load_on auto
-
-<header:public>
-tls_alert.h
-tls_blocking.h
-tls_channel.h
-tls_ciphersuite.h
-tls_client.h
-tls_exceptn.h
-tls_handshake_msg.h
-tls_magic.h
-tls_server_info.h
-tls_policy.h
-tls_server.h
-tls_session.h
-tls_session_manager.h
-tls_version.h
-</header:public>
-
-<header:internal>
-tls_extensions.h
-tls_handshake_hash.h
-tls_handshake_io.h
-tls_handshake_state.h
-tls_heartbeats.h
-tls_messages.h
-tls_reader.h
-tls_record.h
-tls_seq_numbers.h
-tls_session_key.h
-</header:internal>
-
-<source>
-msg_cert_req.cpp
-msg_cert_verify.cpp
-msg_certificate.cpp
-msg_client_hello.cpp
-msg_client_kex.cpp
-msg_finished.cpp
-msg_hello_verify.cpp
-msg_next_protocol.cpp
-msg_server_hello.cpp
-msg_server_kex.cpp
-msg_session_ticket.cpp
-tls_alert.cpp
-tls_blocking.cpp
-tls_channel.cpp
-tls_ciphersuite.cpp
-tls_client.cpp
-tls_extensions.cpp
-tls_handshake_hash.cpp
-tls_handshake_io.cpp
-tls_handshake_state.cpp
-tls_heartbeats.cpp
-tls_policy.cpp
-tls_server.cpp
-tls_session.cpp
-tls_session_key.cpp
-tls_session_manager_memory.cpp
-tls_suite_info.cpp
-tls_record.cpp
-tls_version.cpp
-</source>
-
-<requires>
-aead
-aes
-asn1
-cbc
-credentials
-cryptobox_psk
-dh
-ecdh
-eme_pkcs
-emsa3
-hmac
-kdf2
-md5
-prf_ssl3
-prf_tls
-rng
-rsa
-sha1
-sha2_32
-srp6
-ssl3mac
-x509
-</requires>
diff --git a/src/tls/msg_cert_req.cpp b/src/tls/msg_cert_req.cpp
deleted file mode 100644
index 23d59c6d4..000000000
--- a/src/tls/msg_cert_req.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-* Certificate Request Message
-* (C) 2004-2006,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-std::string cert_type_code_to_name(byte code)
- {
- switch(code)
- {
- case 1:
- return "RSA";
- case 2:
- return "DSA";
- case 64:
- return "ECDSA";
- default:
- return ""; // DH or something else
- }
- }
-
-byte cert_type_name_to_code(const std::string& name)
- {
- if(name == "RSA")
- return 1;
- if(name == "DSA")
- return 2;
- if(name == "ECDSA")
- return 64;
-
- throw Invalid_Argument("Unknown cert type " + name);
- }
-
-}
-
-/**
-* Create a new Certificate Request message
-*/
-Certificate_Req::Certificate_Req(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- const std::vector<X509_DN>& ca_certs,
- Protocol_Version version) :
- m_names(ca_certs),
- m_cert_key_types({ "RSA", "DSA", "ECDSA" })
- {
- if(version.supports_negotiable_signature_algorithms())
- {
- std::vector<std::string> hashes = policy.allowed_signature_hashes();
- std::vector<std::string> sigs = policy.allowed_signature_methods();
-
- for(size_t i = 0; i != hashes.size(); ++i)
- for(size_t j = 0; j != sigs.size(); ++j)
- m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
- }
-
- hash.update(io.send(*this));
- }
-
-/**
-* Deserialize a Certificate Request message
-*/
-Certificate_Req::Certificate_Req(const std::vector<byte>& buf,
- Protocol_Version version)
- {
- if(buf.size() < 4)
- throw Decoding_Error("Certificate_Req: Bad certificate request");
-
- TLS_Data_Reader reader(buf);
-
- std::vector<byte> cert_type_codes = reader.get_range_vector<byte>(1, 1, 255);
-
- for(size_t i = 0; i != cert_type_codes.size(); ++i)
- {
- const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]);
-
- if(cert_type_name == "") // something we don't know
- continue;
-
- m_cert_key_types.push_back(cert_type_name);
- }
-
- if(version.supports_negotiable_signature_algorithms())
- {
- std::vector<byte> sig_hash_algs = reader.get_range_vector<byte>(2, 2, 65534);
-
- if(sig_hash_algs.size() % 2 != 0)
- throw Decoding_Error("Bad length for signature IDs in certificate request");
-
- for(size_t i = 0; i != sig_hash_algs.size(); i += 2)
- {
- std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]);
- std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]);
- m_supported_algos.push_back(std::make_pair(hash, sig));
- }
- }
-
- const u16bit purported_size = reader.get_u16bit();
-
- if(reader.remaining_bytes() != purported_size)
- throw Decoding_Error("Inconsistent length in certificate request");
-
- while(reader.has_remaining())
- {
- std::vector<byte> name_bits = reader.get_range_vector<byte>(2, 0, 65535);
-
- BER_Decoder decoder(&name_bits[0], name_bits.size());
- X509_DN name;
- decoder.decode(name);
- m_names.push_back(name);
- }
- }
-
-/**
-* Serialize a Certificate Request message
-*/
-std::vector<byte> Certificate_Req::serialize() const
- {
- std::vector<byte> buf;
-
- std::vector<byte> cert_types;
-
- for(size_t i = 0; i != m_cert_key_types.size(); ++i)
- cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i]));
-
- append_tls_length_value(buf, cert_types, 1);
-
- if(!m_supported_algos.empty())
- buf += Signature_Algorithms(m_supported_algos).serialize();
-
- std::vector<byte> encoded_names;
-
- for(size_t i = 0; i != m_names.size(); ++i)
- {
- DER_Encoder encoder;
- encoder.encode(m_names[i]);
-
- append_tls_length_value(encoded_names, encoder.get_contents(), 2);
- }
-
- append_tls_length_value(buf, encoded_names, 2);
-
- return buf;
- }
-
-}
-
-}
diff --git a/src/tls/msg_cert_verify.cpp b/src/tls/msg_cert_verify.cpp
deleted file mode 100644
index 436b84c24..000000000
--- a/src/tls/msg_cert_verify.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-* Certificate Verify Message
-* (C) 2004,2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-/*
-* Create a new Certificate Verify message
-*/
-Certificate_Verify::Certificate_Verify(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Private_Key* priv_key)
- {
- BOTAN_ASSERT_NONNULL(priv_key);
-
- std::pair<std::string, Signature_Format> format =
- state.choose_sig_format(*priv_key, m_hash_algo, m_sig_algo, true, policy);
-
- PK_Signer signer(*priv_key, format.first, format.second);
-
- if(state.version() == Protocol_Version::SSL_V3)
- {
- secure_vector<byte> md5_sha = state.hash().final_ssl3(
- state.session_keys().master_secret());
-
- if(priv_key->algo_name() == "DSA")
- m_signature = signer.sign_message(&md5_sha[16], md5_sha.size()-16, rng);
- else
- m_signature = signer.sign_message(md5_sha, rng);
- }
- else
- {
- m_signature = signer.sign_message(state.hash().get_contents(), rng);
- }
-
- state.hash().update(io.send(*this));
- }
-
-/*
-* Deserialize a Certificate Verify message
-*/
-Certificate_Verify::Certificate_Verify(const std::vector<byte>& buf,
- Protocol_Version version)
- {
- TLS_Data_Reader reader(buf);
-
- if(version.supports_negotiable_signature_algorithms())
- {
- m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte());
- m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte());
- }
-
- m_signature = reader.get_range<byte>(2, 0, 65535);
- }
-
-/*
-* Serialize a Certificate Verify message
-*/
-std::vector<byte> Certificate_Verify::serialize() const
- {
- std::vector<byte> buf;
-
- if(m_hash_algo != "" && m_sig_algo != "")
- {
- buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
- buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
- }
-
- const u16bit sig_len = m_signature.size();
- buf.push_back(get_byte(0, sig_len));
- buf.push_back(get_byte(1, sig_len));
- buf += m_signature;
-
- return buf;
- }
-
-/*
-* Verify a Certificate Verify message
-*/
-bool Certificate_Verify::verify(const X509_Certificate& cert,
- const Handshake_State& state) const
- {
- std::unique_ptr<Public_Key> key(cert.subject_public_key());
-
- std::pair<std::string, Signature_Format> format =
- state.understand_sig_format(*key.get(), m_hash_algo, m_sig_algo, true);
-
- PK_Verifier verifier(*key, format.first, format.second);
-
- if(state.version() == Protocol_Version::SSL_V3)
- {
- secure_vector<byte> md5_sha = state.hash().final_ssl3(
- state.session_keys().master_secret());
-
- return verifier.verify_message(&md5_sha[16], md5_sha.size()-16,
- &m_signature[0], m_signature.size());
- }
-
- return verifier.verify_message(state.hash().get_contents(), m_signature);
- }
-
-}
-
-}
diff --git a/src/tls/msg_certificate.cpp b/src/tls/msg_certificate.cpp
deleted file mode 100644
index 417ad34ce..000000000
--- a/src/tls/msg_certificate.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-* Certificate Message
-* (C) 2004-2006,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Create a new Certificate message
-*/
-Certificate::Certificate(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::vector<X509_Certificate>& cert_list) :
- m_certs(cert_list)
- {
- hash.update(io.send(*this));
- }
-
-/**
-* Deserialize a Certificate message
-*/
-Certificate::Certificate(const std::vector<byte>& buf)
- {
- if(buf.size() < 3)
- throw Decoding_Error("Certificate: Message malformed");
-
- const size_t total_size = make_u32bit(0, buf[0], buf[1], buf[2]);
-
- if(total_size != buf.size() - 3)
- throw Decoding_Error("Certificate: Message malformed");
-
- const byte* certs = &buf[3];
-
- while(size_t remaining_bytes = &buf[buf.size()] - certs)
- {
- if(remaining_bytes < 3)
- throw Decoding_Error("Certificate: Message malformed");
-
- const size_t cert_size = make_u32bit(0, certs[0], certs[1], certs[2]);
-
- if(remaining_bytes < (3 + cert_size))
- throw Decoding_Error("Certificate: Message malformed");
-
- DataSource_Memory cert_buf(&certs[3], cert_size);
- m_certs.push_back(X509_Certificate(cert_buf));
-
- certs += cert_size + 3;
- }
- }
-
-/**
-* Serialize a Certificate message
-*/
-std::vector<byte> Certificate::serialize() const
- {
- std::vector<byte> buf(3);
-
- for(size_t i = 0; i != m_certs.size(); ++i)
- {
- std::vector<byte> raw_cert = m_certs[i].BER_encode();
- const size_t cert_size = raw_cert.size();
- for(size_t i = 0; i != 3; ++i)
- buf.push_back(get_byte<u32bit>(i+1, cert_size));
- buf += raw_cert;
- }
-
- const size_t buf_size = buf.size() - 3;
- for(size_t i = 0; i != 3; ++i)
- buf[i] = get_byte<u32bit>(i+1, buf_size);
-
- return buf;
- }
-
-}
-
-}
diff --git a/src/tls/msg_client_hello.cpp b/src/tls/msg_client_hello.cpp
deleted file mode 100644
index 0d91af472..000000000
--- a/src/tls/msg_client_hello.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
-* TLS Hello Request and Client Hello Messages
-* (C) 2004-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_session_key.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/internal/stl_util.h>
-#include <chrono>
-
-namespace Botan {
-
-namespace TLS {
-
-enum {
- TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
-};
-
-std::vector<byte> make_hello_random(RandomNumberGenerator& rng)
- {
- std::vector<byte> buf(32);
-
- const u32bit time32 = static_cast<u32bit>(
- std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
-
- store_be(time32, &buf[0]);
- rng.randomize(&buf[4], buf.size() - 4);
- return buf;
- }
-
-/*
-* Create a new Hello Request message
-*/
-Hello_Request::Hello_Request(Handshake_IO& io)
- {
- io.send(*this);
- }
-
-/*
-* Deserialize a Hello Request message
-*/
-Hello_Request::Hello_Request(const std::vector<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Bad Hello_Request, has non-zero size");
- }
-
-/*
-* Serialize a Hello Request message
-*/
-std::vector<byte> Hello_Request::serialize() const
- {
- return std::vector<byte>();
- }
-
-/*
-* Create a new Client Hello message
-*/
-Client_Hello::Client_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- Protocol_Version version,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<byte>& reneg_info,
- bool next_protocol,
- const std::string& hostname,
- const std::string& srp_identifier) :
- m_version(version),
- m_random(make_hello_random(rng)),
- m_suites(policy.ciphersuite_list(m_version, (srp_identifier != ""))),
- m_comp_methods(policy.compression())
- {
- m_extensions.add(new Renegotiation_Extension(reneg_info));
- m_extensions.add(new SRP_Identifier(srp_identifier));
- m_extensions.add(new Server_Name_Indicator(hostname));
- m_extensions.add(new Session_Ticket());
- m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
-
- if(policy.negotiate_heartbeat_support())
- m_extensions.add(new Heartbeat_Support_Indicator(true));
-
- if(m_version.supports_negotiable_signature_algorithms())
- m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
- policy.allowed_signature_methods()));
-
- if(reneg_info.empty() && next_protocol)
- m_extensions.add(new Next_Protocol_Notification());
-
- hash.update(io.send(*this));
- }
-
-/*
-* Create a new Client Hello message (session resumption case)
-*/
-Client_Hello::Client_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<byte>& reneg_info,
- const Session& session,
- bool next_protocol) :
- m_version(session.version()),
- m_session_id(session.session_id()),
- m_random(make_hello_random(rng)),
- m_suites(policy.ciphersuite_list(m_version, (session.srp_identifier() != ""))),
- m_comp_methods(policy.compression())
- {
- if(!value_exists(m_suites, session.ciphersuite_code()))
- m_suites.push_back(session.ciphersuite_code());
-
- if(!value_exists(m_comp_methods, session.compression_method()))
- m_comp_methods.push_back(session.compression_method());
-
- m_extensions.add(new Renegotiation_Extension(reneg_info));
- m_extensions.add(new SRP_Identifier(session.srp_identifier()));
- m_extensions.add(new Server_Name_Indicator(session.server_info().hostname()));
- m_extensions.add(new Session_Ticket(session.session_ticket()));
- m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
-
- if(policy.negotiate_heartbeat_support())
- m_extensions.add(new Heartbeat_Support_Indicator(true));
-
- if(session.fragment_size() != 0)
- m_extensions.add(new Maximum_Fragment_Length(session.fragment_size()));
-
- if(m_version.supports_negotiable_signature_algorithms())
- m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
- policy.allowed_signature_methods()));
-
- if(reneg_info.empty() && next_protocol)
- m_extensions.add(new Next_Protocol_Notification());
-
- hash.update(io.send(*this));
- }
-
-/*
-* Read a counterparty client hello
-*/
-Client_Hello::Client_Hello(const std::vector<byte>& buf, Handshake_Type type)
- {
- if(type == CLIENT_HELLO)
- deserialize(buf);
- else
- deserialize_sslv2(buf);
- }
-
-void Client_Hello::update_hello_cookie(const Hello_Verify_Request& hello_verify)
- {
- if(!m_version.is_datagram_protocol())
- throw std::runtime_error("Cannot use hello cookie with stream protocol");
-
- m_hello_cookie = hello_verify.cookie();
- }
-
-/*
-* Serialize a Client Hello message
-*/
-std::vector<byte> Client_Hello::serialize() const
- {
- std::vector<byte> buf;
-
- buf.push_back(m_version.major_version());
- buf.push_back(m_version.minor_version());
- buf += m_random;
-
- append_tls_length_value(buf, m_session_id, 1);
-
- if(m_version.is_datagram_protocol())
- append_tls_length_value(buf, m_hello_cookie, 1);
-
- append_tls_length_value(buf, m_suites, 2);
- append_tls_length_value(buf, m_comp_methods, 1);
-
- /*
- * May not want to send extensions at all in some cases. If so,
- * should include SCSV value (if reneg info is empty, if not we are
- * renegotiating with a modern server)
- */
-
- buf += m_extensions.serialize();
-
- return buf;
- }
-
-void Client_Hello::deserialize_sslv2(const std::vector<byte>& buf)
- {
- if(buf.size() < 12 || buf[0] != 1)
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
-
- const size_t cipher_spec_len = make_u16bit(buf[3], buf[4]);
- const size_t m_session_id_len = make_u16bit(buf[5], buf[6]);
- const size_t challenge_len = make_u16bit(buf[7], buf[8]);
-
- const size_t expected_size =
- (9 + m_session_id_len + cipher_spec_len + challenge_len);
-
- if(buf.size() != expected_size)
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
-
- if(m_session_id_len != 0 || cipher_spec_len % 3 != 0 ||
- (challenge_len < 16 || challenge_len > 32))
- {
- throw Decoding_Error("Client_Hello: SSLv2 hello corrupted");
- }
-
- m_version = Protocol_Version(buf[1], buf[2]);
-
- for(size_t i = 9; i != 9 + cipher_spec_len; i += 3)
- {
- if(buf[i] != 0) // a SSLv2 cipherspec; ignore it
- continue;
-
- m_suites.push_back(make_u16bit(buf[i+1], buf[i+2]));
- }
-
- m_random.resize(challenge_len);
- copy_mem(&m_random[0], &buf[9+cipher_spec_len+m_session_id_len], challenge_len);
-
- if(offered_suite(static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
- m_extensions.add(new Renegotiation_Extension());
- }
-
-/*
-* Deserialize a Client Hello message
-*/
-void Client_Hello::deserialize(const std::vector<byte>& buf)
- {
- if(buf.size() == 0)
- throw Decoding_Error("Client_Hello: Packet corrupted");
-
- if(buf.size() < 41)
- throw Decoding_Error("Client_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- const byte major_version = reader.get_byte();
- const byte minor_version = reader.get_byte();
-
- m_version = Protocol_Version(major_version, minor_version);
-
- m_random = reader.get_fixed<byte>(32);
-
- if(m_version.is_datagram_protocol())
- m_hello_cookie = reader.get_range<byte>(1, 0, 255);
-
- m_session_id = reader.get_range<byte>(1, 0, 32);
-
- m_suites = reader.get_range_vector<u16bit>(2, 1, 32767);
-
- m_comp_methods = reader.get_range_vector<byte>(1, 1, 255);
-
- m_extensions.deserialize(reader);
-
- if(offered_suite(static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
- {
- if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
- {
- if(!reneg->renegotiation_info().empty())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Client send renegotiation SCSV and non-empty extension");
- }
- else
- {
- // add fake extension
- m_extensions.add(new Renegotiation_Extension());
- }
- }
- }
-
-/*
-* Check if we offered this ciphersuite
-*/
-bool Client_Hello::offered_suite(u16bit ciphersuite) const
- {
- for(size_t i = 0; i != m_suites.size(); ++i)
- if(m_suites[i] == ciphersuite)
- return true;
- return false;
- }
-
-}
-
-}
diff --git a/src/tls/msg_client_kex.cpp b/src/tls/msg_client_kex.cpp
deleted file mode 100644
index ae8b82fd4..000000000
--- a/src/tls/msg_client_kex.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
-* Client Key Exchange Message
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/credentials_manager.h>
-#include <botan/pubkey.h>
-#include <botan/dh.h>
-#include <botan/ecdh.h>
-#include <botan/rsa.h>
-#include <botan/srp6.h>
-#include <botan/rng.h>
-#include <botan/loadstor.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-secure_vector<byte> strip_leading_zeros(const secure_vector<byte>& input)
- {
- size_t leading_zeros = 0;
-
- for(size_t i = 0; i != input.size(); ++i)
- {
- if(input[i] != 0)
- break;
- ++leading_zeros;
- }
-
- secure_vector<byte> output(&input[leading_zeros],
- &input[input.size()]);
- return output;
- }
-
-}
-
-/*
-* Create a new Client Key Exchange message
-*/
-Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- Credentials_Manager& creds,
- const Public_Key* server_public_key,
- const std::string& hostname,
- RandomNumberGenerator& rng)
- {
- const std::string kex_algo = state.ciphersuite().kex_algo();
-
- if(kex_algo == "PSK")
- {
- std::string identity_hint = "";
-
- if(state.server_kex())
- {
- TLS_Data_Reader reader(state.server_kex()->params());
- identity_hint = reader.get_string(2, 0, 65535);
- }
-
- const std::string hostname = state.client_hello()->sni_hostname();
-
- const std::string psk_identity = creds.psk_identity("tls-client",
- hostname,
- identity_hint);
-
- append_tls_length_value(m_key_material, psk_identity, 2);
-
- SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);
-
- std::vector<byte> zeros(psk.length());
-
- append_tls_length_value(m_pre_master, zeros, 2);
- append_tls_length_value(m_pre_master, psk.bits_of(), 2);
- }
- else if(state.server_kex())
- {
- TLS_Data_Reader reader(state.server_kex()->params());
-
- SymmetricKey psk;
-
- if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
- {
- std::string identity_hint = reader.get_string(2, 0, 65535);
-
- const std::string hostname = state.client_hello()->sni_hostname();
-
- const std::string psk_identity = creds.psk_identity("tls-client",
- hostname,
- identity_hint);
-
- append_tls_length_value(m_key_material, psk_identity, 2);
-
- psk = creds.psk("tls-client", hostname, psk_identity);
- }
-
- if(kex_algo == "DH" || kex_algo == "DHE_PSK")
- {
- BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
-
- if(reader.remaining_bytes())
- throw Decoding_Error("Bad params size for DH key exchange");
-
- if(p.bits() < policy.minimum_dh_group_size())
- throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
- "Server sent DH group of " +
- std::to_string(p.bits()) +
- " bits, policy requires at least " +
- std::to_string(policy.minimum_dh_group_size()));
-
- /*
- * A basic check for key validity. As we do not know q here we
- * cannot check that Y is in the right subgroup. However since
- * our key is ephemeral there does not seem to be any
- * advantage to bogus keys anyway.
- */
- if(Y <= 1 || Y >= p - 1)
- throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
- "Server sent bad DH key for DHE exchange");
-
- DL_Group group(p, g);
-
- if(!group.verify_group(rng, true))
- throw Internal_Error("DH group failed validation, possible attack");
-
- DH_PublicKey counterparty_key(group, Y);
-
- DH_PrivateKey priv_key(rng, group);
-
- PK_Key_Agreement ka(priv_key, "Raw");
-
- secure_vector<byte> dh_secret = strip_leading_zeros(
- ka.derive_key(0, counterparty_key.public_value()).bits_of());
-
- if(kex_algo == "DH")
- m_pre_master = dh_secret;
- else
- {
- append_tls_length_value(m_pre_master, dh_secret, 2);
- append_tls_length_value(m_pre_master, psk.bits_of(), 2);
- }
-
- append_tls_length_value(m_key_material, priv_key.public_value(), 2);
- }
- else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
- {
- const byte curve_type = reader.get_byte();
-
- if(curve_type != 3)
- throw Decoding_Error("Server sent non-named ECC curve");
-
- const u16bit curve_id = reader.get_u16bit();
-
- const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);
-
- if(name == "")
- throw Decoding_Error("Server sent unknown named curve " + std::to_string(curve_id));
-
- EC_Group group(name);
-
- std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);
-
- ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));
-
- ECDH_PrivateKey priv_key(rng, group);
-
- PK_Key_Agreement ka(priv_key, "Raw");
-
- secure_vector<byte> ecdh_secret =
- ka.derive_key(0, counterparty_key.public_value()).bits_of();
-
- if(kex_algo == "ECDH")
- m_pre_master = ecdh_secret;
- else
- {
- append_tls_length_value(m_pre_master, ecdh_secret, 2);
- append_tls_length_value(m_pre_master, psk.bits_of(), 2);
- }
-
- append_tls_length_value(m_key_material, priv_key.public_value(), 1);
- }
- else if(kex_algo == "SRP_SHA")
- {
- const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- std::vector<byte> salt = reader.get_range<byte>(1, 1, 255);
- const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
-
- const std::string srp_group = srp6_group_identifier(N, g);
-
- const std::string srp_identifier =
- creds.srp_identifier("tls-client", hostname);
-
- const std::string srp_password =
- creds.srp_password("tls-client", hostname, srp_identifier);
-
- std::pair<BigInt, SymmetricKey> srp_vals =
- srp6_client_agree(srp_identifier,
- srp_password,
- srp_group,
- "SHA-1",
- salt,
- B,
- rng);
-
- append_tls_length_value(m_key_material, BigInt::encode(srp_vals.first), 2);
- m_pre_master = srp_vals.second.bits_of();
- }
- else
- {
- throw Internal_Error("Client_Key_Exchange: Unknown kex " +
- kex_algo);
- }
-
- reader.assert_done();
- }
- else
- {
- // No server key exchange msg better mean RSA kex + RSA key in cert
-
- if(kex_algo != "RSA")
- throw Unexpected_Message("No server kex but negotiated kex " + kex_algo);
-
- if(!server_public_key)
- throw Internal_Error("No server public key for RSA exchange");
-
- if(auto rsa_pub = dynamic_cast<const RSA_PublicKey*>(server_public_key))
- {
- const Protocol_Version offered_version = state.client_hello()->version();
-
- m_pre_master = rng.random_vec(48);
- m_pre_master[0] = offered_version.major_version();
- m_pre_master[1] = offered_version.minor_version();
-
- PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");
-
- std::vector<byte> encrypted_key = encryptor.encrypt(m_pre_master, rng);
-
- if(state.version() == Protocol_Version::SSL_V3)
- m_key_material = encrypted_key; // no length field
- else
- append_tls_length_value(m_key_material, encrypted_key, 2);
- }
- else
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Expected a RSA key in server cert but got " +
- server_public_key->algo_name());
- }
-
- state.hash().update(io.send(*this));
- }
-
-/*
-* Read a Client Key Exchange message
-*/
-Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents,
- const Handshake_State& state,
- const Private_Key* server_rsa_kex_key,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng)
- {
- const std::string kex_algo = state.ciphersuite().kex_algo();
-
- if(kex_algo == "RSA")
- {
- BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
- "RSA key exchange negotiated so server sent a certificate");
-
- if(!server_rsa_kex_key)
- throw Internal_Error("Expected RSA kex but no server kex key set");
-
- if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
- throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());
-
- PK_Decryptor_EME decryptor(*server_rsa_kex_key, "PKCS1v15");
-
- Protocol_Version client_version = state.client_hello()->version();
-
- /*
- * This is used as the pre-master if RSA decryption fails.
- * Otherwise we can be used as an oracle. See Bleichenbacher
- * "Chosen Ciphertext Attacks against Protocols Based on RSA
- * Encryption Standard PKCS #1", Crypto 98
- *
- * Create it here instead if in the catch clause as otherwise we
- * expose a timing channel WRT the generation of the fake value.
- * Some timing channel likely remains due to exception handling
- * and the like.
- */
- secure_vector<byte> fake_pre_master = rng.random_vec(48);
- fake_pre_master[0] = client_version.major_version();
- fake_pre_master[1] = client_version.minor_version();
-
- try
- {
- if(state.version() == Protocol_Version::SSL_V3)
- {
- m_pre_master = decryptor.decrypt(contents);
- }
- else
- {
- TLS_Data_Reader reader(contents);
- m_pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));
- }
-
- if(m_pre_master.size() != 48 ||
- client_version.major_version() != m_pre_master[0] ||
- client_version.minor_version() != m_pre_master[1])
- {
- throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
- }
- }
- catch(...)
- {
- m_pre_master = fake_pre_master;
- }
- }
- else
- {
- TLS_Data_Reader reader(contents);
-
- SymmetricKey psk;
-
- if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
- {
- const std::string psk_identity = reader.get_string(2, 0, 65535);
-
- psk = creds.psk("tls-server",
- state.client_hello()->sni_hostname(),
- psk_identity);
-
- if(psk.length() == 0)
- {
- if(policy.hide_unknown_users())
- psk = SymmetricKey(rng, 16);
- else
- throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
- "No PSK for identifier " + psk_identity);
- }
- }
-
- if(kex_algo == "PSK")
- {
- std::vector<byte> zeros(psk.length());
- append_tls_length_value(m_pre_master, zeros, 2);
- append_tls_length_value(m_pre_master, psk.bits_of(), 2);
- }
- else if(kex_algo == "SRP_SHA")
- {
- SRP6_Server_Session& srp = state.server_kex()->server_srp_params();
-
- m_pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of();
- }
- else if(kex_algo == "DH" || kex_algo == "DHE_PSK" ||
- kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
- {
- const Private_Key& private_key = state.server_kex()->server_kex_key();
-
- const PK_Key_Agreement_Key* ka_key =
- dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
-
- if(!ka_key)
- throw Internal_Error("Expected key agreement key type but got " +
- private_key.algo_name());
-
- try
- {
- PK_Key_Agreement ka(*ka_key, "Raw");
-
- std::vector<byte> client_pubkey;
-
- if(ka_key->algo_name() == "DH")
- client_pubkey = reader.get_range<byte>(2, 0, 65535);
- else
- client_pubkey = reader.get_range<byte>(1, 0, 255);
-
- secure_vector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
-
- if(ka_key->algo_name() == "DH")
- shared_secret = strip_leading_zeros(shared_secret);
-
- if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
- {
- append_tls_length_value(m_pre_master, shared_secret, 2);
- append_tls_length_value(m_pre_master, psk.bits_of(), 2);
- }
- else
- m_pre_master = shared_secret;
- }
- catch(std::exception &e)
- {
- /*
- * Something failed in the DH computation. To avoid possible
- * timing attacks, randomize the pre-master output and carry
- * on, allowing the protocol to fail later in the finished
- * checks.
- */
- m_pre_master = rng.random_vec(ka_key->public_value().size());
- }
- }
- else
- throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
- }
- }
-
-}
-
-}
diff --git a/src/tls/msg_finished.cpp b/src/tls/msg_finished.cpp
deleted file mode 100644
index c018497c8..000000000
--- a/src/tls/msg_finished.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-* Finished Message
-* (C) 2004-2006,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-/*
-* Compute the verify_data
-*/
-std::vector<byte> finished_compute_verify(const Handshake_State& state,
- Connection_Side side)
- {
- if(state.version() == Protocol_Version::SSL_V3)
- {
- const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 };
- const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 };
-
- Handshake_Hash hash = state.hash(); // don't modify state
-
- std::vector<byte> ssl3_finished;
-
- if(side == CLIENT)
- hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL));
- else
- hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL));
-
- return unlock(hash.final_ssl3(state.session_keys().master_secret()));
- }
- else
- {
- const byte TLS_CLIENT_LABEL[] = {
- 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69,
- 0x73, 0x68, 0x65, 0x64 };
-
- const byte TLS_SERVER_LABEL[] = {
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x66, 0x69, 0x6E, 0x69,
- 0x73, 0x68, 0x65, 0x64 };
-
- std::unique_ptr<KDF> prf(state.protocol_specific_prf());
-
- std::vector<byte> input;
- if(side == CLIENT)
- input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL));
- else
- input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL));
-
- input += state.hash().final(state.version(), state.ciphersuite().prf_algo());
-
- return unlock(prf->derive_key(12, state.session_keys().master_secret(), input));
- }
- }
-
-}
-
-/*
-* Create a new Finished message
-*/
-Finished::Finished(Handshake_IO& io,
- Handshake_State& state,
- Connection_Side side)
- {
- m_verification_data = finished_compute_verify(state, side);
- state.hash().update(io.send(*this));
- }
-
-/*
-* Serialize a Finished message
-*/
-std::vector<byte> Finished::serialize() const
- {
- return m_verification_data;
- }
-
-/*
-* Deserialize a Finished message
-*/
-Finished::Finished(const std::vector<byte>& buf)
- {
- m_verification_data = buf;
- }
-
-/*
-* Verify a Finished message
-*/
-bool Finished::verify(const Handshake_State& state,
- Connection_Side side) const
- {
- return (m_verification_data == finished_compute_verify(state, side));
- }
-
-}
-
-}
diff --git a/src/tls/msg_hello_verify.cpp b/src/tls/msg_hello_verify.cpp
deleted file mode 100644
index f8a117c03..000000000
--- a/src/tls/msg_hello_verify.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-* DTLS Hello Verify Request
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/lookup.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& buf)
- {
- if(buf.size() < 3)
- throw Decoding_Error("Hello verify request too small");
-
- Protocol_Version version(buf[0], buf[1]);
-
- if(version != Protocol_Version::DTLS_V10 &&
- version != Protocol_Version::DTLS_V12)
- {
- throw Decoding_Error("Unknown version from server in hello verify request");
- }
-
- if(static_cast<size_t>(buf[2]) + 3 != buf.size())
- throw Decoding_Error("Bad length in hello verify request");
-
- m_cookie.assign(&buf[3], &buf[buf.size()]);
- }
-
-Hello_Verify_Request::Hello_Verify_Request(const std::vector<byte>& client_hello_bits,
- const std::string& client_identity,
- const SymmetricKey& secret_key)
- {
- std::unique_ptr<MessageAuthenticationCode> hmac(get_mac("HMAC(SHA-256)"));
- hmac->set_key(secret_key);
-
- hmac->update_be(client_hello_bits.size());
- hmac->update(client_hello_bits);
- hmac->update_be(client_identity.size());
- hmac->update(client_identity);
-
- m_cookie = unlock(hmac->final());
- }
-
-std::vector<byte> Hello_Verify_Request::serialize() const
- {
- /* DTLS 1.2 server implementations SHOULD use DTLS version 1.0
- regardless of the version of TLS that is expected to be
- negotiated (RFC 6347, section 4.2.1)
- */
-
- Protocol_Version format_version(Protocol_Version::DTLS_V10);
-
- std::vector<byte> bits;
- bits.push_back(format_version.major_version());
- bits.push_back(format_version.minor_version());
- bits.push_back(static_cast<byte>(m_cookie.size()));
- bits += m_cookie;
- return bits;
- }
-
-}
-
-}
diff --git a/src/tls/msg_next_protocol.cpp b/src/tls/msg_next_protocol.cpp
deleted file mode 100644
index a09fd02d1..000000000
--- a/src/tls/msg_next_protocol.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-* Next Protocol Negotiation
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_handshake_io.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Next_Protocol::Next_Protocol(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::string& protocol) :
- m_protocol(protocol)
- {
- hash.update(io.send(*this));
- }
-
-Next_Protocol::Next_Protocol(const std::vector<byte>& buf)
- {
- TLS_Data_Reader reader(buf);
-
- m_protocol = reader.get_string(1, 0, 255);
-
- reader.get_range_vector<byte>(1, 0, 255); // padding, ignored
- }
-
-std::vector<byte> Next_Protocol::serialize() const
- {
- std::vector<byte> buf;
-
- append_tls_length_value(buf,
- reinterpret_cast<const byte*>(m_protocol.data()),
- m_protocol.size(),
- 1);
-
- const byte padding_len = 32 - ((m_protocol.size() + 2) % 32);
-
- buf.push_back(padding_len);
-
- for(size_t i = 0; i != padding_len; ++i)
- buf.push_back(0);
-
- return buf;
- }
-
-}
-
-}
diff --git a/src/tls/msg_server_hello.cpp b/src/tls/msg_server_hello.cpp
deleted file mode 100644
index a775e0b4b..000000000
--- a/src/tls/msg_server_hello.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-;/*
-* TLS Server Hello and Server Hello Done
-* (C) 2004-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_session_key.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/internal/stl_util.h>
-
-namespace Botan {
-
-namespace TLS {
-
-/*
-* Create a new Server Hello message
-*/
-Server_Hello::Server_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- const std::vector<byte>& session_id,
- Protocol_Version ver,
- u16bit ciphersuite,
- byte compression,
- size_t max_fragment_size,
- bool client_has_secure_renegotiation,
- const std::vector<byte>& reneg_info,
- bool offer_session_ticket,
- bool client_has_npn,
- const std::vector<std::string>& next_protocols,
- bool client_has_heartbeat,
- RandomNumberGenerator& rng) :
- m_version(ver),
- m_session_id(session_id),
- m_random(make_hello_random(rng)),
- m_ciphersuite(ciphersuite),
- m_comp_method(compression)
- {
- if(client_has_heartbeat && policy.negotiate_heartbeat_support())
- m_extensions.add(new Heartbeat_Support_Indicator(true));
-
- /*
- * Even a client that offered SSLv3 and sent the SCSV will get an
- * extension back. This is probably the right thing to do.
- */
- if(client_has_secure_renegotiation)
- m_extensions.add(new Renegotiation_Extension(reneg_info));
-
- if(max_fragment_size)
- m_extensions.add(new Maximum_Fragment_Length(max_fragment_size));
-
- if(client_has_npn)
- m_extensions.add(new Next_Protocol_Notification(next_protocols));
-
- if(offer_session_ticket)
- m_extensions.add(new Session_Ticket());
-
- hash.update(io.send(*this));
- }
-
-/*
-* Deserialize a Server Hello message
-*/
-Server_Hello::Server_Hello(const std::vector<byte>& buf)
- {
- if(buf.size() < 38)
- throw Decoding_Error("Server_Hello: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- const byte major_version = reader.get_byte();
- const byte minor_version = reader.get_byte();
-
- m_version = Protocol_Version(major_version, minor_version);
-
- m_random = reader.get_fixed<byte>(32);
-
- m_session_id = reader.get_range<byte>(1, 0, 32);
-
- m_ciphersuite = reader.get_u16bit();
-
- m_comp_method = reader.get_byte();
-
- m_extensions.deserialize(reader);
- }
-
-/*
-* Serialize a Server Hello message
-*/
-std::vector<byte> Server_Hello::serialize() const
- {
- std::vector<byte> buf;
-
- buf.push_back(m_version.major_version());
- buf.push_back(m_version.minor_version());
- buf += m_random;
-
- append_tls_length_value(buf, m_session_id, 1);
-
- buf.push_back(get_byte(0, m_ciphersuite));
- buf.push_back(get_byte(1, m_ciphersuite));
-
- buf.push_back(m_comp_method);
-
- buf += m_extensions.serialize();
-
- return buf;
- }
-
-/*
-* Create a new Server Hello Done message
-*/
-Server_Hello_Done::Server_Hello_Done(Handshake_IO& io,
- Handshake_Hash& hash)
- {
- hash.update(io.send(*this));
- }
-
-/*
-* Deserialize a Server Hello Done message
-*/
-Server_Hello_Done::Server_Hello_Done(const std::vector<byte>& buf)
- {
- if(buf.size())
- throw Decoding_Error("Server_Hello_Done: Must be empty, and is not");
- }
-
-/*
-* Serialize a Server Hello Done message
-*/
-std::vector<byte> Server_Hello_Done::serialize() const
- {
- return std::vector<byte>();
- }
-
-}
-
-}
diff --git a/src/tls/msg_server_kex.cpp b/src/tls/msg_server_kex.cpp
deleted file mode 100644
index b8293d3e8..000000000
--- a/src/tls/msg_server_kex.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
-* Server Key Exchange Message
-* (C) 2004-2010,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/credentials_manager.h>
-#include <botan/loadstor.h>
-#include <botan/pubkey.h>
-#include <botan/dh.h>
-#include <botan/ecdh.h>
-#include <botan/rsa.h>
-#include <botan/srp6.h>
-#include <botan/oids.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Create a new Server Key Exchange message
-*/
-Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- Credentials_Manager& creds,
- RandomNumberGenerator& rng,
- const Private_Key* signing_key)
- {
- const std::string hostname = state.client_hello()->sni_hostname();
- const std::string kex_algo = state.ciphersuite().kex_algo();
-
- if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
- {
- std::string identity_hint =
- creds.psk_identity_hint("tls-server", hostname);
-
- append_tls_length_value(m_params, identity_hint, 2);
- }
-
- if(kex_algo == "DH" || kex_algo == "DHE_PSK")
- {
- std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, policy.dh_group()));
-
- append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
- append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
- append_tls_length_value(m_params, dh->public_value(), 2);
- m_kex_key.reset(dh.release());
- }
- else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
- {
- const std::vector<std::string>& curves =
- state.client_hello()->supported_ecc_curves();
-
- if(curves.empty())
- throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
-
- const std::string curve_name = policy.choose_curve(curves);
-
- if(curve_name == "")
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Could not agree on an ECC curve with the client");
-
- EC_Group ec_group(curve_name);
-
- std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group));
-
- const std::string ecdh_domain_oid = ecdh->domain().get_oid();
- const std::string domain = OIDS::lookup(OID(ecdh_domain_oid));
-
- if(domain == "")
- throw Internal_Error("Could not find name of ECDH domain " + ecdh_domain_oid);
-
- const u16bit named_curve_id = Supported_Elliptic_Curves::name_to_curve_id(domain);
-
- m_params.push_back(3); // named curve
- m_params.push_back(get_byte(0, named_curve_id));
- m_params.push_back(get_byte(1, named_curve_id));
-
- append_tls_length_value(m_params, ecdh->public_value(), 1);
-
- m_kex_key.reset(ecdh.release());
- }
- else if(kex_algo == "SRP_SHA")
- {
- const std::string srp_identifier = state.client_hello()->srp_identifier();
-
- std::string group_id;
- BigInt v;
- std::vector<byte> salt;
-
- const bool found = creds.srp_verifier("tls-server", hostname,
- srp_identifier,
- group_id, v, salt,
- policy.hide_unknown_users());
-
- if(!found)
- throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
- "Unknown SRP user " + srp_identifier);
-
- m_srp_params.reset(new SRP6_Server_Session);
-
- BigInt B = m_srp_params->step1(v, group_id,
- "SHA-1", rng);
-
- DL_Group group(group_id);
-
- append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2);
- append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2);
- append_tls_length_value(m_params, salt, 1);
- append_tls_length_value(m_params, BigInt::encode(B), 2);
- }
- else if(kex_algo != "PSK")
- throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo);
-
- if(state.ciphersuite().sig_algo() != "")
- {
- BOTAN_ASSERT(signing_key, "Signing key was set");
-
- std::pair<std::string, Signature_Format> format =
- state.choose_sig_format(*signing_key, m_hash_algo, m_sig_algo, false, policy);
-
- PK_Signer signer(*signing_key, format.first, format.second);
-
- signer.update(state.client_hello()->random());
- signer.update(state.server_hello()->random());
- signer.update(params());
- m_signature = signer.signature(rng);
- }
-
- state.hash().update(io.send(*this));
- }
-
-/**
-* Deserialize a Server Key Exchange message
-*/
-Server_Key_Exchange::Server_Key_Exchange(const std::vector<byte>& buf,
- const std::string& kex_algo,
- const std::string& sig_algo,
- Protocol_Version version) :
- m_kex_key(nullptr), m_srp_params(nullptr)
- {
- if(buf.size() < 6)
- throw Decoding_Error("Server_Key_Exchange: Packet corrupted");
-
- TLS_Data_Reader reader(buf);
-
- /*
- * We really are just serializing things back to what they were
- * before, but unfortunately to know where the signature is we need
- * to be able to parse the whole thing anyway.
- */
-
- if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
- {
- const std::string identity_hint = reader.get_string(2, 0, 65535);
- append_tls_length_value(m_params, identity_hint, 2);
- }
-
- if(kex_algo == "DH" || kex_algo == "DHE_PSK")
- {
- // 3 bigints, DH p, g, Y
-
- for(size_t i = 0; i != 3; ++i)
- {
- BigInt v = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- append_tls_length_value(m_params, BigInt::encode(v), 2);
- }
- }
- else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
- {
- const byte curve_type = reader.get_byte();
-
- if(curve_type != 3)
- throw Decoding_Error("Server_Key_Exchange: Server sent non-named ECC curve");
-
- const u16bit curve_id = reader.get_u16bit();
-
- const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);
-
- std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);
-
- if(name == "")
- throw Decoding_Error("Server_Key_Exchange: Server sent unknown named curve " +
- std::to_string(curve_id));
-
- m_params.push_back(curve_type);
- m_params.push_back(get_byte(0, curve_id));
- m_params.push_back(get_byte(1, curve_id));
- append_tls_length_value(m_params, ecdh_key, 1);
- }
- else if(kex_algo == "SRP_SHA")
- {
- // 2 bigints (N,g) then salt, then server B
-
- const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
- std::vector<byte> salt = reader.get_range<byte>(1, 1, 255);
- const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
-
- append_tls_length_value(m_params, BigInt::encode(N), 2);
- append_tls_length_value(m_params, BigInt::encode(g), 2);
- append_tls_length_value(m_params, salt, 1);
- append_tls_length_value(m_params, BigInt::encode(B), 2);
- }
- else if(kex_algo != "PSK")
- throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo);
-
- if(sig_algo != "")
- {
- if(version.supports_negotiable_signature_algorithms())
- {
- m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte());
- m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte());
- }
-
- m_signature = reader.get_range<byte>(2, 0, 65535);
- }
-
- reader.assert_done();
- }
-
-Server_Key_Exchange::~Server_Key_Exchange() {}
-
-/**
-* Serialize a Server Key Exchange message
-*/
-std::vector<byte> Server_Key_Exchange::serialize() const
- {
- std::vector<byte> buf = params();
-
- if(m_signature.size())
- {
- // This should be an explicit version check
- if(m_hash_algo != "" && m_sig_algo != "")
- {
- buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
- buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
- }
-
- append_tls_length_value(buf, m_signature, 2);
- }
-
- return buf;
- }
-
-/**
-* Verify a Server Key Exchange message
-*/
-bool Server_Key_Exchange::verify(const Public_Key& server_key,
- const Handshake_State& state) const
- {
- std::pair<std::string, Signature_Format> format =
- state.understand_sig_format(server_key, m_hash_algo, m_sig_algo, false);
-
- PK_Verifier verifier(server_key, format.first, format.second);
-
- verifier.update(state.client_hello()->random());
- verifier.update(state.server_hello()->random());
- verifier.update(params());
-
- return verifier.check_signature(m_signature);
- }
-
-const Private_Key& Server_Key_Exchange::server_kex_key() const
- {
- BOTAN_ASSERT_NONNULL(m_kex_key);
- return *m_kex_key;
- }
-
-// Only valid for SRP negotiation
-SRP6_Server_Session& Server_Key_Exchange::server_srp_params() const
- {
- BOTAN_ASSERT_NONNULL(m_srp_params);
- return *m_srp_params;
- }
-}
-
-}
diff --git a/src/tls/msg_session_ticket.cpp b/src/tls/msg_session_ticket.cpp
deleted file mode 100644
index 2bb9987a9..000000000
--- a/src/tls/msg_session_ticket.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-* Session Tickets
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-namespace TLS {
-
-New_Session_Ticket::New_Session_Ticket(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::vector<byte>& ticket,
- u32bit lifetime) :
- m_ticket_lifetime_hint(lifetime),
- m_ticket(ticket)
- {
- hash.update(io.send(*this));
- }
-
-New_Session_Ticket::New_Session_Ticket(Handshake_IO& io,
- Handshake_Hash& hash) :
- m_ticket_lifetime_hint(0)
- {
- hash.update(io.send(*this));
- }
-
-New_Session_Ticket::New_Session_Ticket(const std::vector<byte>& buf) :
- m_ticket_lifetime_hint(0)
- {
- if(buf.size() < 6)
- throw Decoding_Error("Session ticket message too short to be valid");
-
- TLS_Data_Reader reader(buf);
-
- m_ticket_lifetime_hint = reader.get_u32bit();
- m_ticket = reader.get_range<byte>(2, 0, 65535);
- }
-
-std::vector<byte> New_Session_Ticket::serialize() const
- {
- std::vector<byte> buf(4);
- store_be(m_ticket_lifetime_hint, &buf[0]);
- append_tls_length_value(buf, m_ticket, 2);
- return buf;
- }
-
-}
-
-}
diff --git a/src/tls/sessions_sqlite/info.txt b/src/tls/sessions_sqlite/info.txt
deleted file mode 100644
index 76d53f995..000000000
--- a/src/tls/sessions_sqlite/info.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-define TLS_SQLITE3_SESSION_MANAGER 20131128
-
-<requires>
-pbkdf2
-sqlite3
-</requires>
diff --git a/src/tls/sessions_sqlite/tls_session_manager_sqlite.cpp b/src/tls/sessions_sqlite/tls_session_manager_sqlite.cpp
deleted file mode 100644
index d4f286a8d..000000000
--- a/src/tls/sessions_sqlite/tls_session_manager_sqlite.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-* SQLite TLS Session Manager
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_session_manager_sqlite.h>
-#include <botan/internal/sqlite3.h>
-#include <botan/lookup.h>
-#include <botan/hex.h>
-#include <botan/loadstor.h>
-#include <memory>
-#include <chrono>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-SymmetricKey derive_key(const std::string& passphrase,
- const byte salt[],
- size_t salt_len,
- size_t iterations,
- size_t& check_val)
- {
- std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-512)"));
-
- secure_vector<byte> x = pbkdf->derive_key(32 + 2,
- passphrase,
- salt, salt_len,
- iterations).bits_of();
-
- check_val = make_u16bit(x[0], x[1]);
- return SymmetricKey(&x[2], x.size() - 2);
- }
-
-}
-
-Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase,
- RandomNumberGenerator& rng,
- const std::string& db_filename,
- size_t max_sessions,
- std::chrono::seconds session_lifetime) :
- m_rng(rng),
- m_max_sessions(max_sessions),
- m_session_lifetime(session_lifetime)
- {
- m_db = new sqlite3_database(db_filename);
-
- m_db->create_table(
- "create table if not exists tls_sessions "
- "("
- "session_id TEXT PRIMARY KEY, "
- "session_start INTEGER, "
- "hostname TEXT, "
- "hostport INTEGER, "
- "session BLOB"
- ")");
-
- m_db->create_table(
- "create table if not exists tls_sessions_metadata "
- "("
- "passphrase_salt BLOB, "
- "passphrase_iterations INTEGER, "
- "passphrase_check INTEGER "
- ")");
-
- const size_t salts = m_db->row_count("tls_sessions_metadata");
-
- if(salts == 1)
- {
- // existing db
- sqlite3_statement stmt(m_db, "select * from tls_sessions_metadata");
-
- if(stmt.step())
- {
- std::pair<const byte*, size_t> salt = stmt.get_blob(0);
- const size_t iterations = stmt.get_size_t(1);
- const size_t check_val_db = stmt.get_size_t(2);
-
- size_t check_val_created;
- m_session_key = derive_key(passphrase,
- salt.first,
- salt.second,
- iterations,
- check_val_created);
-
- if(check_val_created != check_val_db)
- throw std::runtime_error("Session database password not valid");
- }
- }
- else
- {
- // maybe just zap the salts + sessions tables in this case?
- if(salts != 0)
- throw std::runtime_error("Seemingly corrupted database, multiple salts found");
-
- // new database case
-
- std::vector<byte> salt = unlock(rng.random_vec(16));
- const size_t iterations = 256 * 1024;
- size_t check_val = 0;
-
- m_session_key = derive_key(passphrase, &salt[0], salt.size(),
- iterations, check_val);
-
- sqlite3_statement stmt(m_db, "insert into tls_sessions_metadata"
- " values(?1, ?2, ?3)");
-
- stmt.bind(1, salt);
- stmt.bind(2, iterations);
- stmt.bind(3, check_val);
-
- stmt.spin();
- }
- }
-
-Session_Manager_SQLite::~Session_Manager_SQLite()
- {
- delete m_db;
- }
-
-bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& session_id,
- Session& session)
- {
- sqlite3_statement stmt(m_db, "select session from tls_sessions where session_id = ?1");
-
- stmt.bind(1, hex_encode(session_id));
-
- while(stmt.step())
- {
- std::pair<const byte*, size_t> blob = stmt.get_blob(0);
-
- try
- {
- session = Session::decrypt(blob.first, blob.second, m_session_key);
- return true;
- }
- catch(...)
- {
- }
- }
-
- return false;
- }
-
-bool Session_Manager_SQLite::load_from_server_info(const Server_Information& server,
- Session& session)
- {
- sqlite3_statement stmt(m_db, "select session from tls_sessions"
- " where hostname = ?1 and hostport = ?2"
- " order by session_start desc");
-
- stmt.bind(1, server.hostname());
- stmt.bind(2, server.port());
-
- while(stmt.step())
- {
- std::pair<const byte*, size_t> blob = stmt.get_blob(0);
-
- try
- {
- session = Session::decrypt(blob.first, blob.second, m_session_key);
- return true;
- }
- catch(...)
- {
- }
- }
-
- return false;
- }
-
-void Session_Manager_SQLite::remove_entry(const std::vector<byte>& session_id)
- {
- sqlite3_statement stmt(m_db, "delete from tls_sessions where session_id = ?1");
-
- stmt.bind(1, hex_encode(session_id));
-
- stmt.spin();
- }
-
-void Session_Manager_SQLite::save(const Session& session)
- {
- sqlite3_statement stmt(m_db, "insert or replace into tls_sessions"
- " values(?1, ?2, ?3, ?4, ?5)");
-
- stmt.bind(1, hex_encode(session.session_id()));
- stmt.bind(2, session.start_time());
- stmt.bind(3, session.server_info().hostname());
- stmt.bind(4, session.server_info().port());
- stmt.bind(5, session.encrypt(m_session_key, m_rng));
-
- stmt.spin();
-
- prune_session_cache();
- }
-
-void Session_Manager_SQLite::prune_session_cache()
- {
- sqlite3_statement remove_expired(m_db, "delete from tls_sessions where session_start <= ?1");
-
- remove_expired.bind(1, std::chrono::system_clock::now() - m_session_lifetime);
-
- remove_expired.spin();
-
- const size_t sessions = m_db->row_count("tls_sessions");
-
- if(sessions > m_max_sessions)
- {
- sqlite3_statement remove_some(m_db, "delete from tls_sessions where session_id in "
- "(select session_id from tls_sessions limit ?1)");
-
- remove_some.bind(1, sessions - m_max_sessions);
- remove_some.spin();
- }
- }
-
-}
-
-}
diff --git a/src/tls/sessions_sqlite/tls_session_manager_sqlite.h b/src/tls/sessions_sqlite/tls_session_manager_sqlite.h
deleted file mode 100644
index 7892ccd6a..000000000
--- a/src/tls/sessions_sqlite/tls_session_manager_sqlite.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-* SQLite3 TLS Session Manager
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SQLITE3_SESSION_MANAGER_H__
-#define BOTAN_TLS_SQLITE3_SESSION_MANAGER_H__
-
-#include <botan/tls_session_manager.h>
-#include <botan/rng.h>
-
-namespace Botan {
-
-class sqlite3_database;
-
-namespace TLS {
-
-/**
-* An implementation of Session_Manager that saves values in a SQLite3
-* database file, with the session data encrypted using a passphrase.
-*
-* @warning For clients, the hostnames associated with the saved
-* sessions are stored in the database in plaintext. This may be a
-* serious privacy risk in some situations.
-*/
-class BOTAN_DLL Session_Manager_SQLite : public Session_Manager
- {
- public:
- /**
- * @param passphrase used to encrypt the session data
- * @param rng a random number generator
- * @param db_filename filename of the SQLite database file.
- The table names tls_sessions and tls_sessions_metadata
- will be used
- * @param max_sessions a hint on the maximum number of sessions
- * to keep in memory at any one time. (If zero, don't cap)
- * @param session_lifetime sessions are expired after this many
- * seconds have elapsed from initial handshake.
- */
- Session_Manager_SQLite(const std::string& passphrase,
- RandomNumberGenerator& rng,
- const std::string& db_filename,
- size_t max_sessions = 1000,
- std::chrono::seconds session_lifetime = std::chrono::seconds(7200));
-
- ~Session_Manager_SQLite();
-
- bool load_from_session_id(const std::vector<byte>& session_id,
- Session& session) override;
-
- bool load_from_server_info(const Server_Information& info,
- Session& session) override;
-
- void remove_entry(const std::vector<byte>& session_id) override;
-
- void save(const Session& session_data) override;
-
- std::chrono::seconds session_lifetime() const override
- { return m_session_lifetime; }
-
- private:
- Session_Manager_SQLite(const Session_Manager_SQLite&);
- Session_Manager_SQLite& operator=(const Session_Manager_SQLite&);
-
- void prune_session_cache();
-
- SymmetricKey m_session_key;
- RandomNumberGenerator& m_rng;
- size_t m_max_sessions;
- std::chrono::seconds m_session_lifetime;
- sqlite3_database* m_db;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_alert.cpp b/src/tls/tls_alert.cpp
deleted file mode 100644
index 15bb2a2dc..000000000
--- a/src/tls/tls_alert.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-* Alert Message
-* (C) 2004-2006,2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_alert.h>
-#include <botan/exceptn.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Alert::Alert(const secure_vector<byte>& buf)
- {
- if(buf.size() != 2)
- throw Decoding_Error("Alert: Bad size " + std::to_string(buf.size()) +
- " for alert message");
-
- if(buf[0] == 1) m_fatal = false;
- else if(buf[0] == 2) m_fatal = true;
- else
- throw Decoding_Error("Alert: Bad code for alert level");
-
- const byte dc = buf[1];
-
- m_type_code = static_cast<Type>(dc);
- }
-
-std::vector<byte> Alert::serialize() const
- {
- return std::vector<byte>({
- static_cast<byte>(is_fatal() ? 2 : 1),
- static_cast<byte>(type())
- });
- }
-
-std::string Alert::type_string() const
- {
- switch(type())
- {
- case CLOSE_NOTIFY:
- return "close_notify";
- case UNEXPECTED_MESSAGE:
- return "unexpected_message";
- case BAD_RECORD_MAC:
- return "bad_record_mac";
- case DECRYPTION_FAILED:
- return "decryption_failed";
- case RECORD_OVERFLOW:
- return "record_overflow";
- case DECOMPRESSION_FAILURE:
- return "decompression_failure";
- case HANDSHAKE_FAILURE:
- return "handshake_failure";
- case NO_CERTIFICATE:
- return "no_certificate";
- case BAD_CERTIFICATE:
- return "bad_certificate";
- case UNSUPPORTED_CERTIFICATE:
- return "unsupported_certificate";
- case CERTIFICATE_REVOKED:
- return "certificate_revoked";
- case CERTIFICATE_EXPIRED:
- return "certificate_expired";
- case CERTIFICATE_UNKNOWN:
- return "certificate_unknown";
- case ILLEGAL_PARAMETER:
- return "illegal_parameter";
- case UNKNOWN_CA:
- return "unknown_ca";
- case ACCESS_DENIED:
- return "access_denied";
- case DECODE_ERROR:
- return "decode_error";
- case DECRYPT_ERROR:
- return "decrypt_error";
- case EXPORT_RESTRICTION:
- return "export_restriction";
- case PROTOCOL_VERSION:
- return "protocol_version";
- case INSUFFICIENT_SECURITY:
- return "insufficient_security";
- case INTERNAL_ERROR:
- return "internal_error";
- case USER_CANCELED:
- return "user_canceled";
- case NO_RENEGOTIATION:
- return "no_renegotiation";
-
- case UNSUPPORTED_EXTENSION:
- return "unsupported_extension";
- case CERTIFICATE_UNOBTAINABLE:
- return "certificate_unobtainable";
- case UNRECOGNIZED_NAME:
- return "unrecognized_name";
- case BAD_CERTIFICATE_STATUS_RESPONSE:
- return "bad_certificate_status_response";
- case BAD_CERTIFICATE_HASH_VALUE:
- return "bad_certificate_hash_value";
- case UNKNOWN_PSK_IDENTITY:
- return "unknown_psk_identity";
-
- case NULL_ALERT:
- return "none";
-
- case HEARTBEAT_PAYLOAD:
- return "heartbeat_payload";
- }
-
- /*
- * This is effectively the default case for the switch above, but we
- * leave it out so that when an alert type is added to the enum the
- * compiler can warn us that it is not included in the switch
- * statement.
- */
- return "unrecognized_alert_" + std::to_string(type());
- }
-
-}
-
-}
diff --git a/src/tls/tls_alert.h b/src/tls/tls_alert.h
deleted file mode 100644
index bf32178ee..000000000
--- a/src/tls/tls_alert.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-* Alert Message
-* (C) 2004-2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_ALERT_H__
-#define BOTAN_TLS_ALERT_H__
-
-#include <botan/secmem.h>
-#include <string>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* SSL/TLS Alert Message
-*/
-class BOTAN_DLL Alert
- {
- public:
- /**
- * Type codes for TLS alerts
- */
- enum Type {
- CLOSE_NOTIFY = 0,
- UNEXPECTED_MESSAGE = 10,
- BAD_RECORD_MAC = 20,
- DECRYPTION_FAILED = 21,
- RECORD_OVERFLOW = 22,
- DECOMPRESSION_FAILURE = 30,
- HANDSHAKE_FAILURE = 40,
- NO_CERTIFICATE = 41, // SSLv3 only
- BAD_CERTIFICATE = 42,
- UNSUPPORTED_CERTIFICATE = 43,
- CERTIFICATE_REVOKED = 44,
- CERTIFICATE_EXPIRED = 45,
- CERTIFICATE_UNKNOWN = 46,
- ILLEGAL_PARAMETER = 47,
- UNKNOWN_CA = 48,
- ACCESS_DENIED = 49,
- DECODE_ERROR = 50,
- DECRYPT_ERROR = 51,
- EXPORT_RESTRICTION = 60,
- PROTOCOL_VERSION = 70,
- INSUFFICIENT_SECURITY = 71,
- INTERNAL_ERROR = 80,
- USER_CANCELED = 90,
- NO_RENEGOTIATION = 100,
- UNSUPPORTED_EXTENSION = 110,
- CERTIFICATE_UNOBTAINABLE = 111,
- UNRECOGNIZED_NAME = 112,
- BAD_CERTIFICATE_STATUS_RESPONSE = 113,
- BAD_CERTIFICATE_HASH_VALUE = 114,
- UNKNOWN_PSK_IDENTITY = 115,
-
- // pseudo alert values
- NULL_ALERT = 256,
- HEARTBEAT_PAYLOAD = 257
- };
-
- /**
- * @return true iff this alert is non-empty
- */
- bool is_valid() const { return (m_type_code != NULL_ALERT); }
-
- /**
- * @return if this alert is a fatal one or not
- */
- bool is_fatal() const { return m_fatal; }
-
- /**
- * @return type of alert
- */
- Type type() const { return m_type_code; }
-
- /**
- * @return type of alert
- */
- std::string type_string() const;
-
- /**
- * Serialize an alert
- */
- std::vector<byte> serialize() const;
-
- /**
- * Deserialize an Alert message
- * @param buf the serialized alert
- */
- Alert(const secure_vector<byte>& buf);
-
- /**
- * Create a new Alert
- * @param type_code the type of alert
- * @param fatal specifies if this is a fatal alert
- */
- Alert(Type type_code, bool fatal = false) :
- m_fatal(fatal), m_type_code(type_code) {}
-
- Alert() : m_fatal(false), m_type_code(NULL_ALERT) {}
- private:
- bool m_fatal;
- Type m_type_code;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_blocking.cpp b/src/tls/tls_blocking.cpp
deleted file mode 100644
index 4b33ba926..000000000
--- a/src/tls/tls_blocking.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-* TLS Blocking API
-* (C) 2013 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_blocking.h>
-
-namespace Botan {
-
-namespace TLS {
-
-using namespace std::placeholders;
-
-Blocking_Client::Blocking_Client(std::function<size_t (byte[], size_t)> read_fn,
- std::function<void (const byte[], size_t)> write_fn,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Server_Information& server_info,
- const Protocol_Version offer_version,
- std::function<std::string (std::vector<std::string>)> next_protocol) :
- m_read_fn(read_fn),
- m_channel(write_fn,
- std::bind(&Blocking_Client::data_cb, this, _1, _2),
- std::bind(&Blocking_Client::alert_cb, this, _1, _2, _3),
- std::bind(&Blocking_Client::handshake_cb, this, _1),
- session_manager,
- creds,
- policy,
- rng,
- server_info,
- offer_version,
- next_protocol)
- {
- }
-
-bool Blocking_Client::handshake_cb(const Session& session)
- {
- return this->handshake_complete(session);
- }
-
-void Blocking_Client::alert_cb(const Alert alert, const byte[], size_t)
- {
- this->alert_notification(alert);
- }
-
-void Blocking_Client::data_cb(const byte data[], size_t data_len)
- {
- m_plaintext.insert(m_plaintext.end(), data, data + data_len);
- }
-
-void Blocking_Client::do_handshake()
- {
- std::vector<byte> readbuf(4096);
-
- while(!m_channel.is_closed() && !m_channel.is_active())
- {
- const size_t from_socket = m_read_fn(&readbuf[0], readbuf.size());
- m_channel.received_data(&readbuf[0], from_socket);
- }
- }
-
-size_t Blocking_Client::read(byte buf[], size_t buf_len)
- {
- std::vector<byte> readbuf(4096);
-
- while(m_plaintext.empty() && !m_channel.is_closed())
- {
- const size_t from_socket = m_read_fn(&readbuf[0], readbuf.size());
- m_channel.received_data(&readbuf[0], from_socket);
- }
-
- const size_t returned = std::min(buf_len, m_plaintext.size());
-
- for(size_t i = 0; i != returned; ++i)
- buf[i] = m_plaintext[i];
- m_plaintext.erase(m_plaintext.begin(), m_plaintext.begin() + returned);
-
- BOTAN_ASSERT_IMPLICATION(returned == 0, m_channel.is_closed(),
- "Only return zero if channel is closed");
-
- return returned;
- }
-
-}
-
-}
diff --git a/src/tls/tls_blocking.h b/src/tls/tls_blocking.h
deleted file mode 100644
index cfa96ce8d..000000000
--- a/src/tls/tls_blocking.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
-* TLS Blocking API
-* (C) 2013 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_BLOCKING_CHANNELS_H__
-#define BOTAN_TLS_BLOCKING_CHANNELS_H__
-
-#include <botan/tls_client.h>
-#include <botan/tls_server.h>
-#include <deque>
-
-namespace Botan {
-
-template<typename T> using secure_deque = std::vector<T, secure_allocator<T>>;
-
-namespace TLS {
-
-/**
-* Blocking TLS Client
-*/
-class BOTAN_DLL Blocking_Client
- {
- public:
-
- Blocking_Client(std::function<size_t (byte[], size_t)> read_fn,
- std::function<void (const byte[], size_t)> write_fn,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Server_Information& server_info = Server_Information(),
- const Protocol_Version offer_version = Protocol_Version::latest_tls_version(),
- std::function<std::string (std::vector<std::string>)> next_protocol =
- std::function<std::string (std::vector<std::string>)>());
-
- /**
- * Completes full handshake then returns
- */
- void do_handshake();
-
- /**
- * Number of bytes pending read in the plaintext buffer (bytes
- * readable without blocking)
- */
- size_t pending() const { return m_plaintext.size(); }
-
- /**
- * Blocking read, will return at least 1 byte or 0 on connection close
- */
- size_t read(byte buf[], size_t buf_len);
-
- void write(const byte buf[], size_t buf_len) { m_channel.send(buf, buf_len); }
-
- const TLS::Channel& underlying_channel() const { return m_channel; }
- TLS::Channel& underlying_channel() { return m_channel; }
-
- void close() { m_channel.close(); }
-
- bool is_closed() const { return m_channel.is_closed(); }
-
- std::vector<X509_Certificate> peer_cert_chain() const
- { return m_channel.peer_cert_chain(); }
-
- virtual ~Blocking_Client() {}
-
- protected:
- /**
- * Can override to get the handshake complete notification
- */
- virtual bool handshake_complete(const Session&) { return true; }
-
- /**
- * Can override to get notification of alerts
- */
- virtual void alert_notification(const Alert&) {}
-
- private:
-
- bool handshake_cb(const Session&);
-
- void data_cb(const byte data[], size_t data_len);
-
- void alert_cb(const Alert alert, const byte data[], size_t data_len);
-
- std::function<size_t (byte[], size_t)> m_read_fn;
- TLS::Client m_channel;
- secure_deque<byte> m_plaintext;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
deleted file mode 100644
index 8ed876b3f..000000000
--- a/src/tls/tls_channel.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
-* TLS Channels
-* (C) 2011-2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_channel.h>
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_heartbeats.h>
-#include <botan/internal/tls_record.h>
-#include <botan/internal/tls_seq_numbers.h>
-#include <botan/internal/rounding.h>
-#include <botan/internal/stl_util.h>
-#include <botan/loadstor.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Channel::Channel(std::function<void (const byte[], size_t)> output_fn,
- std::function<void (const byte[], size_t)> data_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- RandomNumberGenerator& rng,
- size_t reserved_io_buffer_size) :
- m_handshake_cb(handshake_cb),
- m_data_cb(data_cb),
- m_alert_cb(alert_cb),
- m_output_fn(output_fn),
- m_rng(rng),
- m_session_manager(session_manager)
- {
- m_writebuf.reserve(reserved_io_buffer_size);
- m_readbuf.reserve(reserved_io_buffer_size);
- }
-
-void Channel::reset_state()
- {
- m_active_state.reset();
- m_pending_state.reset();
- m_readbuf.clear();
- m_write_cipher_states.clear();
- m_read_cipher_states.clear();
- }
-
-Channel::~Channel()
- {
- // So unique_ptr destructors run correctly
- }
-
-Connection_Sequence_Numbers& Channel::sequence_numbers() const
- {
- BOTAN_ASSERT(m_sequence_numbers, "Have a sequence numbers object");
- return *m_sequence_numbers;
- }
-
-std::shared_ptr<Connection_Cipher_State> Channel::read_cipher_state_epoch(u16bit epoch) const
- {
- auto i = m_read_cipher_states.find(epoch);
-
- BOTAN_ASSERT(i != m_read_cipher_states.end(),
- "Have a cipher state for the specified epoch");
-
- return i->second;
- }
-
-std::shared_ptr<Connection_Cipher_State> Channel::write_cipher_state_epoch(u16bit epoch) const
- {
- auto i = m_write_cipher_states.find(epoch);
-
- BOTAN_ASSERT(i != m_write_cipher_states.end(),
- "Have a cipher state for the specified epoch");
-
- return i->second;
- }
-
-std::vector<X509_Certificate> Channel::peer_cert_chain() const
- {
- if(auto active = active_state())
- return get_peer_cert_chain(*active);
- return std::vector<X509_Certificate>();
- }
-
-Handshake_State& Channel::create_handshake_state(Protocol_Version version)
- {
- if(pending_state())
- throw Internal_Error("create_handshake_state called during handshake");
-
- if(auto active = active_state())
- {
- Protocol_Version active_version = active->version();
-
- if(active_version.is_datagram_protocol() != version.is_datagram_protocol())
- throw std::runtime_error("Active state using version " +
- active_version.to_string() +
- " cannot change to " +
- version.to_string() +
- " in pending");
- }
-
- if(!m_sequence_numbers)
- {
- if(version.is_datagram_protocol())
- m_sequence_numbers.reset(new Datagram_Sequence_Numbers);
- else
- m_sequence_numbers.reset(new Stream_Sequence_Numbers);
- }
-
- std::unique_ptr<Handshake_IO> io;
- if(version.is_datagram_protocol())
- io.reset(new Datagram_Handshake_IO(
- sequence_numbers(),
- std::bind(&Channel::send_record_under_epoch, this,
- std::placeholders::_1,
- std::placeholders::_2,
- std::placeholders::_3)));
- else
- io.reset(new Stream_Handshake_IO(
- std::bind(&Channel::send_record, this,
- std::placeholders::_1,
- std::placeholders::_2)));
-
- m_pending_state.reset(new_handshake_state(io.release()));
-
- if(auto active = active_state())
- m_pending_state->set_version(active->version());
-
- return *m_pending_state.get();
- }
-
-void Channel::renegotiate(bool force_full_renegotiation)
- {
- if(pending_state()) // currently in handshake?
- return;
-
- if(auto active = active_state())
- initiate_handshake(create_handshake_state(active->version()),
- force_full_renegotiation);
- else
- throw std::runtime_error("Cannot renegotiate on inactive connection");
- }
-
-size_t Channel::maximum_fragment_size() const
- {
- // should we be caching this value?
-
- if(auto pending = pending_state())
- if(auto server_hello = pending->server_hello())
- if(size_t frag = server_hello->fragment_size())
- return frag;
-
- if(auto active = active_state())
- if(size_t frag = active->server_hello()->fragment_size())
- return frag;
-
- return MAX_PLAINTEXT_SIZE;
- }
-
-void Channel::change_cipher_spec_reader(Connection_Side side)
- {
- auto pending = pending_state();
-
- BOTAN_ASSERT(pending && pending->server_hello(),
- "Have received server hello");
-
- if(pending->server_hello()->compression_method() != NO_COMPRESSION)
- throw Internal_Error("Negotiated unknown compression algorithm");
-
- sequence_numbers().new_read_cipher_state();
-
- const u16bit epoch = sequence_numbers().current_read_epoch();
-
- BOTAN_ASSERT(m_read_cipher_states.count(epoch) == 0,
- "No read cipher state currently set for next epoch");
-
- // flip side as we are reading
- std::shared_ptr<Connection_Cipher_State> read_state(
- new Connection_Cipher_State(pending->version(),
- (side == CLIENT) ? SERVER : CLIENT,
- false,
- pending->ciphersuite(),
- pending->session_keys()));
-
- m_read_cipher_states[epoch] = read_state;
- }
-
-void Channel::change_cipher_spec_writer(Connection_Side side)
- {
- auto pending = pending_state();
-
- BOTAN_ASSERT(pending && pending->server_hello(),
- "Have received server hello");
-
- if(pending->server_hello()->compression_method() != NO_COMPRESSION)
- throw Internal_Error("Negotiated unknown compression algorithm");
-
- sequence_numbers().new_write_cipher_state();
-
- const u16bit epoch = sequence_numbers().current_write_epoch();
-
- BOTAN_ASSERT(m_write_cipher_states.count(epoch) == 0,
- "No write cipher state currently set for next epoch");
-
- std::shared_ptr<Connection_Cipher_State> write_state(
- new Connection_Cipher_State(pending->version(),
- side,
- true,
- pending->ciphersuite(),
- pending->session_keys()));
-
- m_write_cipher_states[epoch] = write_state;
- }
-
-bool Channel::is_active() const
- {
- return (active_state() != nullptr);
- }
-
-bool Channel::is_closed() const
- {
- if(active_state() || pending_state())
- return false;
-
- /*
- * If no active or pending state, then either we had a connection
- * and it has been closed, or we are a server which has never
- * received a connection. This case is detectable by also lacking
- * m_sequence_numbers
- */
- return (m_sequence_numbers != nullptr);
- }
-
-void Channel::activate_session()
- {
- std::swap(m_active_state, m_pending_state);
- m_pending_state.reset();
-
- if(m_active_state->version().is_datagram_protocol())
- {
- // FIXME, remove old states when we are sure not needed anymore
- }
- else
- {
- // TLS is easy just remove all but the current state
- auto current_epoch = sequence_numbers().current_write_epoch();
-
- const auto not_current_epoch =
- [current_epoch](u16bit epoch) { return (epoch != current_epoch); };
-
- map_remove_if(not_current_epoch, m_write_cipher_states);
- map_remove_if(not_current_epoch, m_read_cipher_states);
- }
- }
-
-bool Channel::peer_supports_heartbeats() const
- {
- if(auto active = active_state())
- return active->server_hello()->supports_heartbeats();
- return false;
- }
-
-bool Channel::heartbeat_sending_allowed() const
- {
- if(auto active = active_state())
- return active->server_hello()->peer_can_send_heartbeats();
- return false;
- }
-
-size_t Channel::received_data(const std::vector<byte>& buf)
- {
- return this->received_data(&buf[0], buf.size());
- }
-
-size_t Channel::received_data(const byte input[], size_t input_size)
- {
- const auto get_cipherstate = [this](u16bit epoch)
- { return this->read_cipher_state_epoch(epoch).get(); };
-
- const size_t max_fragment_size = maximum_fragment_size();
-
- try
- {
- while(!is_closed() && input_size)
- {
- secure_vector<byte> record;
- u64bit record_sequence = 0;
- Record_Type record_type = NO_RECORD;
- Protocol_Version record_version;
-
- size_t consumed = 0;
-
- const size_t needed =
- read_record(m_readbuf,
- input,
- input_size,
- consumed,
- record,
- &record_sequence,
- &record_version,
- &record_type,
- m_sequence_numbers.get(),
- get_cipherstate);
-
- BOTAN_ASSERT(consumed <= input_size,
- "Record reader consumed sane amount");
-
- input += consumed;
- input_size -= consumed;
-
- BOTAN_ASSERT(input_size == 0 || needed == 0,
- "Got a full record or consumed all input");
-
- if(input_size == 0 && needed != 0)
- return needed; // need more data to complete record
-
- if(record.size() > max_fragment_size)
- throw TLS_Exception(Alert::RECORD_OVERFLOW,
- "Plaintext record is too large");
-
- if(record_type == HANDSHAKE || record_type == CHANGE_CIPHER_SPEC)
- {
- if(!m_pending_state)
- {
- create_handshake_state(record_version);
- if(record_version.is_datagram_protocol())
- sequence_numbers().read_accept(record_sequence);
- }
-
- m_pending_state->handshake_io().add_record(unlock(record),
- record_type,
- record_sequence);
-
- while(auto pending = m_pending_state.get())
- {
- auto msg = pending->get_next_handshake_msg();
-
- if(msg.first == HANDSHAKE_NONE) // no full handshake yet
- break;
-
- process_handshake_msg(active_state(), *pending,
- msg.first, msg.second);
- }
- }
- else if(record_type == HEARTBEAT && peer_supports_heartbeats())
- {
- if(!active_state())
- throw Unexpected_Message("Heartbeat sent before handshake done");
-
- Heartbeat_Message heartbeat(unlock(record));
-
- const std::vector<byte>& payload = heartbeat.payload();
-
- if(heartbeat.is_request())
- {
- if(!pending_state())
- {
- Heartbeat_Message response(Heartbeat_Message::RESPONSE,
- &payload[0], payload.size());
-
- send_record(HEARTBEAT, response.contents());
- }
- }
- else
- {
- m_alert_cb(Alert(Alert::HEARTBEAT_PAYLOAD), &payload[0], payload.size());
- }
- }
- else if(record_type == APPLICATION_DATA)
- {
- if(!active_state())
- throw Unexpected_Message("Application data before handshake done");
-
- /*
- * OpenSSL among others sends empty records in versions
- * before TLS v1.1 in order to randomize the IV of the
- * following record. Avoid spurious callbacks.
- */
- if(record.size() > 0)
- m_data_cb(&record[0], record.size());
- }
- else if(record_type == ALERT)
- {
- Alert alert_msg(record);
-
- if(alert_msg.type() == Alert::NO_RENEGOTIATION)
- m_pending_state.reset();
-
- m_alert_cb(alert_msg, nullptr, 0);
-
- if(alert_msg.is_fatal())
- {
- if(auto active = active_state())
- m_session_manager.remove_entry(active->server_hello()->session_id());
- }
-
- if(alert_msg.type() == Alert::CLOSE_NOTIFY)
- send_warning_alert(Alert::CLOSE_NOTIFY); // reply in kind
-
- if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal())
- {
- reset_state();
- return 0;
- }
- }
- else
- throw Unexpected_Message("Unexpected record type " +
- std::to_string(record_type) +
- " from counterparty");
- }
-
- return 0; // on a record boundary
- }
- catch(TLS_Exception& e)
- {
- send_fatal_alert(e.type());
- throw;
- }
- catch(Integrity_Failure& e)
- {
- send_fatal_alert(Alert::BAD_RECORD_MAC);
- throw;
- }
- catch(Decoding_Error& e)
- {
- send_fatal_alert(Alert::DECODE_ERROR);
- throw;
- }
- catch(...)
- {
- send_fatal_alert(Alert::INTERNAL_ERROR);
- throw;
- }
- }
-
-void Channel::heartbeat(const byte payload[], size_t payload_size)
- {
- if(heartbeat_sending_allowed())
- {
- Heartbeat_Message heartbeat(Heartbeat_Message::REQUEST,
- payload, payload_size);
-
- send_record(HEARTBEAT, heartbeat.contents());
- }
- }
-
-void Channel::write_record(Connection_Cipher_State* cipher_state,
- byte record_type, const byte input[], size_t length)
- {
- BOTAN_ASSERT(m_pending_state || m_active_state,
- "Some connection state exists");
-
- Protocol_Version record_version =
- (m_pending_state) ? (m_pending_state->version()) : (m_active_state->version());
-
- TLS::write_record(m_writebuf,
- record_type,
- input,
- length,
- record_version,
- sequence_numbers().next_write_sequence(),
- cipher_state,
- m_rng);
-
- m_output_fn(&m_writebuf[0], m_writebuf.size());
- }
-
-void Channel::send_record_array(u16bit epoch, byte type, const byte input[], size_t length)
- {
- if(length == 0)
- return;
-
- /*
- * If using CBC mode without an explicit IV (SSL v3 or TLS v1.0),
- * send a single byte of plaintext to randomize the (implicit) IV of
- * the following main block. If using a stream cipher, or TLS v1.1
- * or higher, this isn't necessary.
- *
- * An empty record also works but apparently some implementations do
- * not like this (https://bugzilla.mozilla.org/show_bug.cgi?id=665814)
- *
- * See http://www.openssl.org/~bodo/tls-cbc.txt for background.
- */
-
- auto cipher_state = write_cipher_state_epoch(epoch);
-
- if(type == APPLICATION_DATA && cipher_state->cbc_without_explicit_iv())
- {
- write_record(cipher_state.get(), type, &input[0], 1);
- input += 1;
- length -= 1;
- }
-
- const size_t max_fragment_size = maximum_fragment_size();
-
- while(length)
- {
- const size_t sending = std::min(length, max_fragment_size);
- write_record(cipher_state.get(), type, &input[0], sending);
-
- input += sending;
- length -= sending;
- }
- }
-
-void Channel::send_record(byte record_type, const std::vector<byte>& record)
- {
- send_record_array(sequence_numbers().current_write_epoch(),
- record_type, &record[0], record.size());
- }
-
-void Channel::send_record_under_epoch(u16bit epoch, byte record_type,
- const std::vector<byte>& record)
- {
- send_record_array(epoch, record_type, &record[0], record.size());
- }
-
-void Channel::send(const byte buf[], size_t buf_size)
- {
- if(!is_active())
- throw std::runtime_error("Data cannot be sent on inactive TLS connection");
-
- send_record_array(sequence_numbers().current_write_epoch(),
- APPLICATION_DATA, buf, buf_size);
- }
-
-void Channel::send(const std::string& string)
- {
- this->send(reinterpret_cast<const byte*>(string.c_str()), string.size());
- }
-
-void Channel::send_alert(const Alert& alert)
- {
- if(alert.is_valid() && !is_closed())
- {
- try
- {
- send_record(ALERT, alert.serialize());
- }
- catch(...) { /* swallow it */ }
- }
-
- if(alert.type() == Alert::NO_RENEGOTIATION)
- m_pending_state.reset();
-
- if(alert.is_fatal())
- if(auto active = active_state())
- m_session_manager.remove_entry(active->server_hello()->session_id());
-
- if(alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal())
- reset_state();
- }
-
-void Channel::secure_renegotiation_check(const Client_Hello* client_hello)
- {
- const bool secure_renegotiation = client_hello->secure_renegotiation();
-
- if(auto active = active_state())
- {
- const bool active_sr = active->client_hello()->secure_renegotiation();
-
- if(active_sr != secure_renegotiation)
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Client changed its mind about secure renegotiation");
- }
-
- if(secure_renegotiation)
- {
- const std::vector<byte>& data = client_hello->renegotiation_info();
-
- if(data != secure_renegotiation_data_for_client_hello())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Client sent bad values for secure renegotiation");
- }
- }
-
-void Channel::secure_renegotiation_check(const Server_Hello* server_hello)
- {
- const bool secure_renegotiation = server_hello->secure_renegotiation();
-
- if(auto active = active_state())
- {
- const bool active_sr = active->client_hello()->secure_renegotiation();
-
- if(active_sr != secure_renegotiation)
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server changed its mind about secure renegotiation");
- }
-
- if(secure_renegotiation)
- {
- const std::vector<byte>& data = server_hello->renegotiation_info();
-
- if(data != secure_renegotiation_data_for_server_hello())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server sent bad values for secure renegotiation");
- }
- }
-
-std::vector<byte> Channel::secure_renegotiation_data_for_client_hello() const
- {
- if(auto active = active_state())
- return active->client_finished()->verify_data();
- return std::vector<byte>();
- }
-
-std::vector<byte> Channel::secure_renegotiation_data_for_server_hello() const
- {
- if(auto active = active_state())
- {
- std::vector<byte> buf = active->client_finished()->verify_data();
- buf += active->server_finished()->verify_data();
- return buf;
- }
-
- return std::vector<byte>();
- }
-
-bool Channel::secure_renegotiation_supported() const
- {
- if(auto active = active_state())
- return active->server_hello()->secure_renegotiation();
-
- if(auto pending = pending_state())
- if(auto hello = pending->server_hello())
- return hello->secure_renegotiation();
-
- return false;
- }
-
-SymmetricKey Channel::key_material_export(const std::string& label,
- const std::string& context,
- size_t length) const
- {
- if(auto active = active_state())
- {
- std::unique_ptr<KDF> prf(active->protocol_specific_prf());
-
- const secure_vector<byte>& master_secret =
- active->session_keys().master_secret();
-
- std::vector<byte> salt;
- salt += to_byte_vector(label);
- salt += active->client_hello()->random();
- salt += active->server_hello()->random();
-
- if(context != "")
- {
- size_t context_size = context.length();
- if(context_size > 0xFFFF)
- throw std::runtime_error("key_material_export context is too long");
- salt.push_back(get_byte<u16bit>(0, context_size));
- salt.push_back(get_byte<u16bit>(1, context_size));
- salt += to_byte_vector(context);
- }
-
- return prf->derive_key(length, master_secret, salt);
- }
- else
- throw std::runtime_error("Channel::key_material_export connection not active");
- }
-
-}
-
-}
-
diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h
deleted file mode 100644
index e7b53f563..000000000
--- a/src/tls/tls_channel.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
-* TLS Channel
-* (C) 2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CHANNEL_H__
-#define BOTAN_TLS_CHANNEL_H__
-
-#include <botan/tls_policy.h>
-#include <botan/tls_session.h>
-#include <botan/tls_alert.h>
-#include <botan/tls_session_manager.h>
-#include <botan/x509cert.h>
-#include <vector>
-#include <string>
-#include <memory>
-#include <map>
-
-namespace Botan {
-
-namespace TLS {
-
-class Connection_Cipher_State;
-class Connection_Sequence_Numbers;
-class Handshake_State;
-
-/**
-* Generic interface for TLS endpoint
-*/
-class BOTAN_DLL Channel
- {
- public:
- /**
- * Inject TLS traffic received from counterparty
- * @return a hint as the how many more bytes we need to process the
- * current record (this may be 0 if on a record boundary)
- */
- size_t received_data(const byte buf[], size_t buf_size);
-
- /**
- * Inject TLS traffic received from counterparty
- * @return a hint as the how many more bytes we need to process the
- * current record (this may be 0 if on a record boundary)
- */
- size_t received_data(const std::vector<byte>& buf);
-
- /**
- * Inject plaintext intended for counterparty
- */
- void send(const byte buf[], size_t buf_size);
-
- /**
- * Inject plaintext intended for counterparty
- */
- void send(const std::string& val);
-
- /**
- * Inject plaintext intended for counterparty
- */
- template<typename Alloc>
- void send(const std::vector<unsigned char, Alloc>& val)
- {
- send(&val[0], val.size());
- }
-
- /**
- * Send a TLS alert message. If the alert is fatal, the internal
- * state (keys, etc) will be reset.
- * @param alert the Alert to send
- */
- void send_alert(const Alert& alert);
-
- /**
- * Send a warning alert
- */
- void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); }
-
- /**
- * Send a fatal alert
- */
- void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); }
-
- /**
- * Send a close notification alert
- */
- void close() { send_warning_alert(Alert::CLOSE_NOTIFY); }
-
- /**
- * @return true iff the connection is active for sending application data
- */
- bool is_active() const;
-
- /**
- * @return true iff the connection has been definitely closed
- */
- bool is_closed() const;
-
- /**
- * Attempt to renegotiate the session
- * @param force_full_renegotiation if true, require a full renegotiation,
- * otherwise allow session resumption
- */
- void renegotiate(bool force_full_renegotiation = false);
-
- /**
- * @return true iff the peer supports heartbeat messages
- */
- bool peer_supports_heartbeats() const;
-
- /**
- * @return true iff we are allowed to send heartbeat messages
- */
- bool heartbeat_sending_allowed() const;
-
- /**
- * @return true iff the counterparty supports the secure
- * renegotiation extensions.
- */
- bool secure_renegotiation_supported() const;
-
- /**
- * Attempt to send a heartbeat message (if negotiated with counterparty)
- * @param payload will be echoed back
- * @param payload_size size of payload in bytes
- */
- void heartbeat(const byte payload[], size_t payload_size);
-
- /**
- * Attempt to send a heartbeat message (if negotiated with counterparty)
- */
- void heartbeat() { heartbeat(nullptr, 0); }
-
- /**
- * @return certificate chain of the peer (may be empty)
- */
- std::vector<X509_Certificate> peer_cert_chain() const;
-
- /**
- * Key material export (RFC 5705)
- * @param label a disambiguating label string
- * @param context a per-association context value
- * @param length the length of the desired key in bytes
- * @return key of length bytes
- */
- SymmetricKey key_material_export(const std::string& label,
- const std::string& context,
- size_t length) const;
-
- Channel(std::function<void (const byte[], size_t)> socket_output_fn,
- std::function<void (const byte[], size_t)> data_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- RandomNumberGenerator& rng,
- size_t reserved_io_buffer_size);
-
- Channel(const Channel&) = delete;
-
- Channel& operator=(const Channel&) = delete;
-
- virtual ~Channel();
- protected:
-
- virtual void process_handshake_msg(const Handshake_State* active_state,
- Handshake_State& pending_state,
- Handshake_Type type,
- const std::vector<byte>& contents) = 0;
-
- virtual void initiate_handshake(Handshake_State& state,
- bool force_full_renegotiation) = 0;
-
- virtual std::vector<X509_Certificate>
- get_peer_cert_chain(const Handshake_State& state) const = 0;
-
- virtual Handshake_State* new_handshake_state(class Handshake_IO* io) = 0;
-
- Handshake_State& create_handshake_state(Protocol_Version version);
-
- void activate_session();
-
- void change_cipher_spec_reader(Connection_Side side);
-
- void change_cipher_spec_writer(Connection_Side side);
-
- /* secure renegotiation handling */
-
- void secure_renegotiation_check(const class Client_Hello* client_hello);
- void secure_renegotiation_check(const class Server_Hello* server_hello);
-
- std::vector<byte> secure_renegotiation_data_for_client_hello() const;
- std::vector<byte> secure_renegotiation_data_for_server_hello() const;
-
- RandomNumberGenerator& rng() { return m_rng; }
-
- Session_Manager& session_manager() { return m_session_manager; }
-
- bool save_session(const Session& session) const { return m_handshake_cb(session); }
-
- private:
- size_t maximum_fragment_size() const;
-
- void send_record(byte record_type, const std::vector<byte>& record);
-
- void send_record_under_epoch(u16bit epoch, byte record_type,
- const std::vector<byte>& record);
-
- void send_record_array(u16bit epoch, byte record_type,
- const byte input[], size_t length);
-
- void write_record(Connection_Cipher_State* cipher_state,
- byte type, const byte input[], size_t length);
-
- Connection_Sequence_Numbers& sequence_numbers() const;
-
- std::shared_ptr<Connection_Cipher_State> read_cipher_state_epoch(u16bit epoch) const;
-
- std::shared_ptr<Connection_Cipher_State> write_cipher_state_epoch(u16bit epoch) const;
-
- void reset_state();
-
- const Handshake_State* active_state() const { return m_active_state.get(); }
-
- const Handshake_State* pending_state() const { return m_pending_state.get(); }
-
- /* callbacks */
- std::function<bool (const Session&)> m_handshake_cb;
- std::function<void (const byte[], size_t)> m_data_cb;
- std::function<void (Alert, const byte[], size_t)> m_alert_cb;
- std::function<void (const byte[], size_t)> m_output_fn;
-
- /* external state */
- RandomNumberGenerator& m_rng;
- Session_Manager& m_session_manager;
-
- /* sequence number state */
- std::unique_ptr<Connection_Sequence_Numbers> m_sequence_numbers;
-
- /* pending and active connection states */
- std::unique_ptr<Handshake_State> m_active_state;
- std::unique_ptr<Handshake_State> m_pending_state;
-
- /* cipher states for each epoch - epoch 0 is plaintext, thus null cipher state */
- std::map<u16bit, std::shared_ptr<Connection_Cipher_State>> m_write_cipher_states =
- { { 0, nullptr } };
- std::map<u16bit, std::shared_ptr<Connection_Cipher_State>> m_read_cipher_states =
- { { 0, nullptr } };
-
- /* I/O buffers */
- secure_vector<byte> m_writebuf;
- secure_vector<byte> m_readbuf;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_ciphersuite.cpp b/src/tls/tls_ciphersuite.cpp
deleted file mode 100644
index e8c551b01..000000000
--- a/src/tls/tls_ciphersuite.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-* TLS Cipher Suite
-* (C) 2004-2010,2012,2013 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_ciphersuite.h>
-#include <botan/libstate.h>
-#include <botan/parsing.h>
-#include <sstream>
-#include <stdexcept>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-/*
-* This way all work happens at the constuctor call, and we can
-* rely on that happening only once in C++11.
-*/
-std::vector<Ciphersuite> gather_known_ciphersuites()
- {
- std::vector<Ciphersuite> ciphersuites;
-
- for(size_t i = 0; i <= 0xFFFF; ++i)
- {
- Ciphersuite suite = Ciphersuite::by_id(i);
-
- if(suite.valid())
- ciphersuites.push_back(suite);
- }
-
- return ciphersuites;
- }
-
-}
-
-const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites()
- {
- static std::vector<Ciphersuite> all_ciphersuites(gather_known_ciphersuites());
- return all_ciphersuites;
- }
-
-Ciphersuite Ciphersuite::by_name(const std::string& name)
- {
- for(auto suite : all_known_ciphersuites())
- {
- if(suite.to_string() == name)
- return suite;
- }
-
- return Ciphersuite(); // some unknown ciphersuite
- }
-
-Ciphersuite::Ciphersuite(u16bit ciphersuite_code,
- const char* sig_algo,
- const char* kex_algo,
- const char* cipher_algo,
- size_t cipher_keylen,
- size_t cipher_ivlen,
- const char* mac_algo,
- size_t mac_keylen,
- const char* prf_algo) :
- m_ciphersuite_code(ciphersuite_code),
- m_sig_algo(sig_algo),
- m_kex_algo(kex_algo),
- m_cipher_algo(cipher_algo),
- m_mac_algo(mac_algo),
- m_prf_algo(prf_algo),
- m_cipher_keylen(cipher_keylen),
- m_cipher_ivlen(cipher_ivlen),
- m_mac_keylen(mac_keylen)
- {
- }
-
-bool Ciphersuite::psk_ciphersuite() const
- {
- return (kex_algo() == "PSK" ||
- kex_algo() == "DHE_PSK" ||
- kex_algo() == "ECDHE_PSK");
- }
-
-bool Ciphersuite::ecc_ciphersuite() const
- {
- return (sig_algo() == "ECDSA" || kex_algo() == "ECDH" || kex_algo() == "ECDHE_PSK");
- }
-
-bool Ciphersuite::valid() const
- {
- if(!m_cipher_keylen) // uninitialized object
- return false;
-
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- if(!af.prototype_hash_function(prf_algo()))
- return false;
-
- if(mac_algo() == "AEAD")
- {
- auto cipher_and_mode = split_on(cipher_algo(), '/');
- BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
- if(!af.prototype_block_cipher(cipher_and_mode[0]))
- return false;
-
- const auto mode = cipher_and_mode[1];
-
-#if !defined(BOTAN_HAS_AEAD_CCM)
- if(mode == "CCM" || mode == "CCM-8")
- return false;
-#endif
-
-#if !defined(BOTAN_HAS_AEAD_GCM)
- if(mode == "GCM")
- return false;
-#endif
-
-#if !defined(BOTAN_HAS_AEAD_OCB)
- if(mode == "OCB")
- return false;
-#endif
- }
- else
- {
- if(!af.prototype_block_cipher(cipher_algo()) &&
- !af.prototype_stream_cipher(cipher_algo()))
- return false;
-
- if(!af.prototype_hash_function(mac_algo()))
- return false;
- }
-
- if(kex_algo() == "SRP_SHA")
- {
-#if !defined(BOTAN_HAS_SRP6)
- return false;
-#endif
- }
- else if(kex_algo() == "ECDH" || kex_algo() == "ECDHE_PSK")
- {
-#if !defined(BOTAN_HAS_ECDH)
- return false;
-#endif
- }
- else if(kex_algo() == "DH" || kex_algo() == "DHE_PSK")
- {
-#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
- return false;
-#endif
- }
-
- if(sig_algo() == "DSA")
- {
-#if !defined(BOTAN_HAS_DSA)
- return false;
-#endif
- }
- else if(sig_algo() == "ECDSA")
- {
-#if !defined(BOTAN_HAS_ECDSA)
- return false;
-#endif
- }
- else if(sig_algo() == "RSA")
- {
-#if !defined(BOTAN_HAS_RSA)
- return false;
-#endif
- }
-
- return true;
- }
-
-std::string Ciphersuite::to_string() const
- {
- if(m_cipher_keylen == 0)
- throw std::runtime_error("Ciphersuite::to_string - no value set");
-
- std::ostringstream out;
-
- out << "TLS_";
-
- if(kex_algo() != "RSA")
- {
- if(kex_algo() == "DH")
- out << "DHE";
- else if(kex_algo() == "ECDH")
- out << "ECDHE";
- else
- out << kex_algo();
-
- out << '_';
- }
-
- if(sig_algo() == "DSA")
- out << "DSS_";
- else if(sig_algo() != "")
- out << sig_algo() << '_';
-
- out << "WITH_";
-
- if(cipher_algo() == "RC4")
- {
- out << "RC4_128_";
- }
- else
- {
- if(cipher_algo() == "3DES")
- out << "3DES_EDE";
- else if(cipher_algo().find("Camellia") == 0)
- out << "CAMELLIA_" << std::to_string(8*cipher_keylen());
- else
- out << replace_chars(cipher_algo(), {'-', '/'}, '_');
-
- if(cipher_algo().find("/") != std::string::npos)
- out << "_"; // some explicit mode already included
- else
- out << "_CBC_";
- }
-
- if(mac_algo() == "SHA-1")
- out << "SHA";
- else if(mac_algo() == "AEAD")
- out << erase_chars(prf_algo(), {'-'});
- else
- out << erase_chars(mac_algo(), {'-'});
-
- return out.str();
- }
-
-}
-
-}
-
diff --git a/src/tls/tls_ciphersuite.h b/src/tls/tls_ciphersuite.h
deleted file mode 100644
index 865e66abb..000000000
--- a/src/tls/tls_ciphersuite.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-* TLS Cipher Suites
-* (C) 2004-2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CIPHER_SUITES_H__
-#define BOTAN_TLS_CIPHER_SUITES_H__
-
-#include <botan/types.h>
-#include <string>
-#include <vector>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Ciphersuite Information
-*/
-class BOTAN_DLL Ciphersuite
- {
- public:
- /**
- * Convert an SSL/TLS ciphersuite to algorithm fields
- * @param suite the ciphersuite code number
- * @return ciphersuite object
- */
- static Ciphersuite by_id(u16bit suite);
-
- /**
- * Lookup a ciphersuite by name
- * @param name the name (eg TLS_RSA_WITH_RC4_128_SHA)
- * @return ciphersuite object
- */
- static Ciphersuite by_name(const std::string& name);
-
- /**
- * Generate a static list of all known ciphersuites and return it.
- *
- * @return list of all known ciphersuites
- */
- static const std::vector<Ciphersuite>& all_known_ciphersuites();
-
- /**
- * Formats the ciphersuite back to an RFC-style ciphersuite string
- * @return RFC ciphersuite string identifier
- */
- std::string to_string() const;
-
- /**
- * @return ciphersuite number
- */
- u16bit ciphersuite_code() const { return m_ciphersuite_code; }
-
- /**
- * @return true if this is a PSK ciphersuite
- */
- bool psk_ciphersuite() const;
-
- /**
- * @return true if this is an ECC ciphersuite
- */
- bool ecc_ciphersuite() const;
-
- /**
- * @return key exchange algorithm used by this ciphersuite
- */
- std::string kex_algo() const { return m_kex_algo; }
-
- /**
- * @return signature algorithm used by this ciphersuite
- */
- std::string sig_algo() const { return m_sig_algo; }
-
- /**
- * @return symmetric cipher algorithm used by this ciphersuite
- */
- std::string cipher_algo() const { return m_cipher_algo; }
-
- /**
- * @return message authentication algorithm used by this ciphersuite
- */
- std::string mac_algo() const { return m_mac_algo; }
-
- std::string prf_algo() const
- {
- return (m_prf_algo != "") ? m_prf_algo : m_mac_algo;
- }
-
- /**
- * @return cipher key length used by this ciphersuite
- */
- size_t cipher_keylen() const { return m_cipher_keylen; }
-
- size_t cipher_ivlen() const { return m_cipher_ivlen; }
-
- size_t mac_keylen() const { return m_mac_keylen; }
-
- /**
- * @return true if this is a valid/known ciphersuite
- */
- bool valid() const;
-
- Ciphersuite() {}
-
- private:
-
- Ciphersuite(u16bit ciphersuite_code,
- const char* sig_algo,
- const char* kex_algo,
- const char* cipher_algo,
- size_t cipher_keylen,
- size_t cipher_ivlen,
- const char* mac_algo,
- size_t mac_keylen,
- const char* prf_algo = "");
-
- u16bit m_ciphersuite_code = 0;
-
- std::string m_sig_algo;
- std::string m_kex_algo;
- std::string m_cipher_algo;
- std::string m_mac_algo;
- std::string m_prf_algo;
-
- size_t m_cipher_keylen = 0;
- size_t m_cipher_ivlen = 0;
- size_t m_mac_keylen = 0;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
deleted file mode 100644
index f17247c16..000000000
--- a/src/tls/tls_client.cpp
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
-* TLS Client
-* (C) 2004-2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_client.h>
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/stl_util.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-class Client_Handshake_State : public Handshake_State
- {
- public:
- // using Handshake_State::Handshake_State;
-
- Client_Handshake_State(Handshake_IO* io,
- std::function<void (const Handshake_Message&)> msg_callback =
- std::function<void (const Handshake_Message&)>()) :
- Handshake_State(io, msg_callback) {}
-
- const Public_Key& get_server_public_Key() const
- {
- BOTAN_ASSERT(server_public_key, "Server sent us a certificate");
- return *server_public_key.get();
- }
-
- // Used during session resumption
- secure_vector<byte> resume_master_secret;
-
- std::unique_ptr<Public_Key> server_public_key;
-
- // Used by client using NPN
- std::function<std::string (std::vector<std::string>)> client_npn_cb;
- };
-
-}
-
-/*
-* TLS Client Constructor
-*/
-Client::Client(std::function<void (const byte[], size_t)> output_fn,
- std::function<void (const byte[], size_t)> proc_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Server_Information& info,
- const Protocol_Version offer_version,
- std::function<std::string (std::vector<std::string>)> next_protocol,
- size_t io_buf_sz) :
- Channel(output_fn, proc_cb, alert_cb, handshake_cb, session_manager, rng, io_buf_sz),
- m_policy(policy),
- m_creds(creds),
- m_info(info)
- {
- const std::string srp_identifier = m_creds.srp_identifier("tls-client", m_info.hostname());
-
- Handshake_State& state = create_handshake_state(offer_version);
- send_client_hello(state, false, offer_version, srp_identifier, next_protocol);
- }
-
-Handshake_State* Client::new_handshake_state(Handshake_IO* io)
- {
- return new Client_Handshake_State(io);
- }
-
-std::vector<X509_Certificate>
-Client::get_peer_cert_chain(const Handshake_State& state) const
- {
- if(state.server_certs())
- return state.server_certs()->cert_chain();
- return std::vector<X509_Certificate>();
- }
-
-/*
-* Send a new client hello to renegotiate
-*/
-void Client::initiate_handshake(Handshake_State& state,
- bool force_full_renegotiation)
- {
- send_client_hello(state,
- force_full_renegotiation,
- state.version());
- }
-
-void Client::send_client_hello(Handshake_State& state_base,
- bool force_full_renegotiation,
- Protocol_Version version,
- const std::string& srp_identifier,
- std::function<std::string (std::vector<std::string>)> next_protocol)
- {
- Client_Handshake_State& state = dynamic_cast<Client_Handshake_State&>(state_base);
-
- if(state.version().is_datagram_protocol())
- state.set_expected_next(HELLO_VERIFY_REQUEST); // optional
- state.set_expected_next(SERVER_HELLO);
-
- state.client_npn_cb = next_protocol;
-
- const bool send_npn_request = static_cast<bool>(next_protocol);
-
- if(!force_full_renegotiation && !m_info.empty())
- {
- Session session_info;
- if(session_manager().load_from_server_info(m_info, session_info))
- {
- if(srp_identifier == "" || session_info.srp_identifier() == srp_identifier)
- {
- state.client_hello(new Client_Hello(
- state.handshake_io(),
- state.hash(),
- m_policy,
- rng(),
- secure_renegotiation_data_for_client_hello(),
- session_info,
- send_npn_request));
-
- state.resume_master_secret = session_info.master_secret();
- }
- }
- }
-
- if(!state.client_hello()) // not resuming
- {
- state.client_hello(new Client_Hello(
- state.handshake_io(),
- state.hash(),
- version,
- m_policy,
- rng(),
- secure_renegotiation_data_for_client_hello(),
- send_npn_request,
- m_info.hostname(),
- srp_identifier));
- }
-
- secure_renegotiation_check(state.client_hello());
- }
-
-/*
-* Process a handshake message
-*/
-void Client::process_handshake_msg(const Handshake_State* active_state,
- Handshake_State& state_base,
- Handshake_Type type,
- const std::vector<byte>& contents)
- {
- Client_Handshake_State& state = dynamic_cast<Client_Handshake_State&>(state_base);
-
- if(type == HELLO_REQUEST && active_state)
- {
- Hello_Request hello_request(contents);
-
- // Ignore request entirely if we are currently negotiating a handshake
- if(state.client_hello())
- return;
-
- if(!m_policy.allow_server_initiated_renegotiation() ||
- (!m_policy.allow_insecure_renegotiation() && !secure_renegotiation_supported()))
- {
- // RFC 5746 section 4.2
- send_warning_alert(Alert::NO_RENEGOTIATION);
- return;
- }
-
- this->initiate_handshake(state, false);
-
- return;
- }
-
- state.confirm_transition_to(type);
-
- if(type != HANDSHAKE_CCS && type != FINISHED && type != HELLO_VERIFY_REQUEST)
- state.hash().update(state.handshake_io().format(contents, type));
-
- if(type == HELLO_VERIFY_REQUEST)
- {
- state.set_expected_next(SERVER_HELLO);
- state.set_expected_next(HELLO_VERIFY_REQUEST); // might get it again
-
- Hello_Verify_Request hello_verify_request(contents);
-
- state.hello_verify_request(hello_verify_request);
- }
- else if(type == SERVER_HELLO)
- {
- state.server_hello(new Server_Hello(contents));
-
- if(!state.client_hello()->offered_suite(state.server_hello()->ciphersuite()))
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server replied with ciphersuite we didn't send");
- }
-
- if(!value_exists(state.client_hello()->compression_methods(),
- state.server_hello()->compression_method()))
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server replied with compression method we didn't send");
- }
-
- if(!state.client_hello()->next_protocol_notification() &&
- state.server_hello()->next_protocol_notification())
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server sent next protocol but we didn't request it");
- }
-
- if(state.server_hello()->supports_session_ticket())
- {
- if(!state.client_hello()->supports_session_ticket())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server sent session ticket extension but we did not");
- }
-
- state.set_version(state.server_hello()->version());
-
- secure_renegotiation_check(state.server_hello());
-
- const bool server_returned_same_session_id =
- !state.server_hello()->session_id().empty() &&
- (state.server_hello()->session_id() == state.client_hello()->session_id());
-
- if(server_returned_same_session_id)
- {
- // successful resumption
-
- /*
- * In this case, we offered the version used in the original
- * session, and the server must resume with the same version.
- */
- if(state.server_hello()->version() != state.client_hello()->version())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server resumed session but with wrong version");
-
- state.compute_session_keys(state.resume_master_secret);
-
- if(state.server_hello()->supports_session_ticket())
- state.set_expected_next(NEW_SESSION_TICKET);
- else
- state.set_expected_next(HANDSHAKE_CCS);
- }
- else
- {
- // new session
-
- if(state.client_hello()->version().is_datagram_protocol() !=
- state.server_hello()->version().is_datagram_protocol())
- {
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Server replied with different protocol type than we offered");
- }
-
- if(state.version() > state.client_hello()->version())
- {
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Server replied with later version than in hello");
- }
-
- if(!m_policy.acceptable_protocol_version(state.version()))
- {
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Server version is unacceptable by policy");
- }
-
- if(state.ciphersuite().sig_algo() != "")
- {
- state.set_expected_next(CERTIFICATE);
- }
- else if(state.ciphersuite().kex_algo() == "PSK")
- {
- /* PSK is anonymous so no certificate/cert req message is
- ever sent. The server may or may not send a server kex,
- depending on if it has an identity hint for us.
-
- (EC)DHE_PSK always sends a server key exchange for the
- DH exchange portion.
- */
-
- state.set_expected_next(SERVER_KEX);
- state.set_expected_next(SERVER_HELLO_DONE);
- }
- else if(state.ciphersuite().kex_algo() != "RSA")
- {
- state.set_expected_next(SERVER_KEX);
- }
- else
- {
- state.set_expected_next(CERTIFICATE_REQUEST); // optional
- state.set_expected_next(SERVER_HELLO_DONE);
- }
- }
- }
- else if(type == CERTIFICATE)
- {
- if(state.ciphersuite().kex_algo() != "RSA")
- {
- state.set_expected_next(SERVER_KEX);
- }
- else
- {
- state.set_expected_next(CERTIFICATE_REQUEST); // optional
- state.set_expected_next(SERVER_HELLO_DONE);
- }
-
- state.server_certs(new Certificate(contents));
-
- const std::vector<X509_Certificate>& server_certs =
- state.server_certs()->cert_chain();
-
- if(server_certs.empty())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Client: No certificates sent by server");
-
- try
- {
- m_creds.verify_certificate_chain("tls-client", m_info.hostname(), server_certs);
- }
- catch(std::exception& e)
- {
- throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
- }
-
- std::unique_ptr<Public_Key> peer_key(server_certs[0].subject_public_key());
-
- if(peer_key->algo_name() != state.ciphersuite().sig_algo())
- throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
- "Certificate key type did not match ciphersuite");
-
- state.server_public_key.reset(peer_key.release());
- }
- else if(type == SERVER_KEX)
- {
- state.set_expected_next(CERTIFICATE_REQUEST); // optional
- state.set_expected_next(SERVER_HELLO_DONE);
-
- state.server_kex(
- new Server_Key_Exchange(contents,
- state.ciphersuite().kex_algo(),
- state.ciphersuite().sig_algo(),
- state.version())
- );
-
- if(state.ciphersuite().sig_algo() != "")
- {
- const Public_Key& server_key = state.get_server_public_Key();
-
- if(!state.server_kex()->verify(server_key, state))
- {
- throw TLS_Exception(Alert::DECRYPT_ERROR,
- "Bad signature on server key exchange");
- }
- }
- }
- else if(type == CERTIFICATE_REQUEST)
- {
- state.set_expected_next(SERVER_HELLO_DONE);
- state.cert_req(
- new Certificate_Req(contents, state.version())
- );
- }
- else if(type == SERVER_HELLO_DONE)
- {
- state.server_hello_done(
- new Server_Hello_Done(contents)
- );
-
- if(state.received_handshake_msg(CERTIFICATE_REQUEST))
- {
- const std::vector<std::string>& types =
- state.cert_req()->acceptable_cert_types();
-
- std::vector<X509_Certificate> client_certs =
- m_creds.cert_chain(types,
- "tls-client",
- m_info.hostname());
-
- state.client_certs(
- new Certificate(state.handshake_io(),
- state.hash(),
- client_certs)
- );
- }
-
- state.client_kex(
- new Client_Key_Exchange(state.handshake_io(),
- state,
- m_policy,
- m_creds,
- state.server_public_key.get(),
- m_info.hostname(),
- rng())
- );
-
- state.compute_session_keys();
-
- if(state.received_handshake_msg(CERTIFICATE_REQUEST) &&
- !state.client_certs()->empty())
- {
- Private_Key* private_key =
- m_creds.private_key_for(state.client_certs()->cert_chain()[0],
- "tls-client",
- m_info.hostname());
-
- state.client_verify(
- new Certificate_Verify(state.handshake_io(),
- state,
- m_policy,
- rng(),
- private_key)
- );
- }
-
- state.handshake_io().send(Change_Cipher_Spec());
-
- change_cipher_spec_writer(CLIENT);
-
- if(state.server_hello()->next_protocol_notification())
- {
- const std::string protocol = state.client_npn_cb(
- state.server_hello()->next_protocols());
-
- state.next_protocol(
- new Next_Protocol(state.handshake_io(), state.hash(), protocol)
- );
- }
-
- state.client_finished(
- new Finished(state.handshake_io(), state, CLIENT)
- );
-
- if(state.server_hello()->supports_session_ticket())
- state.set_expected_next(NEW_SESSION_TICKET);
- else
- state.set_expected_next(HANDSHAKE_CCS);
- }
- else if(type == NEW_SESSION_TICKET)
- {
- state.new_session_ticket(new New_Session_Ticket(contents));
-
- state.set_expected_next(HANDSHAKE_CCS);
- }
- else if(type == HANDSHAKE_CCS)
- {
- state.set_expected_next(FINISHED);
-
- change_cipher_spec_reader(CLIENT);
- }
- else if(type == FINISHED)
- {
- state.server_finished(new Finished(contents));
-
- if(!state.server_finished()->verify(state, SERVER))
- throw TLS_Exception(Alert::DECRYPT_ERROR,
- "Finished message didn't verify");
-
- state.hash().update(state.handshake_io().format(contents, type));
-
- if(!state.client_finished()) // session resume case
- {
- state.handshake_io().send(Change_Cipher_Spec());
-
- change_cipher_spec_writer(CLIENT);
-
- if(state.server_hello()->next_protocol_notification())
- {
- const std::string protocol = state.client_npn_cb(
- state.server_hello()->next_protocols());
-
- state.next_protocol(
- new Next_Protocol(state.handshake_io(), state.hash(), protocol)
- );
- }
-
- state.client_finished(
- new Finished(state.handshake_io(), state, CLIENT)
- );
- }
-
- std::vector<byte> session_id = state.server_hello()->session_id();
-
- const std::vector<byte>& session_ticket = state.session_ticket();
-
- if(session_id.empty() && !session_ticket.empty())
- session_id = make_hello_random(rng());
-
- Session session_info(
- session_id,
- state.session_keys().master_secret(),
- state.server_hello()->version(),
- state.server_hello()->ciphersuite(),
- state.server_hello()->compression_method(),
- CLIENT,
- state.server_hello()->fragment_size(),
- get_peer_cert_chain(state),
- session_ticket,
- m_info,
- ""
- );
-
- const bool should_save = save_session(session_info);
-
- if(!session_id.empty())
- {
- if(should_save)
- session_manager().save(session_info);
- else
- session_manager().remove_entry(session_info.session_id());
- }
-
- activate_session();
- }
- else
- throw Unexpected_Message("Unknown handshake message received");
- }
-
-}
-
-}
diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h
deleted file mode 100644
index c4440c7ac..000000000
--- a/src/tls/tls_client.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-* TLS Client
-* (C) 2004-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_CLIENT_H__
-#define BOTAN_TLS_CLIENT_H__
-
-#include <botan/tls_channel.h>
-#include <botan/credentials_manager.h>
-#include <vector>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* SSL/TLS Client
-*/
-class BOTAN_DLL Client : public Channel
- {
- public:
- /**
- * Set up a new TLS client session
- *
- * @param socket_output_fn is called with data for the outbound socket
- *
- * @param proc_cb is called when new application data is received
- *
- * @param alert_cb is called when a TLS alert is received
- *
- * @param handshake_cb is called when a handshake is completed
- *
- * @param session_manager manages session state
- *
- * @param creds manages application/user credentials
- *
- * @param policy specifies other connection policy information
- *
- * @param rng a random number generator
- *
- * @param server_info is identifying information about the TLS server
- *
- * @param offer_version specifies which version we will offer
- * to the TLS server.
- *
- * @param next_protocol allows the client to specify what the next
- * protocol will be. For more information read
- * http://technotes.googlecode.com/git/nextprotoneg.html.
- *
- * If the function is not empty, NPN will be negotiated
- * and if the server supports NPN the function will be
- * called with the list of protocols the server advertised;
- * the client should return the protocol it would like to use.
- *
- * @param reserved_io_buffer_size This many bytes of memory will
- * be preallocated for the read and write buffers. Smaller
- * values just mean reallocations and copies are more likely.
- */
- Client(std::function<void (const byte[], size_t)> socket_output_fn,
- std::function<void (const byte[], size_t)> data_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Server_Information& server_info = Server_Information(),
- const Protocol_Version offer_version = Protocol_Version::latest_tls_version(),
- std::function<std::string (std::vector<std::string>)> next_protocol =
- std::function<std::string (std::vector<std::string>)>(),
- size_t reserved_io_buffer_size = 16*1024
- );
- private:
- std::vector<X509_Certificate>
- get_peer_cert_chain(const Handshake_State& state) const override;
-
- void initiate_handshake(Handshake_State& state,
- bool force_full_renegotiation) override;
-
- void send_client_hello(Handshake_State& state,
- bool force_full_renegotiation,
- Protocol_Version version,
- const std::string& srp_identifier = "",
- std::function<std::string (std::vector<std::string>)> next_protocol =
- std::function<std::string (std::vector<std::string>)>());
-
- void process_handshake_msg(const Handshake_State* active_state,
- Handshake_State& pending_state,
- Handshake_Type type,
- const std::vector<byte>& contents) override;
-
- Handshake_State* new_handshake_state(Handshake_IO* io) override;
-
- const Policy& m_policy;
- Credentials_Manager& m_creds;
- const Server_Information m_info;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_exceptn.h b/src/tls/tls_exceptn.h
deleted file mode 100644
index 529d1f315..000000000
--- a/src/tls/tls_exceptn.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-* Exceptions
-* (C) 2004-2006 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_EXCEPTION_H__
-#define BOTAN_TLS_EXCEPTION_H__
-
-#include <botan/exceptn.h>
-#include <botan/tls_alert.h>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Exception Base Class
-*/
-class BOTAN_DLL TLS_Exception : public Exception
- {
- public:
- Alert::Type type() const noexcept { return alert_type; }
-
- TLS_Exception(Alert::Type type,
- const std::string& err_msg = "Unknown error") :
- Exception(err_msg), alert_type(type) {}
-
- private:
- Alert::Type alert_type;
- };
-
-/**
-* Unexpected_Message Exception
-*/
-struct BOTAN_DLL Unexpected_Message : public TLS_Exception
- {
- Unexpected_Message(const std::string& err) :
- TLS_Exception(Alert::UNEXPECTED_MESSAGE, err) {}
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
deleted file mode 100644
index 1ae9f1749..000000000
--- a/src/tls/tls_extensions.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
-* TLS Extensions
-* (C) 2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/tls_exceptn.h>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-Extension* make_extension(TLS_Data_Reader& reader,
- u16bit code,
- u16bit size)
- {
- switch(code)
- {
- case TLSEXT_SERVER_NAME_INDICATION:
- return new Server_Name_Indicator(reader, size);
-
- case TLSEXT_MAX_FRAGMENT_LENGTH:
- return new Maximum_Fragment_Length(reader, size);
-
- case TLSEXT_SRP_IDENTIFIER:
- return new SRP_Identifier(reader, size);
-
- case TLSEXT_USABLE_ELLIPTIC_CURVES:
- return new Supported_Elliptic_Curves(reader, size);
-
- case TLSEXT_SAFE_RENEGOTIATION:
- return new Renegotiation_Extension(reader, size);
-
- case TLSEXT_SIGNATURE_ALGORITHMS:
- return new Signature_Algorithms(reader, size);
-
- case TLSEXT_NEXT_PROTOCOL:
- return new Next_Protocol_Notification(reader, size);
-
- case TLSEXT_HEARTBEAT_SUPPORT:
- return new Heartbeat_Support_Indicator(reader, size);
-
- case TLSEXT_SESSION_TICKET:
- return new Session_Ticket(reader, size);
-
- default:
- return nullptr; // not known
- }
- }
-
-}
-
-void Extensions::deserialize(TLS_Data_Reader& reader)
- {
- if(reader.has_remaining())
- {
- const u16bit all_extn_size = reader.get_u16bit();
-
- if(reader.remaining_bytes() != all_extn_size)
- throw Decoding_Error("Bad extension size");
-
- while(reader.has_remaining())
- {
- const u16bit extension_code = reader.get_u16bit();
- const u16bit extension_size = reader.get_u16bit();
-
- Extension* extn = make_extension(reader,
- extension_code,
- extension_size);
-
- if(extn)
- this->add(extn);
- else // unknown/unhandled extension
- reader.discard_next(extension_size);
- }
- }
- }
-
-std::vector<byte> Extensions::serialize() const
- {
- std::vector<byte> buf(2); // 2 bytes for length field
-
- for(auto& extn : extensions)
- {
- if(extn.second->empty())
- continue;
-
- const u16bit extn_code = extn.second->type();
-
- std::vector<byte> extn_val = extn.second->serialize();
-
- buf.push_back(get_byte(0, extn_code));
- buf.push_back(get_byte(1, extn_code));
-
- buf.push_back(get_byte<u16bit>(0, extn_val.size()));
- buf.push_back(get_byte<u16bit>(1, extn_val.size()));
-
- buf += extn_val;
- }
-
- const u16bit extn_size = buf.size() - 2;
-
- buf[0] = get_byte(0, extn_size);
- buf[1] = get_byte(1, extn_size);
-
- // avoid sending a completely empty extensions block
- if(buf.size() == 2)
- return std::vector<byte>();
-
- return buf;
- }
-
-Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- /*
- * This is used by the server to confirm that it knew the name
- */
- if(extension_size == 0)
- return;
-
- u16bit name_bytes = reader.get_u16bit();
-
- if(name_bytes + 2 != extension_size)
- throw Decoding_Error("Bad encoding of SNI extension");
-
- while(name_bytes)
- {
- byte name_type = reader.get_byte();
- name_bytes--;
-
- if(name_type == 0) // DNS
- {
- sni_host_name = reader.get_string(2, 1, 65535);
- name_bytes -= (2 + sni_host_name.size());
- }
- else // some other unknown name type
- {
- reader.discard_next(name_bytes);
- name_bytes = 0;
- }
- }
- }
-
-std::vector<byte> Server_Name_Indicator::serialize() const
- {
- std::vector<byte> buf;
-
- size_t name_len = sni_host_name.size();
-
- buf.push_back(get_byte<u16bit>(0, name_len+3));
- buf.push_back(get_byte<u16bit>(1, name_len+3));
- buf.push_back(0); // DNS
-
- buf.push_back(get_byte<u16bit>(0, name_len));
- buf.push_back(get_byte<u16bit>(1, name_len));
-
- buf += std::make_pair(
- reinterpret_cast<const byte*>(sni_host_name.data()),
- sni_host_name.size());
-
- return buf;
- }
-
-SRP_Identifier::SRP_Identifier(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- srp_identifier = reader.get_string(1, 1, 255);
-
- if(srp_identifier.size() + 1 != extension_size)
- throw Decoding_Error("Bad encoding for SRP identifier extension");
- }
-
-std::vector<byte> SRP_Identifier::serialize() const
- {
- std::vector<byte> buf;
-
- const byte* srp_bytes =
- reinterpret_cast<const byte*>(srp_identifier.data());
-
- append_tls_length_value(buf, srp_bytes, srp_identifier.size(), 1);
-
- return buf;
- }
-
-Renegotiation_Extension::Renegotiation_Extension(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- reneg_data = reader.get_range<byte>(1, 0, 255);
-
- if(reneg_data.size() + 1 != extension_size)
- throw Decoding_Error("Bad encoding for secure renegotiation extn");
- }
-
-std::vector<byte> Renegotiation_Extension::serialize() const
- {
- std::vector<byte> buf;
- append_tls_length_value(buf, reneg_data, 1);
- return buf;
- }
-
-std::vector<byte> Maximum_Fragment_Length::serialize() const
- {
- const std::map<size_t, byte> fragment_to_code = { { 512, 1 },
- { 1024, 2 },
- { 2048, 3 },
- { 4096, 4 } };
-
- auto i = fragment_to_code.find(m_max_fragment);
-
- if(i == fragment_to_code.end())
- throw std::invalid_argument("Bad setting " +
- std::to_string(m_max_fragment) +
- " for maximum fragment size");
-
- return std::vector<byte>(1, i->second);
- }
-
-Maximum_Fragment_Length::Maximum_Fragment_Length(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- if(extension_size != 1)
- throw Decoding_Error("Bad size for maximum fragment extension");
- byte val = reader.get_byte();
-
- const std::map<byte, size_t> code_to_fragment = { { 1, 512 },
- { 2, 1024 },
- { 3, 2048 },
- { 4, 4096 } };
-
- auto i = code_to_fragment.find(val);
-
- if(i == code_to_fragment.end())
- throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
- "Bad value in maximum fragment extension");
-
- m_max_fragment = i->second;
- }
-
-Next_Protocol_Notification::Next_Protocol_Notification(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- if(extension_size == 0)
- return; // empty extension
-
- size_t bytes_remaining = extension_size;
-
- while(bytes_remaining)
- {
- const std::string p = reader.get_string(1, 0, 255);
-
- if(bytes_remaining < p.size() + 1)
- throw Decoding_Error("Bad encoding for next protocol extension");
-
- bytes_remaining -= (p.size() + 1);
-
- m_protocols.push_back(p);
- }
- }
-
-std::vector<byte> Next_Protocol_Notification::serialize() const
- {
- std::vector<byte> buf;
-
- for(size_t i = 0; i != m_protocols.size(); ++i)
- {
- const std::string p = m_protocols[i];
-
- if(p != "")
- append_tls_length_value(buf,
- reinterpret_cast<const byte*>(p.data()),
- p.size(),
- 1);
- }
-
- return buf;
- }
-
-std::string Supported_Elliptic_Curves::curve_id_to_name(u16bit id)
- {
- switch(id)
- {
- case 15:
- return "secp160k1";
- case 16:
- return "secp160r1";
- case 17:
- return "secp160r2";
- case 18:
- return "secp192k1";
- case 19:
- return "secp192r1";
- case 20:
- return "secp224k1";
- case 21:
- return "secp224r1";
- case 22:
- return "secp256k1";
- case 23:
- return "secp256r1";
- case 24:
- return "secp384r1";
- case 25:
- return "secp521r1";
- case 26:
- return "brainpool256r1";
- case 27:
- return "brainpool384r1";
- case 28:
- return "brainpool512r1";
- default:
- return ""; // something we don't know or support
- }
- }
-
-u16bit Supported_Elliptic_Curves::name_to_curve_id(const std::string& name)
- {
- if(name == "secp160k1")
- return 15;
- if(name == "secp160r1")
- return 16;
- if(name == "secp160r2")
- return 17;
- if(name == "secp192k1")
- return 18;
- if(name == "secp192r1")
- return 19;
- if(name == "secp224k1")
- return 20;
- if(name == "secp224r1")
- return 21;
- if(name == "secp256k1")
- return 22;
- if(name == "secp256r1")
- return 23;
- if(name == "secp384r1")
- return 24;
- if(name == "secp521r1")
- return 25;
- if(name == "brainpool256r1")
- return 26;
- if(name == "brainpool384r1")
- return 27;
- if(name == "brainpool512r1")
- return 28;
-
- throw Invalid_Argument("name_to_curve_id unknown name " + name);
- }
-
-std::vector<byte> Supported_Elliptic_Curves::serialize() const
- {
- std::vector<byte> buf(2);
-
- for(size_t i = 0; i != m_curves.size(); ++i)
- {
- const u16bit id = name_to_curve_id(m_curves[i]);
- buf.push_back(get_byte(0, id));
- buf.push_back(get_byte(1, id));
- }
-
- buf[0] = get_byte<u16bit>(0, buf.size()-2);
- buf[1] = get_byte<u16bit>(1, buf.size()-2);
-
- return buf;
- }
-
-Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- u16bit len = reader.get_u16bit();
-
- if(len + 2 != extension_size)
- throw Decoding_Error("Inconsistent length field in elliptic curve list");
-
- if(len % 2 == 1)
- throw Decoding_Error("Elliptic curve list of strange size");
-
- len /= 2;
-
- for(size_t i = 0; i != len; ++i)
- {
- const u16bit id = reader.get_u16bit();
- const std::string name = curve_id_to_name(id);
-
- if(name != "")
- m_curves.push_back(name);
- }
- }
-
-std::string Signature_Algorithms::hash_algo_name(byte code)
- {
- switch(code)
- {
- case 1:
- return "MD5";
- // code 1 is MD5 - ignore it
-
- case 2:
- return "SHA-1";
- case 3:
- return "SHA-224";
- case 4:
- return "SHA-256";
- case 5:
- return "SHA-384";
- case 6:
- return "SHA-512";
- default:
- return "";
- }
- }
-
-byte Signature_Algorithms::hash_algo_code(const std::string& name)
- {
- if(name == "MD5")
- return 1;
-
- if(name == "SHA-1")
- return 2;
-
- if(name == "SHA-224")
- return 3;
-
- if(name == "SHA-256")
- return 4;
-
- if(name == "SHA-384")
- return 5;
-
- if(name == "SHA-512")
- return 6;
-
- throw Internal_Error("Unknown hash ID " + name + " for signature_algorithms");
- }
-
-std::string Signature_Algorithms::sig_algo_name(byte code)
- {
- switch(code)
- {
- case 1:
- return "RSA";
- case 2:
- return "DSA";
- case 3:
- return "ECDSA";
- default:
- return "";
- }
- }
-
-byte Signature_Algorithms::sig_algo_code(const std::string& name)
- {
- if(name == "RSA")
- return 1;
-
- if(name == "DSA")
- return 2;
-
- if(name == "ECDSA")
- return 3;
-
- throw Internal_Error("Unknown sig ID " + name + " for signature_algorithms");
- }
-
-std::vector<byte> Signature_Algorithms::serialize() const
- {
- std::vector<byte> buf(2);
-
- for(size_t i = 0; i != m_supported_algos.size(); ++i)
- {
- try
- {
- const byte hash_code = hash_algo_code(m_supported_algos[i].first);
- const byte sig_code = sig_algo_code(m_supported_algos[i].second);
-
- buf.push_back(hash_code);
- buf.push_back(sig_code);
- }
- catch(...)
- {}
- }
-
- buf[0] = get_byte<u16bit>(0, buf.size()-2);
- buf[1] = get_byte<u16bit>(1, buf.size()-2);
-
- return buf;
- }
-
-Signature_Algorithms::Signature_Algorithms(const std::vector<std::string>& hashes,
- const std::vector<std::string>& sigs)
- {
- for(size_t i = 0; i != hashes.size(); ++i)
- for(size_t j = 0; j != sigs.size(); ++j)
- m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
- }
-
-Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- u16bit len = reader.get_u16bit();
-
- if(len + 2 != extension_size)
- throw Decoding_Error("Bad encoding on signature algorithms extension");
-
- while(len)
- {
- const std::string hash_code = hash_algo_name(reader.get_byte());
- const std::string sig_code = sig_algo_name(reader.get_byte());
-
- len -= 2;
-
- // If not something we know, ignore it completely
- if(hash_code == "" || sig_code == "")
- continue;
-
- m_supported_algos.push_back(std::make_pair(hash_code, sig_code));
- }
- }
-
-Session_Ticket::Session_Ticket(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- m_ticket = reader.get_elem<byte, std::vector<byte> >(extension_size);
- }
-
-}
-
-}
diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h
deleted file mode 100644
index de3654fd3..000000000
--- a/src/tls/tls_extensions.h
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
-* TLS Extensions
-* (C) 2011-2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_EXTENSIONS_H__
-#define BOTAN_TLS_EXTENSIONS_H__
-
-#include <botan/secmem.h>
-#include <botan/tls_magic.h>
-#include <vector>
-#include <string>
-#include <memory>
-#include <map>
-
-namespace Botan {
-
-namespace TLS {
-
-class TLS_Data_Reader;
-
-enum Handshake_Extension_Type {
- TLSEXT_SERVER_NAME_INDICATION = 0,
- TLSEXT_MAX_FRAGMENT_LENGTH = 1,
- TLSEXT_CLIENT_CERT_URL = 2,
- TLSEXT_TRUSTED_CA_KEYS = 3,
- TLSEXT_TRUNCATED_HMAC = 4,
-
- TLSEXT_CERTIFICATE_TYPES = 9,
- TLSEXT_USABLE_ELLIPTIC_CURVES = 10,
- TLSEXT_EC_POINT_FORMATS = 11,
- TLSEXT_SRP_IDENTIFIER = 12,
- TLSEXT_SIGNATURE_ALGORITHMS = 13,
- TLSEXT_HEARTBEAT_SUPPORT = 15,
-
- TLSEXT_SESSION_TICKET = 35,
-
- TLSEXT_NEXT_PROTOCOL = 13172,
-
- TLSEXT_SAFE_RENEGOTIATION = 65281,
-};
-
-/**
-* Base class representing a TLS extension of some kind
-*/
-class Extension
- {
- public:
- /**
- * @return code number of the extension
- */
- virtual Handshake_Extension_Type type() const = 0;
-
- /**
- * @return serialized binary for the extension
- */
- virtual std::vector<byte> serialize() const = 0;
-
- /**
- * @return if we should encode this extension or not
- */
- virtual bool empty() const = 0;
-
- virtual ~Extension() {}
- };
-
-/**
-* Server Name Indicator extension (RFC 3546)
-*/
-class Server_Name_Indicator : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_SERVER_NAME_INDICATION; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- Server_Name_Indicator(const std::string& host_name) :
- sni_host_name(host_name) {}
-
- Server_Name_Indicator(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- std::string host_name() const { return sni_host_name; }
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return sni_host_name == ""; }
- private:
- std::string sni_host_name;
- };
-
-/**
-* SRP identifier extension (RFC 5054)
-*/
-class SRP_Identifier : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_SRP_IDENTIFIER; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- SRP_Identifier(const std::string& identifier) :
- srp_identifier(identifier) {}
-
- SRP_Identifier(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- std::string identifier() const { return srp_identifier; }
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return srp_identifier == ""; }
- private:
- std::string srp_identifier;
- };
-
-/**
-* Renegotiation Indication Extension (RFC 5746)
-*/
-class Renegotiation_Extension : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_SAFE_RENEGOTIATION; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- Renegotiation_Extension() {}
-
- Renegotiation_Extension(const std::vector<byte>& bits) :
- reneg_data(bits) {}
-
- Renegotiation_Extension(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- const std::vector<byte>& renegotiation_info() const
- { return reneg_data; }
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return false; } // always send this
- private:
- std::vector<byte> reneg_data;
- };
-
-/**
-* Maximum Fragment Length Negotiation Extension (RFC 4366 sec 3.2)
-*/
-class Maximum_Fragment_Length : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_MAX_FRAGMENT_LENGTH; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- bool empty() const { return false; }
-
- size_t fragment_size() const { return m_max_fragment; }
-
- std::vector<byte> serialize() const;
-
- /**
- * @param max_fragment specifies what maximum fragment size to
- * advertise. Currently must be one of 512, 1024, 2048, or
- * 4096.
- */
- Maximum_Fragment_Length(size_t max_fragment) :
- m_max_fragment(max_fragment) {}
-
- Maximum_Fragment_Length(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- private:
- size_t m_max_fragment;
- };
-
-/**
-* Next Protocol Negotiation
-* http://technotes.googlecode.com/git/nextprotoneg.html
-*
-* This implementation requires the semantics defined in the Google
-* spec (implemented in Chromium); the internet draft leaves the format
-* unspecified.
-*/
-class Next_Protocol_Notification : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_NEXT_PROTOCOL; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- const std::vector<std::string>& protocols() const
- { return m_protocols; }
-
- /**
- * Empty extension, used by client
- */
- Next_Protocol_Notification() {}
-
- /**
- * List of protocols, used by server
- */
- Next_Protocol_Notification(const std::vector<std::string>& protocols) :
- m_protocols(protocols) {}
-
- Next_Protocol_Notification(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return false; }
- private:
- std::vector<std::string> m_protocols;
- };
-
-/**
-* Session Ticket Extension (RFC 5077)
-*/
-class Session_Ticket : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_SESSION_TICKET; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- /**
- * @return contents of the session ticket
- */
- const std::vector<byte>& contents() const { return m_ticket; }
-
- /**
- * Create empty extension, used by both client and server
- */
- Session_Ticket() {}
-
- /**
- * Extension with ticket, used by client
- */
- Session_Ticket(const std::vector<byte>& session_ticket) :
- m_ticket(session_ticket) {}
-
- /**
- * Deserialize a session ticket
- */
- Session_Ticket(TLS_Data_Reader& reader, u16bit extension_size);
-
- std::vector<byte> serialize() const { return m_ticket; }
-
- bool empty() const { return false; }
- private:
- std::vector<byte> m_ticket;
- };
-
-/**
-* Supported Elliptic Curves Extension (RFC 4492)
-*/
-class Supported_Elliptic_Curves : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_USABLE_ELLIPTIC_CURVES; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- static std::string curve_id_to_name(u16bit id);
- static u16bit name_to_curve_id(const std::string& name);
-
- const std::vector<std::string>& curves() const { return m_curves; }
-
- std::vector<byte> serialize() const;
-
- Supported_Elliptic_Curves(const std::vector<std::string>& curves) :
- m_curves(curves) {}
-
- Supported_Elliptic_Curves(TLS_Data_Reader& reader,
- u16bit extension_size);
-
- bool empty() const { return m_curves.empty(); }
- private:
- std::vector<std::string> m_curves;
- };
-
-/**
-* Signature Algorithms Extension for TLS 1.2 (RFC 5246)
-*/
-class Signature_Algorithms : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_SIGNATURE_ALGORITHMS; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- static std::string hash_algo_name(byte code);
- static byte hash_algo_code(const std::string& name);
-
- static std::string sig_algo_name(byte code);
- static byte sig_algo_code(const std::string& name);
-
- std::vector<std::pair<std::string, std::string> >
- supported_signature_algorthms() const
- {
- return m_supported_algos;
- }
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return false; }
-
- Signature_Algorithms(const std::vector<std::string>& hashes,
- const std::vector<std::string>& sig_algos);
-
- Signature_Algorithms(const std::vector<std::pair<std::string, std::string> >& algos) :
- m_supported_algos(algos) {}
-
- Signature_Algorithms(TLS_Data_Reader& reader,
- u16bit extension_size);
- private:
- std::vector<std::pair<std::string, std::string> > m_supported_algos;
- };
-
-/**
-* Heartbeat Extension (RFC 6520)
-*/
-class Heartbeat_Support_Indicator : public Extension
- {
- public:
- static Handshake_Extension_Type static_type()
- { return TLSEXT_HEARTBEAT_SUPPORT; }
-
- Handshake_Extension_Type type() const { return static_type(); }
-
- bool peer_allowed_to_send() const { return m_peer_allowed_to_send; }
-
- std::vector<byte> serialize() const;
-
- bool empty() const { return false; }
-
- Heartbeat_Support_Indicator(bool peer_allowed_to_send) :
- m_peer_allowed_to_send(peer_allowed_to_send) {}
-
- Heartbeat_Support_Indicator(TLS_Data_Reader& reader, u16bit extension_size);
-
- private:
- bool m_peer_allowed_to_send;
- };
-
-/**
-* Represents a block of extensions in a hello message
-*/
-class Extensions
- {
- public:
- template<typename T>
- T* get() const
- {
- Handshake_Extension_Type type = T::static_type();
-
- auto i = extensions.find(type);
-
- if(i != extensions.end())
- return dynamic_cast<T*>(i->second.get());
- return nullptr;
- }
-
- void add(Extension* extn)
- {
- extensions[extn->type()].reset(extn);
- }
-
- std::vector<byte> serialize() const;
-
- void deserialize(TLS_Data_Reader& reader);
-
- Extensions() {}
-
- Extensions(TLS_Data_Reader& reader) { deserialize(reader); }
-
- private:
- Extensions(const Extensions&) {}
- Extensions& operator=(const Extensions&) { return (*this); }
-
- std::map<Handshake_Extension_Type, std::unique_ptr<Extension>> extensions;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_handshake_hash.cpp b/src/tls/tls_handshake_hash.cpp
deleted file mode 100644
index 4e7a0b9b7..000000000
--- a/src/tls/tls_handshake_hash.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-* TLS Handshake Hash
-* (C) 2004-2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_handshake_hash.h>
-#include <botan/tls_exceptn.h>
-#include <botan/libstate.h>
-#include <botan/hash.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Return a TLS Handshake Hash
-*/
-secure_vector<byte> Handshake_Hash::final(Protocol_Version version,
- const std::string& mac_algo) const
- {
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- std::unique_ptr<HashFunction> hash;
-
- if(version.supports_ciphersuite_specific_prf())
- {
- if(mac_algo == "MD5" || mac_algo == "SHA-1")
- hash.reset(af.make_hash_function("SHA-256"));
- else
- hash.reset(af.make_hash_function(mac_algo));
- }
- else
- hash.reset(af.make_hash_function("Parallel(MD5,SHA-160)"));
-
- hash->update(data);
- return hash->final();
- }
-
-/**
-* Return a SSLv3 Handshake Hash
-*/
-secure_vector<byte> Handshake_Hash::final_ssl3(const secure_vector<byte>& secret) const
- {
- const byte PAD_INNER = 0x36, PAD_OUTER = 0x5C;
-
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- std::unique_ptr<HashFunction> md5(af.make_hash_function("MD5"));
- std::unique_ptr<HashFunction> sha1(af.make_hash_function("SHA-1"));
-
- md5->update(data);
- sha1->update(data);
-
- md5->update(secret);
- sha1->update(secret);
-
- for(size_t i = 0; i != 48; ++i)
- md5->update(PAD_INNER);
- for(size_t i = 0; i != 40; ++i)
- sha1->update(PAD_INNER);
-
- secure_vector<byte> inner_md5 = md5->final(), inner_sha1 = sha1->final();
-
- md5->update(secret);
- sha1->update(secret);
-
- for(size_t i = 0; i != 48; ++i)
- md5->update(PAD_OUTER);
- for(size_t i = 0; i != 40; ++i)
- sha1->update(PAD_OUTER);
-
- md5->update(inner_md5);
- sha1->update(inner_sha1);
-
- secure_vector<byte> output;
- output += md5->final();
- output += sha1->final();
- return output;
- }
-
-}
-
-}
diff --git a/src/tls/tls_handshake_hash.h b/src/tls/tls_handshake_hash.h
deleted file mode 100644
index 840895963..000000000
--- a/src/tls/tls_handshake_hash.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-* TLS Handshake Hash
-* (C) 2004-2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_HASH_H__
-#define BOTAN_TLS_HANDSHAKE_HASH_H__
-
-#include <botan/secmem.h>
-#include <botan/tls_version.h>
-#include <botan/tls_magic.h>
-
-namespace Botan {
-
-namespace TLS {
-
-using namespace Botan;
-
-/**
-* TLS Handshake Hash
-*/
-class Handshake_Hash
- {
- public:
- void update(const byte in[], size_t length)
- { data += std::make_pair(in, length); }
-
- void update(const std::vector<byte>& in)
- { data += in; }
-
- secure_vector<byte> final(Protocol_Version version,
- const std::string& mac_algo) const;
-
- secure_vector<byte> final_ssl3(const secure_vector<byte>& master_secret) const;
-
- const std::vector<byte>& get_contents() const
- { return data; }
-
- void reset() { data.clear(); }
- private:
- std::vector<byte> data;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_handshake_io.cpp b/src/tls/tls_handshake_io.cpp
deleted file mode 100644
index 38def13a2..000000000
--- a/src/tls/tls_handshake_io.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-* TLS Handshake IO
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_record.h>
-#include <botan/internal/tls_seq_numbers.h>
-#include <botan/exceptn.h>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-inline size_t load_be24(const byte q[3])
- {
- return make_u32bit(0,
- q[0],
- q[1],
- q[2]);
- }
-
-void store_be24(byte out[3], size_t val)
- {
- out[0] = get_byte<u32bit>(1, val);
- out[1] = get_byte<u32bit>(2, val);
- out[2] = get_byte<u32bit>(3, val);
- }
-
-}
-
-Protocol_Version Stream_Handshake_IO::initial_record_version() const
- {
- return Protocol_Version::TLS_V10;
- }
-
-void Stream_Handshake_IO::add_record(const std::vector<byte>& record,
- Record_Type record_type, u64bit)
- {
- if(record_type == HANDSHAKE)
- {
- m_queue.insert(m_queue.end(), record.begin(), record.end());
- }
- else if(record_type == CHANGE_CIPHER_SPEC)
- {
- if(record.size() != 1 || record[0] != 1)
- throw Decoding_Error("Invalid ChangeCipherSpec");
-
- // Pretend it's a regular handshake message of zero length
- const byte ccs_hs[] = { HANDSHAKE_CCS, 0, 0, 0 };
- m_queue.insert(m_queue.end(), ccs_hs, ccs_hs + sizeof(ccs_hs));
- }
- else
- throw Decoding_Error("Unknown message type in handshake processing");
- }
-
-std::pair<Handshake_Type, std::vector<byte>>
-Stream_Handshake_IO::get_next_record(bool)
- {
- if(m_queue.size() >= 4)
- {
- const size_t length = load_be24(&m_queue[1]);
-
- if(m_queue.size() >= length + 4)
- {
- Handshake_Type type = static_cast<Handshake_Type>(m_queue[0]);
-
- std::vector<byte> contents(m_queue.begin() + 4,
- m_queue.begin() + 4 + length);
-
- m_queue.erase(m_queue.begin(), m_queue.begin() + 4 + length);
-
- return std::make_pair(type, contents);
- }
- }
-
- return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());
- }
-
-std::vector<byte>
-Stream_Handshake_IO::format(const std::vector<byte>& msg,
- Handshake_Type type) const
- {
- std::vector<byte> send_buf(4 + msg.size());
-
- const size_t buf_size = msg.size();
-
- send_buf[0] = type;
-
- store_be24(&send_buf[1], buf_size);
-
- copy_mem(&send_buf[4], &msg[0], msg.size());
-
- return send_buf;
- }
-
-std::vector<byte> Stream_Handshake_IO::send(const Handshake_Message& msg)
- {
- const std::vector<byte> msg_bits = msg.serialize();
-
- if(msg.type() == HANDSHAKE_CCS)
- {
- m_send_hs(CHANGE_CIPHER_SPEC, msg_bits);
- return std::vector<byte>(); // not included in handshake hashes
- }
-
- const std::vector<byte> buf = format(msg_bits, msg.type());
- m_send_hs(HANDSHAKE, buf);
- return buf;
- }
-
-Protocol_Version Datagram_Handshake_IO::initial_record_version() const
- {
- return Protocol_Version::DTLS_V10;
- }
-
-void Datagram_Handshake_IO::add_record(const std::vector<byte>& record,
- Record_Type record_type,
- u64bit record_sequence)
- {
- const u16bit epoch = static_cast<u16bit>(record_sequence >> 48);
-
- if(record_type == CHANGE_CIPHER_SPEC)
- {
- m_ccs_epochs.insert(epoch);
- return;
- }
-
- const size_t DTLS_HANDSHAKE_HEADER_LEN = 12;
-
- const byte* record_bits = &record[0];
- size_t record_size = record.size();
-
- while(record_size)
- {
- if(record_size < DTLS_HANDSHAKE_HEADER_LEN)
- return; // completely bogus? at least degenerate/weird
-
- const byte msg_type = record_bits[0];
- const size_t msg_len = load_be24(&record_bits[1]);
- const u16bit message_seq = load_be<u16bit>(&record_bits[4], 0);
- const size_t fragment_offset = load_be24(&record_bits[6]);
- const size_t fragment_length = load_be24(&record_bits[9]);
-
- const size_t total_size = DTLS_HANDSHAKE_HEADER_LEN + fragment_length;
-
- if(record_size < total_size)
- throw Decoding_Error("Bad lengths in DTLS header");
-
- if(message_seq >= m_in_message_seq)
- {
- m_messages[message_seq].add_fragment(&record_bits[DTLS_HANDSHAKE_HEADER_LEN],
- fragment_length,
- fragment_offset,
- epoch,
- msg_type,
- msg_len);
- }
-
- record_bits += total_size;
- record_size -= total_size;
- }
- }
-
-std::pair<Handshake_Type, std::vector<byte>>
-Datagram_Handshake_IO::get_next_record(bool expecting_ccs)
- {
- if(!m_flights.rbegin()->empty())
- m_flights.push_back(std::vector<u16bit>());
-
- if(expecting_ccs)
- {
- if(!m_messages.empty())
- {
- const u16bit current_epoch = m_messages.begin()->second.epoch();
-
- if(m_ccs_epochs.count(current_epoch))
- return std::make_pair(HANDSHAKE_CCS, std::vector<byte>());
- }
-
- return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());
- }
-
- auto i = m_messages.find(m_in_message_seq);
-
- if(i == m_messages.end() || !i->second.complete())
- return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());
-
- m_in_message_seq += 1;
-
- return i->second.message();
- }
-
-void Datagram_Handshake_IO::Handshake_Reassembly::add_fragment(
- const byte fragment[],
- size_t fragment_length,
- size_t fragment_offset,
- u16bit epoch,
- byte msg_type,
- size_t msg_length)
- {
- if(complete())
- return; // already have entire message, ignore this
-
- if(m_msg_type == HANDSHAKE_NONE)
- {
- m_epoch = epoch;
- m_msg_type = msg_type;
- m_msg_length = msg_length;
- }
-
- if(msg_type != m_msg_type || msg_length != m_msg_length || epoch != m_epoch)
- throw Decoding_Error("Inconsistent values in DTLS handshake header");
-
- if(fragment_offset > m_msg_length)
- throw Decoding_Error("Fragment offset past end of message");
-
- if(fragment_offset + fragment_length > m_msg_length)
- throw Decoding_Error("Fragment overlaps past end of message");
-
- if(fragment_offset == 0 && fragment_length == m_msg_length)
- {
- m_fragments.clear();
- m_message.assign(fragment, fragment+fragment_length);
- }
- else
- {
- /*
- * FIXME. This is a pretty lame way to do defragmentation, huge
- * overhead with a tree node per byte.
- *
- * Also should confirm that all overlaps have no changes,
- * otherwise we expose ourselves to the classic fingerprinting
- * and IDS evasion attacks on IP fragmentation.
- */
- for(size_t i = 0; i != fragment_length; ++i)
- m_fragments[fragment_offset+i] = fragment[i];
-
- if(m_fragments.size() == m_msg_length)
- {
- m_message.resize(m_msg_length);
- for(size_t i = 0; i != m_msg_length; ++i)
- m_message[i] = m_fragments[i];
- m_fragments.clear();
- }
- }
- }
-
-bool Datagram_Handshake_IO::Handshake_Reassembly::complete() const
- {
- return (m_msg_type != HANDSHAKE_NONE && m_message.size() == m_msg_length);
- }
-
-std::pair<Handshake_Type, std::vector<byte>>
-Datagram_Handshake_IO::Handshake_Reassembly::message() const
- {
- if(!complete())
- throw Internal_Error("Datagram_Handshake_IO - message not complete");
-
- return std::make_pair(static_cast<Handshake_Type>(m_msg_type), m_message);
- }
-
-std::vector<byte>
-Datagram_Handshake_IO::format_fragment(const byte fragment[],
- size_t frag_len,
- u16bit frag_offset,
- u16bit msg_len,
- Handshake_Type type,
- u16bit msg_sequence) const
- {
- std::vector<byte> send_buf(12 + frag_len);
-
- send_buf[0] = type;
-
- store_be24(&send_buf[1], msg_len);
-
- store_be(msg_sequence, &send_buf[4]);
-
- store_be24(&send_buf[6], frag_offset);
- store_be24(&send_buf[9], frag_len);
-
- copy_mem(&send_buf[12], &fragment[0], frag_len);
-
- return send_buf;
- }
-
-std::vector<byte>
-Datagram_Handshake_IO::format_w_seq(const std::vector<byte>& msg,
- Handshake_Type type,
- u16bit msg_sequence) const
- {
- return format_fragment(&msg[0], msg.size(), 0, msg.size(), type, msg_sequence);
- }
-
-std::vector<byte>
-Datagram_Handshake_IO::format(const std::vector<byte>& msg,
- Handshake_Type type) const
- {
- return format_w_seq(msg, type, m_in_message_seq - 1);
- }
-
-namespace {
-
-size_t split_for_mtu(size_t mtu, size_t msg_size)
- {
- const size_t DTLS_HEADERS_SIZE = 25; // DTLS record+handshake headers
-
- const size_t parts = (msg_size + mtu) / mtu;
-
- if(parts + DTLS_HEADERS_SIZE > mtu)
- return parts + 1;
-
- return parts;
- }
-
-}
-
-std::vector<byte>
-Datagram_Handshake_IO::send(const Handshake_Message& msg)
- {
- const std::vector<byte> msg_bits = msg.serialize();
- const u16bit epoch = m_seqs.current_write_epoch();
- const Handshake_Type msg_type = msg.type();
-
- std::tuple<u16bit, byte, std::vector<byte>> msg_info(epoch, msg_type, msg_bits);
-
- if(msg_type == HANDSHAKE_CCS)
- {
- m_send_hs(epoch, CHANGE_CIPHER_SPEC, msg_bits);
- return std::vector<byte>(); // not included in handshake hashes
- }
-
- const std::vector<byte> no_fragment =
- format_w_seq(msg_bits, msg_type, m_out_message_seq);
-
- if(no_fragment.size() + DTLS_HEADER_SIZE <= m_mtu)
- m_send_hs(epoch, HANDSHAKE, no_fragment);
- else
- {
- const size_t parts = split_for_mtu(m_mtu, msg_bits.size());
-
- const size_t parts_size = (msg_bits.size() + parts) / parts;
-
- size_t frag_offset = 0;
-
- while(frag_offset != msg_bits.size())
- {
- const size_t frag_len =
- std::min<size_t>(msg_bits.size() - frag_offset,
- parts_size);
-
- m_send_hs(epoch,
- HANDSHAKE,
- format_fragment(&msg_bits[frag_offset],
- frag_len,
- frag_offset,
- msg_bits.size(),
- msg_type,
- m_out_message_seq));
-
- frag_offset += frag_len;
- }
- }
-
- // Note: not saving CCS, instead we know it was there due to change in epoch
- m_flights.rbegin()->push_back(m_out_message_seq);
- m_flight_data[m_out_message_seq] = msg_info;
-
- m_out_message_seq += 1;
-
- return no_fragment;
- }
-
-}
-
-}
diff --git a/src/tls/tls_handshake_io.h b/src/tls/tls_handshake_io.h
deleted file mode 100644
index 36c605c30..000000000
--- a/src/tls/tls_handshake_io.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-* TLS Handshake Serialization
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_IO_H__
-#define BOTAN_TLS_HANDSHAKE_IO_H__
-
-#include <botan/tls_magic.h>
-#include <botan/tls_version.h>
-#include <botan/loadstor.h>
-#include <functional>
-#include <vector>
-#include <deque>
-#include <map>
-#include <set>
-#include <utility>
-#include <tuple>
-
-namespace Botan {
-
-namespace TLS {
-
-class Handshake_Message;
-
-/**
-* Handshake IO Interface
-*/
-class Handshake_IO
- {
- public:
- virtual Protocol_Version initial_record_version() const = 0;
-
- virtual std::vector<byte> send(const Handshake_Message& msg) = 0;
-
- virtual std::vector<byte> format(
- const std::vector<byte>& handshake_msg,
- Handshake_Type handshake_type) const = 0;
-
- virtual void add_record(const std::vector<byte>& record,
- Record_Type type,
- u64bit sequence_number) = 0;
-
- /**
- * Returns (HANDSHAKE_NONE, std::vector<>()) if no message currently available
- */
- virtual std::pair<Handshake_Type, std::vector<byte>>
- get_next_record(bool expecting_ccs) = 0;
-
- Handshake_IO() {}
-
- Handshake_IO(const Handshake_IO&) = delete;
-
- Handshake_IO& operator=(const Handshake_IO&) = delete;
-
- virtual ~Handshake_IO() {}
- };
-
-/**
-* Handshake IO for stream-based handshakes
-*/
-class Stream_Handshake_IO : public Handshake_IO
- {
- public:
- Stream_Handshake_IO(std::function<void (byte, const std::vector<byte>&)> writer) :
- m_send_hs(writer) {}
-
- Protocol_Version initial_record_version() const override;
-
- std::vector<byte> send(const Handshake_Message& msg) override;
-
- std::vector<byte> format(
- const std::vector<byte>& handshake_msg,
- Handshake_Type handshake_type) const override;
-
- void add_record(const std::vector<byte>& record,
- Record_Type type,
- u64bit sequence_number) override;
-
- std::pair<Handshake_Type, std::vector<byte>>
- get_next_record(bool expecting_ccs) override;
- private:
- std::deque<byte> m_queue;
- std::function<void (byte, const std::vector<byte>&)> m_send_hs;
- };
-
-/**
-* Handshake IO for datagram-based handshakes
-*/
-class Datagram_Handshake_IO : public Handshake_IO
- {
- public:
- Datagram_Handshake_IO(class Connection_Sequence_Numbers& seq,
- std::function<void (u16bit, byte, const std::vector<byte>&)> writer) :
- m_seqs(seq), m_flights(1), m_send_hs(writer) {}
-
- Protocol_Version initial_record_version() const override;
-
- std::vector<byte> send(const Handshake_Message& msg) override;
-
- std::vector<byte> format(
- const std::vector<byte>& handshake_msg,
- Handshake_Type handshake_type) const override;
-
- void add_record(const std::vector<byte>& record,
- Record_Type type,
- u64bit sequence_number) override;
-
- std::pair<Handshake_Type, std::vector<byte>>
- get_next_record(bool expecting_ccs) override;
- private:
- std::vector<byte> format_fragment(
- const byte fragment[],
- size_t fragment_len,
- u16bit frag_offset,
- u16bit msg_len,
- Handshake_Type type,
- u16bit msg_sequence) const;
-
- std::vector<byte> format_w_seq(
- const std::vector<byte>& handshake_msg,
- Handshake_Type handshake_type,
- u16bit msg_sequence) const;
-
- class Handshake_Reassembly
- {
- public:
- void add_fragment(const byte fragment[],
- size_t fragment_length,
- size_t fragment_offset,
- u16bit epoch,
- byte msg_type,
- size_t msg_length);
-
- bool complete() const;
-
- u16bit epoch() const { return m_epoch; }
-
- std::pair<Handshake_Type, std::vector<byte>> message() const;
- private:
- byte m_msg_type = HANDSHAKE_NONE;
- size_t m_msg_length = 0;
- u16bit m_epoch = 0;
-
- std::map<size_t, byte> m_fragments;
- std::vector<byte> m_message;
- };
-
- class Connection_Sequence_Numbers& m_seqs;
- std::map<u16bit, Handshake_Reassembly> m_messages;
- std::set<u16bit> m_ccs_epochs;
- std::vector<std::vector<u16bit>> m_flights;
- std::map<u16bit, std::tuple<u16bit, byte, std::vector<byte>>> m_flight_data;
-
- // default MTU is IPv6 min MTU minus UDP/IP headers
- u16bit m_mtu = 1280 - 40 - 8;
- u16bit m_in_message_seq = 0;
- u16bit m_out_message_seq = 0;
- std::function<void (u16bit, byte, const std::vector<byte>&)> m_send_hs;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_handshake_msg.h b/src/tls/tls_handshake_msg.h
deleted file mode 100644
index 1c44554d3..000000000
--- a/src/tls/tls_handshake_msg.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-* TLS Handshake Message
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_MSG_H__
-#define BOTAN_TLS_HANDSHAKE_MSG_H__
-
-#include <botan/tls_magic.h>
-#include <vector>
-#include <string>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Handshake Message Base Class
-*/
-class BOTAN_DLL Handshake_Message
- {
- public:
- virtual Handshake_Type type() const = 0;
-
- virtual std::vector<byte> serialize() const = 0;
-
- virtual ~Handshake_Message() {}
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp
deleted file mode 100644
index 84b22cc09..000000000
--- a/src/tls/tls_handshake_state.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
-* TLS Handshaking
-* (C) 2004-2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/tls_record.h>
-#include <botan/lookup.h>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-u32bit bitmask_for_handshake_type(Handshake_Type type)
- {
- switch(type)
- {
- case HELLO_VERIFY_REQUEST:
- return (1 << 0);
-
- case HELLO_REQUEST:
- return (1 << 1);
-
- /*
- * Same code point for both client hello styles
- */
- case CLIENT_HELLO:
- case CLIENT_HELLO_SSLV2:
- return (1 << 2);
-
- case SERVER_HELLO:
- return (1 << 3);
-
- case CERTIFICATE:
- return (1 << 4);
-
- case CERTIFICATE_URL:
- return (1 << 5);
-
- case CERTIFICATE_STATUS:
- return (1 << 6);
-
- case SERVER_KEX:
- return (1 << 7);
-
- case CERTIFICATE_REQUEST:
- return (1 << 8);
-
- case SERVER_HELLO_DONE:
- return (1 << 9);
-
- case CERTIFICATE_VERIFY:
- return (1 << 10);
-
- case CLIENT_KEX:
- return (1 << 11);
-
- case NEXT_PROTOCOL:
- return (1 << 12);
-
- case NEW_SESSION_TICKET:
- return (1 << 13);
-
- case HANDSHAKE_CCS:
- return (1 << 14);
-
- case FINISHED:
- return (1 << 15);
-
- // allow explicitly disabling new handshakes
- case HANDSHAKE_NONE:
- return 0;
- }
-
- throw Internal_Error("Unknown handshake type " + std::to_string(type));
- }
-
-}
-
-/*
-* Initialize the SSL/TLS Handshake State
-*/
-Handshake_State::Handshake_State(Handshake_IO* io,
- std::function<void (const Handshake_Message&)> msg_callback) :
- m_msg_callback(msg_callback),
- m_handshake_io(io),
- m_version(m_handshake_io->initial_record_version())
- {
- }
-
-Handshake_State::~Handshake_State() {}
-
-void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify)
- {
- note_message(hello_verify);
-
- m_client_hello->update_hello_cookie(hello_verify);
- hash().reset();
- hash().update(handshake_io().send(*m_client_hello));
- note_message(*m_client_hello);
- }
-
-void Handshake_State::client_hello(Client_Hello* client_hello)
- {
- m_client_hello.reset(client_hello);
- note_message(*m_client_hello);
- }
-
-void Handshake_State::server_hello(Server_Hello* server_hello)
- {
- m_server_hello.reset(server_hello);
- m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite());
- note_message(*m_server_hello);
- }
-
-void Handshake_State::server_certs(Certificate* server_certs)
- {
- m_server_certs.reset(server_certs);
- note_message(*m_server_certs);
- }
-
-void Handshake_State::server_kex(Server_Key_Exchange* server_kex)
- {
- m_server_kex.reset(server_kex);
- note_message(*m_server_kex);
- }
-
-void Handshake_State::cert_req(Certificate_Req* cert_req)
- {
- m_cert_req.reset(cert_req);
- note_message(*m_cert_req);
- }
-
-void Handshake_State::server_hello_done(Server_Hello_Done* server_hello_done)
- {
- m_server_hello_done.reset(server_hello_done);
- note_message(*m_server_hello_done);
- }
-
-void Handshake_State::client_certs(Certificate* client_certs)
- {
- m_client_certs.reset(client_certs);
- note_message(*m_client_certs);
- }
-
-void Handshake_State::client_kex(Client_Key_Exchange* client_kex)
- {
- m_client_kex.reset(client_kex);
- note_message(*m_client_kex);
- }
-
-void Handshake_State::client_verify(Certificate_Verify* client_verify)
- {
- m_client_verify.reset(client_verify);
- note_message(*m_client_verify);
- }
-
-void Handshake_State::next_protocol(Next_Protocol* next_protocol)
- {
- m_next_protocol.reset(next_protocol);
- note_message(*m_next_protocol);
- }
-
-void Handshake_State::new_session_ticket(New_Session_Ticket* new_session_ticket)
- {
- m_new_session_ticket.reset(new_session_ticket);
- note_message(*m_new_session_ticket);
- }
-
-void Handshake_State::server_finished(Finished* server_finished)
- {
- m_server_finished.reset(server_finished);
- note_message(*m_server_finished);
- }
-
-void Handshake_State::client_finished(Finished* client_finished)
- {
- m_client_finished.reset(client_finished);
- note_message(*m_client_finished);
- }
-
-void Handshake_State::set_version(const Protocol_Version& version)
- {
- m_version = version;
- }
-
-void Handshake_State::compute_session_keys()
- {
- m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false);
- }
-
-void Handshake_State::compute_session_keys(const secure_vector<byte>& resume_master_secret)
- {
- m_session_keys = Session_Keys(this, resume_master_secret, true);
- }
-
-void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg)
- {
- const u32bit mask = bitmask_for_handshake_type(handshake_msg);
-
- m_hand_received_mask |= mask;
-
- const bool ok = (m_hand_expecting_mask & mask); // overlap?
-
- if(!ok)
- throw Unexpected_Message("Unexpected state transition in handshake, got " +
- std::to_string(handshake_msg) +
- " expected " + std::to_string(m_hand_expecting_mask) +
- " received " + std::to_string(m_hand_received_mask));
-
- /* We don't know what to expect next, so force a call to
- set_expected_next; if it doesn't happen, the next transition
- check will always fail which is what we want.
- */
- m_hand_expecting_mask = 0;
- }
-
-void Handshake_State::set_expected_next(Handshake_Type handshake_msg)
- {
- m_hand_expecting_mask |= bitmask_for_handshake_type(handshake_msg);
- }
-
-bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const
- {
- const u32bit mask = bitmask_for_handshake_type(handshake_msg);
-
- return (m_hand_received_mask & mask);
- }
-
-std::pair<Handshake_Type, std::vector<byte>>
-Handshake_State::get_next_handshake_msg()
- {
- const bool expecting_ccs =
- (bitmask_for_handshake_type(HANDSHAKE_CCS) & m_hand_expecting_mask);
-
- return m_handshake_io->get_next_record(expecting_ccs);
- }
-
-std::string Handshake_State::srp_identifier() const
- {
- if(ciphersuite().valid() && ciphersuite().kex_algo() == "SRP_SHA")
- return client_hello()->srp_identifier();
-
- return "";
- }
-
-std::vector<byte> Handshake_State::session_ticket() const
- {
- if(new_session_ticket() && !new_session_ticket()->ticket().empty())
- return new_session_ticket()->ticket();
-
- return client_hello()->session_ticket();
- }
-
-KDF* Handshake_State::protocol_specific_prf() const
- {
- if(version() == Protocol_Version::SSL_V3)
- {
- return get_kdf("SSL3-PRF");
- }
- else if(version().supports_ciphersuite_specific_prf())
- {
- const std::string prf_algo = ciphersuite().prf_algo();
-
- if(prf_algo == "MD5" || prf_algo == "SHA-1")
- return get_kdf("TLS-12-PRF(SHA-256)");
-
- return get_kdf("TLS-12-PRF(" + prf_algo + ")");
- }
- else
- {
- // TLS v1.0, v1.1 and DTLS v1.0
- return get_kdf("TLS-PRF");
- }
-
- throw Internal_Error("Unknown version code " + version().to_string());
- }
-
-namespace {
-
-std::string choose_hash(const std::string& sig_algo,
- Protocol_Version negotiated_version,
- const Policy& policy,
- bool for_client_auth,
- const Client_Hello* client_hello,
- const Certificate_Req* cert_req)
- {
- if(!negotiated_version.supports_negotiable_signature_algorithms())
- {
- if(for_client_auth && negotiated_version == Protocol_Version::SSL_V3)
- return "Raw";
-
- if(sig_algo == "RSA")
- return "Parallel(MD5,SHA-160)";
-
- if(sig_algo == "DSA")
- return "SHA-1";
-
- if(sig_algo == "ECDSA")
- return "SHA-1";
-
- throw Internal_Error("Unknown TLS signature algo " + sig_algo);
- }
-
- const auto supported_algos = for_client_auth ?
- cert_req->supported_algos() :
- client_hello->supported_algos();
-
- if(!supported_algos.empty())
- {
- const auto hashes = policy.allowed_signature_hashes();
-
- /*
- * Choose our most preferred hash that the counterparty supports
- * in pairing with the signature algorithm we want to use.
- */
- for(auto hash : hashes)
- {
- for(auto algo : supported_algos)
- {
- if(algo.first == hash && algo.second == sig_algo)
- return hash;
- }
- }
- }
-
- // TLS v1.2 default hash if the counterparty sent nothing
- return "SHA-1";
- }
-
-}
-
-std::pair<std::string, Signature_Format>
-Handshake_State::choose_sig_format(const Private_Key& key,
- std::string& hash_algo_out,
- std::string& sig_algo_out,
- bool for_client_auth,
- const Policy& policy) const
- {
- const std::string sig_algo = key.algo_name();
-
- const std::string hash_algo =
- choose_hash(sig_algo,
- this->version(),
- policy,
- for_client_auth,
- client_hello(),
- cert_req());
-
- if(this->version().supports_negotiable_signature_algorithms())
- {
- hash_algo_out = hash_algo;
- sig_algo_out = sig_algo;
- }
-
- if(sig_algo == "RSA")
- {
- const std::string padding = "EMSA3(" + hash_algo + ")";
-
- return std::make_pair(padding, IEEE_1363);
- }
- else if(sig_algo == "DSA" || sig_algo == "ECDSA")
- {
- const std::string padding = "EMSA1(" + hash_algo + ")";
-
- return std::make_pair(padding, DER_SEQUENCE);
- }
-
- throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures");
- }
-
-std::pair<std::string, Signature_Format>
-Handshake_State::understand_sig_format(const Public_Key& key,
- std::string hash_algo,
- std::string sig_algo,
- bool for_client_auth) const
- {
- const std::string algo_name = key.algo_name();
-
- /*
- FIXME: This should check what was sent against the client hello
- preferences, or the certificate request, to ensure it was allowed
- by those restrictions.
-
- Or not?
- */
-
- if(this->version().supports_negotiable_signature_algorithms())
- {
- if(hash_algo == "")
- throw Decoding_Error("Counterparty did not send hash/sig IDS");
-
- if(sig_algo != algo_name)
- throw Decoding_Error("Counterparty sent inconsistent key and sig types");
- }
- else
- {
- if(hash_algo != "" || sig_algo != "")
- throw Decoding_Error("Counterparty sent hash/sig IDs with old version");
- }
-
- if(algo_name == "RSA")
- {
- if(for_client_auth && this->version() == Protocol_Version::SSL_V3)
- {
- hash_algo = "Raw";
- }
- else if(!this->version().supports_negotiable_signature_algorithms())
- {
- hash_algo = "Parallel(MD5,SHA-160)";
- }
-
- const std::string padding = "EMSA3(" + hash_algo + ")";
- return std::make_pair(padding, IEEE_1363);
- }
- else if(algo_name == "DSA" || algo_name == "ECDSA")
- {
- if(algo_name == "DSA" && for_client_auth && this->version() == Protocol_Version::SSL_V3)
- {
- hash_algo = "Raw";
- }
- else if(!this->version().supports_negotiable_signature_algorithms())
- {
- hash_algo = "SHA-1";
- }
-
- const std::string padding = "EMSA1(" + hash_algo + ")";
-
- return std::make_pair(padding, DER_SEQUENCE);
- }
-
- throw Invalid_Argument(algo_name + " is invalid/unknown for TLS signatures");
- }
-
-}
-
-}
diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h
deleted file mode 100644
index 9afcd0374..000000000
--- a/src/tls/tls_handshake_state.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-* TLS Handshake State
-* (C) 2004-2006,2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HANDSHAKE_STATE_H__
-#define BOTAN_TLS_HANDSHAKE_STATE_H__
-
-#include <botan/internal/tls_handshake_hash.h>
-#include <botan/internal/tls_handshake_io.h>
-#include <botan/internal/tls_session_key.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/tls_exceptn.h>
-#include <botan/tls_handshake_msg.h>
-#include <botan/pk_keys.h>
-#include <botan/pubkey.h>
-#include <functional>
-#include <memory>
-
-namespace Botan {
-
-class KDF;
-
-namespace TLS {
-
-class Policy;
-
-class Hello_Verify_Request;
-class Client_Hello;
-class Server_Hello;
-class Certificate;
-class Server_Key_Exchange;
-class Certificate_Req;
-class Server_Hello_Done;
-class Certificate;
-class Client_Key_Exchange;
-class Certificate_Verify;
-class Next_Protocol;
-class New_Session_Ticket;
-class Finished;
-
-/**
-* SSL/TLS Handshake State
-*/
-class Handshake_State
- {
- public:
- Handshake_State(Handshake_IO* io,
- std::function<void (const Handshake_Message&)> msg_callback =
- std::function<void (const Handshake_Message&)>());
-
- virtual ~Handshake_State();
-
- Handshake_State(const Handshake_State&) = delete;
- Handshake_State& operator=(const Handshake_State&) = delete;
-
- Handshake_IO& handshake_io() { return *m_handshake_io; }
-
- /**
- * Return true iff we have received a particular message already
- * @param msg_type the message type
- */
- bool received_handshake_msg(Handshake_Type msg_type) const;
-
- /**
- * Confirm that we were expecting this message type
- * @param msg_type the message type
- */
- void confirm_transition_to(Handshake_Type msg_type);
-
- /**
- * Record that we are expecting a particular message type next
- * @param msg_type the message type
- */
- void set_expected_next(Handshake_Type msg_type);
-
- std::pair<Handshake_Type, std::vector<byte>>
- get_next_handshake_msg();
-
- std::vector<byte> session_ticket() const;
-
- std::pair<std::string, Signature_Format>
- understand_sig_format(const Public_Key& key,
- std::string hash_algo,
- std::string sig_algo,
- bool for_client_auth) const;
-
- std::pair<std::string, Signature_Format>
- choose_sig_format(const Private_Key& key,
- std::string& hash_algo,
- std::string& sig_algo,
- bool for_client_auth,
- const Policy& policy) const;
-
- std::string srp_identifier() const;
-
- KDF* protocol_specific_prf() const;
-
- Protocol_Version version() const { return m_version; }
-
- void set_version(const Protocol_Version& version);
-
- void hello_verify_request(const Hello_Verify_Request& hello_verify);
-
- void client_hello(Client_Hello* client_hello);
- void server_hello(Server_Hello* server_hello);
- void server_certs(Certificate* server_certs);
- void server_kex(Server_Key_Exchange* server_kex);
- void cert_req(Certificate_Req* cert_req);
- void server_hello_done(Server_Hello_Done* server_hello_done);
- void client_certs(Certificate* client_certs);
- void client_kex(Client_Key_Exchange* client_kex);
- void client_verify(Certificate_Verify* client_verify);
- void next_protocol(Next_Protocol* next_protocol);
- void new_session_ticket(New_Session_Ticket* new_session_ticket);
- void server_finished(Finished* server_finished);
- void client_finished(Finished* client_finished);
-
- const Client_Hello* client_hello() const
- { return m_client_hello.get(); }
-
- const Server_Hello* server_hello() const
- { return m_server_hello.get(); }
-
- const Certificate* server_certs() const
- { return m_server_certs.get(); }
-
- const Server_Key_Exchange* server_kex() const
- { return m_server_kex.get(); }
-
- const Certificate_Req* cert_req() const
- { return m_cert_req.get(); }
-
- const Server_Hello_Done* server_hello_done() const
- { return m_server_hello_done.get(); }
-
- const Certificate* client_certs() const
- { return m_client_certs.get(); }
-
- const Client_Key_Exchange* client_kex() const
- { return m_client_kex.get(); }
-
- const Certificate_Verify* client_verify() const
- { return m_client_verify.get(); }
-
- const Next_Protocol* next_protocol() const
- { return m_next_protocol.get(); }
-
- const New_Session_Ticket* new_session_ticket() const
- { return m_new_session_ticket.get(); }
-
- const Finished* server_finished() const
- { return m_server_finished.get(); }
-
- const Finished* client_finished() const
- { return m_client_finished.get(); }
-
- const Ciphersuite& ciphersuite() const { return m_ciphersuite; }
-
- const Session_Keys& session_keys() const { return m_session_keys; }
-
- void compute_session_keys();
-
- void compute_session_keys(const secure_vector<byte>& resume_master_secret);
-
- Handshake_Hash& hash() { return m_handshake_hash; }
-
- const Handshake_Hash& hash() const { return m_handshake_hash; }
-
- void note_message(const Handshake_Message& msg)
- {
- if(m_msg_callback)
- m_msg_callback(msg);
- }
-
- private:
-
- std::function<void (const Handshake_Message&)> m_msg_callback;
-
- std::unique_ptr<Handshake_IO> m_handshake_io;
-
- u32bit m_hand_expecting_mask = 0;
- u32bit m_hand_received_mask = 0;
- Protocol_Version m_version;
- Ciphersuite m_ciphersuite;
- Session_Keys m_session_keys;
- Handshake_Hash m_handshake_hash;
-
- std::unique_ptr<Client_Hello> m_client_hello;
- std::unique_ptr<Server_Hello> m_server_hello;
- std::unique_ptr<Certificate> m_server_certs;
- std::unique_ptr<Server_Key_Exchange> m_server_kex;
- std::unique_ptr<Certificate_Req> m_cert_req;
- std::unique_ptr<Server_Hello_Done> m_server_hello_done;
- std::unique_ptr<Certificate> m_client_certs;
- std::unique_ptr<Client_Key_Exchange> m_client_kex;
- std::unique_ptr<Certificate_Verify> m_client_verify;
- std::unique_ptr<Next_Protocol> m_next_protocol;
- std::unique_ptr<New_Session_Ticket> m_new_session_ticket;
- std::unique_ptr<Finished> m_server_finished;
- std::unique_ptr<Finished> m_client_finished;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_heartbeats.cpp b/src/tls/tls_heartbeats.cpp
deleted file mode 100644
index 8c129858e..000000000
--- a/src/tls/tls_heartbeats.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-* TLS Heartbeats
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_heartbeats.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/internal/tls_reader.h>
-#include <botan/tls_exceptn.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Heartbeat_Message::Heartbeat_Message(const std::vector<byte>& buf)
- {
- TLS_Data_Reader reader(buf);
-
- const byte type = reader.get_byte();
-
- if(type != 1 && type != 2)
- throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
- "Unknown heartbeat message type");
-
- m_type = static_cast<Type>(type);
-
- m_payload = reader.get_range<byte>(2, 0, 16*1024);
-
- // padding follows and is ignored
- }
-
-Heartbeat_Message::Heartbeat_Message(Type type,
- const byte payload[],
- size_t payload_len) :
- m_type(type),
- m_payload(payload, payload + payload_len)
- {
- }
-
-std::vector<byte> Heartbeat_Message::contents() const
- {
- std::vector<byte> send_buf(3 + m_payload.size() + 16);
- send_buf[0] = m_type;
- send_buf[1] = get_byte<u16bit>(0, m_payload.size());
- send_buf[2] = get_byte<u16bit>(1, m_payload.size());
- copy_mem(&send_buf[3], &m_payload[0], m_payload.size());
- // leave padding as all zeros
-
- return send_buf;
- }
-
-std::vector<byte> Heartbeat_Support_Indicator::serialize() const
- {
- std::vector<byte> heartbeat(1);
- heartbeat[0] = (m_peer_allowed_to_send ? 1 : 2);
- return heartbeat;
- }
-
-Heartbeat_Support_Indicator::Heartbeat_Support_Indicator(TLS_Data_Reader& reader,
- u16bit extension_size)
- {
- if(extension_size != 1)
- throw Decoding_Error("Strange size for heartbeat extension");
-
- const byte code = reader.get_byte();
-
- if(code != 1 && code != 2)
- throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
- "Unknown heartbeat code " + std::to_string(code));
-
- m_peer_allowed_to_send = (code == 1);
- }
-
-}
-
-}
diff --git a/src/tls/tls_heartbeats.h b/src/tls/tls_heartbeats.h
deleted file mode 100644
index 00b197089..000000000
--- a/src/tls/tls_heartbeats.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-* TLS Heartbeats
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_HEARTBEATS_H__
-#define BOTAN_TLS_HEARTBEATS_H__
-
-#include <botan/secmem.h>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Heartbeat message
-*/
-class Heartbeat_Message
- {
- public:
- enum Type { REQUEST = 1, RESPONSE = 2 };
-
- std::vector<byte> contents() const;
-
- const std::vector<byte>& payload() const { return m_payload; }
-
- bool is_request() const { return m_type == REQUEST; }
-
- Heartbeat_Message(const std::vector<byte>& buf);
-
- Heartbeat_Message(Type type, const byte payload[], size_t payload_len);
- private:
- Type m_type;
- std::vector<byte> m_payload;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h
deleted file mode 100644
index 51f1fce47..000000000
--- a/src/tls/tls_magic.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-* SSL/TLS Protocol Constants
-* (C) 2004-2010 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_PROTOCOL_MAGIC_H__
-#define BOTAN_TLS_PROTOCOL_MAGIC_H__
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Protocol Constants for SSL/TLS
-*/
-enum Size_Limits {
- TLS_HEADER_SIZE = 5,
- DTLS_HEADER_SIZE = TLS_HEADER_SIZE + 8,
-
- MAX_PLAINTEXT_SIZE = 16*1024,
- MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024,
- MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024,
-};
-
-enum Connection_Side { CLIENT = 1, SERVER = 2 };
-
-enum Record_Type {
- NO_RECORD = 0,
-
- CHANGE_CIPHER_SPEC = 20,
- ALERT = 21,
- HANDSHAKE = 22,
- APPLICATION_DATA = 23,
- HEARTBEAT = 24,
-};
-
-enum Handshake_Type {
- HELLO_REQUEST = 0,
- CLIENT_HELLO = 1,
- CLIENT_HELLO_SSLV2 = 253, // Not a wire value
- SERVER_HELLO = 2,
- HELLO_VERIFY_REQUEST = 3,
- NEW_SESSION_TICKET = 4, // RFC 5077
- CERTIFICATE = 11,
- SERVER_KEX = 12,
- CERTIFICATE_REQUEST = 13,
- SERVER_HELLO_DONE = 14,
- CERTIFICATE_VERIFY = 15,
- CLIENT_KEX = 16,
- FINISHED = 20,
-
- CERTIFICATE_URL = 21,
- CERTIFICATE_STATUS = 22,
-
- NEXT_PROTOCOL = 67,
-
- HANDSHAKE_CCS = 254, // Not a wire value
- HANDSHAKE_NONE = 255 // Null value
-};
-
-enum Compression_Method {
- NO_COMPRESSION = 0x00,
- DEFLATE_COMPRESSION = 0x01
-};
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
deleted file mode 100644
index 155d2427b..000000000
--- a/src/tls/tls_messages.h
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
-* TLS Messages
-* (C) 2004-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_MESSAGES_H__
-#define BOTAN_TLS_MESSAGES_H__
-
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_extensions.h>
-#include <botan/tls_handshake_msg.h>
-#include <botan/tls_session.h>
-#include <botan/tls_policy.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/bigint.h>
-#include <botan/pkcs8.h>
-#include <botan/x509cert.h>
-#include <vector>
-#include <memory>
-#include <string>
-
-namespace Botan {
-
-class Credentials_Manager;
-class SRP6_Server_Session;
-
-namespace TLS {
-
-class Handshake_IO;
-
-std::vector<byte> make_hello_random(RandomNumberGenerator& rng);
-
-/**
-* DTLS Hello Verify Request
-*/
-class Hello_Verify_Request : public Handshake_Message
- {
- public:
- std::vector<byte> serialize() const override;
- Handshake_Type type() const override { return HELLO_VERIFY_REQUEST; }
-
- std::vector<byte> cookie() const { return m_cookie; }
-
- Hello_Verify_Request(const std::vector<byte>& buf);
-
- Hello_Verify_Request(const std::vector<byte>& client_hello_bits,
- const std::string& client_identity,
- const SymmetricKey& secret_key);
- private:
- std::vector<byte> m_cookie;
- };
-
-/**
-* Client Hello Message
-*/
-class Client_Hello : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return CLIENT_HELLO; }
-
- Protocol_Version version() const { return m_version; }
-
- const std::vector<byte>& random() const { return m_random; }
-
- const std::vector<byte>& session_id() const { return m_session_id; }
-
- std::vector<u16bit> ciphersuites() const { return m_suites; }
-
- std::vector<byte> compression_methods() const { return m_comp_methods; }
-
- bool offered_suite(u16bit ciphersuite) const;
-
- std::vector<std::pair<std::string, std::string>> supported_algos() const
- {
- if(Signature_Algorithms* sigs = m_extensions.get<Signature_Algorithms>())
- return sigs->supported_signature_algorthms();
- return std::vector<std::pair<std::string, std::string>>();
- }
-
- std::vector<std::string> supported_ecc_curves() const
- {
- if(Supported_Elliptic_Curves* ecc = m_extensions.get<Supported_Elliptic_Curves>())
- return ecc->curves();
- return std::vector<std::string>();
- }
-
- std::string sni_hostname() const
- {
- if(Server_Name_Indicator* sni = m_extensions.get<Server_Name_Indicator>())
- return sni->host_name();
- return "";
- }
-
- std::string srp_identifier() const
- {
- if(SRP_Identifier* srp = m_extensions.get<SRP_Identifier>())
- return srp->identifier();
- return "";
- }
-
- bool secure_renegotiation() const
- {
- return m_extensions.get<Renegotiation_Extension>();
- }
-
- std::vector<byte> renegotiation_info() const
- {
- if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
- return reneg->renegotiation_info();
- return std::vector<byte>();
- }
-
- bool next_protocol_notification() const
- {
- return m_extensions.get<Next_Protocol_Notification>();
- }
-
- size_t fragment_size() const
- {
- if(Maximum_Fragment_Length* frag = m_extensions.get<Maximum_Fragment_Length>())
- return frag->fragment_size();
- return 0;
- }
-
- bool supports_session_ticket() const
- {
- return m_extensions.get<Session_Ticket>();
- }
-
- std::vector<byte> session_ticket() const
- {
- if(Session_Ticket* ticket = m_extensions.get<Session_Ticket>())
- return ticket->contents();
- return std::vector<byte>();
- }
-
- bool supports_heartbeats() const
- {
- return m_extensions.get<Heartbeat_Support_Indicator>();
- }
-
- bool peer_can_send_heartbeats() const
- {
- if(Heartbeat_Support_Indicator* hb = m_extensions.get<Heartbeat_Support_Indicator>())
- return hb->peer_allowed_to_send();
- return false;
- }
-
- void update_hello_cookie(const Hello_Verify_Request& hello_verify);
-
- Client_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- Protocol_Version version,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<byte>& reneg_info,
- bool next_protocol = false,
- const std::string& hostname = "",
- const std::string& srp_identifier = "");
-
- Client_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<byte>& reneg_info,
- const Session& resumed_session,
- bool next_protocol = false);
-
- Client_Hello(const std::vector<byte>& buf,
- Handshake_Type type);
-
- private:
- std::vector<byte> serialize() const override;
- void deserialize(const std::vector<byte>& buf);
- void deserialize_sslv2(const std::vector<byte>& buf);
-
- Protocol_Version m_version;
- std::vector<byte> m_session_id;
- std::vector<byte> m_random;
- std::vector<u16bit> m_suites;
- std::vector<byte> m_comp_methods;
- std::vector<byte> m_hello_cookie; // DTLS only
-
- Extensions m_extensions;
- };
-
-/**
-* Server Hello Message
-*/
-class Server_Hello : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return SERVER_HELLO; }
-
- Protocol_Version version() const { return m_version; }
-
- const std::vector<byte>& random() const { return m_random; }
-
- const std::vector<byte>& session_id() const { return m_session_id; }
-
- u16bit ciphersuite() const { return m_ciphersuite; }
-
- byte compression_method() const { return m_comp_method; }
-
- bool secure_renegotiation() const
- {
- return m_extensions.get<Renegotiation_Extension>();
- }
-
- std::vector<byte> renegotiation_info() const
- {
- if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
- return reneg->renegotiation_info();
- return std::vector<byte>();
- }
-
- bool next_protocol_notification() const
- {
- return m_extensions.get<Next_Protocol_Notification>();
- }
-
- std::vector<std::string> next_protocols() const
- {
- if(Next_Protocol_Notification* npn = m_extensions.get<Next_Protocol_Notification>())
- return npn->protocols();
- return std::vector<std::string>();
- }
-
- size_t fragment_size() const
- {
- if(Maximum_Fragment_Length* frag = m_extensions.get<Maximum_Fragment_Length>())
- return frag->fragment_size();
- return 0;
- }
-
- bool supports_session_ticket() const
- {
- return m_extensions.get<Session_Ticket>();
- }
-
- bool supports_heartbeats() const
- {
- return m_extensions.get<Heartbeat_Support_Indicator>();
- }
-
- bool peer_can_send_heartbeats() const
- {
- if(Heartbeat_Support_Indicator* hb = m_extensions.get<Heartbeat_Support_Indicator>())
- return hb->peer_allowed_to_send();
- return false;
- }
-
- Server_Hello(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- const std::vector<byte>& session_id,
- Protocol_Version ver,
- u16bit ciphersuite,
- byte compression,
- size_t max_fragment_size,
- bool client_has_secure_renegotiation,
- const std::vector<byte>& reneg_info,
- bool offer_session_ticket,
- bool client_has_npn,
- const std::vector<std::string>& next_protocols,
- bool client_has_heartbeat,
- RandomNumberGenerator& rng);
-
- Server_Hello(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
-
- Protocol_Version m_version;
- std::vector<byte> m_session_id, m_random;
- u16bit m_ciphersuite;
- byte m_comp_method;
-
- Extensions m_extensions;
- };
-
-/**
-* Client Key Exchange Message
-*/
-class Client_Key_Exchange : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return CLIENT_KEX; }
-
- const secure_vector<byte>& pre_master_secret() const
- { return m_pre_master; }
-
- Client_Key_Exchange(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- Credentials_Manager& creds,
- const Public_Key* server_public_key,
- const std::string& hostname,
- RandomNumberGenerator& rng);
-
- Client_Key_Exchange(const std::vector<byte>& buf,
- const Handshake_State& state,
- const Private_Key* server_rsa_kex_key,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng);
-
- private:
- std::vector<byte> serialize() const override
- { return m_key_material; }
-
- std::vector<byte> m_key_material;
- secure_vector<byte> m_pre_master;
- };
-
-/**
-* Certificate Message
-*/
-class Certificate : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return CERTIFICATE; }
- const std::vector<X509_Certificate>& cert_chain() const { return m_certs; }
-
- size_t count() const { return m_certs.size(); }
- bool empty() const { return m_certs.empty(); }
-
- Certificate(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::vector<X509_Certificate>& certs);
-
- Certificate(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
-
- std::vector<X509_Certificate> m_certs;
- };
-
-/**
-* Certificate Request Message
-*/
-class Certificate_Req : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return CERTIFICATE_REQUEST; }
-
- const std::vector<std::string>& acceptable_cert_types() const
- { return m_cert_key_types; }
-
- std::vector<X509_DN> acceptable_CAs() const { return m_names; }
-
- std::vector<std::pair<std::string, std::string> > supported_algos() const
- { return m_supported_algos; }
-
- Certificate_Req(Handshake_IO& io,
- Handshake_Hash& hash,
- const Policy& policy,
- const std::vector<X509_DN>& allowed_cas,
- Protocol_Version version);
-
- Certificate_Req(const std::vector<byte>& buf,
- Protocol_Version version);
- private:
- std::vector<byte> serialize() const override;
-
- std::vector<X509_DN> m_names;
- std::vector<std::string> m_cert_key_types;
-
- std::vector<std::pair<std::string, std::string> > m_supported_algos;
- };
-
-/**
-* Certificate Verify Message
-*/
-class Certificate_Verify : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return CERTIFICATE_VERIFY; }
-
- /**
- * Check the signature on a certificate verify message
- * @param cert the purported certificate
- * @param state the handshake state
- */
- bool verify(const X509_Certificate& cert,
- const Handshake_State& state) const;
-
- Certificate_Verify(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const Private_Key* key);
-
- Certificate_Verify(const std::vector<byte>& buf,
- Protocol_Version version);
- private:
- std::vector<byte> serialize() const override;
-
- std::string m_sig_algo; // sig algo used to create signature
- std::string m_hash_algo; // hash used to create signature
- std::vector<byte> m_signature;
- };
-
-/**
-* Finished Message
-*/
-class Finished : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return FINISHED; }
-
- std::vector<byte> verify_data() const
- { return m_verification_data; }
-
- bool verify(const Handshake_State& state,
- Connection_Side side) const;
-
- Finished(Handshake_IO& io,
- Handshake_State& state,
- Connection_Side side);
-
- Finished(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
-
- std::vector<byte> m_verification_data;
- };
-
-/**
-* Hello Request Message
-*/
-class Hello_Request : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return HELLO_REQUEST; }
-
- Hello_Request(Handshake_IO& io);
- Hello_Request(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
- };
-
-/**
-* Server Key Exchange Message
-*/
-class Server_Key_Exchange : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return SERVER_KEX; }
-
- const std::vector<byte>& params() const { return m_params; }
-
- bool verify(const Public_Key& server_key,
- const Handshake_State& state) const;
-
- // Only valid for certain kex types
- const Private_Key& server_kex_key() const;
-
- // Only valid for SRP negotiation
- SRP6_Server_Session& server_srp_params() const;
-
- Server_Key_Exchange(Handshake_IO& io,
- Handshake_State& state,
- const Policy& policy,
- Credentials_Manager& creds,
- RandomNumberGenerator& rng,
- const Private_Key* signing_key = nullptr);
-
- Server_Key_Exchange(const std::vector<byte>& buf,
- const std::string& kex_alg,
- const std::string& sig_alg,
- Protocol_Version version);
-
- ~Server_Key_Exchange();
- private:
- std::vector<byte> serialize() const override;
-
- std::unique_ptr<Private_Key> m_kex_key;
- std::unique_ptr<SRP6_Server_Session> m_srp_params;
-
- std::vector<byte> m_params;
-
- std::string m_sig_algo; // sig algo used to create signature
- std::string m_hash_algo; // hash used to create signature
- std::vector<byte> m_signature;
- };
-
-/**
-* Server Hello Done Message
-*/
-class Server_Hello_Done : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return SERVER_HELLO_DONE; }
-
- Server_Hello_Done(Handshake_IO& io, Handshake_Hash& hash);
- Server_Hello_Done(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
- };
-
-/**
-* Next Protocol Message
-*/
-class Next_Protocol : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return NEXT_PROTOCOL; }
-
- std::string protocol() const { return m_protocol; }
-
- Next_Protocol(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::string& protocol);
-
- Next_Protocol(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
-
- std::string m_protocol;
- };
-
-/**
-* New Session Ticket Message
-*/
-class New_Session_Ticket : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return NEW_SESSION_TICKET; }
-
- u32bit ticket_lifetime_hint() const { return m_ticket_lifetime_hint; }
- const std::vector<byte>& ticket() const { return m_ticket; }
-
- New_Session_Ticket(Handshake_IO& io,
- Handshake_Hash& hash,
- const std::vector<byte>& ticket,
- u32bit lifetime);
-
- New_Session_Ticket(Handshake_IO& io,
- Handshake_Hash& hash);
-
- New_Session_Ticket(const std::vector<byte>& buf);
- private:
- std::vector<byte> serialize() const override;
-
- u32bit m_ticket_lifetime_hint;
- std::vector<byte> m_ticket;
- };
-
-/**
-* Change Cipher Spec
-*/
-class Change_Cipher_Spec : public Handshake_Message
- {
- public:
- Handshake_Type type() const override { return HANDSHAKE_CCS; }
-
- std::vector<byte> serialize() const override
- { return std::vector<byte>(1, 1); }
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp
deleted file mode 100644
index 05251e186..000000000
--- a/src/tls/tls_policy.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-* Policies for TLS
-* (C) 2004-2010,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_policy.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/tls_magic.h>
-#include <botan/tls_exceptn.h>
-#include <botan/internal/stl_util.h>
-
-namespace Botan {
-
-namespace TLS {
-
-std::vector<std::string> Policy::allowed_ciphers() const
- {
- return std::vector<std::string>({
- "AES-256/GCM",
- "AES-128/GCM",
- "AES-256/CCM",
- "AES-128/CCM",
- "AES-256/CCM-8",
- "AES-128/CCM-8",
- //"Camellia-256/GCM",
- //"Camellia-128/GCM",
- "AES-256",
- "AES-128",
- //"Camellia-256",
- //"Camellia-128",
- //"SEED"
- //"3DES",
- //"RC4",
- });
- }
-
-std::vector<std::string> Policy::allowed_signature_hashes() const
- {
- return std::vector<std::string>({
- "SHA-512",
- "SHA-384",
- "SHA-256",
- "SHA-224",
- //"SHA-1",
- //"MD5",
- });
- }
-
-std::vector<std::string> Policy::allowed_macs() const
- {
- return std::vector<std::string>({
- "AEAD",
- "SHA-384",
- "SHA-256",
- "SHA-1",
- //"MD5",
- });
- }
-
-std::vector<std::string> Policy::allowed_key_exchange_methods() const
- {
- return std::vector<std::string>({
- "SRP_SHA",
- //"ECDHE_PSK",
- //"DHE_PSK",
- //"PSK",
- "ECDH",
- "DH",
- "RSA",
- });
- }
-
-std::vector<std::string> Policy::allowed_signature_methods() const
- {
- return std::vector<std::string>({
- "ECDSA",
- "RSA",
- "DSA",
- //""
- });
- }
-
-std::vector<std::string> Policy::allowed_ecc_curves() const
- {
- return std::vector<std::string>({
- "brainpool512r1",
- "brainpool384r1",
- "brainpool256r1",
- "secp521r1",
- "secp384r1",
- "secp256r1",
- "secp256k1",
- "secp224r1",
- "secp224k1",
- //"secp192r1",
- //"secp192k1",
- //"secp160r2",
- //"secp160r1",
- //"secp160k1",
- });
- }
-
-/*
-* Choose an ECC curve to use
-*/
-std::string Policy::choose_curve(const std::vector<std::string>& curve_names) const
- {
- const std::vector<std::string> our_curves = allowed_ecc_curves();
-
- for(size_t i = 0; i != our_curves.size(); ++i)
- if(value_exists(curve_names, our_curves[i]))
- return our_curves[i];
-
- return ""; // no shared curve
- }
-
-DL_Group Policy::dh_group() const
- {
- return DL_Group("modp/ietf/2048");
- }
-
-size_t Policy::minimum_dh_group_size() const
- {
- return 1024;
- }
-
-/*
-* Return allowed compression algorithms
-*/
-std::vector<byte> Policy::compression() const
- {
- return std::vector<byte>{ NO_COMPRESSION };
- }
-
-u32bit Policy::session_ticket_lifetime() const
- {
- return 86400; // 1 day
- }
-
-bool Policy::acceptable_protocol_version(Protocol_Version version) const
- {
- // By default require TLS to minimize surprise
- if(version.is_datagram_protocol())
- return false;
-
- return (version > Protocol_Version::SSL_V3);
- }
-
-bool Policy::acceptable_ciphersuite(const Ciphersuite&) const
- {
- return true;
- }
-
-namespace {
-
-class Ciphersuite_Preference_Ordering
- {
- public:
- Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
- const std::vector<std::string>& macs,
- const std::vector<std::string>& kex,
- const std::vector<std::string>& sigs) :
- m_ciphers(ciphers), m_macs(macs), m_kex(kex), m_sigs(sigs) {}
-
- bool operator()(const Ciphersuite& a, const Ciphersuite& b) const
- {
- if(a.kex_algo() != b.kex_algo())
- {
- for(size_t i = 0; i != m_kex.size(); ++i)
- {
- if(a.kex_algo() == m_kex[i])
- return true;
- if(b.kex_algo() == m_kex[i])
- return false;
- }
- }
-
- if(a.cipher_algo() != b.cipher_algo())
- {
- for(size_t i = 0; i != m_ciphers.size(); ++i)
- {
- if(a.cipher_algo() == m_ciphers[i])
- return true;
- if(b.cipher_algo() == m_ciphers[i])
- return false;
- }
- }
-
- if(a.cipher_keylen() != b.cipher_keylen())
- {
- if(a.cipher_keylen() < b.cipher_keylen())
- return false;
- if(a.cipher_keylen() > b.cipher_keylen())
- return true;
- }
-
- if(a.sig_algo() != b.sig_algo())
- {
- for(size_t i = 0; i != m_sigs.size(); ++i)
- {
- if(a.sig_algo() == m_sigs[i])
- return true;
- if(b.sig_algo() == m_sigs[i])
- return false;
- }
- }
-
- if(a.mac_algo() != b.mac_algo())
- {
- for(size_t i = 0; i != m_macs.size(); ++i)
- {
- if(a.mac_algo() == m_macs[i])
- return true;
- if(b.mac_algo() == m_macs[i])
- return false;
- }
- }
-
- return false; // equal (?!?)
- }
- private:
- std::vector<std::string> m_ciphers, m_macs, m_kex, m_sigs;
- };
-
-}
-
-std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version,
- bool have_srp) const
- {
- const std::vector<std::string> ciphers = allowed_ciphers();
- const std::vector<std::string> macs = allowed_macs();
- const std::vector<std::string> kex = allowed_key_exchange_methods();
- const std::vector<std::string> sigs = allowed_signature_methods();
-
- Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
-
- std::set<Ciphersuite, Ciphersuite_Preference_Ordering> ciphersuites(order);
-
- for(auto suite : Ciphersuite::all_known_ciphersuites())
- {
- if(!acceptable_ciphersuite(suite))
- continue;
-
- if(!have_srp && suite.kex_algo() == "SRP_SHA")
- continue;
-
- if(version.is_datagram_protocol() && suite.cipher_algo() == "RC4")
- continue;
-
- if(!version.supports_aead_modes() && suite.mac_algo() == "AEAD")
- continue;
-
- if(!value_exists(kex, suite.kex_algo()))
- continue; // unsupported key exchange
-
- if(!value_exists(ciphers, suite.cipher_algo()))
- continue; // unsupported cipher
-
- if(!value_exists(macs, suite.mac_algo()))
- continue; // unsupported MAC algo
-
- if(!value_exists(sigs, suite.sig_algo()))
- {
- // allow if it's an empty sig algo and we want to use PSK
- if(suite.sig_algo() != "" || !suite.psk_ciphersuite())
- continue;
- }
-
- // OK, allow it:
- ciphersuites.insert(suite);
- }
-
- if(ciphersuites.empty())
- throw std::logic_error("Policy does not allow any available cipher suite");
-
- std::vector<u16bit> ciphersuite_codes;
- for(auto i : ciphersuites)
- ciphersuite_codes.push_back(i.ciphersuite_code());
- return ciphersuite_codes;
- }
-
-}
-
-}
diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h
deleted file mode 100644
index 5b205dfeb..000000000
--- a/src/tls/tls_policy.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-* Hooks for application level policies on TLS connections
-* (C) 2004-2006,2013 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_POLICY_H__
-#define BOTAN_TLS_POLICY_H__
-
-#include <botan/tls_version.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/x509cert.h>
-#include <botan/dl_group.h>
-#include <vector>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Policy Base Class
-* Inherit and overload as desired to suit local policy concerns
-*/
-class BOTAN_DLL Policy
- {
- public:
-
- /**
- * Returns a list of ciphers we are willing to negotiate, in
- * order of preference.
- */
- virtual std::vector<std::string> allowed_ciphers() const;
-
- /**
- * Returns a list of hash algorithms we are willing to use for
- * signatures, in order of preference.
- */
- virtual std::vector<std::string> allowed_signature_hashes() const;
-
- /**
- * Returns a list of MAC algorithms we are willing to use.
- */
- virtual std::vector<std::string> allowed_macs() const;
-
- /**
- * Returns a list of key exchange algorithms we are willing to
- * use, in order of preference. Allowed values: DH, empty string
- * (representing RSA using server certificate key)
- */
- virtual std::vector<std::string> allowed_key_exchange_methods() const;
-
- /**
- * Returns a list of signature algorithms we are willing to
- * use, in order of preference. Allowed values RSA and DSA.
- */
- virtual std::vector<std::string> allowed_signature_methods() const;
-
- /**
- * Return list of ECC curves we are willing to use in order of preference
- */
- virtual std::vector<std::string> allowed_ecc_curves() const;
-
- /**
- * Returns a list of compression algorithms we are willing to use,
- * in order of preference. Allowed values any value of
- * Compression_Method.
- *
- * @note Compression is not currently supported
- */
- virtual std::vector<byte> compression() const;
-
- /**
- * Choose an elliptic curve to use
- */
- virtual std::string choose_curve(const std::vector<std::string>& curve_names) const;
-
- /**
- * Attempt to negotiate the use of the heartbeat extension
- */
- virtual bool negotiate_heartbeat_support() const { return false; }
-
- /**
- * Allow renegotiation even if the counterparty doesn't
- * support the secure renegotiation extension.
- *
- * @warning Changing this to true exposes you to injected
- * plaintext attacks. Read RFC 5746 for background.
- */
- virtual bool allow_insecure_renegotiation() const { return false; }
-
- /**
- * Allow servers to initiate a new handshake
- */
- virtual bool allow_server_initiated_renegotiation() const { return true; }
-
- /**
- * Return the group to use for ephemeral Diffie-Hellman key agreement
- */
- virtual DL_Group dh_group() const;
-
- /**
- * Return the minimum DH group size we're willing to use
- */
- virtual size_t minimum_dh_group_size() const;
-
- /**
- * If this function returns false, unknown SRP/PSK identifiers
- * will be rejected with an unknown_psk_identifier alert as soon
- * as the non-existence is identified. Otherwise, a false
- * identifier value will be used and the protocol allowed to
- * proceed, causing the handshake to eventually fail without
- * revealing that the username does not exist on this system.
- */
- virtual bool hide_unknown_users() const { return false; }
-
- /**
- * Return the allowed lifetime of a session ticket. If 0, session
- * tickets do not expire until the session ticket key rolls over.
- * Expired session tickets cannot be used to resume a session.
- */
- virtual u32bit session_ticket_lifetime() const;
-
- /**
- * @return true if and only if we are willing to accept this version
- * Default accepts only TLS, so override if you want to enable DTLS
- * in your application.
- */
- virtual bool acceptable_protocol_version(Protocol_Version version) const;
-
- virtual bool acceptable_ciphersuite(const Ciphersuite& suite) const;
-
- /**
- * @return true if servers should choose the ciphersuite matching
- * their highest preference, rather than the clients.
- * Has no effect on client side.
- */
- virtual bool server_uses_own_ciphersuite_preferences() const { return true; }
-
- /**
- * Return allowed ciphersuites, in order of preference
- */
- virtual std::vector<u16bit> ciphersuite_list(Protocol_Version version,
- bool have_srp) const;
-
- virtual ~Policy() {}
- };
-
-/**
-* NSA Suite B 128-bit security level (see @rfc 6460)
-*/
-class BOTAN_DLL NSA_Suite_B_128 : public Policy
- {
- public:
- std::vector<std::string> allowed_ciphers() const override
- { return std::vector<std::string>({"AES-128/GCM"}); }
-
- std::vector<std::string> allowed_signature_hashes() const override
- { return std::vector<std::string>({"SHA-256"}); }
-
- std::vector<std::string> allowed_macs() const override
- { return std::vector<std::string>({"AEAD"}); }
-
- std::vector<std::string> allowed_key_exchange_methods() const override
- { return std::vector<std::string>({"ECDH"}); }
-
- std::vector<std::string> allowed_signature_methods() const override
- { return std::vector<std::string>({"ECDSA"}); }
-
- std::vector<std::string> allowed_ecc_curves() const override
- { return std::vector<std::string>({"secp256r1"}); }
-
- bool acceptable_protocol_version(Protocol_Version version) const override
- { return version == Protocol_Version::TLS_V12; }
- };
-
-/**
-* Policy for DTLS. We require DTLS v1.2 and an AEAD mode
-*/
-class BOTAN_DLL Datagram_Policy : public Policy
- {
- public:
- std::vector<std::string> allowed_macs() const override
- { return std::vector<std::string>({"AEAD"}); }
-
- bool acceptable_protocol_version(Protocol_Version version) const override
- { return version == Protocol_Version::DTLS_V12; }
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_reader.h b/src/tls/tls_reader.h
deleted file mode 100644
index 7440e16b7..000000000
--- a/src/tls/tls_reader.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
-* TLS Data Reader
-* (C) 2010-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_READER_H__
-#define BOTAN_TLS_READER_H__
-
-#include <botan/exceptn.h>
-#include <botan/secmem.h>
-#include <botan/loadstor.h>
-#include <string>
-#include <vector>
-#include <stdexcept>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Helper class for decoding TLS protocol messages
-*/
-class TLS_Data_Reader
- {
- public:
- TLS_Data_Reader(const std::vector<byte>& buf_in) :
- buf(buf_in), offset(0) {}
-
- void assert_done() const
- {
- if(has_remaining())
- throw Decoding_Error("Extra bytes at end of message");
- }
-
- size_t remaining_bytes() const
- {
- return buf.size() - offset;
- }
-
- bool has_remaining() const
- {
- return (remaining_bytes() > 0);
- }
-
- void discard_next(size_t bytes)
- {
- assert_at_least(bytes);
- offset += bytes;
- }
-
- u16bit get_u32bit()
- {
- assert_at_least(4);
- u16bit result = make_u32bit(buf[offset ], buf[offset+1],
- buf[offset+2], buf[offset+3]);
- offset += 4;
- return result;
- }
-
- u16bit get_u16bit()
- {
- assert_at_least(2);
- u16bit result = make_u16bit(buf[offset], buf[offset+1]);
- offset += 2;
- return result;
- }
-
- byte get_byte()
- {
- assert_at_least(1);
- byte result = buf[offset];
- offset += 1;
- return result;
- }
-
- template<typename T, typename Container>
- Container get_elem(size_t num_elems)
- {
- assert_at_least(num_elems * sizeof(T));
-
- Container result(num_elems);
-
- for(size_t i = 0; i != num_elems; ++i)
- result[i] = load_be<T>(&buf[offset], i);
-
- offset += num_elems * sizeof(T);
-
- return result;
- }
-
- template<typename T>
- std::vector<T> get_range(size_t len_bytes,
- size_t min_elems,
- size_t max_elems)
- {
- const size_t num_elems =
- get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
-
- return get_elem<T, std::vector<T> >(num_elems);
- }
-
- template<typename T>
- std::vector<T> get_range_vector(size_t len_bytes,
- size_t min_elems,
- size_t max_elems)
- {
- const size_t num_elems =
- get_num_elems(len_bytes, sizeof(T), min_elems, max_elems);
-
- return get_elem<T, std::vector<T> >(num_elems);
- }
-
- std::string get_string(size_t len_bytes,
- size_t min_bytes,
- size_t max_bytes)
- {
- std::vector<byte> v =
- get_range_vector<byte>(len_bytes, min_bytes, max_bytes);
-
- return std::string(reinterpret_cast<char*>(&v[0]), v.size());
- }
-
- template<typename T>
- std::vector<T> get_fixed(size_t size)
- {
- return get_elem<T, std::vector<T> >(size);
- }
-
- private:
- size_t get_length_field(size_t len_bytes)
- {
- assert_at_least(len_bytes);
-
- if(len_bytes == 1)
- return get_byte();
- else if(len_bytes == 2)
- return get_u16bit();
-
- throw Decoding_Error("TLS_Data_Reader: Bad length size");
- }
-
- size_t get_num_elems(size_t len_bytes,
- size_t T_size,
- size_t min_elems,
- size_t max_elems)
- {
- const size_t byte_length = get_length_field(len_bytes);
-
- if(byte_length % T_size != 0)
- throw Decoding_Error("TLS_Data_Reader: Size isn't multiple of T");
-
- const size_t num_elems = byte_length / T_size;
-
- if(num_elems < min_elems || num_elems > max_elems)
- throw Decoding_Error("TLS_Data_Reader: Range outside paramaters");
-
- return num_elems;
- }
-
- void assert_at_least(size_t n) const
- {
- if(buf.size() - offset < n)
- {
- throw Decoding_Error("TLS_Data_Reader: Expected " + std::to_string(n) +
- " bytes remaining, only " + std::to_string(buf.size()-offset) +
- " left");
- }
- }
-
- const std::vector<byte>& buf;
- size_t offset;
- };
-
-/**
-* Helper function for encoding length-tagged vectors
-*/
-template<typename T, typename Alloc>
-void append_tls_length_value(std::vector<byte, Alloc>& buf,
- const T* vals,
- size_t vals_size,
- size_t tag_size)
- {
- const size_t T_size = sizeof(T);
- const size_t val_bytes = T_size * vals_size;
-
- if(tag_size != 1 && tag_size != 2)
- throw std::invalid_argument("append_tls_length_value: invalid tag size");
-
- if((tag_size == 1 && val_bytes > 255) ||
- (tag_size == 2 && val_bytes > 65535))
- throw std::invalid_argument("append_tls_length_value: value too large");
-
- for(size_t i = 0; i != tag_size; ++i)
- buf.push_back(get_byte(sizeof(val_bytes)-tag_size+i, val_bytes));
-
- for(size_t i = 0; i != vals_size; ++i)
- for(size_t j = 0; j != T_size; ++j)
- buf.push_back(get_byte(j, vals[i]));
- }
-
-template<typename T, typename Alloc, typename Alloc2>
-void append_tls_length_value(std::vector<byte, Alloc>& buf,
- const std::vector<T, Alloc2>& vals,
- size_t tag_size)
- {
- append_tls_length_value(buf, &vals[0], vals.size(), tag_size);
- }
-
-template<typename Alloc>
-void append_tls_length_value(std::vector<byte, Alloc>& buf,
- const std::string& str,
- size_t tag_size)
- {
- append_tls_length_value(buf,
- reinterpret_cast<const byte*>(&str[0]),
- str.size(),
- tag_size);
- }
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_record.cpp b/src/tls/tls_record.cpp
deleted file mode 100644
index fc4908dc5..000000000
--- a/src/tls/tls_record.cpp
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
-* TLS Record Handling
-* (C) 2012,2013 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_record.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/tls_exceptn.h>
-#include <botan/libstate.h>
-#include <botan/loadstor.h>
-#include <botan/internal/tls_seq_numbers.h>
-#include <botan/internal/tls_session_key.h>
-#include <botan/internal/rounding.h>
-#include <botan/internal/xor_buf.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version,
- Connection_Side side,
- bool our_side,
- const Ciphersuite& suite,
- const Session_Keys& keys) :
- m_start_time(std::chrono::system_clock::now()),
- m_is_ssl3(version == Protocol_Version::SSL_V3)
- {
- SymmetricKey mac_key, cipher_key;
- InitializationVector iv;
-
- if(side == CLIENT)
- {
- cipher_key = keys.client_cipher_key();
- iv = keys.client_iv();
- mac_key = keys.client_mac_key();
- }
- else
- {
- cipher_key = keys.server_cipher_key();
- iv = keys.server_iv();
- mac_key = keys.server_mac_key();
- }
-
- const std::string cipher_algo = suite.cipher_algo();
- const std::string mac_algo = suite.mac_algo();
-
- if(AEAD_Mode* aead = get_aead(cipher_algo, our_side ? ENCRYPTION : DECRYPTION))
- {
- m_aead.reset(aead);
- m_aead->set_key(cipher_key + mac_key);
-
- BOTAN_ASSERT(iv.length() == 4, "Using 4/8 partial implicit nonce");
- m_nonce = iv.bits_of();
- m_nonce.resize(12);
- return;
- }
-
- Algorithm_Factory& af = global_state().algorithm_factory();
-
- if(const BlockCipher* bc = af.prototype_block_cipher(cipher_algo))
- {
- m_block_cipher.reset(bc->clone());
- m_block_cipher->set_key(cipher_key);
- m_block_cipher_cbc_state = iv.bits_of();
- m_block_size = bc->block_size();
-
- if(version.supports_explicit_cbc_ivs())
- m_iv_size = m_block_size;
- }
- else if(const StreamCipher* sc = af.prototype_stream_cipher(cipher_algo))
- {
- m_stream_cipher.reset(sc->clone());
- m_stream_cipher->set_key(cipher_key);
- }
- else
- throw Invalid_Argument("Unknown TLS cipher " + cipher_algo);
-
- if(version == Protocol_Version::SSL_V3)
- m_mac.reset(af.make_mac("SSL3-MAC(" + mac_algo + ")"));
- else
- m_mac.reset(af.make_mac("HMAC(" + mac_algo + ")"));
-
- m_mac->set_key(mac_key);
- }
-
-const secure_vector<byte>& Connection_Cipher_State::aead_nonce(u64bit seq)
- {
- BOTAN_ASSERT(m_aead, "Using AEAD mode");
- BOTAN_ASSERT(m_nonce.size() == 12, "Expected nonce size");
- store_be(seq, &m_nonce[4]);
- return m_nonce;
- }
-
-const secure_vector<byte>&
-Connection_Cipher_State::aead_nonce(const byte record[], size_t record_len)
- {
- BOTAN_ASSERT(m_aead, "Using AEAD mode");
- BOTAN_ASSERT(m_nonce.size() == 12, "Expected nonce size");
- BOTAN_ASSERT(record_len >= 8, "Record includes nonce");
- copy_mem(&m_nonce[4], record, 8);
- return m_nonce;
- }
-
-const secure_vector<byte>&
-Connection_Cipher_State::format_ad(u64bit msg_sequence,
- byte msg_type,
- Protocol_Version version,
- u16bit msg_length)
- {
- m_ad.clear();
- for(size_t i = 0; i != 8; ++i)
- m_ad.push_back(get_byte(i, msg_sequence));
- m_ad.push_back(msg_type);
-
- if(version != Protocol_Version::SSL_V3)
- {
- m_ad.push_back(version.major_version());
- m_ad.push_back(version.minor_version());
- }
-
- m_ad.push_back(get_byte(0, msg_length));
- m_ad.push_back(get_byte(1, msg_length));
-
- return m_ad;
- }
-
-void write_record(secure_vector<byte>& output,
- byte msg_type, const byte msg[], size_t msg_length,
- Protocol_Version version,
- u64bit msg_sequence,
- Connection_Cipher_State* cipherstate,
- RandomNumberGenerator& rng)
- {
- output.clear();
-
- output.push_back(msg_type);
- output.push_back(version.major_version());
- output.push_back(version.minor_version());
-
- if(version.is_datagram_protocol())
- {
- for(size_t i = 0; i != 8; ++i)
- output.push_back(get_byte(i, msg_sequence));
- }
-
- if(!cipherstate) // initial unencrypted handshake records
- {
- output.push_back(get_byte<u16bit>(0, msg_length));
- output.push_back(get_byte<u16bit>(1, msg_length));
-
- output.insert(output.end(), &msg[0], &msg[msg_length]);
-
- return;
- }
-
- if(AEAD_Mode* aead = cipherstate->aead())
- {
- const size_t ctext_size = aead->output_length(msg_length);
-
- auto nonce = cipherstate->aead_nonce(msg_sequence);
- const size_t implicit_nonce_bytes = 4; // FIXME, take from ciphersuite
- const size_t explicit_nonce_bytes = 8;
-
- BOTAN_ASSERT(nonce.size() == implicit_nonce_bytes + explicit_nonce_bytes,
- "Expected nonce size");
-
- // wrong if start_vec returns something
- const size_t rec_size = ctext_size + explicit_nonce_bytes;
-
- BOTAN_ASSERT(rec_size <= 0xFFFF, "Ciphertext length fits in field");
-
- output.push_back(get_byte<u16bit>(0, rec_size));
- output.push_back(get_byte<u16bit>(1, rec_size));
-
- aead->set_associated_data_vec(
- cipherstate->format_ad(msg_sequence, msg_type, version, msg_length)
- );
-
- output += std::make_pair(&nonce[implicit_nonce_bytes], explicit_nonce_bytes);
- output += aead->start_vec(nonce);
-
- const size_t offset = output.size();
- output += std::make_pair(&msg[0], msg_length);
- aead->finish(output, offset);
-
- BOTAN_ASSERT(output.size() == offset + ctext_size, "Expected size");
-
- BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE,
- "Produced ciphertext larger than protocol allows");
- return;
- }
-
- cipherstate->mac()->update(
- cipherstate->format_ad(msg_sequence, msg_type, version, msg_length)
- );
-
- cipherstate->mac()->update(msg, msg_length);
-
- const size_t block_size = cipherstate->block_size();
- const size_t iv_size = cipherstate->iv_size();
- const size_t mac_size = cipherstate->mac_size();
-
- const size_t buf_size = round_up(
- iv_size + msg_length + mac_size + (block_size ? 1 : 0),
- block_size);
-
- if(buf_size > MAX_CIPHERTEXT_SIZE)
- throw Internal_Error("Output record is larger than allowed by protocol");
-
- output.push_back(get_byte<u16bit>(0, buf_size));
- output.push_back(get_byte<u16bit>(1, buf_size));
-
- const size_t header_size = output.size();
-
- if(iv_size)
- {
- output.resize(output.size() + iv_size);
- rng.randomize(&output[output.size() - iv_size], iv_size);
- }
-
- output.insert(output.end(), &msg[0], &msg[msg_length]);
-
- output.resize(output.size() + mac_size);
- cipherstate->mac()->final(&output[output.size() - mac_size]);
-
- if(block_size)
- {
- const size_t pad_val =
- buf_size - (iv_size + msg_length + mac_size + 1);
-
- for(size_t i = 0; i != pad_val + 1; ++i)
- output.push_back(pad_val);
- }
-
- if(buf_size > MAX_CIPHERTEXT_SIZE)
- throw Internal_Error("Produced ciphertext larger than protocol allows");
-
- BOTAN_ASSERT(buf_size + header_size == output.size(),
- "Output buffer is sized properly");
-
- if(StreamCipher* sc = cipherstate->stream_cipher())
- {
- sc->cipher1(&output[header_size], buf_size);
- }
- else if(BlockCipher* bc = cipherstate->block_cipher())
- {
- secure_vector<byte>& cbc_state = cipherstate->cbc_state();
-
- BOTAN_ASSERT(buf_size % block_size == 0,
- "Buffer is an even multiple of block size");
-
- byte* buf = &output[header_size];
-
- const size_t blocks = buf_size / block_size;
-
- xor_buf(&buf[0], &cbc_state[0], block_size);
- bc->encrypt(&buf[0]);
-
- for(size_t i = 1; i < blocks; ++i)
- {
- xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size);
- bc->encrypt(&buf[block_size*i]);
- }
-
- cbc_state.assign(&buf[block_size*(blocks-1)],
- &buf[block_size*blocks]);
- }
- else
- throw Internal_Error("NULL cipher not supported");
- }
-
-namespace {
-
-size_t fill_buffer_to(secure_vector<byte>& readbuf,
- const byte*& input,
- size_t& input_size,
- size_t& input_consumed,
- size_t desired)
- {
- if(readbuf.size() >= desired)
- return 0; // already have it
-
- const size_t taken = std::min(input_size, desired - readbuf.size());
-
- readbuf.insert(readbuf.end(), &input[0], &input[taken]);
- input_consumed += taken;
- input_size -= taken;
- input += taken;
-
- return (desired - readbuf.size()); // how many bytes do we still need?
- }
-
-/*
-* Checks the TLS padding. Returns 0 if the padding is invalid (we
-* count the padding_length field as part of the padding size so a
-* valid padding will always be at least one byte long), or the length
-* of the padding otherwise. This is actually padding_length + 1
-* because both the padding and padding_length fields are padding from
-* our perspective.
-*
-* Returning 0 in the error case should ensure the MAC check will fail.
-* This approach is suggested in section 6.2.3.2 of RFC 5246.
-*
-* Also returns 0 if block_size == 0, so can be safely called with a
-* stream cipher in use.
-*
-* @fixme This should run in constant time
-*/
-size_t tls_padding_check(bool sslv3_padding,
- size_t block_size,
- const byte record[],
- size_t record_len)
- {
- const size_t padding_length = record[(record_len-1)];
-
- if(padding_length >= record_len)
- return 0;
-
- /*
- * SSL v3 requires that the padding be less than the block size
- * but not does specify the value of the padding bytes.
- */
- if(sslv3_padding)
- {
- if(padding_length > 0 && padding_length < block_size)
- return (padding_length + 1);
- else
- return 0;
- }
-
- /*
- * TLS v1.0 and up require all the padding bytes be the same value
- * and allows up to 255 bytes.
- */
- const size_t pad_start = record_len - padding_length - 1;
-
- volatile size_t cmp = 0;
-
- for(size_t i = 0; i != padding_length; ++i)
- cmp += record[pad_start + i] ^ padding_length;
-
- return cmp ? 0 : padding_length + 1;
- }
-
-void cbc_decrypt_record(byte record_contents[], size_t record_len,
- Connection_Cipher_State& cipherstate,
- const BlockCipher& bc)
- {
- const size_t block_size = cipherstate.block_size();
-
- BOTAN_ASSERT(record_len % block_size == 0,
- "Buffer is an even multiple of block size");
-
- const size_t blocks = record_len / block_size;
-
- BOTAN_ASSERT(blocks >= 1, "At least one ciphertext block");
-
- byte* buf = record_contents;
-
- secure_vector<byte> last_ciphertext(block_size);
- copy_mem(&last_ciphertext[0], &buf[0], block_size);
-
- bc.decrypt(&buf[0]);
- xor_buf(&buf[0], &cipherstate.cbc_state()[0], block_size);
-
- secure_vector<byte> last_ciphertext2;
-
- for(size_t i = 1; i < blocks; ++i)
- {
- last_ciphertext2.assign(&buf[block_size*i], &buf[block_size*(i+1)]);
- bc.decrypt(&buf[block_size*i]);
- xor_buf(&buf[block_size*i], &last_ciphertext[0], block_size);
- std::swap(last_ciphertext, last_ciphertext2);
- }
-
- cipherstate.cbc_state() = last_ciphertext;
- }
-
-void decrypt_record(secure_vector<byte>& output,
- byte record_contents[], size_t record_len,
- u64bit record_sequence,
- Protocol_Version record_version,
- Record_Type record_type,
- Connection_Cipher_State& cipherstate)
- {
- if(AEAD_Mode* aead = cipherstate.aead())
- {
- auto nonce = cipherstate.aead_nonce(record_contents, record_len);
- const size_t nonce_length = 8; // fixme, take from ciphersuite
-
- BOTAN_ASSERT(record_len > nonce_length, "Have data past the nonce");
- const byte* msg = &record_contents[nonce_length];
- const size_t msg_length = record_len - nonce_length;
-
- const size_t ptext_size = aead->output_length(msg_length);
-
- aead->set_associated_data_vec(
- cipherstate.format_ad(record_sequence, record_type, record_version, ptext_size)
- );
-
- output += aead->start_vec(nonce);
-
- const size_t offset = output.size();
- output += std::make_pair(&msg[0], msg_length);
- aead->finish(output, offset);
-
- BOTAN_ASSERT(output.size() == ptext_size + offset, "Produced expected size");
- }
- else
- {
- // GenericBlockCipher / GenericStreamCipher case
-
- volatile bool padding_bad = false;
- size_t pad_size = 0;
-
- if(StreamCipher* sc = cipherstate.stream_cipher())
- {
- sc->cipher1(record_contents, record_len);
- // no padding to check or remove
- }
- else if(BlockCipher* bc = cipherstate.block_cipher())
- {
- cbc_decrypt_record(record_contents, record_len, cipherstate, *bc);
-
- pad_size = tls_padding_check(cipherstate.cipher_padding_single_byte(),
- cipherstate.block_size(),
- record_contents, record_len);
-
- padding_bad = (pad_size == 0);
- }
- else
- {
- throw Internal_Error("No cipher state set but needed to decrypt");
- }
-
- const size_t mac_size = cipherstate.mac_size();
- const size_t iv_size = cipherstate.iv_size();
-
- const size_t mac_pad_iv_size = mac_size + pad_size + iv_size;
-
- if(record_len < mac_pad_iv_size)
- throw Decoding_Error("Record sent with invalid length");
-
- const byte* plaintext_block = &record_contents[iv_size];
- const u16bit plaintext_length = record_len - mac_pad_iv_size;
-
- cipherstate.mac()->update(
- cipherstate.format_ad(record_sequence, record_type, record_version, plaintext_length)
- );
-
- cipherstate.mac()->update(plaintext_block, plaintext_length);
-
- std::vector<byte> mac_buf(mac_size);
- cipherstate.mac()->final(&mac_buf[0]);
-
- const size_t mac_offset = record_len - (mac_size + pad_size);
-
- const bool mac_bad = !same_mem(&record_contents[mac_offset], &mac_buf[0], mac_size);
-
- if(mac_bad || padding_bad)
- throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
-
- output.assign(plaintext_block, plaintext_block + plaintext_length);
- }
- }
-
-}
-
-size_t read_record(secure_vector<byte>& readbuf,
- const byte input[],
- size_t input_sz,
- size_t& consumed,
- secure_vector<byte>& record,
- u64bit* record_sequence,
- Protocol_Version* record_version,
- Record_Type* record_type,
- Connection_Sequence_Numbers* sequence_numbers,
- std::function<Connection_Cipher_State* (u16bit)> get_cipherstate)
- {
- consumed = 0;
-
- if(readbuf.size() < TLS_HEADER_SIZE) // header incomplete?
- {
- if(size_t needed = fill_buffer_to(readbuf,
- input, input_sz, consumed,
- TLS_HEADER_SIZE))
- return needed;
-
- BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE,
- "Have an entire header");
- }
-
- // Possible SSLv2 format client hello
- if(!sequence_numbers && (readbuf[0] & 0x80) && (readbuf[2] == 1))
- {
- if(readbuf[3] == 0 && readbuf[4] == 2)
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Client claims to only support SSLv2, rejecting");
-
- if(readbuf[3] >= 3) // SSLv2 mapped TLS hello, then?
- {
- const size_t record_len = make_u16bit(readbuf[0], readbuf[1]) & 0x7FFF;
-
- if(size_t needed = fill_buffer_to(readbuf,
- input, input_sz, consumed,
- record_len + 2))
- return needed;
-
- BOTAN_ASSERT_EQUAL(readbuf.size(), (record_len + 2),
- "Have the entire SSLv2 hello");
-
- // Fake v3-style handshake message wrapper
- *record_version = Protocol_Version::TLS_V10;
- *record_sequence = 0;
- *record_type = HANDSHAKE;
-
- record.resize(4 + readbuf.size() - 2);
-
- record[0] = CLIENT_HELLO_SSLV2;
- record[1] = 0;
- record[2] = readbuf[0] & 0x7F;
- record[3] = readbuf[1];
- copy_mem(&record[4], &readbuf[2], readbuf.size() - 2);
-
- readbuf.clear();
- return 0;
- }
- }
-
- *record_version = Protocol_Version(readbuf[1], readbuf[2]);
-
- const bool is_dtls = record_version->is_datagram_protocol();
-
- if(is_dtls && readbuf.size() < DTLS_HEADER_SIZE)
- {
- if(size_t needed = fill_buffer_to(readbuf,
- input, input_sz, consumed,
- DTLS_HEADER_SIZE))
- return needed;
-
- BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE,
- "Have an entire header");
- }
-
- const size_t header_size = (is_dtls) ? DTLS_HEADER_SIZE : TLS_HEADER_SIZE;
-
- const size_t record_len = make_u16bit(readbuf[header_size-2],
- readbuf[header_size-1]);
-
- if(record_len > MAX_CIPHERTEXT_SIZE)
- throw TLS_Exception(Alert::RECORD_OVERFLOW,
- "Got message that exceeds maximum size");
-
- if(size_t needed = fill_buffer_to(readbuf,
- input, input_sz, consumed,
- header_size + record_len))
- return needed; // wrong for DTLS?
-
- BOTAN_ASSERT_EQUAL(static_cast<size_t>(header_size) + record_len,
- readbuf.size(),
- "Have the full record");
-
- *record_type = static_cast<Record_Type>(readbuf[0]);
-
- u16bit epoch = 0;
-
- if(is_dtls)
- {
- *record_sequence = load_be<u64bit>(&readbuf[3], 0);
- epoch = (*record_sequence >> 48);
- }
- else if(sequence_numbers)
- {
- *record_sequence = sequence_numbers->next_read_sequence();
- epoch = sequence_numbers->current_read_epoch();
- }
- else
- {
- // server initial handshake case
- *record_sequence = 0;
- epoch = 0;
- }
-
- if(sequence_numbers && sequence_numbers->already_seen(*record_sequence))
- return 0;
-
- byte* record_contents = &readbuf[header_size];
-
- if(epoch == 0) // Unencrypted initial handshake
- {
- record.assign(&readbuf[header_size], &readbuf[header_size + record_len]);
- readbuf.clear();
- return 0; // got a full record
- }
-
- // Otherwise, decrypt, check MAC, return plaintext
- Connection_Cipher_State* cipherstate = get_cipherstate(epoch);
-
- // FIXME: DTLS reordering might cause us not to have the cipher state
-
- BOTAN_ASSERT(cipherstate, "Have cipherstate for this epoch");
-
- decrypt_record(record,
- record_contents,
- record_len,
- *record_sequence,
- *record_version,
- *record_type,
- *cipherstate);
-
- if(sequence_numbers)
- sequence_numbers->read_accept(*record_sequence);
-
- readbuf.clear();
- return 0;
- }
-
-}
-
-}
diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h
deleted file mode 100644
index ef27a0a02..000000000
--- a/src/tls/tls_record.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-* TLS Record Handling
-* (C) 2004-2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_RECORDS_H__
-#define BOTAN_TLS_RECORDS_H__
-
-#include <botan/tls_magic.h>
-#include <botan/tls_version.h>
-#include <botan/aead.h>
-#include <botan/block_cipher.h>
-#include <botan/stream_cipher.h>
-#include <botan/mac.h>
-#include <vector>
-#include <memory>
-#include <chrono>
-
-namespace Botan {
-
-namespace TLS {
-
-class Ciphersuite;
-class Session_Keys;
-
-class Connection_Sequence_Numbers;
-
-/**
-* TLS Cipher State
-*/
-class Connection_Cipher_State
- {
- public:
- /**
- * Initialize a new cipher state
- */
- Connection_Cipher_State(Protocol_Version version,
- Connection_Side which_side,
- bool is_our_side,
- const Ciphersuite& suite,
- const Session_Keys& keys);
-
- AEAD_Mode* aead() { return m_aead.get(); }
-
- const secure_vector<byte>& aead_nonce(u64bit seq);
-
- const secure_vector<byte>& aead_nonce(const byte record[], size_t record_len);
-
- const secure_vector<byte>& format_ad(u64bit seq, byte type,
- Protocol_Version version,
- u16bit ptext_length);
-
- BlockCipher* block_cipher() { return m_block_cipher.get(); }
-
- StreamCipher* stream_cipher() { return m_stream_cipher.get(); }
-
- MessageAuthenticationCode* mac() { return m_mac.get(); }
-
- secure_vector<byte>& cbc_state() { return m_block_cipher_cbc_state; }
-
- size_t block_size() const { return m_block_size; }
-
- size_t mac_size() const { return m_mac->output_length(); }
-
- size_t iv_size() const { return m_iv_size; }
-
- bool mac_includes_record_version() const { return !m_is_ssl3; }
-
- bool cipher_padding_single_byte() const { return m_is_ssl3; }
-
- bool cbc_without_explicit_iv() const
- { return (m_block_size > 0) && (m_iv_size == 0); }
-
- std::chrono::seconds age() const
- {
- return std::chrono::duration_cast<std::chrono::seconds>(
- std::chrono::system_clock::now() - m_start_time);
- }
-
- private:
- std::chrono::system_clock::time_point m_start_time;
- std::unique_ptr<BlockCipher> m_block_cipher;
- secure_vector<byte> m_block_cipher_cbc_state;
- std::unique_ptr<StreamCipher> m_stream_cipher;
- std::unique_ptr<MessageAuthenticationCode> m_mac;
-
- std::unique_ptr<AEAD_Mode> m_aead;
- secure_vector<byte> m_nonce, m_ad;
-
- size_t m_block_size = 0;
- size_t m_iv_size = 0;
- bool m_is_ssl3 = false;
- };
-
-/**
-* Create a TLS record
-* @param write_buffer the output record is placed here
-* @param msg_type is the type of the message (handshake, alert, ...)
-* @param msg is the plaintext message
-* @param msg_length is the length of msg
-* @param msg_sequence is the sequence number
-* @param version is the protocol version
-* @param cipherstate is the writing cipher state
-* @param rng is a random number generator
-* @return number of bytes written to write_buffer
-*/
-void write_record(secure_vector<byte>& write_buffer,
- byte msg_type, const byte msg[], size_t msg_length,
- Protocol_Version version,
- u64bit msg_sequence,
- Connection_Cipher_State* cipherstate,
- RandomNumberGenerator& rng);
-
-/**
-* Decode a TLS record
-* @return zero if full message, else number of bytes still needed
-*/
-size_t read_record(secure_vector<byte>& read_buffer,
- const byte input[],
- size_t input_length,
- size_t& input_consumed,
- secure_vector<byte>& record,
- u64bit* record_sequence,
- Protocol_Version* record_version,
- Record_Type* record_type,
- Connection_Sequence_Numbers* sequence_numbers,
- std::function<Connection_Cipher_State* (u16bit)> get_cipherstate);
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_seq_numbers.h b/src/tls/tls_seq_numbers.h
deleted file mode 100644
index 87edf3130..000000000
--- a/src/tls/tls_seq_numbers.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-* TLS Sequence Number Handling
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SEQ_NUMBERS_H__
-#define BOTAN_TLS_SEQ_NUMBERS_H__
-
-#include <botan/types.h>
-#include <stdexcept>
-
-namespace Botan {
-
-namespace TLS {
-
-class Connection_Sequence_Numbers
- {
- public:
- virtual void new_read_cipher_state() = 0;
- virtual void new_write_cipher_state() = 0;
-
- virtual u16bit current_read_epoch() const = 0;
- virtual u16bit current_write_epoch() const = 0;
-
- virtual u64bit next_write_sequence() = 0;
- virtual u64bit next_read_sequence() = 0;
-
- virtual bool already_seen(u64bit seq) const = 0;
- virtual void read_accept(u64bit seq) = 0;
- };
-
-class Stream_Sequence_Numbers : public Connection_Sequence_Numbers
- {
- public:
- void new_read_cipher_state() override { m_read_seq_no = 0; m_read_epoch += 1; }
- void new_write_cipher_state() override { m_write_seq_no = 0; m_write_epoch += 1; }
-
- u16bit current_read_epoch() const override { return m_read_epoch; }
- u16bit current_write_epoch() const override { return m_write_epoch; }
-
- u64bit next_write_sequence() override { return m_write_seq_no++; }
- u64bit next_read_sequence() override { return m_read_seq_no; }
-
- bool already_seen(u64bit) const override { return false; }
- void read_accept(u64bit) override { m_read_seq_no++; }
- private:
- u64bit m_write_seq_no = 0;
- u64bit m_read_seq_no = 0;
- u16bit m_read_epoch = 0;
- u16bit m_write_epoch = 0;
- };
-
-class Datagram_Sequence_Numbers : public Connection_Sequence_Numbers
- {
- public:
- void new_read_cipher_state() override { m_read_epoch += 1; }
-
- void new_write_cipher_state() override
- {
- // increment epoch
- m_write_seq_no = ((m_write_seq_no >> 48) + 1) << 48;
- }
-
- u16bit current_read_epoch() const override { return m_read_epoch; }
- u16bit current_write_epoch() const override { return (m_write_seq_no >> 48); }
-
- u64bit next_write_sequence() override { return m_write_seq_no++; }
-
- u64bit next_read_sequence() override
- {
- throw std::runtime_error("DTLS uses explicit sequence numbers");
- }
-
- bool already_seen(u64bit sequence) const override
- {
- const size_t window_size = sizeof(m_window_bits) * 8;
-
- if(sequence > m_window_highest)
- return false;
-
- const u64bit offset = m_window_highest - sequence;
-
- if(offset >= window_size)
- return true; // really old?
-
- return (((m_window_bits >> offset) & 1) == 1);
- }
-
- void read_accept(u64bit sequence) override
- {
- const size_t window_size = sizeof(m_window_bits) * 8;
-
- if(sequence > m_window_highest)
- {
- const size_t offset = sequence - m_window_highest;
- m_window_highest += offset;
-
- if(offset >= window_size)
- m_window_bits = 0;
- else
- m_window_bits <<= offset;
-
- m_window_bits |= 0x01;
- }
- else
- {
- const u64bit offset = m_window_highest - sequence;
- m_window_bits |= (static_cast<u64bit>(1) << offset);
- }
- }
-
- private:
- u64bit m_write_seq_no = 0;
- u16bit m_read_epoch = 0;
- u64bit m_window_highest = 0;
- u64bit m_window_bits = 0;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
deleted file mode 100644
index bc518571b..000000000
--- a/src/tls/tls_server.cpp
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
-* TLS Server
-* (C) 2004-2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_server.h>
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/internal/stl_util.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-namespace {
-
-class Server_Handshake_State : public Handshake_State
- {
- public:
- // using Handshake_State::Handshake_State;
-
- Server_Handshake_State(Handshake_IO* io) : Handshake_State(io) {}
-
- // Used by the server only, in case of RSA key exchange. Not owned
- Private_Key* server_rsa_kex_key = nullptr;
-
- /*
- * Used by the server to know if resumption should be allowed on
- * a server-initiated renegotiation
- */
- bool allow_session_resumption = true;
- };
-
-bool check_for_resume(Session& session_info,
- Session_Manager& session_manager,
- Credentials_Manager& credentials,
- const Client_Hello* client_hello,
- std::chrono::seconds session_ticket_lifetime)
- {
- const std::vector<byte>& client_session_id = client_hello->session_id();
- const std::vector<byte>& session_ticket = client_hello->session_ticket();
-
- if(session_ticket.empty())
- {
- if(client_session_id.empty()) // not resuming
- return false;
-
- // not found
- if(!session_manager.load_from_session_id(client_session_id, session_info))
- return false;
- }
- else
- {
- // If a session ticket was sent, ignore client session ID
- try
- {
- session_info = Session::decrypt(
- session_ticket,
- credentials.psk("tls-server", "session-ticket", ""));
-
- if(session_ticket_lifetime != std::chrono::seconds(0) &&
- session_info.session_age() > session_ticket_lifetime)
- return false; // ticket has expired
- }
- catch(...)
- {
- return false;
- }
- }
-
- // wrong version
- if(client_hello->version() != session_info.version())
- return false;
-
- // client didn't send original ciphersuite
- if(!value_exists(client_hello->ciphersuites(),
- session_info.ciphersuite_code()))
- return false;
-
- // client didn't send original compression method
- if(!value_exists(client_hello->compression_methods(),
- session_info.compression_method()))
- return false;
-
- // client sent a different SRP identity
- if(client_hello->srp_identifier() != "")
- {
- if(client_hello->srp_identifier() != session_info.srp_identifier())
- return false;
- }
-
- // client sent a different SNI hostname
- if(client_hello->sni_hostname() != "")
- {
- if(client_hello->sni_hostname() != session_info.server_info().hostname())
- return false;
- }
-
- return true;
- }
-
-/*
-* Choose which ciphersuite to use
-*/
-u16bit choose_ciphersuite(
- const Policy& policy,
- Protocol_Version version,
- Credentials_Manager& creds,
- const std::map<std::string, std::vector<X509_Certificate> >& cert_chains,
- const Client_Hello* client_hello)
- {
- const bool our_choice = policy.server_uses_own_ciphersuite_preferences();
-
- const bool have_srp = creds.attempt_srp("tls-server",
- client_hello->sni_hostname());
-
- const std::vector<u16bit> client_suites = client_hello->ciphersuites();
-
- const std::vector<u16bit> server_suites = policy.ciphersuite_list(version, have_srp);
-
- if(server_suites.empty())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Policy forbids us from negotiating any ciphersuite");
-
- const bool have_shared_ecc_curve =
- (policy.choose_curve(client_hello->supported_ecc_curves()) != "");
-
- std::vector<u16bit> pref_list = server_suites;
- std::vector<u16bit> other_list = client_suites;
-
- if(!our_choice)
- std::swap(pref_list, other_list);
-
- for(auto suite_id : pref_list)
- {
- if(!value_exists(other_list, suite_id))
- continue;
-
- Ciphersuite suite = Ciphersuite::by_id(suite_id);
-
- if(!have_shared_ecc_curve && suite.ecc_ciphersuite())
- continue;
-
- if(suite.sig_algo() != "" && cert_chains.count(suite.sig_algo()) == 0)
- continue;
-
- /*
- The client may offer SRP cipher suites in the hello message but
- omit the SRP extension. If the server would like to select an
- SRP cipher suite in this case, the server SHOULD return a fatal
- "unknown_psk_identity" alert immediately after processing the
- client hello message.
- - RFC 5054 section 2.5.1.2
- */
- if(suite.kex_algo() == "SRP_SHA" && client_hello->srp_identifier() == "")
- throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
- "Client wanted SRP but did not send username");
-
- return suite_id;
- }
-
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Can't agree on a ciphersuite with client");
- }
-
-
-/*
-* Choose which compression algorithm to use
-*/
-byte choose_compression(const Policy& policy,
- const std::vector<byte>& c_comp)
- {
- std::vector<byte> s_comp = policy.compression();
-
- for(size_t i = 0; i != s_comp.size(); ++i)
- for(size_t j = 0; j != c_comp.size(); ++j)
- if(s_comp[i] == c_comp[j])
- return s_comp[i];
-
- return NO_COMPRESSION;
- }
-
-std::map<std::string, std::vector<X509_Certificate> >
-get_server_certs(const std::string& hostname,
- Credentials_Manager& creds)
- {
- const char* cert_types[] = { "RSA", "DSA", "ECDSA", nullptr };
-
- std::map<std::string, std::vector<X509_Certificate> > cert_chains;
-
- for(size_t i = 0; cert_types[i]; ++i)
- {
- std::vector<X509_Certificate> certs =
- creds.cert_chain_single_type(cert_types[i], "tls-server", hostname);
-
- if(!certs.empty())
- cert_chains[cert_types[i]] = certs;
- }
-
- return cert_chains;
- }
-
-}
-
-/*
-* TLS Server Constructor
-*/
-Server::Server(std::function<void (const byte[], size_t)> output_fn,
- std::function<void (const byte[], size_t)> data_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<std::string>& next_protocols,
- size_t io_buf_sz) :
- Channel(output_fn, data_cb, alert_cb, handshake_cb, session_manager, rng, io_buf_sz),
- m_policy(policy),
- m_creds(creds),
- m_possible_protocols(next_protocols)
- {
- }
-
-Handshake_State* Server::new_handshake_state(Handshake_IO* io)
- {
- std::unique_ptr<Handshake_State> state(new Server_Handshake_State(io));
- state->set_expected_next(CLIENT_HELLO);
- return state.release();
- }
-
-std::vector<X509_Certificate>
-Server::get_peer_cert_chain(const Handshake_State& state) const
- {
- if(state.client_certs())
- return state.client_certs()->cert_chain();
- return std::vector<X509_Certificate>();
- }
-
-/*
-* Send a hello request to the client
-*/
-void Server::initiate_handshake(Handshake_State& state,
- bool force_full_renegotiation)
- {
- dynamic_cast<Server_Handshake_State&>(state).allow_session_resumption =
- !force_full_renegotiation;
-
- Hello_Request hello_req(state.handshake_io());
- }
-
-/*
-* Process a handshake message
-*/
-void Server::process_handshake_msg(const Handshake_State* active_state,
- Handshake_State& state_base,
- Handshake_Type type,
- const std::vector<byte>& contents)
- {
- Server_Handshake_State& state = dynamic_cast<Server_Handshake_State&>(state_base);
-
- state.confirm_transition_to(type);
-
- /*
- * The change cipher spec message isn't technically a handshake
- * message so it's not included in the hash. The finished and
- * certificate verify messages are verified based on the current
- * state of the hash *before* this message so we delay adding them
- * to the hash computation until we've processed them below.
- */
- if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY)
- {
- if(type == CLIENT_HELLO_SSLV2)
- state.hash().update(contents);
- else
- state.hash().update(state.handshake_io().format(contents, type));
- }
-
- if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
- {
- const bool initial_handshake = !active_state;
-
- if(!m_policy.allow_insecure_renegotiation() &&
- !(initial_handshake || secure_renegotiation_supported()))
- {
- send_warning_alert(Alert::NO_RENEGOTIATION);
- return;
- }
-
- state.client_hello(new Client_Hello(contents, type));
-
- Protocol_Version client_version = state.client_hello()->version();
-
- Protocol_Version negotiated_version;
-
- if((initial_handshake && client_version.known_version()) ||
- (!initial_handshake && client_version == active_state->version()))
- {
- /*
- Common cases: new client hello with some known version, or a
- renegotiation using the same version as previously
- negotiated.
- */
-
- negotiated_version = client_version;
- }
- else if(!initial_handshake && (client_version != active_state->version()))
- {
- /*
- * If this is a renegotiation, and the client has offered a
- * later version than what it initially negotiated, negotiate
- * the old version. This matches OpenSSL's behavior. If the
- * client is offering a version earlier than what it initially
- * negotiated, reject as a probable attack.
- */
- if(active_state->version() > client_version)
- {
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Client negotiated " +
- active_state->version().to_string() +
- " then renegotiated with " +
- client_version.to_string());
- }
- else
- negotiated_version = active_state->version();
- }
- else
- {
- /*
- New negotiation using a version we don't know. Offer
- them the best we currently know.
- */
- negotiated_version = client_version.best_known_match();
- }
-
- if(!m_policy.acceptable_protocol_version(negotiated_version))
- {
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Client version is unacceptable by policy");
- }
-
- if(!initial_handshake && state.client_hello()->next_protocol_notification())
- throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
- "Client included NPN extension for renegotiation");
-
- secure_renegotiation_check(state.client_hello());
-
- state.set_version(negotiated_version);
-
- Session session_info;
- const bool resuming =
- state.allow_session_resumption &&
- check_for_resume(session_info,
- session_manager(),
- m_creds,
- state.client_hello(),
- std::chrono::seconds(m_policy.session_ticket_lifetime()));
-
- bool have_session_ticket_key = false;
-
- try
- {
- have_session_ticket_key =
- m_creds.psk("tls-server", "session-ticket", "").length() > 0;
- }
- catch(...) {}
-
- if(resuming)
- {
- // resume session
-
- const bool offer_new_session_ticket =
- (state.client_hello()->supports_session_ticket() &&
- state.client_hello()->session_ticket().empty() &&
- have_session_ticket_key);
-
- state.server_hello(
- new Server_Hello(
- state.handshake_io(),
- state.hash(),
- m_policy,
- state.client_hello()->session_id(),
- Protocol_Version(session_info.version()),
- session_info.ciphersuite_code(),
- session_info.compression_method(),
- session_info.fragment_size(),
- state.client_hello()->secure_renegotiation(),
- secure_renegotiation_data_for_server_hello(),
- offer_new_session_ticket,
- state.client_hello()->next_protocol_notification(),
- m_possible_protocols,
- state.client_hello()->supports_heartbeats(),
- rng())
- );
-
- secure_renegotiation_check(state.server_hello());
-
- state.compute_session_keys(session_info.master_secret());
-
- if(!save_session(session_info))
- {
- session_manager().remove_entry(session_info.session_id());
-
- if(state.server_hello()->supports_session_ticket()) // send an empty ticket
- {
- state.new_session_ticket(
- new New_Session_Ticket(state.handshake_io(),
- state.hash())
- );
- }
- }
-
- if(state.server_hello()->supports_session_ticket() && !state.new_session_ticket())
- {
- try
- {
- const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", "");
-
- state.new_session_ticket(
- new New_Session_Ticket(state.handshake_io(),
- state.hash(),
- session_info.encrypt(ticket_key, rng()),
- m_policy.session_ticket_lifetime())
- );
- }
- catch(...) {}
-
- if(!state.new_session_ticket())
- {
- state.new_session_ticket(
- new New_Session_Ticket(state.handshake_io(), state.hash())
- );
- }
- }
-
- state.handshake_io().send(Change_Cipher_Spec());
-
- change_cipher_spec_writer(SERVER);
-
- state.server_finished(
- new Finished(state.handshake_io(), state, SERVER)
- );
-
- state.set_expected_next(HANDSHAKE_CCS);
- }
- else // new session
- {
- std::map<std::string, std::vector<X509_Certificate> > cert_chains;
-
- const std::string sni_hostname = state.client_hello()->sni_hostname();
-
- cert_chains = get_server_certs(sni_hostname, m_creds);
-
- if(sni_hostname != "" && cert_chains.empty())
- {
- cert_chains = get_server_certs("", m_creds);
-
- /*
- * Only send the unrecognized_name alert if we couldn't
- * find any certs for the requested name but did find at
- * least one cert to use in general. That avoids sending an
- * unrecognized_name when a server is configured for purely
- * anonymous operation.
- */
- if(!cert_chains.empty())
- send_alert(Alert(Alert::UNRECOGNIZED_NAME));
- }
-
- state.server_hello(
- new Server_Hello(
- state.handshake_io(),
- state.hash(),
- m_policy,
- make_hello_random(rng()), // new session ID
- state.version(),
- choose_ciphersuite(m_policy,
- state.version(),
- m_creds,
- cert_chains,
- state.client_hello()),
- choose_compression(m_policy, state.client_hello()->compression_methods()),
- state.client_hello()->fragment_size(),
- state.client_hello()->secure_renegotiation(),
- secure_renegotiation_data_for_server_hello(),
- state.client_hello()->supports_session_ticket() && have_session_ticket_key,
- state.client_hello()->next_protocol_notification(),
- m_possible_protocols,
- state.client_hello()->supports_heartbeats(),
- rng())
- );
-
- secure_renegotiation_check(state.server_hello());
-
- const std::string sig_algo = state.ciphersuite().sig_algo();
- const std::string kex_algo = state.ciphersuite().kex_algo();
-
- if(sig_algo != "")
- {
- BOTAN_ASSERT(!cert_chains[sig_algo].empty(),
- "Attempting to send empty certificate chain");
-
- state.server_certs(
- new Certificate(state.handshake_io(),
- state.hash(),
- cert_chains[sig_algo])
- );
- }
-
- Private_Key* private_key = nullptr;
-
- if(kex_algo == "RSA" || sig_algo != "")
- {
- private_key = m_creds.private_key_for(
- state.server_certs()->cert_chain()[0],
- "tls-server",
- sni_hostname);
-
- if(!private_key)
- throw Internal_Error("No private key located for associated server cert");
- }
-
- if(kex_algo == "RSA")
- {
- state.server_rsa_kex_key = private_key;
- }
- else
- {
- state.server_kex(
- new Server_Key_Exchange(state.handshake_io(),
- state,
- m_policy,
- m_creds,
- rng(),
- private_key)
- );
- }
-
- auto trusted_CAs =
- m_creds.trusted_certificate_authorities("tls-server", sni_hostname);
-
- std::vector<X509_DN> client_auth_CAs;
-
- for(auto store : trusted_CAs)
- {
- auto subjects = store->all_subjects();
- client_auth_CAs.insert(client_auth_CAs.end(),
- subjects.begin(),
- subjects.end());
- }
-
- if(!client_auth_CAs.empty() && state.ciphersuite().sig_algo() != "")
- {
- state.cert_req(
- new Certificate_Req(state.handshake_io(),
- state.hash(),
- m_policy,
- client_auth_CAs,
- state.version())
- );
-
- state.set_expected_next(CERTIFICATE);
- }
-
- /*
- * If the client doesn't have a cert they want to use they are
- * allowed to send either an empty cert message or proceed
- * directly to the client key exchange, so allow either case.
- */
- state.set_expected_next(CLIENT_KEX);
-
- state.server_hello_done(
- new Server_Hello_Done(state.handshake_io(), state.hash())
- );
- }
- }
- else if(type == CERTIFICATE)
- {
- state.client_certs(new Certificate(contents));
-
- state.set_expected_next(CLIENT_KEX);
- }
- else if(type == CLIENT_KEX)
- {
- if(state.received_handshake_msg(CERTIFICATE) && !state.client_certs()->empty())
- state.set_expected_next(CERTIFICATE_VERIFY);
- else
- state.set_expected_next(HANDSHAKE_CCS);
-
- state.client_kex(
- new Client_Key_Exchange(contents, state,
- state.server_rsa_kex_key,
- m_creds, m_policy, rng())
- );
-
- state.compute_session_keys();
- }
- else if(type == CERTIFICATE_VERIFY)
- {
- state.client_verify(new Certificate_Verify(contents, state.version()));
-
- const std::vector<X509_Certificate>& client_certs =
- state.client_certs()->cert_chain();
-
- const bool sig_valid =
- state.client_verify()->verify(client_certs[0], state);
-
- state.hash().update(state.handshake_io().format(contents, type));
-
- /*
- * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for
- * "A handshake cryptographic operation failed, including being
- * unable to correctly verify a signature, ..."
- */
- if(!sig_valid)
- throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed");
-
- try
- {
- m_creds.verify_certificate_chain("tls-server", "", client_certs);
- }
- catch(std::exception& e)
- {
- throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what());
- }
-
- state.set_expected_next(HANDSHAKE_CCS);
- }
- else if(type == HANDSHAKE_CCS)
- {
- if(state.server_hello()->next_protocol_notification())
- state.set_expected_next(NEXT_PROTOCOL);
- else
- state.set_expected_next(FINISHED);
-
- change_cipher_spec_reader(SERVER);
- }
- else if(type == NEXT_PROTOCOL)
- {
- state.set_expected_next(FINISHED);
-
- state.next_protocol(new Next_Protocol(contents));
-
- // should this be a callback?
- m_next_protocol = state.next_protocol()->protocol();
- }
- else if(type == FINISHED)
- {
- state.set_expected_next(HANDSHAKE_NONE);
-
- state.client_finished(new Finished(contents));
-
- if(!state.client_finished()->verify(state, CLIENT))
- throw TLS_Exception(Alert::DECRYPT_ERROR,
- "Finished message didn't verify");
-
- if(!state.server_finished())
- {
- // already sent finished if resuming, so this is a new session
-
- state.hash().update(state.handshake_io().format(contents, type));
-
- Session session_info(
- state.server_hello()->session_id(),
- state.session_keys().master_secret(),
- state.server_hello()->version(),
- state.server_hello()->ciphersuite(),
- state.server_hello()->compression_method(),
- SERVER,
- state.server_hello()->fragment_size(),
- get_peer_cert_chain(state),
- std::vector<byte>(),
- Server_Information(state.client_hello()->sni_hostname()),
- state.srp_identifier()
- );
-
- if(save_session(session_info))
- {
- if(state.server_hello()->supports_session_ticket())
- {
- try
- {
- const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", "");
-
- state.new_session_ticket(
- new New_Session_Ticket(state.handshake_io(),
- state.hash(),
- session_info.encrypt(ticket_key, rng()),
- m_policy.session_ticket_lifetime())
- );
- }
- catch(...) {}
- }
- else
- session_manager().save(session_info);
- }
-
- if(!state.new_session_ticket() &&
- state.server_hello()->supports_session_ticket())
- {
- state.new_session_ticket(
- new New_Session_Ticket(state.handshake_io(), state.hash())
- );
- }
-
- state.handshake_io().send(Change_Cipher_Spec());
-
- change_cipher_spec_writer(SERVER);
-
- state.server_finished(
- new Finished(state.handshake_io(), state, SERVER)
- );
- }
-
- activate_session();
- }
- else
- throw Unexpected_Message("Unknown handshake message received");
- }
-
-}
-
-}
diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h
deleted file mode 100644
index a514607ba..000000000
--- a/src/tls/tls_server.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-* TLS Server
-* (C) 2004-2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SERVER_H__
-#define BOTAN_TLS_SERVER_H__
-
-#include <botan/tls_channel.h>
-#include <botan/credentials_manager.h>
-#include <vector>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Server
-*/
-class BOTAN_DLL Server : public Channel
- {
- public:
- /**
- * Server initialization
- */
- Server(std::function<void (const byte[], size_t)> socket_output_fn,
- std::function<void (const byte[], size_t)> data_cb,
- std::function<void (Alert, const byte[], size_t)> alert_cb,
- std::function<bool (const Session&)> handshake_cb,
- Session_Manager& session_manager,
- Credentials_Manager& creds,
- const Policy& policy,
- RandomNumberGenerator& rng,
- const std::vector<std::string>& protocols = std::vector<std::string>(),
- size_t reserved_io_buffer_size = 16*1024
- );
-
- /**
- * Return the protocol notification set by the client (using the
- * NPN extension) for this connection, if any
- */
- std::string next_protocol() const { return m_next_protocol; }
-
- private:
- std::vector<X509_Certificate>
- get_peer_cert_chain(const Handshake_State& state) const override;
-
- void initiate_handshake(Handshake_State& state,
- bool force_full_renegotiation) override;
-
- void process_handshake_msg(const Handshake_State* active_state,
- Handshake_State& pending_state,
- Handshake_Type type,
- const std::vector<byte>& contents) override;
-
- Handshake_State* new_handshake_state(Handshake_IO* io) override;
-
- const Policy& m_policy;
- Credentials_Manager& m_creds;
-
- std::vector<std::string> m_possible_protocols;
- std::string m_next_protocol;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_server_info.h b/src/tls/tls_server_info.h
deleted file mode 100644
index 773296eaf..000000000
--- a/src/tls/tls_server_info.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-* TLS Server Information
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SERVER_INFO_H__
-#define BOTAN_TLS_SERVER_INFO_H__
-
-#include <botan/types.h>
-#include <string>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Represents information known about a TLS server.
-*/
-class BOTAN_DLL Server_Information
- {
- public:
- /**
- * An empty server info - nothing known
- */
- Server_Information() : m_hostname(""), m_service(""), m_port(0) {}
-
- /**
- * @param hostname the host's DNS name, if known
- * @param port specifies the protocol port of the server (eg for
- * TCP/UDP). Zero represents unknown.
- */
- Server_Information(const std::string& hostname,
- u16bit port = 0) :
- m_hostname(hostname), m_service(""), m_port(port) {}
-
- /**
- * @param hostname the host's DNS name, if known
- * @param service is a text string of the service type
- * (eg "https", "tor", or "git")
- * @param port specifies the protocol port of the server (eg for
- * TCP/UDP). Zero represents unknown.
- */
- Server_Information(const std::string& hostname,
- const std::string& service,
- u16bit port = 0) :
- m_hostname(hostname), m_service(service), m_port(port) {}
-
- std::string hostname() const { return m_hostname; }
-
- std::string service() const { return m_service; }
-
- u16bit port() const { return m_port; }
-
- bool empty() const { return m_hostname.empty(); }
-
- private:
- std::string m_hostname, m_service;
- u16bit m_port;
- };
-
-inline bool operator==(const Server_Information& a, const Server_Information& b)
- {
- return (a.hostname() == b.hostname()) &&
- (a.service() == b.service()) &&
- (a.port() == b.port());
-
- }
-
-inline bool operator!=(const Server_Information& a, const Server_Information& b)
- {
- return !(a == b);
- }
-
-inline bool operator<(const Server_Information& a, const Server_Information& b)
- {
- if(a.hostname() != b.hostname())
- return (a.hostname() < b.hostname());
- if(a.service() != b.service())
- return (a.service() < b.service());
- if(a.port() != b.port())
- return (a.port() < b.port());
- return false; // equal
- }
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp
deleted file mode 100644
index 6596804b5..000000000
--- a/src/tls/tls_session.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-* TLS Session State
-* (C) 2011-2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_session.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/asn1_str.h>
-#include <botan/pem.h>
-#include <botan/cryptobox_psk.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-Session::Session(const std::vector<byte>& session_identifier,
- const secure_vector<byte>& master_secret,
- Protocol_Version version,
- u16bit ciphersuite,
- byte compression_method,
- Connection_Side side,
- size_t fragment_size,
- const std::vector<X509_Certificate>& certs,
- const std::vector<byte>& ticket,
- const Server_Information& server_info,
- const std::string& srp_identifier) :
- m_start_time(std::chrono::system_clock::now()),
- m_identifier(session_identifier),
- m_session_ticket(ticket),
- m_master_secret(master_secret),
- m_version(version),
- m_ciphersuite(ciphersuite),
- m_compression_method(compression_method),
- m_connection_side(side),
- m_fragment_size(fragment_size),
- m_peer_certs(certs),
- m_server_info(server_info),
- m_srp_identifier(srp_identifier)
- {
- }
-
-Session::Session(const std::string& pem)
- {
- secure_vector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION");
-
- *this = Session(&der[0], der.size());
- }
-
-Session::Session(const byte ber[], size_t ber_len)
- {
- byte side_code = 0;
-
- ASN1_String server_hostname;
- ASN1_String server_service;
- size_t server_port;
-
- ASN1_String srp_identifier_str;
-
- byte major_version = 0, minor_version = 0;
-
- std::vector<byte> peer_cert_bits;
-
- size_t start_time = 0;
-
- BER_Decoder(ber, ber_len)
- .start_cons(SEQUENCE)
- .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
- "Unknown version in session structure")
- .decode_integer_type(start_time)
- .decode_integer_type(major_version)
- .decode_integer_type(minor_version)
- .decode(m_identifier, OCTET_STRING)
- .decode(m_session_ticket, OCTET_STRING)
- .decode_integer_type(m_ciphersuite)
- .decode_integer_type(m_compression_method)
- .decode_integer_type(side_code)
- .decode_integer_type(m_fragment_size)
- .decode(m_master_secret, OCTET_STRING)
- .decode(peer_cert_bits, OCTET_STRING)
- .decode(server_hostname)
- .decode(server_service)
- .decode(server_port)
- .decode(srp_identifier_str)
- .end_cons()
- .verify_end();
-
- m_version = Protocol_Version(major_version, minor_version);
- m_start_time = std::chrono::system_clock::from_time_t(start_time);
- m_connection_side = static_cast<Connection_Side>(side_code);
-
- m_server_info = Server_Information(server_hostname.value(),
- server_service.value(),
- server_port);
-
- m_srp_identifier = srp_identifier_str.value();
-
- if(!peer_cert_bits.empty())
- {
- DataSource_Memory certs(&peer_cert_bits[0], peer_cert_bits.size());
-
- while(!certs.end_of_data())
- m_peer_certs.push_back(X509_Certificate(certs));
- }
- }
-
-secure_vector<byte> Session::DER_encode() const
- {
- std::vector<byte> peer_cert_bits;
- for(size_t i = 0; i != m_peer_certs.size(); ++i)
- peer_cert_bits += m_peer_certs[i].BER_encode();
-
- return DER_Encoder()
- .start_cons(SEQUENCE)
- .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
- .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
- .encode(static_cast<size_t>(m_version.major_version()))
- .encode(static_cast<size_t>(m_version.minor_version()))
- .encode(m_identifier, OCTET_STRING)
- .encode(m_session_ticket, OCTET_STRING)
- .encode(static_cast<size_t>(m_ciphersuite))
- .encode(static_cast<size_t>(m_compression_method))
- .encode(static_cast<size_t>(m_connection_side))
- .encode(static_cast<size_t>(m_fragment_size))
- .encode(m_master_secret, OCTET_STRING)
- .encode(peer_cert_bits, OCTET_STRING)
- .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
- .encode(ASN1_String(m_server_info.service(), UTF8_STRING))
- .encode(static_cast<size_t>(m_server_info.port()))
- .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
- .end_cons()
- .get_contents();
- }
-
-std::string Session::PEM_encode() const
- {
- return PEM_Code::encode(this->DER_encode(), "SSL SESSION");
- }
-
-std::chrono::seconds Session::session_age() const
- {
- return std::chrono::duration_cast<std::chrono::seconds>(
- std::chrono::system_clock::now() - m_start_time);
- }
-
-std::vector<byte>
-Session::encrypt(const SymmetricKey& master_key,
- RandomNumberGenerator& rng) const
- {
- const auto der = this->DER_encode();
-
- return CryptoBox::encrypt(&der[0], der.size(), master_key, rng);
- }
-
-Session Session::decrypt(const byte buf[], size_t buf_len,
- const SymmetricKey& master_key)
- {
- try
- {
- const auto ber = CryptoBox::decrypt(buf, buf_len, master_key);
-
- return Session(&ber[0], ber.size());
- }
- catch(std::exception& e)
- {
- throw Decoding_Error("Failed to decrypt encrypted session -" +
- std::string(e.what()));
- }
- }
-
-}
-
-}
-
diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h
deleted file mode 100644
index 65154dfce..000000000
--- a/src/tls/tls_session.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-* TLS Session
-* (C) 2011-2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SESSION_STATE_H__
-#define BOTAN_TLS_SESSION_STATE_H__
-
-#include <botan/x509cert.h>
-#include <botan/tls_version.h>
-#include <botan/tls_ciphersuite.h>
-#include <botan/tls_magic.h>
-#include <botan/tls_server_info.h>
-#include <botan/secmem.h>
-#include <botan/symkey.h>
-#include <chrono>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Class representing a TLS session state
-*/
-class BOTAN_DLL Session
- {
- public:
-
- /**
- * Uninitialized session
- */
- Session() :
- m_start_time(std::chrono::system_clock::time_point::min()),
- m_version(),
- m_ciphersuite(0),
- m_compression_method(0),
- m_connection_side(static_cast<Connection_Side>(0)),
- m_fragment_size(0)
- {}
-
- /**
- * New session (sets session start time)
- */
- Session(const std::vector<byte>& session_id,
- const secure_vector<byte>& master_secret,
- Protocol_Version version,
- u16bit ciphersuite,
- byte compression_method,
- Connection_Side side,
- size_t fragment_size,
- const std::vector<X509_Certificate>& peer_certs,
- const std::vector<byte>& session_ticket,
- const Server_Information& server_info,
- const std::string& srp_identifier);
-
- /**
- * Load a session from DER representation (created by DER_encode)
- */
- Session(const byte ber[], size_t ber_len);
-
- /**
- * Load a session from PEM representation (created by PEM_encode)
- */
- Session(const std::string& pem);
-
- /**
- * Encode this session data for storage
- * @warning if the master secret is compromised so is the
- * session traffic
- */
- secure_vector<byte> DER_encode() const;
-
- /**
- * Encrypt a session (useful for serialization or session tickets)
- */
- std::vector<byte> encrypt(const SymmetricKey& key,
- RandomNumberGenerator& rng) const;
-
-
- /**
- * Decrypt a session created by encrypt
- * @param ctext the ciphertext returned by encrypt
- * @param ctext_size the size of ctext in bytes
- * @param key the same key used by the encrypting side
- */
- static Session decrypt(const byte ctext[],
- size_t ctext_size,
- const SymmetricKey& key);
-
- /**
- * Decrypt a session created by encrypt
- * @param ctext the ciphertext returned by encrypt
- * @param key the same key used by the encrypting side
- */
- static inline Session decrypt(const std::vector<byte>& ctext,
- const SymmetricKey& key)
- {
- return Session::decrypt(&ctext[0], ctext.size(), key);
- }
-
- /**
- * Encode this session data for storage
- * @warning if the master secret is compromised so is the
- * session traffic
- */
- std::string PEM_encode() const;
-
- /**
- * Get the version of the saved session
- */
- Protocol_Version version() const { return m_version; }
-
- /**
- * Get the ciphersuite code of the saved session
- */
- u16bit ciphersuite_code() const { return m_ciphersuite; }
-
- /**
- * Get the ciphersuite info of the saved session
- */
- Ciphersuite ciphersuite() const { return Ciphersuite::by_id(m_ciphersuite); }
-
- /**
- * Get the compression method used in the saved session
- */
- byte compression_method() const { return m_compression_method; }
-
- /**
- * Get which side of the connection the resumed session we are/were
- * acting as.
- */
- Connection_Side side() const { return m_connection_side; }
-
- /**
- * Get the SRP identity (if sent by the client in the initial handshake)
- */
- std::string srp_identifier() const { return m_srp_identifier; }
-
- /**
- * Get the saved master secret
- */
- const secure_vector<byte>& master_secret() const
- { return m_master_secret; }
-
- /**
- * Get the session identifier
- */
- const std::vector<byte>& session_id() const
- { return m_identifier; }
-
- /**
- * Get the negotiated maximum fragment size (or 0 if default)
- */
- size_t fragment_size() const { return m_fragment_size; }
-
- /**
- * Return the certificate chain of the peer (possibly empty)
- */
- std::vector<X509_Certificate> peer_certs() const { return m_peer_certs; }
-
- /**
- * Get the wall clock time this session began
- */
- std::chrono::system_clock::time_point start_time() const
- { return m_start_time; }
-
- /**
- * Return how long this session has existed (in seconds)
- */
- std::chrono::seconds session_age() const;
-
- /**
- * Return the session ticket the server gave us
- */
- const std::vector<byte>& session_ticket() const { return m_session_ticket; }
-
- Server_Information server_info() const { return m_server_info; }
-
- private:
- enum { TLS_SESSION_PARAM_STRUCT_VERSION = 0x2994e301 };
-
- std::chrono::system_clock::time_point m_start_time;
-
- std::vector<byte> m_identifier;
- std::vector<byte> m_session_ticket; // only used by client side
- secure_vector<byte> m_master_secret;
-
- Protocol_Version m_version;
- u16bit m_ciphersuite;
- byte m_compression_method;
- Connection_Side m_connection_side;
-
- size_t m_fragment_size;
-
- std::vector<X509_Certificate> m_peer_certs;
- Server_Information m_server_info; // optional
- std::string m_srp_identifier; // optional
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp
deleted file mode 100644
index 06cd1d0a1..000000000
--- a/src/tls/tls_session_key.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-* TLS Session Key
-* (C) 2004-2006,2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/internal/tls_session_key.h>
-#include <botan/internal/tls_handshake_state.h>
-#include <botan/internal/tls_messages.h>
-#include <botan/lookup.h>
-#include <memory>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Session_Keys Constructor
-*/
-Session_Keys::Session_Keys(const Handshake_State* state,
- const secure_vector<byte>& pre_master_secret,
- bool resuming)
- {
- const size_t cipher_keylen = state->ciphersuite().cipher_keylen();
- const size_t mac_keylen = state->ciphersuite().mac_keylen();
- const size_t cipher_ivlen = state->ciphersuite().cipher_ivlen();
-
- const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen);
-
- const byte MASTER_SECRET_MAGIC[] = {
- 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 };
-
- const byte KEY_GEN_MAGIC[] = {
- 0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E };
-
- std::unique_ptr<KDF> prf(state->protocol_specific_prf());
-
- if(resuming)
- {
- master_sec = pre_master_secret;
- }
- else
- {
- secure_vector<byte> salt;
-
- if(state->version() != Protocol_Version::SSL_V3)
- salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC));
-
- salt += state->client_hello()->random();
- salt += state->server_hello()->random();
-
- master_sec = prf->derive_key(48, pre_master_secret, salt);
- }
-
- secure_vector<byte> salt;
- if(state->version() != Protocol_Version::SSL_V3)
- salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC));
- salt += state->server_hello()->random();
- salt += state->client_hello()->random();
-
- SymmetricKey keyblock = prf->derive_key(prf_gen, master_sec, salt);
-
- const byte* key_data = keyblock.begin();
-
- c_mac = SymmetricKey(key_data, mac_keylen);
- key_data += mac_keylen;
-
- s_mac = SymmetricKey(key_data, mac_keylen);
- key_data += mac_keylen;
-
- c_cipher = SymmetricKey(key_data, cipher_keylen);
- key_data += cipher_keylen;
-
- s_cipher = SymmetricKey(key_data, cipher_keylen);
- key_data += cipher_keylen;
-
- c_iv = InitializationVector(key_data, cipher_ivlen);
- key_data += cipher_ivlen;
-
- s_iv = InitializationVector(key_data, cipher_ivlen);
- }
-
-}
-
-}
diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h
deleted file mode 100644
index d62e3400d..000000000
--- a/src/tls/tls_session_key.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-* TLS Session Key
-* (C) 2004-2006,2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SESSION_KEYS_H__
-#define BOTAN_TLS_SESSION_KEYS_H__
-
-#include <botan/symkey.h>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Session Keys
-*/
-class Session_Keys
- {
- public:
- SymmetricKey client_cipher_key() const { return c_cipher; }
- SymmetricKey server_cipher_key() const { return s_cipher; }
-
- SymmetricKey client_mac_key() const { return c_mac; }
- SymmetricKey server_mac_key() const { return s_mac; }
-
- InitializationVector client_iv() const { return c_iv; }
- InitializationVector server_iv() const { return s_iv; }
-
- const secure_vector<byte>& master_secret() const { return master_sec; }
-
- Session_Keys() {}
-
- Session_Keys(const class Handshake_State* state,
- const secure_vector<byte>& pre_master,
- bool resuming);
-
- private:
- secure_vector<byte> master_sec;
- SymmetricKey c_cipher, s_cipher, c_mac, s_mac;
- InitializationVector c_iv, s_iv;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_session_manager.h b/src/tls/tls_session_manager.h
deleted file mode 100644
index e6eacc88c..000000000
--- a/src/tls/tls_session_manager.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-* TLS Session Manager
-* (C) 2011 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_SESSION_MANAGER_H__
-#define BOTAN_TLS_SESSION_MANAGER_H__
-
-#include <botan/tls_session.h>
-#include <mutex>
-#include <chrono>
-#include <map>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* Session_Manager is an interface to systems which can save
-* session parameters for supporting session resumption.
-*
-* Saving sessions is done on a best-effort basis; an implementation is
-* allowed to drop sessions due to space constraints.
-*
-* Implementations should strive to be thread safe
-*/
-class BOTAN_DLL Session_Manager
- {
- public:
- /**
- * Try to load a saved session (using session ID)
- * @param session_id the session identifier we are trying to resume
- * @param session will be set to the saved session data (if found),
- or not modified if not found
- * @return true if session was modified
- */
- virtual bool load_from_session_id(const std::vector<byte>& session_id,
- Session& session) = 0;
-
- /**
- * Try to load a saved session (using info about server)
- * @param info the information about the server
- * @param session will be set to the saved session data (if found),
- or not modified if not found
- * @return true if session was modified
- */
- virtual bool load_from_server_info(const Server_Information& info,
- Session& session) = 0;
-
- /**
- * Remove this session id from the cache, if it exists
- */
- virtual void remove_entry(const std::vector<byte>& session_id) = 0;
-
- /**
- * Save a session on a best effort basis; the manager may not in
- * fact be able to save the session for whatever reason; this is
- * not an error. Caller cannot assume that calling save followed
- * immediately by load_from_* will result in a successful lookup.
- *
- * @param session to save
- */
- virtual void save(const Session& session) = 0;
-
- /**
- * Return the allowed lifetime of a session; beyond this time,
- * sessions are not resumed. Returns 0 if unknown/no explicit
- * expiration policy.
- */
- virtual std::chrono::seconds session_lifetime() const = 0;
-
- virtual ~Session_Manager() {}
- };
-
-/**
-* An implementation of Session_Manager that does not save sessions at
-* all, preventing session resumption.
-*/
-class BOTAN_DLL Session_Manager_Noop : public Session_Manager
- {
- public:
- bool load_from_session_id(const std::vector<byte>&, Session&) override
- { return false; }
-
- bool load_from_server_info(const Server_Information&, Session&) override
- { return false; }
-
- void remove_entry(const std::vector<byte>&) override {}
-
- void save(const Session&) override {}
-
- std::chrono::seconds session_lifetime() const override
- { return std::chrono::seconds(0); }
- };
-
-/**
-* An implementation of Session_Manager that saves values in memory.
-*/
-class BOTAN_DLL Session_Manager_In_Memory : public Session_Manager
- {
- public:
- /**
- * @param max_sessions a hint on the maximum number of sessions
- * to keep in memory at any one time. (If zero, don't cap)
- * @param session_lifetime sessions are expired after this many
- * seconds have elapsed from initial handshake.
- */
- Session_Manager_In_Memory(RandomNumberGenerator& rng,
- size_t max_sessions = 1000,
- std::chrono::seconds session_lifetime =
- std::chrono::seconds(7200));
-
- bool load_from_session_id(const std::vector<byte>& session_id,
- Session& session) override;
-
- bool load_from_server_info(const Server_Information& info,
- Session& session) override;
-
- void remove_entry(const std::vector<byte>& session_id) override;
-
- void save(const Session& session_data) override;
-
- std::chrono::seconds session_lifetime() const override
- { return m_session_lifetime; }
-
- private:
- bool load_from_session_str(const std::string& session_str,
- Session& session);
-
- std::mutex m_mutex;
-
- size_t m_max_sessions;
-
- std::chrono::seconds m_session_lifetime;
-
- RandomNumberGenerator& m_rng;
- SymmetricKey m_session_key;
-
- std::map<std::string, std::vector<byte>> m_sessions; // hex(session_id) -> session
- std::map<Server_Information, std::string> m_info_sessions;
- };
-
-}
-
-}
-
-#endif
diff --git a/src/tls/tls_session_manager_memory.cpp b/src/tls/tls_session_manager_memory.cpp
deleted file mode 100644
index 24ede276c..000000000
--- a/src/tls/tls_session_manager_memory.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-* TLS Session Management
-* (C) 2011,2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_session_manager.h>
-#include <botan/hex.h>
-#include <chrono>
-
-namespace Botan {
-
-namespace TLS {
-
-Session_Manager_In_Memory::Session_Manager_In_Memory(
- RandomNumberGenerator& rng,
- size_t max_sessions,
- std::chrono::seconds session_lifetime) :
- m_max_sessions(max_sessions),
- m_session_lifetime(session_lifetime),
- m_rng(rng),
- m_session_key(m_rng, 32)
- {}
-
-bool Session_Manager_In_Memory::load_from_session_str(
- const std::string& session_str, Session& session)
- {
- // assert(lock is held)
-
- auto i = m_sessions.find(session_str);
-
- if(i == m_sessions.end())
- return false;
-
- try
- {
- session = Session::decrypt(i->second, m_session_key);
- }
- catch(...)
- {
- return false;
- }
-
- // if session has expired, remove it
- const auto now = std::chrono::system_clock::now();
-
- if(session.start_time() + session_lifetime() < now)
- {
- m_sessions.erase(i);
- return false;
- }
-
- return true;
- }
-
-bool Session_Manager_In_Memory::load_from_session_id(
- const std::vector<byte>& session_id, Session& session)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
-
- return load_from_session_str(hex_encode(session_id), session);
- }
-
-bool Session_Manager_In_Memory::load_from_server_info(
- const Server_Information& info, Session& session)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
-
- auto i = m_info_sessions.find(info);
-
- if(i == m_info_sessions.end())
- return false;
-
- if(load_from_session_str(i->second, session))
- return true;
-
- /*
- * It existed at one point but was removed from the sessions map,
- * remove m_info_sessions entry as well
- */
- m_info_sessions.erase(i);
-
- return false;
- }
-
-void Session_Manager_In_Memory::remove_entry(
- const std::vector<byte>& session_id)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
-
- auto i = m_sessions.find(hex_encode(session_id));
-
- if(i != m_sessions.end())
- m_sessions.erase(i);
- }
-
-void Session_Manager_In_Memory::save(const Session& session)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
-
- if(m_max_sessions != 0)
- {
- /*
- We generate new session IDs with the first 4 bytes being a
- timestamp, so this actually removes the oldest sessions first.
- */
- while(m_sessions.size() >= m_max_sessions)
- m_sessions.erase(m_sessions.begin());
- }
-
- const std::string session_id_str = hex_encode(session.session_id());
-
- m_sessions[session_id_str] = session.encrypt(m_session_key, m_rng);
-
- if(session.side() == CLIENT && !session.server_info().empty())
- m_info_sessions[session.server_info()] = session_id_str;
- }
-
-}
-
-}
diff --git a/src/tls/tls_suite_info.cpp b/src/tls/tls_suite_info.cpp
deleted file mode 100644
index 2984fd535..000000000
--- a/src/tls/tls_suite_info.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
-* TLS cipher suite information
-*
-* This file was automatically generated from the IANA assignments
-* (tls-parameters.txt hash a794db70c6546a47e3bc3181dc0fd908a322e50c)
-* by ./src/build-data/scripts/tls_suite_info.py on 2013-12-04
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_ciphersuite.h>
-
-namespace Botan {
-
-namespace TLS {
-
-Ciphersuite Ciphersuite::by_id(u16bit suite)
- {
- switch(suite)
- {
- case 0x0013: // DHE_DSS_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x0013, "DSA", "DH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x0032: // DHE_DSS_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x0032, "DSA", "DH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x0040: // DHE_DSS_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x0040, "DSA", "DH", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0x00A2: // DHE_DSS_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x00A2, "DSA", "DH", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0038: // DHE_DSS_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x0038, "DSA", "DH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x006A: // DHE_DSS_WITH_AES_256_CBC_SHA256
- return Ciphersuite(0x006A, "DSA", "DH", "AES-256", 32, 16, "SHA-256", 32);
-
- case 0x00A3: // DHE_DSS_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x00A3, "DSA", "DH", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0044: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
- return Ciphersuite(0x0044, "DSA", "DH", "Camellia-128", 16, 16, "SHA-1", 20);
-
- case 0x00BD: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0x00BD, "DSA", "DH", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC080: // DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC080, "DSA", "DH", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0087: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
- return Ciphersuite(0x0087, "DSA", "DH", "Camellia-256", 32, 16, "SHA-1", 20);
-
- case 0x00C3: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
- return Ciphersuite(0x00C3, "DSA", "DH", "Camellia-256", 32, 16, "SHA-256", 32);
-
- case 0xC081: // DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC081, "DSA", "DH", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0066: // DHE_DSS_WITH_RC4_128_SHA
- return Ciphersuite(0x0066, "DSA", "DH", "RC4", 16, 0, "SHA-1", 20);
-
- case 0x0099: // DHE_DSS_WITH_SEED_CBC_SHA
- return Ciphersuite(0x0099, "DSA", "DH", "SEED", 16, 16, "SHA-1", 20);
-
- case 0x008F: // DHE_PSK_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x008F, "", "DHE_PSK", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x0090: // DHE_PSK_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x0090, "", "DHE_PSK", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x00B2: // DHE_PSK_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x00B2, "", "DHE_PSK", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC0A6: // DHE_PSK_WITH_AES_128_CCM
- return Ciphersuite(0xC0A6, "", "DHE_PSK", "AES-128/CCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x00AA: // DHE_PSK_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x00AA, "", "DHE_PSK", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0091: // DHE_PSK_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x0091, "", "DHE_PSK", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x00B3: // DHE_PSK_WITH_AES_256_CBC_SHA384
- return Ciphersuite(0x00B3, "", "DHE_PSK", "AES-256", 32, 16, "SHA-384", 48);
-
- case 0xC0A7: // DHE_PSK_WITH_AES_256_CCM
- return Ciphersuite(0xC0A7, "", "DHE_PSK", "AES-256/CCM", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0x00AB: // DHE_PSK_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x00AB, "", "DHE_PSK", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC096: // DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0xC096, "", "DHE_PSK", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC090: // DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC090, "", "DHE_PSK", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC097: // DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- return Ciphersuite(0xC097, "", "DHE_PSK", "Camellia-256", 32, 16, "SHA-384", 48);
-
- case 0xC091: // DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC091, "", "DHE_PSK", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x008E: // DHE_PSK_WITH_RC4_128_SHA
- return Ciphersuite(0x008E, "", "DHE_PSK", "RC4", 16, 0, "SHA-1", 20);
-
- case 0x0016: // DHE_RSA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x0016, "RSA", "DH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x0033: // DHE_RSA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x0033, "RSA", "DH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x0067: // DHE_RSA_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x0067, "RSA", "DH", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC09E: // DHE_RSA_WITH_AES_128_CCM
- return Ciphersuite(0xC09E, "RSA", "DH", "AES-128/CCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A2: // DHE_RSA_WITH_AES_128_CCM_8
- return Ciphersuite(0xC0A2, "RSA", "DH", "AES-128/CCM-8", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x009E: // DHE_RSA_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x009E, "RSA", "DH", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0039: // DHE_RSA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x0039, "RSA", "DH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x006B: // DHE_RSA_WITH_AES_256_CBC_SHA256
- return Ciphersuite(0x006B, "RSA", "DH", "AES-256", 32, 16, "SHA-256", 32);
-
- case 0xC09F: // DHE_RSA_WITH_AES_256_CCM
- return Ciphersuite(0xC09F, "RSA", "DH", "AES-256/CCM", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A3: // DHE_RSA_WITH_AES_256_CCM_8
- return Ciphersuite(0xC0A3, "RSA", "DH", "AES-256/CCM-8", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0x009F: // DHE_RSA_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x009F, "RSA", "DH", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0045: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- return Ciphersuite(0x0045, "RSA", "DH", "Camellia-128", 16, 16, "SHA-1", 20);
-
- case 0x00BE: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0x00BE, "RSA", "DH", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC07C: // DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC07C, "RSA", "DH", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0088: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- return Ciphersuite(0x0088, "RSA", "DH", "Camellia-256", 32, 16, "SHA-1", 20);
-
- case 0x00C4: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- return Ciphersuite(0x00C4, "RSA", "DH", "Camellia-256", 32, 16, "SHA-256", 32);
-
- case 0xC07D: // DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC07D, "RSA", "DH", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA
- return Ciphersuite(0x009A, "RSA", "DH", "SEED", 16, 16, "SHA-1", 20);
-
- case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x001B, "", "DH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x0034, "", "DH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x006C, "", "DH", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0x00A6: // DH_anon_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x00A6, "", "DH", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x003A, "", "DH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256
- return Ciphersuite(0x006D, "", "DH", "AES-256", 32, 16, "SHA-256", 32);
-
- case 0x00A7: // DH_anon_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x00A7, "", "DH", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA
- return Ciphersuite(0x0046, "", "DH", "Camellia-128", 16, 16, "SHA-1", 20);
-
- case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0x00BF, "", "DH", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC084: // DH_anon_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC084, "", "DH", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA
- return Ciphersuite(0x0089, "", "DH", "Camellia-256", 32, 16, "SHA-1", 20);
-
- case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256
- return Ciphersuite(0x00C5, "", "DH", "Camellia-256", 32, 16, "SHA-256", 32);
-
- case 0xC085: // DH_anon_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC085, "", "DH", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0018: // DH_anon_WITH_RC4_128_MD5
- return Ciphersuite(0x0018, "", "DH", "RC4", 16, 0, "MD5", 16);
-
- case 0x009B: // DH_anon_WITH_SEED_CBC_SHA
- return Ciphersuite(0x009B, "", "DH", "SEED", 16, 16, "SHA-1", 20);
-
- case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC008, "ECDSA", "ECDH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC009, "ECDSA", "ECDH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0xC023, "ECDSA", "ECDH", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC02B: // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0xC02B, "ECDSA", "ECDH", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC00A, "ECDSA", "ECDH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- return Ciphersuite(0xC024, "ECDSA", "ECDH", "AES-256", 32, 16, "SHA-384", 48);
-
- case 0xC02C: // ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0xC02C, "ECDSA", "ECDH", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0xC072, "ECDSA", "ECDH", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC086: // ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC086, "ECDSA", "ECDH", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- return Ciphersuite(0xC073, "ECDSA", "ECDH", "Camellia-256", 32, 16, "SHA-384", 48);
-
- case 0xC087: // ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC087, "ECDSA", "ECDH", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC007: // ECDHE_ECDSA_WITH_RC4_128_SHA
- return Ciphersuite(0xC007, "ECDSA", "ECDH", "RC4", 16, 0, "SHA-1", 20);
-
- case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC034, "", "ECDHE_PSK", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC035, "", "ECDHE_PSK", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0xC037, "", "ECDHE_PSK", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC036, "", "ECDHE_PSK", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384
- return Ciphersuite(0xC038, "", "ECDHE_PSK", "AES-256", 32, 16, "SHA-384", 48);
-
- case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0xC09A, "", "ECDHE_PSK", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- return Ciphersuite(0xC09B, "", "ECDHE_PSK", "Camellia-256", 32, 16, "SHA-384", 48);
-
- case 0xC033: // ECDHE_PSK_WITH_RC4_128_SHA
- return Ciphersuite(0xC033, "", "ECDHE_PSK", "RC4", 16, 0, "SHA-1", 20);
-
- case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC012, "RSA", "ECDH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC013, "RSA", "ECDH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0xC027, "RSA", "ECDH", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC02F: // ECDHE_RSA_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0xC02F, "RSA", "ECDH", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC014, "RSA", "ECDH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384
- return Ciphersuite(0xC028, "RSA", "ECDH", "AES-256", 32, 16, "SHA-384", 48);
-
- case 0xC030: // ECDHE_RSA_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0xC030, "RSA", "ECDH", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0xC076, "RSA", "ECDH", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC08A: // ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC08A, "RSA", "ECDH", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
- return Ciphersuite(0xC077, "RSA", "ECDH", "Camellia-256", 32, 16, "SHA-384", 48);
-
- case 0xC08B: // ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC08B, "RSA", "ECDH", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC011: // ECDHE_RSA_WITH_RC4_128_SHA
- return Ciphersuite(0xC011, "RSA", "ECDH", "RC4", 16, 0, "SHA-1", 20);
-
- case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC017, "", "ECDH", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC018, "", "ECDH", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC019, "", "ECDH", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC016: // ECDH_anon_WITH_RC4_128_SHA
- return Ciphersuite(0xC016, "", "ECDH", "RC4", 16, 0, "SHA-1", 20);
-
- case 0xC0AA: // PSK_DHE_WITH_AES_128_CCM_8
- return Ciphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM-8", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0AB: // PSK_DHE_WITH_AES_256_CCM_8
- return Ciphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM-8", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x008B, "", "PSK", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x008C: // PSK_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x008C, "", "PSK", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x00AE, "", "PSK", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC0A4: // PSK_WITH_AES_128_CCM
- return Ciphersuite(0xC0A4, "", "PSK", "AES-128/CCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A8: // PSK_WITH_AES_128_CCM_8
- return Ciphersuite(0xC0A8, "", "PSK", "AES-128/CCM-8", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x00A8: // PSK_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x00A8, "", "PSK", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x008D: // PSK_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x008D, "", "PSK", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384
- return Ciphersuite(0x00AF, "", "PSK", "AES-256", 32, 16, "SHA-384", 48);
-
- case 0xC0A5: // PSK_WITH_AES_256_CCM
- return Ciphersuite(0xC0A5, "", "PSK", "AES-256/CCM", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A9: // PSK_WITH_AES_256_CCM_8
- return Ciphersuite(0xC0A9, "", "PSK", "AES-256/CCM-8", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0x00A9: // PSK_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x00A9, "", "PSK", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0xC094, "", "PSK", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC08E: // PSK_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC08E, "", "PSK", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384
- return Ciphersuite(0xC095, "", "PSK", "Camellia-256", 32, 16, "SHA-384", 48);
-
- case 0xC08F: // PSK_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC08F, "", "PSK", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x008A: // PSK_WITH_RC4_128_SHA
- return Ciphersuite(0x008A, "", "PSK", "RC4", 16, 0, "SHA-1", 20);
-
- case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0x000A, "RSA", "RSA", "3DES", 24, 8, "SHA-1", 20);
-
- case 0x002F: // RSA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0x002F, "RSA", "RSA", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0x003C: // RSA_WITH_AES_128_CBC_SHA256
- return Ciphersuite(0x003C, "RSA", "RSA", "AES-128", 16, 16, "SHA-256", 32);
-
- case 0xC09C: // RSA_WITH_AES_128_CCM
- return Ciphersuite(0xC09C, "RSA", "RSA", "AES-128/CCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A0: // RSA_WITH_AES_128_CCM_8
- return Ciphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM-8", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x009C: // RSA_WITH_AES_128_GCM_SHA256
- return Ciphersuite(0x009C, "RSA", "RSA", "AES-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0035: // RSA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0x0035, "RSA", "RSA", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0x003D: // RSA_WITH_AES_256_CBC_SHA256
- return Ciphersuite(0x003D, "RSA", "RSA", "AES-256", 32, 16, "SHA-256", 32);
-
- case 0xC09D: // RSA_WITH_AES_256_CCM
- return Ciphersuite(0xC09D, "RSA", "RSA", "AES-256/CCM", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0xC0A1: // RSA_WITH_AES_256_CCM_8
- return Ciphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM-8", 32, 4, "AEAD", 0, "SHA-256");
-
- case 0x009D: // RSA_WITH_AES_256_GCM_SHA384
- return Ciphersuite(0x009D, "RSA", "RSA", "AES-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA
- return Ciphersuite(0x0041, "RSA", "RSA", "Camellia-128", 16, 16, "SHA-1", 20);
-
- case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256
- return Ciphersuite(0x00BA, "RSA", "RSA", "Camellia-128", 16, 16, "SHA-256", 32);
-
- case 0xC07A: // RSA_WITH_CAMELLIA_128_GCM_SHA256
- return Ciphersuite(0xC07A, "RSA", "RSA", "Camellia-128/GCM", 16, 4, "AEAD", 0, "SHA-256");
-
- case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA
- return Ciphersuite(0x0084, "RSA", "RSA", "Camellia-256", 32, 16, "SHA-1", 20);
-
- case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256
- return Ciphersuite(0x00C0, "RSA", "RSA", "Camellia-256", 32, 16, "SHA-256", 32);
-
- case 0xC07B: // RSA_WITH_CAMELLIA_256_GCM_SHA384
- return Ciphersuite(0xC07B, "RSA", "RSA", "Camellia-256/GCM", 32, 4, "AEAD", 0, "SHA-384");
-
- case 0x0004: // RSA_WITH_RC4_128_MD5
- return Ciphersuite(0x0004, "RSA", "RSA", "RC4", 16, 0, "MD5", 16);
-
- case 0x0005: // RSA_WITH_RC4_128_SHA
- return Ciphersuite(0x0005, "RSA", "RSA", "RC4", 16, 0, "SHA-1", 20);
-
- case 0x0096: // RSA_WITH_SEED_CBC_SHA
- return Ciphersuite(0x0096, "RSA", "RSA", "SEED", 16, 16, "SHA-1", 20);
-
- case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC01C, "DSA", "SRP_SHA", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC01F, "DSA", "SRP_SHA", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC022, "DSA", "SRP_SHA", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC01B, "RSA", "SRP_SHA", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC01E, "RSA", "SRP_SHA", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC021, "RSA", "SRP_SHA", "AES-256", 32, 16, "SHA-1", 20);
-
- case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA
- return Ciphersuite(0xC01A, "", "SRP_SHA", "3DES", 24, 8, "SHA-1", 20);
-
- case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA
- return Ciphersuite(0xC01D, "", "SRP_SHA", "AES-128", 16, 16, "SHA-1", 20);
-
- case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA
- return Ciphersuite(0xC020, "", "SRP_SHA", "AES-256", 32, 16, "SHA-1", 20);
-
- }
-
- return Ciphersuite(); // some unknown ciphersuite
- }
-
-}
-
-}
diff --git a/src/tls/tls_version.cpp b/src/tls/tls_version.cpp
deleted file mode 100644
index 7b880d98c..000000000
--- a/src/tls/tls_version.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-* TLS Protocol Version Management
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#include <botan/tls_version.h>
-#include <botan/tls_exceptn.h>
-#include <botan/parsing.h>
-
-namespace Botan {
-
-namespace TLS {
-
-std::string Protocol_Version::to_string() const
- {
- const byte maj = major_version();
- const byte min = minor_version();
-
- if(maj == 3 && min == 0)
- return "SSL v3";
-
- if(maj == 3 && min >= 1) // TLS v1.x
- return "TLS v1." + std::to_string(min-1);
-
- if(maj == 254) // DTLS 1.x
- return "DTLS v1." + std::to_string(255 - min);
-
- // Some very new or very old protocol (or bogus data)
- return "Unknown " + std::to_string(maj) + "." + std::to_string(min);
- }
-
-bool Protocol_Version::is_datagram_protocol() const
- {
- return major_version() == 254;
- }
-
-bool Protocol_Version::operator>(const Protocol_Version& other) const
- {
- if(this->is_datagram_protocol() != other.is_datagram_protocol())
- throw TLS_Exception(Alert::PROTOCOL_VERSION,
- "Version comparing " + to_string() +
- " with " + other.to_string());
-
- if(this->is_datagram_protocol())
- return m_version < other.m_version; // goes backwards
-
- return m_version > other.m_version;
- }
-
-Protocol_Version Protocol_Version::best_known_match() const
- {
- if(known_version())
- return *this; // known version is its own best match
-
- if(is_datagram_protocol())
- return Protocol_Version::DTLS_V12;
- else
- return Protocol_Version::TLS_V12;
- }
-
-bool Protocol_Version::known_version() const
- {
- return (m_version == Protocol_Version::SSL_V3 ||
- m_version == Protocol_Version::TLS_V10 ||
- m_version == Protocol_Version::TLS_V11 ||
- m_version == Protocol_Version::TLS_V12 ||
- m_version == Protocol_Version::DTLS_V10 ||
- m_version == Protocol_Version::DTLS_V12);
- }
-
-bool Protocol_Version::supports_negotiable_signature_algorithms() const
- {
- return (m_version == Protocol_Version::TLS_V12 ||
- m_version == Protocol_Version::DTLS_V12);
- }
-
-bool Protocol_Version::supports_explicit_cbc_ivs() const
- {
- return (m_version == Protocol_Version::TLS_V11 ||
- m_version == Protocol_Version::TLS_V12 ||
- m_version == Protocol_Version::DTLS_V10 ||
- m_version == Protocol_Version::DTLS_V12);
- }
-
-bool Protocol_Version::supports_ciphersuite_specific_prf() const
- {
- return (m_version == Protocol_Version::TLS_V12 ||
- m_version == Protocol_Version::DTLS_V12);
- }
-
-bool Protocol_Version::supports_aead_modes() const
- {
- return (m_version == Protocol_Version::TLS_V12 ||
- m_version == Protocol_Version::DTLS_V12);
- }
-
-}
-
-}
diff --git a/src/tls/tls_version.h b/src/tls/tls_version.h
deleted file mode 100644
index 9fd71b629..000000000
--- a/src/tls/tls_version.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-* TLS Protocol Version Management
-* (C) 2012 Jack Lloyd
-*
-* Released under the terms of the Botan license
-*/
-
-#ifndef BOTAN_TLS_PROTOCOL_VERSION_H__
-#define BOTAN_TLS_PROTOCOL_VERSION_H__
-
-#include <botan/get_byte.h>
-#include <string>
-
-namespace Botan {
-
-namespace TLS {
-
-/**
-* TLS Protocol Version
-*/
-class BOTAN_DLL Protocol_Version
- {
- public:
- enum Version_Code {
- SSL_V3 = 0x0300,
- TLS_V10 = 0x0301,
- TLS_V11 = 0x0302,
- TLS_V12 = 0x0303,
-
- DTLS_V10 = 0xFEFF,
- DTLS_V12 = 0xFEFD
- };
-
- static Protocol_Version latest_tls_version()
- {
- return Protocol_Version(TLS_V12);
- }
-
- static Protocol_Version latest_dtls_version()
- {
- return Protocol_Version(DTLS_V12);
- }
-
- Protocol_Version() : m_version(0) {}
-
- /**
- * @param named_version a specific named version of the protocol
- */
- Protocol_Version(Version_Code named_version) :
- m_version(static_cast<u16bit>(named_version)) {}
-
- /**
- * @param major the major version
- * @param minor the minor version
- */
- Protocol_Version(byte major, byte minor) :
- m_version((static_cast<u16bit>(major) << 8) | minor) {}
-
- /**
- * @return true if this is a valid protocol version
- */
- bool valid() const { return (m_version != 0); }
-
- /**
- * @return true if this is a protocol version we know about
- */
- bool known_version() const;
-
- /**
- * @return major version of the protocol version
- */
- byte major_version() const { return get_byte(0, m_version); }
-
- /**
- * @return minor version of the protocol version
- */
- byte minor_version() const { return get_byte(1, m_version); }
-
- /**
- * @return human-readable description of this version
- */
- std::string to_string() const;
-
- /**
- * If this version is known, return that. Otherwise return the
- * best (most recent) version we know of.
- * @return best matching protocol version
- */
- Protocol_Version best_known_match() const;
-
- /**
- * @return true iff this is a DTLS version
- */
- bool is_datagram_protocol() const;
-
- /**
- * @return true if this version supports negotiable signature algorithms
- */
- bool supports_negotiable_signature_algorithms() const;
-
- /**
- * @return true if this version uses explicit IVs for block ciphers
- */
- bool supports_explicit_cbc_ivs() const;
-
- /**
- * @return true if this version uses a ciphersuite specific PRF
- */
- bool supports_ciphersuite_specific_prf() const;
-
- bool supports_aead_modes() const;
-
- /**
- * @return if this version is equal to other
- */
- bool operator==(const Protocol_Version& other) const
- {
- return (m_version == other.m_version);
- }
-
- /**
- * @return if this version is not equal to other
- */
- bool operator!=(const Protocol_Version& other) const
- {
- return (m_version != other.m_version);
- }
-
- /**
- * @return if this version is later than other
- */
- bool operator>(const Protocol_Version& other) const;
-
- /**
- * @return if this version is later than or equal to other
- */
- bool operator>=(const Protocol_Version& other) const
- {
- return (*this == other || *this > other);
- }
-
- private:
- u16bit m_version;
- };
-
-}
-
-}
-
-#endif
-