aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2011-12-28 22:39:18 +0000
committerlloyd <[email protected]>2011-12-28 22:39:18 +0000
commiteb6b59f2aef6a4999be244c7d90ace3f6bbcac5d (patch)
tree7b15e8034769e1a9d57335e1fb0259167299fcc6 /src
parentb48a5b800a00e955cada6c418848c3bc460e44e7 (diff)
Don't buffer in the record writer at all - we immediately process and
send out inputs as they are available. Thus, flushing is never required, and we avoid some unnecessary copying. If we are using a CBC mode cipher in SSLv3/TLSv1.0, send a 1-byte fragment to start to prevent the adaptive plaintext attack.
Diffstat (limited to 'src')
-rw-r--r--src/tls/hello.cpp1
-rw-r--r--src/tls/rec_wri.cpp76
-rw-r--r--src/tls/tls_channel.cpp2
-rw-r--r--src/tls/tls_client.cpp1
-rw-r--r--src/tls/tls_record.h12
-rw-r--r--src/tls/tls_server.cpp2
-rw-r--r--src/utils/rounding.h12
7 files changed, 42 insertions, 64 deletions
diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp
index 45eedbd76..510aabb3a 100644
--- a/src/tls/hello.cpp
+++ b/src/tls/hello.cpp
@@ -32,7 +32,6 @@ void HandshakeMessage::send(Record_Writer& writer, TLS_Handshake_Hash& hash) con
hash.update(send_buf);
writer.send(HANDSHAKE, &send_buf[0], send_buf.size());
- writer.flush();
}
/*
diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp
index ade2bd2d6..336c18ab4 100644
--- a/src/tls/rec_wri.cpp
+++ b/src/tls/rec_wri.cpp
@@ -22,7 +22,7 @@ namespace Botan {
Record_Writer::Record_Writer(std::tr1::function<void (const byte[], size_t)> out,
size_t max_fragment) :
output_fn(out),
- buffer(max_fragment ? max_fragment : static_cast<size_t>(MAX_PLAINTEXT_SIZE))
+ max_fragment(clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE))
{
mac = 0;
reset();
@@ -38,10 +38,7 @@ void Record_Writer::reset()
delete mac;
mac = 0;
- zeroise(buffer);
- buf_pos = 0;
-
- major = minor = buf_type = 0;
+ major = minor = 0;
block_size = 0;
mac_size = 0;
iv_size = 0;
@@ -134,51 +131,35 @@ void Record_Writer::set_keys(const CipherSuite& suite,
*/
void Record_Writer::send(byte type, const byte input[], size_t length)
{
- if(type != buf_type)
- flush();
-
- const size_t BUFFER_SIZE = buffer.size();
- buf_type = type;
-
- // FIXME: compression right here
-
- buffer.copy(buf_pos, input, length);
- if(buf_pos + length >= BUFFER_SIZE)
+ if(length == 0)
+ return;
+
+ /*
+ * If using CBC mode in SSLv3/TLS1.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, this isn't
+ * necessary.
+ *
+ * An empty record also works but apparently some implementations do
+ * not like this.
+ *
+ * See http://www.openssl.org/~bodo/tls-cbc.txt for background.
+ */
+ if((block_size > 0) && (iv_size == 0))
{
- send_record(buf_type, &buffer[0], length);
- input += (BUFFER_SIZE - buf_pos);
- length -= (BUFFER_SIZE - buf_pos);
- while(length >= BUFFER_SIZE)
- {
- send_record(buf_type, input, BUFFER_SIZE);
- input += BUFFER_SIZE;
- length -= BUFFER_SIZE;
- }
- buffer.copy(input, length);
- buf_pos = 0;
+ send_record(type, &input[0], 1);
+ input += 1;
+ length -= 1;
}
- buf_pos += length;
- }
-/*
-* Split buffer into records, and send them all
-*/
-void Record_Writer::flush()
- {
- const byte* buf_ptr = &buffer[0];
- size_t offset = 0;
-
- while(offset != buf_pos)
+ while(length)
{
- size_t record_size = buf_pos - offset;
- if(record_size > MAX_PLAINTEXT_SIZE)
- record_size = MAX_PLAINTEXT_SIZE;
+ const size_t sending = std::min(length, max_fragment);
+ send_record(type, &input[0], sending);
- send_record(buf_type, buf_ptr + offset, record_size);
- offset += record_size;
+ input += sending;
+ length -= sending;
}
- buf_type = 0;
- buf_pos = 0;
}
/*
@@ -186,16 +167,12 @@ void Record_Writer::flush()
*/
void Record_Writer::send_record(byte type, const byte input[], size_t length)
{
- if(length >= MAX_COMPRESSED_SIZE)
+ if(length >= MAX_PLAINTEXT_SIZE)
throw TLS_Exception(INTERNAL_ERROR,
"Record_Writer: Compressed packet is too big");
if(mac_size == 0)
{
- if(length >= MAX_CIPHERTEXT_SIZE)
- throw TLS_Exception(INTERNAL_ERROR,
- "Record_Writer: Record is too big");
-
const byte header[5] = {
type,
major,
@@ -285,7 +262,6 @@ void Record_Writer::alert(Alert_Level level, Alert_Type type)
{
byte alert[2] = { level, type };
send(ALERT, alert, sizeof(alert));
- flush();
}
}
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
index 553f65836..96d08a5f4 100644
--- a/src/tls/tls_channel.cpp
+++ b/src/tls/tls_channel.cpp
@@ -166,7 +166,6 @@ void TLS_Channel::queue_for_sending(const byte buf[], size_t buf_size)
}
writer.send(APPLICATION_DATA, buf, buf_size);
- writer.flush();
}
else
pre_handshake_write_queue.write(buf, buf_size);
@@ -179,7 +178,6 @@ void TLS_Channel::alert(Alert_Level alert_level, Alert_Type alert_code)
try
{
writer.alert(alert_level, alert_code);
- writer.flush();
}
catch(...) { /* swallow it */ }
}
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 5dbcadaea..b58a6766f 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -236,7 +236,6 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
state->server_hello->random());
writer.send(CHANGE_CIPHER_SPEC, 1);
- writer.flush();
writer.set_keys(state->suite, state->keys, CLIENT);
diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h
index d2dbdf596..51a7cd310 100644
--- a/src/tls/tls_record.h
+++ b/src/tls/tls_record.h
@@ -43,8 +43,6 @@ class BOTAN_DLL Record_Writer
void send(byte type, const byte input[], size_t length);
void send(byte type, byte val) { send(type, &val, 1); }
- void flush();
-
void alert(Alert_Level level, Alert_Type type);
void set_keys(const CipherSuite& suite,
@@ -56,23 +54,21 @@ class BOTAN_DLL Record_Writer
void reset();
Record_Writer(std::tr1::function<void (const byte[], size_t)> output_fn,
- size_t max_fragment = 0);
+ size_t max_fragment = MAX_PLAINTEXT_SIZE);
~Record_Writer() { delete mac; }
private:
void send_record(byte type, const byte input[], size_t length);
std::tr1::function<void (const byte[], size_t)> output_fn;
+
Pipe cipher;
MessageAuthenticationCode* mac;
- SecureVector<byte> buffer;
- size_t buf_pos;
-
- size_t block_size, mac_size, iv_size;
+ size_t block_size, mac_size, iv_size, max_fragment;
u64bit seq_no;
- byte major, minor, buf_type;
+ byte major, minor;
};
/**
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index a22e6854e..16bf554d3 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -184,7 +184,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
true);
writer.send(CHANGE_CIPHER_SPEC, 1);
- writer.flush();
writer.set_keys(state->suite, state->keys, SERVER);
@@ -337,7 +336,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
state->hash.update(type, contents);
writer.send(CHANGE_CIPHER_SPEC, 1);
- writer.flush();
writer.set_keys(state->suite, state->keys, SERVER);
diff --git a/src/utils/rounding.h b/src/utils/rounding.h
index 78b9eeb5d..4ddd7a432 100644
--- a/src/utils/rounding.h
+++ b/src/utils/rounding.h
@@ -44,6 +44,18 @@ inline T round_down(T n, T align_to)
return (n - (n % align_to));
}
+/**
+* Clamp
+*/
+inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound)
+ {
+ if(n < lower_bound)
+ return lower_bound;
+ if(n > upper_bound)
+ return upper_bound;
+ return n;
+ }
+
}
#endif