aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_record.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-09-07 00:30:34 +0000
committerlloyd <[email protected]>2013-09-07 00:30:34 +0000
commit6fba8f5d3f1da6360e585f1647924985cfd236ef (patch)
tree327bf551b63f18656802d96a6e6fc250e28f83cc /src/tls/tls_record.cpp
parentc032dd416d182adbf43ffeba51529e7d6890a4d6 (diff)
Remove Record struct
Diffstat (limited to 'src/tls/tls_record.cpp')
-rw-r--r--src/tls/tls_record.cpp226
1 files changed, 93 insertions, 133 deletions
diff --git a/src/tls/tls_record.cpp b/src/tls/tls_record.cpp
index d9b222a85..2bfe78152 100644
--- a/src/tls/tls_record.cpp
+++ b/src/tls/tls_record.cpp
@@ -297,60 +297,6 @@ size_t fill_buffer_to(secure_vector<byte>& readbuf,
}
/*
-* MAC scheme used in SSLv3/TLSv1 for RC4 and CBC ciphers
-*/
-bool traditional_mac_check(Record& output_record,
- byte record_contents[], size_t record_len,
- size_t pad_size,
- volatile bool padding_bad,
- u64bit record_sequence,
- Protocol_Version record_version,
- Record_Type record_type,
- Connection_Cipher_State& cipherstate)
- {
- const size_t mac_size = cipherstate.mac_size();
- const size_t iv_size = cipherstate.iv_size();
-
- cipherstate.mac()->update_be(record_sequence);
- cipherstate.mac()->update(static_cast<byte>(record_type));
-
- if(cipherstate.mac_includes_record_version())
- {
- cipherstate.mac()->update(record_version.major_version());
- cipherstate.mac()->update(record_version.minor_version());
- }
-
- const size_t mac_pad_iv_size = mac_size + pad_size + iv_size;
-
- if(record_len < mac_pad_iv_size)
- throw Decoding_Error("Record sent with invalid length");
-
- const byte* plaintext_block = &record_contents[iv_size];
- const u16bit plaintext_length = record_len - mac_pad_iv_size;
-
- cipherstate.mac()->update_be(plaintext_length);
- cipherstate.mac()->update(plaintext_block, plaintext_length);
-
- std::vector<byte> mac_buf(mac_size);
- cipherstate.mac()->final(&mac_buf[0]);
-
- const size_t mac_offset = record_len - (mac_size + pad_size);
-
- const bool mac_bad = !same_mem(&record_contents[mac_offset], &mac_buf[0], mac_size);
-
- if(mac_bad || padding_bad)
- throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
-
- output_record = Record(record_sequence,
- record_version,
- record_type,
- plaintext_block,
- plaintext_length);
-
- return true;
- }
-
-/*
* Checks the TLS padding. Returns 0 if the padding is invalid (we
* count the padding_length field as part of the padding size so a
* valid padding will always be at least one byte long), or the length
@@ -436,7 +382,7 @@ void cbc_decrypt_record(byte record_contents[], size_t record_len,
cipherstate.cbc_state() = last_ciphertext;
}
-bool decrypt_record(Record& output_record,
+void decrypt_record(secure_vector<byte>& output,
byte record_contents[], size_t record_len,
u64bit record_sequence,
Protocol_Version record_version,
@@ -458,57 +404,76 @@ bool decrypt_record(Record& output_record,
cipherstate.format_ad(record_sequence, record_type, record_version, ptext_size)
);
- // fixme - making a copy, should steal from Record
- secure_vector<byte> buffer;
- buffer += aead->start_vec(nonce);
+ output += aead->start_vec(nonce);
- const size_t offset = buffer.size();
- buffer += std::make_pair(&msg[0], msg_length);
- aead->finish(buffer, offset);
+ const size_t offset = output.size();
+ output += std::make_pair(&msg[0], msg_length);
+ aead->finish(output, offset);
- BOTAN_ASSERT(buffer.size() == ptext_size + offset, "Produced expected size");
+ BOTAN_ASSERT(output.size() == ptext_size + offset, "Produced expected size");
+ }
+ else
+ {
+ // GenericBlockCipher / GenericStreamCipher case
- output_record = Record(record_sequence,
- record_version,
- record_type,
- &buffer[0],
- buffer.size());
+ volatile bool padding_bad = false;
+ size_t pad_size = 0;
- return true;
- }
+ if(StreamCipher* sc = cipherstate.stream_cipher())
+ {
+ sc->cipher1(record_contents, record_len);
+ // no padding to check or remove
+ }
+ else if(BlockCipher* bc = cipherstate.block_cipher())
+ {
+ cbc_decrypt_record(record_contents, record_len, cipherstate, *bc);
- volatile bool padding_bad = false;
- size_t pad_size = 0;
+ pad_size = tls_padding_check(cipherstate.cipher_padding_single_byte(),
+ cipherstate.block_size(),
+ record_contents, record_len);
- if(StreamCipher* sc = cipherstate.stream_cipher())
- {
- sc->cipher1(record_contents, record_len);
- // no padding to check or remove
- }
- else if(BlockCipher* bc = cipherstate.block_cipher())
- {
- cbc_decrypt_record(record_contents, record_len, cipherstate, *bc);
+ padding_bad = (pad_size == 0);
+ }
+ else
+ {
+ throw Internal_Error("No cipher state set but needed to decrypt");
+ }
- pad_size = tls_padding_check(cipherstate.cipher_padding_single_byte(),
- cipherstate.block_size(),
- record_contents, record_len);
+ const size_t mac_size = cipherstate.mac_size();
+ const size_t iv_size = cipherstate.iv_size();
- padding_bad = (pad_size == 0);
- }
- else
- {
- throw Internal_Error("No cipher state set but needed to decrypt");
- }
+ cipherstate.mac()->update_be(record_sequence);
+ cipherstate.mac()->update(static_cast<byte>(record_type));
- return traditional_mac_check(output_record,
- record_contents,
- record_len,
- pad_size,
- padding_bad,
- record_sequence,
- record_version,
- record_type,
- cipherstate);
+ if(cipherstate.mac_includes_record_version())
+ {
+ cipherstate.mac()->update(record_version.major_version());
+ cipherstate.mac()->update(record_version.minor_version());
+ }
+
+ const size_t mac_pad_iv_size = mac_size + pad_size + iv_size;
+
+ if(record_len < mac_pad_iv_size)
+ throw Decoding_Error("Record sent with invalid length");
+
+ const byte* plaintext_block = &record_contents[iv_size];
+ const u16bit plaintext_length = record_len - mac_pad_iv_size;
+
+ cipherstate.mac()->update_be(plaintext_length);
+ cipherstate.mac()->update(plaintext_block, plaintext_length);
+
+ std::vector<byte> mac_buf(mac_size);
+ cipherstate.mac()->final(&mac_buf[0]);
+
+ const size_t mac_offset = record_len - (mac_size + pad_size);
+
+ const bool mac_bad = !same_mem(&record_contents[mac_offset], &mac_buf[0], mac_size);
+
+ if(mac_bad || padding_bad)
+ throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
+
+ output.assign(plaintext_block, plaintext_block + plaintext_length);
+ }
}
}
@@ -517,7 +482,10 @@ size_t read_record(secure_vector<byte>& readbuf,
const byte input[],
size_t input_sz,
size_t& consumed,
- Record& record,
+ secure_vector<byte>& record,
+ u64bit* record_sequence,
+ Protocol_Version* record_version,
+ Record_Type* record_type,
Connection_Sequence_Numbers* sequence_numbers,
std::function<Connection_Cipher_State* (u16bit)> get_cipherstate)
{
@@ -554,28 +522,26 @@ size_t read_record(secure_vector<byte>& readbuf,
"Have the entire SSLv2 hello");
// Fake v3-style handshake message wrapper
- std::vector<byte> sslv2_hello(4 + readbuf.size() - 2);
-
- sslv2_hello[0] = CLIENT_HELLO_SSLV2;
- sslv2_hello[1] = 0;
- sslv2_hello[2] = readbuf[0] & 0x7F;
- sslv2_hello[3] = readbuf[1];
+ *record_version = Protocol_Version::TLS_V10;
+ *record_sequence = 0;
+ *record_type = HANDSHAKE;
- copy_mem(&sslv2_hello[4], &readbuf[2], readbuf.size() - 2);
+ record.resize(4 + readbuf.size() - 2);
- record = Record(0,
- Protocol_Version::TLS_V10,
- HANDSHAKE,
- std::move(sslv2_hello));
+ record[0] = CLIENT_HELLO_SSLV2;
+ record[1] = 0;
+ record[2] = readbuf[0] & 0x7F;
+ record[3] = readbuf[1];
+ copy_mem(&record[4], &readbuf[2], readbuf.size() - 2);
readbuf.clear();
return 0;
}
}
- Protocol_Version record_version = Protocol_Version(readbuf[1], readbuf[2]);
+ *record_version = Protocol_Version(readbuf[1], readbuf[2]);
- const bool is_dtls = record_version.is_datagram_protocol();
+ const bool is_dtls = record_version->is_datagram_protocol();
if(is_dtls && readbuf.size() < DTLS_HEADER_SIZE)
{
@@ -606,41 +572,35 @@ size_t read_record(secure_vector<byte>& readbuf,
readbuf.size(),
"Have the full record");
- Record_Type record_type = static_cast<Record_Type>(readbuf[0]);
+ *record_type = static_cast<Record_Type>(readbuf[0]);
- u64bit record_sequence = 0;
u16bit epoch = 0;
if(is_dtls)
{
- record_sequence = load_be<u64bit>(&readbuf[3], 0);
- epoch = (record_sequence >> 48);
+ *record_sequence = load_be<u64bit>(&readbuf[3], 0);
+ epoch = (*record_sequence >> 48);
}
else if(sequence_numbers)
{
- record_sequence = sequence_numbers->next_read_sequence();
+ *record_sequence = sequence_numbers->next_read_sequence();
epoch = sequence_numbers->current_read_epoch();
}
else
{
// server initial handshake case
- record_sequence = 0;
+ *record_sequence = 0;
epoch = 0;
}
- if(sequence_numbers && sequence_numbers->already_seen(record_sequence))
+ if(sequence_numbers && sequence_numbers->already_seen(*record_sequence))
return 0;
byte* record_contents = &readbuf[header_size];
if(epoch == 0) // Unencrypted initial handshake
{
- record = Record(record_sequence,
- record_version,
- record_type,
- &readbuf[header_size],
- record_len);
-
+ record.assign(&readbuf[header_size], &readbuf[header_size + record_len]);
readbuf.clear();
return 0; // got a full record
}
@@ -652,16 +612,16 @@ size_t read_record(secure_vector<byte>& readbuf,
BOTAN_ASSERT(cipherstate, "Have cipherstate for this epoch");
- const bool ok = decrypt_record(record,
- record_contents,
- record_len,
- record_sequence,
- record_version,
- record_type,
- *cipherstate);
+ decrypt_record(record,
+ record_contents,
+ record_len,
+ *record_sequence,
+ *record_version,
+ *record_type,
+ *cipherstate);
- if(ok && sequence_numbers)
- sequence_numbers->read_accept(record_sequence);
+ if(sequence_numbers)
+ sequence_numbers->read_accept(*record_sequence);
readbuf.clear();
return 0;