diff options
-rw-r--r-- | doc/examples/tls_client.cpp | 16 | ||||
-rw-r--r-- | doc/examples/tls_server.cpp | 18 | ||||
-rw-r--r-- | src/tls/c_kex.cpp | 2 | ||||
-rw-r--r-- | src/tls/rec_read.cpp | 12 | ||||
-rw-r--r-- | src/tls/rec_wri.cpp | 15 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 11 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 10 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 11 | ||||
-rw-r--r-- | src/tls/tls_client.h | 2 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 1 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 2 | ||||
-rw-r--r-- | src/tls/tls_record.h | 8 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 23 | ||||
-rw-r--r-- | src/tls/tls_server.h | 1 | ||||
-rw-r--r-- | src/tls/tls_session_key.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_session_key.h | 2 | ||||
-rw-r--r-- | src/tls/tls_suites.cpp | 10 | ||||
-rw-r--r-- | src/tls/tls_suites.h | 12 |
18 files changed, 118 insertions, 40 deletions
diff --git a/doc/examples/tls_client.cpp b/doc/examples/tls_client.cpp index 3fb7f10c6..be72a65e7 100644 --- a/doc/examples/tls_client.cpp +++ b/doc/examples/tls_client.cpp @@ -66,6 +66,16 @@ int connect_to_host(const std::string& host, u16bit port) return fd; } +void handshake_complete(const TLS_Session_Params& session) + { + printf("Handshake complete, protocol=%04X ciphersuite=%04X compression=%d\n", + session.version(), session.ciphersuite(), + session.compression_method()); + + printf("Session id = %s\n", hex_encode(session.session_id()).c_str()); + printf("Master secret = %s\n", hex_encode(session.master_secret()).c_str()); + } + void socket_write(int sockfd, const byte buf[], size_t length) { size_t offset = 0; @@ -123,6 +133,7 @@ int main(int argc, char* argv[]) TLS_Client client(std::tr1::bind(socket_write, sockfd, _1, _2), process_data, + handshake_complete, session_manager, policy, rng, @@ -130,6 +141,8 @@ int main(int argc, char* argv[]) fd_set readfds; + bool version_reported = false; + while(true) { FD_ZERO(&readfds); @@ -141,6 +154,9 @@ int main(int argc, char* argv[]) if(client.is_closed()) break; + if(client.is_active() && !version_reported) + printf("Negotiated version %04X\n", client.protocol_version()); + if(FD_ISSET(sockfd, &readfds)) { byte buf[1024] = { 0 }; diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp index f43af1dcf..0710c35f9 100644 --- a/doc/examples/tls_server.cpp +++ b/doc/examples/tls_server.cpp @@ -15,6 +15,16 @@ using namespace Botan; #include <iostream> #include <memory> +void handshake_complete(const TLS_Session_Params& session) + { + printf("Handshake complete, protocol=%04X ciphersuite=%04X compression=%d\n", + session.version(), session.ciphersuite(), + session.compression_method()); + + printf("Session id = %s\n", hex_encode(session.session_id()).c_str()); + printf("Master secret = %s\n", hex_encode(session.master_secret()).c_str()); + } + class Blocking_TLS_Server { public: @@ -29,6 +39,7 @@ class Blocking_TLS_Server server( output_fn, std::tr1::bind(&Blocking_TLS_Server::reader_fn, std::tr1::ref(*this), _1, _2, _3), + handshake_complete, sessions, policy, rng, @@ -146,7 +157,7 @@ int main(int argc, char* argv[]) //DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024")); X509_Cert_Options options( - "localhost/US/Syn Ack Labs/Mathematical Munitions Dept"); + "localhost/US/Botan Library/Test Server"); X509_Certificate cert = X509::create_self_signed_cert(options, key, "SHA-1", rng); @@ -199,9 +210,14 @@ int main(int argc, char* argv[]) break; } + if(line == "reneg\n") + tls.underlying().renegotiate(); + line.clear(); } } + + delete sock; } catch(std::exception& e) { printf("Connection problem: %s\n", e.what()); } } diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index 341ae1e14..48d76d1e6 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -61,7 +61,7 @@ Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, * Read a Client Key Exchange message */ Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents, - const CipherSuite& suite, + const TLS_Cipher_Suite& suite, Version_Code using_version) { include_length = true; diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp index 63c08cad5..f6cc1057d 100644 --- a/src/tls/rec_read.cpp +++ b/src/tls/rec_read.cpp @@ -42,9 +42,19 @@ void Record_Reader::set_version(Version_Code version) } /* +* Get the version in use +*/ +Version_Code Record_Reader::get_version() const + { + return static_cast<Version_Code>( + (static_cast<u16bit>(major) << 8) | minor); + } + +/* * Set the keys for reading */ -void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, +void Record_Reader::activate(const TLS_Cipher_Suite& suite, + const SessionKeys& keys, Connection_Side side) { cipher.reset(); diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index a9a5b4549..9af48b4ee 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -14,8 +14,6 @@ #include <botan/loadstor.h> #include <botan/libstate.h> -#include <stdio.h> - namespace Botan { /* @@ -34,8 +32,6 @@ void Record_Writer::set_maximum_fragment_size(size_t max_fragment) m_max_fragment = MAX_PLAINTEXT_SIZE; else m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE); - - printf("Setting max fragment size to %d\n", m_max_fragment); } /* @@ -70,9 +66,18 @@ void Record_Writer::set_version(Version_Code version) } /* +* Get the version in use +*/ +Version_Code Record_Writer::get_version() const + { + return static_cast<Version_Code>( + (static_cast<u16bit>(m_major) << 8) | m_minor); + } + +/* * Set the keys for writing */ -void Record_Writer::set_keys(const CipherSuite& suite, +void Record_Writer::activate(const TLS_Cipher_Suite& suite, const SessionKeys& keys, Connection_Side side) { diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 3831a6792..0e119c2a3 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -13,8 +13,10 @@ namespace Botan { TLS_Channel::TLS_Channel(std::tr1::function<void (const byte[], size_t)> socket_output_fn, - std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn) : + std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_complete) : proc_fn(proc_fn), + handshake_fn(handshake_complete), writer(socket_output_fn), state(0), handshake_completed(false), @@ -29,6 +31,13 @@ TLS_Channel::~TLS_Channel() state = 0; } +Version_Code TLS_Channel::protocol_version() const + { + if(!handshake_completed) + throw std::logic_error("Version not known until handshake complete"); + return writer.get_version(); + } + size_t TLS_Channel::received_data(const byte buf[], size_t buf_size) { try diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h index 52036c78d..4b5a91a65 100644 --- a/src/tls/tls_channel.h +++ b/src/tls/tls_channel.h @@ -10,6 +10,7 @@ #include <botan/tls_policy.h> #include <botan/tls_record.h> +#include <botan/tls_session_state.h> #include <botan/x509cert.h> #include <vector> @@ -56,6 +57,11 @@ class BOTAN_DLL TLS_Channel bool is_closed() const { return connection_closed; } /** + * Return the negotiated version (if session is currently active) + */ + Version_Code protocol_version() const; + + /** * Attempt to renegotiate the session */ virtual void renegotiate() = 0; @@ -66,7 +72,8 @@ class BOTAN_DLL TLS_Channel std::vector<X509_Certificate> peer_cert_chain() const { return peer_certs; } TLS_Channel(std::tr1::function<void (const byte[], size_t)> socket_output_fn, - std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn); + std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_complete); virtual ~TLS_Channel(); protected: @@ -77,6 +84,7 @@ class BOTAN_DLL TLS_Channel const MemoryRegion<byte>& contents) = 0; std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn; + std::tr1::function<void (const TLS_Session_Params&)> handshake_fn; Record_Writer writer; Record_Reader reader; diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index bd6b66ba0..5dbf9dc9c 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -19,17 +19,18 @@ namespace Botan { */ TLS_Client::TLS_Client(std::tr1::function<void (const byte[], size_t)> output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_fn, TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng, const std::string& hostname, const std::string& srp_username) : - TLS_Channel(output_fn, proc_fn), + TLS_Channel(output_fn, proc_fn, handshake_fn), policy(policy), rng(rng), session_manager(session_manager) { - writer.set_version(policy.pref_version()); + writer.set_version(SSL_V3); state = new Handshake_State; state->set_expected_next(SERVER_HELLO); @@ -146,7 +147,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, secure_renegotiation.update(state->server_hello); - state->suite = CipherSuite(state->server_hello->ciphersuite()); + state->suite = TLS_Cipher_Suite(state->server_hello->ciphersuite()); // if resuming, next is HANDSHAKE_CCS @@ -284,7 +285,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, writer.send(CHANGE_CIPHER_SPEC, 1); - writer.set_keys(state->suite, state->keys, CLIENT); + writer.activate(state->suite, state->keys, CLIENT); state->client_finished = new Finished(writer, state->hash, state->version, CLIENT, @@ -294,7 +295,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, { state->set_expected_next(FINISHED); - reader.set_keys(state->suite, state->keys, CLIENT); + reader.activate(state->suite, state->keys, CLIENT); } else if(type == FINISHED) { diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h index 279f4bc16..e2623015a 100644 --- a/src/tls/tls_client.h +++ b/src/tls/tls_client.h @@ -24,6 +24,7 @@ class BOTAN_DLL TLS_Client : public TLS_Channel * Set up a new TLS client session * @param socket_output_fn is called with data for the outbound socket * @param proc_fn is called when new data (application or alerts) is received + * @param handshake_complete is called when a handshake is completed * @param session_manager manages session resumption * @param policy specifies other connection policy information * @param rng a random number generator @@ -32,6 +33,7 @@ class BOTAN_DLL TLS_Client : public TLS_Channel */ TLS_Client(std::tr1::function<void (const byte[], size_t)> socket_output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_complete, TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng, diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp index b793971c5..a08597d21 100644 --- a/src/tls/tls_extensions.cpp +++ b/src/tls/tls_extensions.cpp @@ -7,6 +7,7 @@ #include <botan/internal/tls_extensions.h> #include <botan/internal/tls_reader.h> +#include <botan/tls_exceptn.h> namespace Botan { diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 8f9195412..2d66dfa11 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -196,7 +196,7 @@ class Client_Key_Exchange : public HandshakeMessage Version_Code pref_version); Client_Key_Exchange(const MemoryRegion<byte>& buf, - const CipherSuite& suite, + const TLS_Cipher_Suite& suite, Version_Code using_version); private: MemoryVector<byte> serialize() const; diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h index 55cb66034..be9fe6e73 100644 --- a/src/tls/tls_record.h +++ b/src/tls/tls_record.h @@ -45,12 +45,14 @@ class BOTAN_DLL Record_Writer void alert(Alert_Level level, Alert_Type type); - void set_keys(const CipherSuite& suite, + void activate(const TLS_Cipher_Suite& suite, const SessionKeys& keys, Connection_Side side); void set_version(Version_Code version); + Version_Code get_version() const; + void reset(); void set_maximum_fragment_size(size_t max_fragment); @@ -90,12 +92,14 @@ class BOTAN_DLL Record_Reader SecureVector<byte> get_record(byte& msg_type); - void set_keys(const CipherSuite& suite, + void activate(const TLS_Cipher_Suite& suite, const SessionKeys& keys, Connection_Side side); void set_version(Version_Code version); + Version_Code get_version() const; + void reset(); bool currently_empty() const { return input_queue.size() == 0; } diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 3077476e3..f5efa10e4 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -39,7 +39,7 @@ bool check_for_resume(TLS_Session_Params& session_info, if(client_session_id.empty()) // not resuming return false; - // wrong side + // not found if(!session_manager.find(client_session_id, session_info)) return false; @@ -81,18 +81,17 @@ bool check_for_resume(TLS_Session_Params& session_info, */ TLS_Server::TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_fn, TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng, const X509_Certificate& cert, const Private_Key& cert_key) : - TLS_Channel(output_fn, proc_fn), + TLS_Channel(output_fn, proc_fn, handshake_fn), policy(policy), rng(rng), session_manager(session_manager) { - writer.set_version(TLS_V10); - cert_chain.push_back(cert); private_key = PKCS8::copy_key(cert_key, rng); } @@ -196,7 +195,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, if(session_info.fragment_size()) writer.set_maximum_fragment_size(session_info.fragment_size()); - state->suite = CipherSuite(state->server_hello->ciphersuite()); + state->suite = TLS_Cipher_Suite(state->server_hello->ciphersuite()); state->keys = SessionKeys(state->suite, state->version, session_info.master_secret(), @@ -206,12 +205,15 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, writer.send(CHANGE_CIPHER_SPEC, 1); - writer.set_keys(state->suite, state->keys, SERVER); + writer.activate(state->suite, state->keys, SERVER); state->server_finished = new Finished(writer, state->hash, state->version, SERVER, state->keys.master_secret()); + if(handshake_fn) + handshake_fn(session_info); + state->set_expected_next(HANDSHAKE_CCS); } else // new session @@ -231,7 +233,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, if(state->client_hello->fragment_size()) writer.set_maximum_fragment_size(state->client_hello->fragment_size()); - state->suite = CipherSuite(state->server_hello->ciphersuite()); + state->suite = TLS_Cipher_Suite(state->server_hello->ciphersuite()); if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON) { @@ -345,7 +347,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, { state->set_expected_next(FINISHED); - reader.set_keys(state->suite, state->keys, SERVER); + reader.activate(state->suite, state->keys, SERVER); } else if(type == FINISHED) { @@ -365,7 +367,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, writer.send(CHANGE_CIPHER_SPEC, 1); - writer.set_keys(state->suite, state->keys, SERVER); + writer.activate(state->suite, state->keys, SERVER); state->server_finished = new Finished(writer, state->hash, state->version, SERVER, @@ -391,6 +393,9 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, ); session_manager.save(session_info); + + if(handshake_fn) + handshake_fn(session_info); } secure_renegotiation.update(state->client_finished, diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h index 45e25f0f9..16c6f8e3e 100644 --- a/src/tls/tls_server.h +++ b/src/tls/tls_server.h @@ -29,6 +29,7 @@ class BOTAN_DLL TLS_Server : public TLS_Channel */ TLS_Server(std::tr1::function<void (const byte[], size_t)> socket_output_fn, std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn, + std::tr1::function<void (const TLS_Session_Params&)> handshake_complete, TLS_Session_Manager& session_manager, const TLS_Policy& policy, RandomNumberGenerator& rng, diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp index 43118d921..f0ddc4493 100644 --- a/src/tls/tls_session_key.cpp +++ b/src/tls/tls_session_key.cpp @@ -28,7 +28,7 @@ std::string lookup_prf_name(Version_Code version) /** * SessionKeys Constructor */ -SessionKeys::SessionKeys(const CipherSuite& suite, +SessionKeys::SessionKeys(const TLS_Cipher_Suite& suite, Version_Code version, const MemoryRegion<byte>& pre_master_secret, const MemoryRegion<byte>& client_random, diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h index 76cb7e3e1..a698dfcfc 100644 --- a/src/tls/tls_session_key.h +++ b/src/tls/tls_session_key.h @@ -33,7 +33,7 @@ class SessionKeys SessionKeys() {} - SessionKeys(const CipherSuite& suite, + SessionKeys(const TLS_Cipher_Suite& suite, Version_Code version, const MemoryRegion<byte>& pre_master, const MemoryRegion<byte>& client_random, diff --git a/src/tls/tls_suites.cpp b/src/tls/tls_suites.cpp index 8dbd74e4e..aff15d68f 100644 --- a/src/tls/tls_suites.cpp +++ b/src/tls/tls_suites.cpp @@ -13,7 +13,7 @@ namespace Botan { /** * Convert an SSL/TLS ciphersuite to algorithm fields */ -TLS_Ciphersuite_Algos CipherSuite::lookup_ciphersuite(u16bit suite) +TLS_Ciphersuite_Algos TLS_Cipher_Suite::lookup_ciphersuite(u16bit suite) { if(suite == TLS_RSA_WITH_RC4_128_MD5) return TLS_Ciphersuite_Algos(TLS_ALGO_SIGNER_RSA | @@ -274,7 +274,7 @@ std::pair<std::string, size_t> cipher_code_to_name(TLS_Ciphersuite_Algos algo) return std::make_pair("SEED", 16); throw TLS_Exception(INTERNAL_ERROR, - "CipherSuite: Unknown cipher type " + to_string(algo)); + "TLS_Cipher_Suite: Unknown cipher type " + to_string(algo)); } std::string mac_code_to_name(TLS_Ciphersuite_Algos algo) @@ -292,15 +292,15 @@ std::string mac_code_to_name(TLS_Ciphersuite_Algos algo) return "SHA-384"; throw TLS_Exception(INTERNAL_ERROR, - "CipherSuite: Unknown MAC type " + to_string(algo)); + "TLS_Cipher_Suite: Unknown MAC type " + to_string(algo)); } } /** -* CipherSuite Constructor +* TLS_Cipher_Suite Constructor */ -CipherSuite::CipherSuite(u16bit suite_code) +TLS_Cipher_Suite::TLS_Cipher_Suite(u16bit suite_code) { if(suite_code == 0) return; diff --git a/src/tls/tls_suites.h b/src/tls/tls_suites.h index 8d6db0e8b..3256dc198 100644 --- a/src/tls/tls_suites.h +++ b/src/tls/tls_suites.h @@ -1,12 +1,12 @@ /* -* Cipher Suites -* (C) 2004-2010 Jack Lloyd +* TLS Cipher Suites +* (C) 2004-2011 Jack Lloyd * * Released under the terms of the Botan license */ -#ifndef BOTAN_TLS_CIPHERSUITES_H__ -#define BOTAN_TLS_CIPHERSUITES_H__ +#ifndef BOTAN_TLS_CIPHER_SUITES_H__ +#define BOTAN_TLS_CIPHER_SUITES_H__ #include <botan/types.h> #include <botan/tls_magic.h> @@ -17,7 +17,7 @@ namespace Botan { /** * Ciphersuite Information */ -class BOTAN_DLL CipherSuite +class BOTAN_DLL TLS_Cipher_Suite { public: static TLS_Ciphersuite_Algos lookup_ciphersuite(u16bit suite); @@ -30,7 +30,7 @@ class BOTAN_DLL CipherSuite TLS_Ciphersuite_Algos kex_type() const { return kex_algo; } TLS_Ciphersuite_Algos sig_type() const { return sig_algo; } - CipherSuite(u16bit = 0); + TLS_Cipher_Suite(u16bit ciphersuite_code = 0); private: TLS_Ciphersuite_Algos kex_algo, sig_algo; std::string cipher, mac; |