diff options
author | lloyd <[email protected]> | 2010-03-23 22:12:53 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2010-03-23 22:12:53 +0000 |
commit | 7479e66bb43e843c067e9a45145bafc84bdd41dc (patch) | |
tree | dcbd947508ab3bd8182816677d7d0d94edbf84c6 /src/ssl | |
parent | 8fda37bf5b79bf6569e1e375c48e9d74171cb141 (diff) |
Make Record_Reader event driven. Callers (eg TLS_Client and
TLS_Server) are not; they instead loop blocking on the socket. Will
move the event-driven behavior upwards as I go.
Diffstat (limited to 'src/ssl')
-rw-r--r-- | src/ssl/rec_read.cpp | 68 | ||||
-rw-r--r-- | src/ssl/tls_client.cpp | 49 | ||||
-rw-r--r-- | src/ssl/tls_client.h | 2 | ||||
-rw-r--r-- | src/ssl/tls_record.h | 31 | ||||
-rw-r--r-- | src/ssl/tls_server.cpp | 25 | ||||
-rw-r--r-- | src/ssl/tls_server.h | 2 |
6 files changed, 132 insertions, 45 deletions
diff --git a/src/ssl/rec_read.cpp b/src/ssl/rec_read.cpp index 95059dbf2..ad28b2dd8 100644 --- a/src/ssl/rec_read.cpp +++ b/src/ssl/rec_read.cpp @@ -1,6 +1,6 @@ /** -* TLS Record Reading -* (C) 2004-2006 Jack Lloyd +* TLS Record Reading +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -13,14 +13,6 @@ namespace Botan { /** -* Record_Reader Constructor -*/ -Record_Reader::Record_Reader(Socket& sock) : socket(sock) - { - reset(); - } - -/** * Reset the state */ void Record_Reader::reset() @@ -112,37 +104,57 @@ void Record_Reader::set_keys(const CipherSuite& suite, const SessionKeys& keys, throw Invalid_Argument("Record_Reader: Unknown hash " + mac_algo); } +void Record_Reader::add_input(const byte input[], u32bit input_size) + { + input_queue.write(input, input_size); + } + /** * Retrieve the next record */ -SecureVector<byte> Record_Reader::get_record(byte& msg_type) +u32bit Record_Reader::get_record(byte& msg_type, + MemoryRegion<byte>& output) { byte header[5] = { 0 }; - u32bit got = socket.read(header, sizeof(header)); + const u32bit have_in_queue = input_queue.size(); - if(got == 0) - { - msg_type = CONNECTION_CLOSED; - return SecureVector<byte>(); - } - else if(got != sizeof(header)) - throw Decoding_Error("Record_Reader: Record truncated"); + if(have_in_queue < sizeof(header)) + return (sizeof(header) - have_in_queue); - msg_type = header[0]; + /* + * We peek first to make sure we have the full record + */ + input_queue.peek(header, sizeof(header)); - const u16bit version = make_u16bit(header[1], header[2]); + const u16bit version = make_u16bit(header[1], header[2]); + const u16bit record_len = make_u16bit(header[3], header[4]); if(major && (header[1] != major || header[2] != minor)) throw TLS_Exception(PROTOCOL_VERSION, "Record_Reader: Got unexpected version"); - SecureVector<byte> buffer(make_u16bit(header[3], header[4])); - if(socket.read(buffer, buffer.size()) != buffer.size()) - throw Decoding_Error("Record_Reader: Record truncated"); + // If insufficient data, return without doing anything + if(have_in_queue < (sizeof(header) + record_len)) + return (sizeof(header) + record_len - have_in_queue); + + SecureVector<byte> buffer(record_len); + + input_queue.read(header, sizeof(header)); // pull off the header + input_queue.read(buffer, buffer.size()); + /* + * We are handshaking, no crypto to do so return as-is + * TODO: Check msg_type to confirm a handshake? + */ if(mac_size == 0) - return buffer; + { + msg_type = header[0]; + output = buffer; + return 0; // got a full record + } + + // Otherwise, decrypt, check MAC, return plaintext cipher.process_msg(buffer); SecureVector<byte> plaintext = cipher.read_all(Pipe::LAST_MESSAGE); @@ -180,7 +192,7 @@ SecureVector<byte> Record_Reader::get_record(byte& msg_type) mac.start_msg(); for(u32bit j = 0; j != 8; j++) mac.write(get_byte(j, seq_no)); - mac.write(msg_type); + mac.write(header[0]); // msg_type if(version != SSL_V3) for(u32bit j = 0; j != 2; j++) @@ -198,7 +210,9 @@ SecureVector<byte> Record_Reader::get_record(byte& msg_type) if(recieved_mac != computed_mac) throw TLS_Exception(BAD_RECORD_MAC, "Record_Reader: MAC failure"); - return SecureVector<byte>(plaintext, mac_offset); + msg_type = header[0]; + output.set(plaintext, mac_offset); + return 0; } } diff --git a/src/ssl/tls_client.cpp b/src/ssl/tls_client.cpp index ce33573f5..783cd39cf 100644 --- a/src/ssl/tls_client.cpp +++ b/src/ssl/tls_client.cpp @@ -1,6 +1,6 @@ /** -* TLS Client -* (C) 2004-2006 Jack Lloyd +* TLS Client +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -83,7 +83,7 @@ void client_check_state(Handshake_Type new_msg, Handshake_State* state) */ TLS_Client::TLS_Client(RandomNumberGenerator& r, Socket& sock, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -96,7 +96,7 @@ TLS_Client::TLS_Client(RandomNumberGenerator& r, TLS_Client::TLS_Client(RandomNumberGenerator& r, Socket& sock, const X509_Certificate& cert, const Private_Key& key, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -133,10 +133,12 @@ void TLS_Client::initialize() } catch(TLS_Exception& e) { + printf("Handshake exception %s\n", e.what()); error_type = e.type(); } catch(std::exception& e) { + printf("Handshake exception %s\n", e.what()); error_type = HANDSHAKE_FAILURE; } @@ -243,11 +245,32 @@ void TLS_Client::close(Alert_Level level, Alert_Type alert_code) */ void TLS_Client::state_machine() { - byte rec_type; - SecureVector<byte> record = reader.get_record(rec_type); + byte rec_type = CONNECTION_CLOSED; + SecureVector<byte> record(1024); + + u32bit bytes_needed = reader.get_record(rec_type, record); + + while(bytes_needed) + { + u32bit to_get = std::min<u32bit>(record.size(), bytes_needed); + u32bit got = peer.read(&record[0], to_get); + + if(got == 0) + { + rec_type = CONNECTION_CLOSED; + break; + } + + reader.add_input(&record[0], got); + + bytes_needed = reader.get_record(rec_type, record); + } + + printf("state_machine %d\n", rec_type); if(rec_type == CONNECTION_CLOSED) { + printf("CLOSED\n"); active = false; reader.reset(); writer.reset(); @@ -270,6 +293,8 @@ void TLS_Client::state_machine() if(alert.type() == CLOSE_NOTIFY) writer.alert(WARNING, CLOSE_NOTIFY); + printf("ALERT\n"); + reader.reset(); writer.reset(); active = false; @@ -321,7 +346,10 @@ void TLS_Client::read_handshake(byte rec_type, if(state->queue.size() == 0 && rec_buf.size() == 1 && rec_buf[0] == 1) type = HANDSHAKE_CCS; else + { + printf("Bad CCS message? %d\n", state->queue.size()); throw Decoding_Error("Malformed ChangeCipherSpec message"); + } } else throw Decoding_Error("Unknown message type in handshake processing"); @@ -342,6 +370,8 @@ void TLS_Client::read_handshake(byte rec_type, void TLS_Client::process_handshake_msg(Handshake_Type type, const MemoryRegion<byte>& contents) { + printf("process_handshake_msg(%d)\n", type); + if(type == HELLO_REQUEST) { if(state == 0) @@ -524,13 +554,18 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, } else if(type == HANDSHAKE_CCS) { + printf("In process_handshake_msg\n"); + client_check_state(type, state); + printf("Setting keys\n"); reader.set_keys(state->suite, state->keys, CLIENT); + printf("Done with keys\n"); state->got_server_ccs = true; } else if(type == FINISHED) { + printf("Checking finished message\n"); client_check_state(type, state); state->server_finished = new Finished(contents); @@ -562,7 +597,7 @@ void TLS_Client::do_handshake() if(active && !state) break; if(!active && !state) - throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed"); + throw TLS_Exception(HANDSHAKE_FAILURE, "TLS_Client: Handshake failed (do_handshake)"); state_machine(); } diff --git a/src/ssl/tls_client.h b/src/ssl/tls_client.h index 896decdf9..2439a58f0 100644 --- a/src/ssl/tls_client.h +++ b/src/ssl/tls_client.h @@ -60,6 +60,8 @@ class BOTAN_DLL TLS_Client : public TLS_Connection RandomNumberGenerator& rng; + Socket& peer; + Record_Writer writer; Record_Reader reader; const TLS_Policy* policy; diff --git a/src/ssl/tls_record.h b/src/ssl/tls_record.h index 3bec2e8ef..fa6ed2d17 100644 --- a/src/ssl/tls_record.h +++ b/src/ssl/tls_record.h @@ -1,6 +1,6 @@ /** -* TLS Record Handling -* (C) 2004-2006 Jack Lloyd +* TLS Record Handling +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ @@ -12,6 +12,7 @@ #include <botan/socket.h> #include <botan/tls_suites.h> #include <botan/pipe.h> +#include <botan/secqueue.h> #include <vector> namespace Botan { @@ -55,18 +56,32 @@ class BOTAN_DLL Record_Writer class BOTAN_DLL Record_Reader { public: - SecureVector<byte> get_record(byte&); + void add_input(const byte input[], u32bit input_size); - void set_keys(const CipherSuite&, const SessionKeys&, Connection_Side); - void set_compressor(Filter*); + /** + * @param msg_type (output variable) + * @param buffer (output variable) + * @return Number of bytes still needed (minimum), or 0 if success + */ + u32bit get_record(byte& msg_type, + MemoryRegion<byte>& buffer); - void set_version(Version_Code); + SecureVector<byte> get_record(byte& msg_type); + + void set_keys(const CipherSuite& suite, + const SessionKeys& keys, + Connection_Side side); + + void set_compressor(Filter* compressor); + + void set_version(Version_Code version); void reset(); - Record_Reader(Socket&); + Record_Reader() { reset(); } private: - Socket& socket; + SecureQueue input_queue; + Pipe compress, cipher, mac; u32bit pad_amount, mac_size; u64bit seq_no; diff --git a/src/ssl/tls_server.cpp b/src/ssl/tls_server.cpp index 37d9dbcd1..8d33fca64 100644 --- a/src/ssl/tls_server.cpp +++ b/src/ssl/tls_server.cpp @@ -88,7 +88,8 @@ void server_check_state(Handshake_Type new_msg, Handshake_State* state) TLS_Server::TLS_Server(RandomNumberGenerator& r, Socket& sock, const X509_Certificate& cert, const Private_Key& key, const TLS_Policy* pol) : - rng(r), writer(sock), reader(sock), policy(pol ? pol : new TLS_Policy) + rng(r), peer(sock), + writer(sock), policy(pol ? pol : new TLS_Policy) { peer_id = sock.peer_id(); @@ -207,8 +208,26 @@ void TLS_Server::close(Alert_Level level, Alert_Type alert_code) */ void TLS_Server::state_machine() { - byte rec_type; - SecureVector<byte> record = reader.get_record(rec_type); + byte rec_type = CONNECTION_CLOSED; + SecureVector<byte> record(1024); + + u32bit bytes_needed = reader.get_record(rec_type, record); + + while(bytes_needed) + { + u32bit to_get = std::min<u32bit>(record.size(), bytes_needed); + u32bit got = peer.read(&record[0], to_get); + + if(got == 0) + { + rec_type = CONNECTION_CLOSED; + break; + } + + reader.add_input(&record[0], got); + + bytes_needed = reader.get_record(rec_type, record); + } if(rec_type == CONNECTION_CLOSED) { diff --git a/src/ssl/tls_server.h b/src/ssl/tls_server.h index 683c3413a..3f4ff6473 100644 --- a/src/ssl/tls_server.h +++ b/src/ssl/tls_server.h @@ -49,6 +49,8 @@ class BOTAN_DLL TLS_Server : public TLS_Connection RandomNumberGenerator& rng; + Socket& peer; + Record_Writer writer; Record_Reader reader; const TLS_Policy* policy; |