aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-02-11 16:09:02 +0000
committerlloyd <[email protected]>2013-02-11 16:09:02 +0000
commit90885b9670c4d001e3bab48d72d713bc7c58fa44 (patch)
treedb866785ad8c0d9e8145b0fa43e8d17c10fa2de2 /src/tls
parent2265684c7e1d580e31fa12c973df6d42106de200 (diff)
Move record decrypt to its own function
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/tls_record.cpp190
1 files changed, 104 insertions, 86 deletions
diff --git a/src/tls/tls_record.cpp b/src/tls/tls_record.cpp
index a030d479a..ecaf7d113 100644
--- a/src/tls/tls_record.cpp
+++ b/src/tls/tls_record.cpp
@@ -262,6 +262,102 @@ size_t tls_padding_check(bool sslv3_padding,
return padding_length + 1;
}
+bool decrypt_record(Record& output_record,
+ byte record_contents[], size_t record_len,
+ u64bit record_sequence,
+ Protocol_Version record_version,
+ Record_Type record_type,
+ Connection_Cipher_State& cipherstate)
+ {
+ const size_t block_size = cipherstate.block_size();
+ const size_t iv_size = cipherstate.iv_size();
+ const size_t mac_size = cipherstate.mac_size();
+
+ if(StreamCipher* sc = cipherstate.stream_cipher())
+ {
+ sc->cipher1(record_contents, record_len);
+ }
+ else if(BlockCipher* bc = cipherstate.block_cipher())
+ {
+ BOTAN_ASSERT(record_len % block_size == 0,
+ "Buffer is an even multiple of block size");
+
+ const size_t blocks = record_len / block_size;
+
+ BOTAN_ASSERT(blocks > 0, "At least one ciphertext block");
+
+ byte* buf = record_contents;
+
+ secure_vector<byte> last_ciphertext(block_size);
+ copy_mem(&last_ciphertext[0], &buf[0], block_size);
+
+ bc->decrypt(&buf[0]);
+ xor_buf(&buf[0], &cipherstate.cbc_state()[0], block_size);
+
+ secure_vector<byte> last_ciphertext2;
+
+ for(size_t i = 1; i < blocks; ++i)
+ {
+ last_ciphertext2.assign(&buf[block_size*i], &buf[block_size*(i+1)]);
+ bc->decrypt(&buf[block_size*i]);
+ xor_buf(&buf[block_size*i], &last_ciphertext[0], block_size);
+ std::swap(last_ciphertext, last_ciphertext2);
+ }
+
+ cipherstate.cbc_state() = last_ciphertext;
+ }
+ else
+ throw Internal_Error("NULL cipher not supported");
+
+ /*
+ * This is actually padding_length + 1 because both the padding and
+ * padding_length fields are padding from our perspective.
+ */
+ const size_t pad_size =
+ tls_padding_check(cipherstate.cipher_padding_single_byte(),
+ block_size, record_contents, record_len);
+
+ 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");
+
+ 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 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);
+
+ const bool padding_bad = (block_size > 0) && (pad_size == 0);
+
+ 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;
+ }
+
}
size_t read_record(std::vector<byte>& readbuf,
@@ -403,95 +499,17 @@ size_t read_record(std::vector<byte>& readbuf,
BOTAN_ASSERT(cipherstate, "Have cipherstate for this epoch");
- const size_t block_size = cipherstate->block_size();
- const size_t iv_size = cipherstate->iv_size();
- const size_t mac_size = cipherstate->mac_size();
-
- if(StreamCipher* sc = cipherstate->stream_cipher())
- {
- sc->cipher1(record_contents, record_len);
- }
- else if(BlockCipher* bc = cipherstate->block_cipher())
- {
- BOTAN_ASSERT(record_len % block_size == 0,
- "Buffer is an even multiple of block size");
-
- const size_t blocks = record_len / block_size;
+ const bool ok = decrypt_record(record,
+ record_contents,
+ record_len,
+ record_sequence,
+ record_version,
+ record_type,
+ *cipherstate);
- BOTAN_ASSERT(blocks > 0, "At least one ciphertext block");
-
- byte* buf = record_contents;
-
- secure_vector<byte> last_ciphertext(block_size);
- copy_mem(&last_ciphertext[0], &buf[0], block_size);
-
- bc->decrypt(&buf[0]);
- xor_buf(&buf[0], &cipherstate->cbc_state()[0], block_size);
-
- secure_vector<byte> last_ciphertext2;
-
- for(size_t i = 1; i < blocks; ++i)
- {
- last_ciphertext2.assign(&buf[block_size*i], &buf[block_size*(i+1)]);
- bc->decrypt(&buf[block_size*i]);
- xor_buf(&buf[block_size*i], &last_ciphertext[0], block_size);
- std::swap(last_ciphertext, last_ciphertext2);
- }
-
- cipherstate->cbc_state() = last_ciphertext;
- }
- else
- throw Internal_Error("NULL cipher not supported");
-
- /*
- * This is actually padding_length + 1 because both the padding and
- * padding_length fields are padding from our perspective.
- */
- const size_t pad_size =
- tls_padding_check(cipherstate->cipher_padding_single_byte(),
- block_size, record_contents, record_len);
-
- 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");
-
- 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 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);
-
- const bool padding_bad = (block_size > 0) && (pad_size == 0);
-
- if(mac_bad || padding_bad)
- throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
-
- if(sequence_numbers)
+ if(ok && sequence_numbers)
sequence_numbers->read_accept(record_sequence);
- record = Record(record_sequence,
- record_version,
- record_type,
- plaintext_block,
- plaintext_length);
-
readbuf.clear();
return 0;
}