aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-03-23 22:12:53 +0000
committerlloyd <[email protected]>2010-03-23 22:12:53 +0000
commit7479e66bb43e843c067e9a45145bafc84bdd41dc (patch)
treedcbd947508ab3bd8182816677d7d0d94edbf84c6 /src
parent8fda37bf5b79bf6569e1e375c48e9d74171cb141 (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')
-rw-r--r--src/ssl/rec_read.cpp68
-rw-r--r--src/ssl/tls_client.cpp49
-rw-r--r--src/ssl/tls_client.h2
-rw-r--r--src/ssl/tls_record.h31
-rw-r--r--src/ssl/tls_server.cpp25
-rw-r--r--src/ssl/tls_server.h2
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;