aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/rec_wri.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/rec_wri.cpp')
-rw-r--r--src/tls/rec_wri.cpp180
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));
}
}
+
+}