aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/rec_wri.cpp
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/tls/rec_wri.cpp
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/tls/rec_wri.cpp')
-rw-r--r--src/tls/rec_wri.cpp76
1 files changed, 26 insertions, 50 deletions
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();
}
}