I'm currently taking a university class on security and cryptography, and one of the projects we're doing involves implementing a basic TLS socket.
So, I've studied the TLS protocol using both my textbook as well as the latest RFC, so I have a pretty good understanding of how TLS/SSL works, and also how the TLS record format is laid out, byte-by-byte.
So, to start out I decided to write a server program that listens on port 443 and accepts incoming secure HTTP connections. All it does is accept a client connection and then print out a hex dump of the initial message sent by the client.
But when I connect to my server using a web-browser (Firefox), I'm totally baffled by the bytestream the browser sends me. According to the RFC, the first thing a TLS client must do is send a ClientHello
message. All messages must be encapsulated in a TLS record format, which is supposed to be formatted like this (using the C-ish notation the RFC uses):
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
The ContentType
field is a single enum value that must be one of the following types: change_cipher_spec = 0x14, alert = 0x15, handshake = 0x16, application_data = 0x17
So, since the first thing a client must do is send a ClientHello message, which is part of the handshake, I'd expect the very first byte in the bytestream to be a 0x16
, indicating this is a handshake message.
But instead, the actual bytestream my browser sends is:
80 55 01 03 00 00 3c 00 00 00 10 00 00 88 00 00 87 00 00 39 00 00
38 00 00 84 00 00 35 00 00 45 00 00 44 00 00 33 00 00 32 00 00 96
00 00 41 00 00 04 00 00 05 00 00 2f 00 00 16 00 00 13 00 fe ff 00
00 0a 00 00 ff 07 99 58 ad 17 f3 17 23 be 63 8c 6d cb 9b 5f 6f
I can't make any sense of this bytestream, even after pouring over the RFC for hours. Everything I read about TLS tells me that the first byte should be a 0x16
to indicate a handshake, followed by a two-byte version field, followed by a two-byte record length field. But this byte-stream begins with an 0x80 0x55
, which is meaningless to me.
Can anyone clear up what's going on here? Am I misunderstanding some part of the TLS protocol?
What you are seeing is the SSL version 2 compatible hello. Look at appendix E of RFC 5246. I don't believe the newest versions of firefox will send that, they'll only send the V3 hello format that you were expecting.
Wireshark has a parser for HTTPS/TLS/SSL, this will be able to make sense of the plain text part of the handshake.
Also make sure to read The First few milliseconds of an HTTPS connection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With