diff options
Diffstat (limited to 'src/tls/rec_wri.cpp')
-rw-r--r-- | src/tls/rec_wri.cpp | 180 |
1 files changed, 104 insertions, 76 deletions
diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index fdcb98cc9..cc7c6f79a 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -6,6 +6,7 @@ */ #include <botan/tls_record.h> +#include <botan/internal/tls_messages.h> #include <botan/internal/tls_session_key.h> #include <botan/internal/tls_handshake_hash.h> #include <botan/lookup.h> @@ -16,6 +17,8 @@ namespace Botan { +namespace TLS { + /* * Record_Writer Constructor */ @@ -46,8 +49,7 @@ void Record_Writer::reset() delete m_mac; m_mac = 0; - m_major = 0; - m_minor = 0; + m_version = Protocol_Version(); m_block_size = 0; m_mac_size = 0; m_iv_size = 0; @@ -58,26 +60,26 @@ void Record_Writer::reset() /* * Set the version to use */ -void Record_Writer::set_version(Version_Code version) +void Record_Writer::set_version(Protocol_Version version) { - if(version != SSL_V3 && version != TLS_V10 && version != TLS_V11) - throw Invalid_Argument("Record_Writer: Invalid protocol version"); - - m_major = (version >> 8) & 0xFF; - m_minor = (version & 0xFF); + m_version = version; } /* * Set the keys for writing */ -void Record_Writer::activate(const TLS_Cipher_Suite& suite, - const SessionKeys& keys, - Connection_Side side) +void Record_Writer::activate(Connection_Side side, + const Ciphersuite& suite, + const Session_Keys& keys, + byte compression_method) { m_cipher.reset(); delete m_mac; m_mac = 0; + if(compression_method != NO_COMPRESSION) + throw Internal_Error("Negotiated unknown compression algorithm"); + /* RFC 4346: A sequence number is incremented after each record: specifically, @@ -113,7 +115,7 @@ void Record_Writer::activate(const TLS_Cipher_Suite& suite, ); m_block_size = block_size_of(cipher_algo); - if(m_major > 3 || (m_major == 3 && m_minor >= 2)) + if(m_version >= Protocol_Version::TLS_V11) m_iv_size = m_block_size; else m_iv_size = 0; @@ -131,7 +133,7 @@ void Record_Writer::activate(const TLS_Cipher_Suite& suite, { Algorithm_Factory& af = global_state().algorithm_factory(); - if(m_major == 3 && m_minor == 0) + if(m_version == Protocol_Version::SSL_V3) m_mac = af.make_mac("SSL3-MAC(" + mac_algo + ")"); else m_mac = af.make_mac("HMAC(" + mac_algo + ")"); @@ -143,6 +145,25 @@ void Record_Writer::activate(const TLS_Cipher_Suite& suite, throw Invalid_Argument("Record_Writer: Unknown hash " + mac_algo); } +MemoryVector<byte> Record_Writer::send(Handshake_Message& msg) + { + const MemoryVector<byte> buf = msg.serialize(); + MemoryVector<byte> send_buf(4); + + const size_t buf_size = buf.size(); + + send_buf[0] = msg.type(); + + for(size_t i = 1; i != 4; ++i) + send_buf[i] = get_byte<u32bit>(i, buf_size); + + send_buf += buf; + + send(HANDSHAKE, &send_buf[0], send_buf.size()); + + return send_buf; + } + /* * Send one or more records to the other side */ @@ -185,105 +206,112 @@ void Record_Writer::send(byte type, const byte input[], size_t length) void Record_Writer::send_record(byte type, const byte input[], size_t length) { if(length >= MAX_PLAINTEXT_SIZE) - throw TLS_Exception(INTERNAL_ERROR, - "Record_Writer: Compressed packet is too big"); + throw Internal_Error("Record_Writer: Compressed packet is too big"); - if(m_mac_size == 0) + if(m_mac_size == 0) // initial unencrypted handshake records { const byte header[TLS_HEADER_SIZE] = { type, - m_major, - m_minor, + m_version.major_version(), + m_version.minor_version(), get_byte<u16bit>(0, length), get_byte<u16bit>(1, length) }; m_output_fn(header, TLS_HEADER_SIZE); m_output_fn(input, length); + return; } - else + + m_mac->update_be(m_seq_no); + m_mac->update(type); + + if(m_version != Protocol_Version::SSL_V3) { - m_mac->update_be(m_seq_no); - m_mac->update(type); + m_mac->update(m_version.major_version()); + m_mac->update(m_version.minor_version()); + } - if(m_major > 3 || (m_major == 3 && m_minor != 0)) - { - m_mac->update(m_major); - m_mac->update(m_minor); - } + m_mac->update(get_byte<u16bit>(0, length)); + m_mac->update(get_byte<u16bit>(1, length)); + m_mac->update(input, length); - m_mac->update(get_byte<u16bit>(0, length)); - m_mac->update(get_byte<u16bit>(1, length)); - m_mac->update(input, length); + const size_t buf_size = round_up(m_iv_size + length + + m_mac->output_length() + + (m_block_size ? 1 : 0), + m_block_size); - const size_t buf_size = round_up(m_iv_size + length + - m_mac->output_length() + - (m_block_size ? 1 : 0), - m_block_size); + if(buf_size >= MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Record_Writer: Record is too big"); - if(buf_size >= MAX_CIPHERTEXT_SIZE) - throw TLS_Exception(INTERNAL_ERROR, - "Record_Writer: Record is too big"); + BOTAN_ASSERT(m_writebuf.size() >= TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE, + "Write buffer is big enough"); - 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); - // TLS record header - m_writebuf[0] = type; - m_writebuf[1] = m_major; - m_writebuf[2] = m_minor; - 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]; - byte* buf_write_ptr = &m_writebuf[TLS_HEADER_SIZE]; + if(m_iv_size) + { + RandomNumberGenerator& rng = global_state().global_rng(); + rng.randomize(buf_write_ptr, m_iv_size); + buf_write_ptr += m_iv_size; + } - if(m_iv_size) - { - RandomNumberGenerator& rng = global_state().global_rng(); - rng.randomize(buf_write_ptr, m_iv_size); - buf_write_ptr += m_iv_size; - } + copy_mem(buf_write_ptr, input, length); + buf_write_ptr += length; - copy_mem(buf_write_ptr, input, length); - buf_write_ptr += length; + m_mac->final(buf_write_ptr); + buf_write_ptr += m_mac->output_length(); - m_mac->final(buf_write_ptr); - buf_write_ptr += m_mac->output_length(); + if(m_block_size) + { + const size_t pad_val = + buf_size - (m_iv_size + length + m_mac->output_length() + 1); - if(m_block_size) + for(size_t i = 0; i != pad_val + 1; ++i) { - const size_t pad_val = - buf_size - (m_iv_size + length + m_mac->output_length() + 1); - - for(size_t i = 0; i != pad_val + 1; ++i) - { - *buf_write_ptr = pad_val; - buf_write_ptr += 1; - } + *buf_write_ptr = pad_val; + buf_write_ptr += 1; } + } - // FIXME: this could be done in-place without copying - m_cipher.process_msg(&m_writebuf[TLS_HEADER_SIZE], buf_size); - const size_t got_back = m_cipher.read(&m_writebuf[TLS_HEADER_SIZE], buf_size, Pipe::LAST_MESSAGE); + // FIXME: this could be done in-place without copying + m_cipher.process_msg(&m_writebuf[TLS_HEADER_SIZE], buf_size); - BOTAN_ASSERT_EQUAL(got_back, buf_size, "Cipher encrypted full amount"); + const size_t ctext_size = m_cipher.remaining(Pipe::LAST_MESSAGE); - BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0, - "No data remains in pipe"); + BOTAN_ASSERT_EQUAL(ctext_size, buf_size, "Cipher encrypted full amount"); - m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + buf_size); + if(ctext_size > MAX_CIPHERTEXT_SIZE) + throw Internal_Error("Produced ciphertext larger than protocol allows"); - m_seq_no++; - } + m_cipher.read(&m_writebuf[TLS_HEADER_SIZE], ctext_size, Pipe::LAST_MESSAGE); + + BOTAN_ASSERT_EQUAL(m_cipher.remaining(Pipe::LAST_MESSAGE), 0, + "No data remains in pipe"); + + m_output_fn(&m_writebuf[0], TLS_HEADER_SIZE + buf_size); + + m_seq_no++; } /* * Send an alert */ -void Record_Writer::alert(Alert_Level level, Alert_Type type) +void Record_Writer::send_alert(const Alert& alert) { - byte alert[2] = { level, type }; - send(ALERT, alert, sizeof(alert)); + const byte alert_bits[2] = { alert.is_fatal() ? 2 : 1, + alert.type() }; + + send(ALERT, alert_bits, sizeof(alert_bits)); } } + +} |