How are TLS records encrypted? posted March 2016
Once we are done with the handshake, both parties are now holding the same set of keys. Right after the Server sends its ChangeCipherSpec message it starts encrypting. Right after the Client sends his own ChangeCipherSpec he starts encrypting his messages as well.
The encrypted records still start with the type of record, the TLS version and the length of the following bytes in clear. The rest is encrypted.
We won't talk about compression because there are a bunch of vulnerabilities that should make you think twice about using compression. So here it is, null! (more about that)
Let's follow the TLS 1.2 RFC here
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
select (SecurityParameters.cipher_type) {
case stream: GenericStreamCipher;
case block: GenericBlockCipher;
case aead: GenericAEADCipher;
} fragment;
} TLSCiphertext;
So as I said, we start with the type, the version and the length.
Right after the CipherSpecChange both parties will send an encrypted handshake message (a MAC of the whole transcript to authenticate the handshake), but most of the messages after will be encrypted Application data messages containing the real communications we want to protect.
0x17
is the byte for application data, then we have the TLS version, for TLS 1.2 it is 0x0303
(don't bother), then we have the length of the fragment which is described below for the AES-CBC case.
struct {
opaque IV[SecurityParameters.record_iv_length];
block-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
};
} GenericBlockCipher;
So in the case of AES-128, you would have an IV of 16 bytes followed by the encrypted data.
Yup, the MAC is not here because it is encrypted. TLS is a MAC-then-encrypt construction (...), you can do encrypt-then-MAC in practice but through an extension (cf. RFC 7366).
The rest is pretty straight forward, after decryption of the block-ciphered structure you remove the padding, check the MAC, use the content.
Here's how the mac is used:
MAC(MAC_write_key, seq_num +
TLSCompressed.type +
TLSCompressed.version +
TLSCompressed.length +
TLSCompressed.fragment);
where "+" denotes concatenation.
That's it for today!
Comments
toto
if client encrypts with his write key, the server has to decrypt with server write key?
david
the server will decrypt with server read key! (which is the same as the client write key)
leave a comment...