diff options
author | lloyd <[email protected]> | 2012-09-06 14:06:47 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-09-06 14:06:47 +0000 |
commit | 94fec1bb0293cf1c5ae7ddcb8d53f21a3edb58ae (patch) | |
tree | 431a11d77ff88133652905e8de698515cadb51f1 /src/tls | |
parent | bbc108d963e5d5e2424e564bb076a7ae4e5ad46f (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.cpp | 129 | ||||
-rw-r--r-- | src/tls/tls_record.cpp | 119 | ||||
-rw-r--r-- | src/tls/tls_record.h | 10 |
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 |