aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-09-06 14:06:47 +0000
committerlloyd <[email protected]>2012-09-06 14:06:47 +0000
commit94fec1bb0293cf1c5ae7ddcb8d53f21a3edb58ae (patch)
tree431a11d77ff88133652905e8de698515cadb51f1 /src/tls
parentbbc108d963e5d5e2424e564bb076a7ae4e5ad46f (diff)
Move the actual creation of new TLS records to TLS::write_record which
is side effect free (besides updating CBC state).
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/rec_wri.cpp129
-rw-r--r--src/tls/tls_record.cpp119
-rw-r--r--src/tls/tls_record.h10
3 files changed, 142 insertions, 116 deletions
diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp
index 5b75ccf6f..33edbfb2f 100644
--- a/src/tls/rec_wri.cpp
+++ b/src/tls/rec_wri.cpp
@@ -6,13 +6,9 @@
*/
#include <botan/tls_record.h>
-#include <botan/internal/tls_messages.h>
+#include <botan/tls_magic.h>
#include <botan/internal/tls_session_key.h>
-#include <botan/internal/tls_handshake_hash.h>
#include <botan/internal/rounding.h>
-#include <botan/internal/assert.h>
-#include <botan/internal/xor_buf.h>
-#include <botan/loadstor.h>
namespace Botan {
@@ -103,7 +99,7 @@ void Record_Writer::send_array(byte type, const byte input[], size_t length)
*
* See http://www.openssl.org/~bodo/tls-cbc.txt for background.
*/
- if((type == APPLICATION) &&
+ if((type == APPLICATION_DATA) &&
(m_write_cipherstate->block_size() > 0) &&
(m_write_cipherstate->iv_size() == 0))
{
@@ -130,116 +126,17 @@ void Record_Writer::send_record(byte type, const byte input[], size_t length)
if(length >= MAX_PLAINTEXT_SIZE)
throw Internal_Error("Record_Writer: Compressed packet is too big");
- if(!m_write_cipherstate) // initial unencrypted handshake records
- {
- m_writebuf[0] = type;
- m_writebuf[1] = m_version.major_version();
- m_writebuf[2] = m_version.minor_version();
- m_writebuf[3] = get_byte<u16bit>(0, length);
- m_writebuf[4] = get_byte<u16bit>(1, length);
-
- copy_mem(&m_writebuf[TLS_HEADER_SIZE], input, length);
-
- m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + length);
- return;
- }
-
- m_write_cipherstate->mac()->update_be(m_write_seq_no);
- m_write_cipherstate->mac()->update(type);
-
- if(m_version != Protocol_Version::SSL_V3)
- {
- m_write_cipherstate->mac()->update(m_version.major_version());
- m_write_cipherstate->mac()->update(m_version.minor_version());
- }
-
- m_write_cipherstate->mac()->update(get_byte<u16bit>(0, length));
- m_write_cipherstate->mac()->update(get_byte<u16bit>(1, length));
- m_write_cipherstate->mac()->update(input, length);
-
- const size_t block_size = m_write_cipherstate->block_size();
- const size_t iv_size = m_write_cipherstate->iv_size();
- const size_t mac_size = m_write_cipherstate->mac_size();
-
- const size_t buf_size = round_up(
- iv_size + length + mac_size + (block_size ? 1 : 0),
- block_size);
-
- if(buf_size >= MAX_CIPHERTEXT_SIZE)
- throw Internal_Error("Record_Writer: Record is too big");
-
- BOTAN_ASSERT(m_writebuf.size() >= TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE,
- "Write buffer is big enough");
-
- // TLS record header
- m_writebuf[0] = type;
- m_writebuf[1] = m_version.major_version();
- m_writebuf[2] = m_version.minor_version();
- m_writebuf[3] = get_byte<u16bit>(0, buf_size);
- m_writebuf[4] = get_byte<u16bit>(1, buf_size);
-
- byte* buf_write_ptr = &m_writebuf[TLS_HEADER_SIZE];
-
- if(iv_size)
- {
- m_rng.randomize(buf_write_ptr, iv_size);
- buf_write_ptr += iv_size;
- }
-
- copy_mem(buf_write_ptr, input, length);
- buf_write_ptr += length;
-
- m_write_cipherstate->mac()->final(buf_write_ptr);
- buf_write_ptr += mac_size;
-
- if(block_size)
- {
- const size_t pad_val =
- buf_size - (iv_size + length + mac_size + 1);
-
- for(size_t i = 0; i != pad_val + 1; ++i)
- {
- *buf_write_ptr = pad_val;
- buf_write_ptr += 1;
- }
- }
-
- if(buf_size > MAX_CIPHERTEXT_SIZE)
- throw Internal_Error("Produced ciphertext larger than protocol allows");
-
- if(StreamCipher* sc = m_write_cipherstate->stream_cipher())
- {
- sc->cipher1(&m_writebuf[TLS_HEADER_SIZE], buf_size);
- }
- else if(BlockCipher* bc = m_write_cipherstate->block_cipher())
- {
- secure_vector<byte>& cbc_state = m_write_cipherstate->cbc_state();
-
- BOTAN_ASSERT(buf_size % block_size == 0,
- "Buffer is an even multiple of block size");
-
- byte* buf = &m_writebuf[TLS_HEADER_SIZE];
-
- const size_t blocks = buf_size / block_size;
-
- xor_buf(&buf[0], &cbc_state[0], block_size);
- bc->encrypt(&buf[0]);
-
- for(size_t i = 1; i <= blocks; ++i)
- {
- xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size);
- bc->encrypt(&buf[block_size*i]);
- }
-
- cbc_state.assign(&buf[block_size*(blocks-1)],
- &buf[block_size*blocks]);
- }
- else
- throw Internal_Error("NULL cipher not supported");
-
- m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + buf_size);
-
- m_write_seq_no++;
+ const size_t written = write_record(m_writebuf,
+ type,
+ input,
+ length,
+ m_write_seq_no,
+ m_version,
+ m_write_cipherstate.get(),
+ m_rng);
+
+ m_write_seq_no += 1;
+ m_output_fn(&m_writebuf[0], written);
}
}
diff --git a/src/tls/tls_record.cpp b/src/tls/tls_record.cpp
index d8d25448f..58aa5bfc9 100644
--- a/src/tls/tls_record.cpp
+++ b/src/tls/tls_record.cpp
@@ -8,6 +8,9 @@
#include <botan/tls_record.h>
#include <botan/internal/tls_session_key.h>
#include <botan/libstate.h>
+#include <botan/internal/rounding.h>
+#include <botan/internal/assert.h>
+#include <botan/internal/xor_buf.h>
namespace Botan {
@@ -70,6 +73,122 @@ Connection_Cipher_State::Connection_Cipher_State(
m_mac->set_key(mac_key);
}
+size_t write_record(std::vector<byte>& output,
+ byte msg_type, const byte msg[], size_t msg_length,
+ u64bit msg_sequence_number,
+ Protocol_Version version,
+ Connection_Cipher_State* cipherstate,
+ RandomNumberGenerator& rng)
+ {
+ BOTAN_ASSERT(output.size() >= TLS_HEADER_SIZE + msg_length,
+ "Write buffer is big enough");
+
+ output[0] = msg_type;
+ output[1] = version.major_version();
+ output[2] = version.minor_version();
+
+ if(!cipherstate) // initial unencrypted handshake records
+ {
+ output[3] = get_byte<u16bit>(0, msg_length);
+ output[4] = get_byte<u16bit>(1, msg_length);
+
+ copy_mem(&output[TLS_HEADER_SIZE], msg, msg_length);
+
+ return (TLS_HEADER_SIZE + msg_length);
+ }
+
+ cipherstate->mac()->update_be(msg_sequence_number);
+ cipherstate->mac()->update(msg_type);
+
+ if(version != Protocol_Version::SSL_V3)
+ {
+ cipherstate->mac()->update(version.major_version());
+ cipherstate->mac()->update(version.minor_version());
+ }
+
+ cipherstate->mac()->update(get_byte<u16bit>(0, msg_length));
+ cipherstate->mac()->update(get_byte<u16bit>(1, msg_length));
+ cipherstate->mac()->update(msg, msg_length);
+
+ const size_t block_size = cipherstate->block_size();
+ const size_t iv_size = cipherstate->iv_size();
+ const size_t mac_size = cipherstate->mac_size();
+
+ const size_t buf_size = round_up(
+ iv_size + msg_length + mac_size + (block_size ? 1 : 0),
+ block_size);
+
+ if(buf_size >= MAX_CIPHERTEXT_SIZE)
+ throw Internal_Error("Record_Writer: Record is too big");
+
+ BOTAN_ASSERT(output.size() >= TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE,
+ "Write buffer is big enough");
+
+ output[3] = get_byte<u16bit>(0, buf_size);
+ output[4] = get_byte<u16bit>(1, buf_size);
+
+ byte* buf_write_ptr = &output[TLS_HEADER_SIZE];
+
+ if(iv_size)
+ {
+ rng.randomize(buf_write_ptr, iv_size);
+ buf_write_ptr += iv_size;
+ }
+
+ copy_mem(buf_write_ptr, msg, msg_length);
+ buf_write_ptr += msg_length;
+
+ cipherstate->mac()->final(buf_write_ptr);
+ buf_write_ptr += mac_size;
+
+ if(block_size)
+ {
+ const size_t pad_val =
+ buf_size - (iv_size + msg_length + mac_size + 1);
+
+ for(size_t i = 0; i != pad_val + 1; ++i)
+ {
+ *buf_write_ptr = pad_val;
+ buf_write_ptr += 1;
+ }
+ }
+
+ if(buf_size > MAX_CIPHERTEXT_SIZE)
+ throw Internal_Error("Produced ciphertext larger than protocol allows");
+
+ if(StreamCipher* sc = cipherstate->stream_cipher())
+ {
+ sc->cipher1(&output[TLS_HEADER_SIZE], buf_size);
+ }
+ else if(BlockCipher* bc = cipherstate->block_cipher())
+ {
+ secure_vector<byte>& cbc_state = cipherstate->cbc_state();
+
+ BOTAN_ASSERT(buf_size % block_size == 0,
+ "Buffer is an even multiple of block size");
+
+ byte* buf = &output[TLS_HEADER_SIZE];
+
+ const size_t blocks = buf_size / block_size;
+
+ xor_buf(&buf[0], &cbc_state[0], block_size);
+ bc->encrypt(&buf[0]);
+
+ for(size_t i = 1; i <= blocks; ++i)
+ {
+ xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size);
+ bc->encrypt(&buf[block_size*i]);
+ }
+
+ cbc_state.assign(&buf[block_size*(blocks-1)],
+ &buf[block_size*blocks]);
+ }
+ else
+ throw Internal_Error("NULL cipher not supported");
+
+ return (TLS_HEADER_SIZE + buf_size);
+ }
+
}
}
diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h
index d23fe1e39..90b03531d 100644
--- a/src/tls/tls_record.h
+++ b/src/tls/tls_record.h
@@ -67,6 +67,16 @@ class Connection_Cipher_State
};
/**
+* Create a TLS record
+*/
+size_t write_record(std::vector<byte>& write_buffer,
+ byte msg_type, const byte msg[], size_t msg_length,
+ u64bit msg_sequence_number,
+ Protocol_Version version,
+ Connection_Cipher_State* cipherstate,
+ RandomNumberGenerator& rng);
+
+/**
* TLS Record Writer
*/
class BOTAN_DLL Record_Writer