1 # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3 # Licensed under the OpenSSL license (the "License"). You may not use
4 # this file except in compliance with the License. You can obtain a copy
5 # in the file LICENSE in the source distribution or at
6 # https://www.openssl.org/source/license.html
12 package TLSProxy::Record;
14 my $server_ccs_seen = 0;
15 my $client_ccs_seen = 0;
18 use constant TLS_RECORD_HEADER_LENGTH => 5;
22 RT_APPLICATION_DATA => 23,
30 RT_APPLICATION_DATA, "APPLICATION DATA",
31 RT_HANDSHAKE, "HANDSHAKE",
43 VERS_SSL_LT_3_0 => 767
47 VERS_TLS_1_3, "TLS1.3",
48 VERS_TLS_1_2, "TLS1.2",
49 VERS_TLS_1_1, "TLS1.1",
50 VERS_TLS_1_0, "TLS1.0",
52 VERS_SSL_LT_3_0, "SSL<3"
55 #Class method to extract records from a packet of data
63 my @message_list = ();
72 while (length ($packet) > 0) {
73 print " Record $recnum";
75 print " (server -> client)\n";
77 print " (client -> server)\n";
79 #Get the record header
80 if (length($packet) < TLS_RECORD_HEADER_LENGTH) {
81 print "Partial data : ".length($packet)." bytes\n";
84 ($content_type, $version, $len) = unpack('CnnC*', $packet);
85 $data = substr($packet, 5, $len);
87 print " Content type: ".$record_type{$content_type}."\n";
88 print " Version: $tls_version{$version}\n";
89 print " Length: $len";
90 if ($len == length($data)) {
92 $decrypt_len = $len_real = $len;
94 print " (expected), ".length($data)." (actual)\n";
95 $decrypt_len = $len_real = length($data);
98 my $record = TLSProxy::Record->new(
106 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
107 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
110 if (($server && $server_ccs_seen)
111 || (!$server && $client_ccs_seen)) {
112 if ($version != VERS_TLS_1_3() && $etm) {
113 $record->decryptETM();
119 push @record_list, $record;
121 #Now figure out what messages are contained within this record
122 my @messages = TLSProxy::Message->get_messages($server, $record);
123 push @message_list, @messages;
125 $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
130 return (\@record_list, \@message_list);
135 $server_ccs_seen = 0;
136 $client_ccs_seen = 0;
139 #Class level accessors
144 $server_ccs_seen = shift;
146 return $server_ccs_seen;
152 $client_ccs_seen = shift;
154 return $client_ccs_seen;
156 #Enable/Disable Encrypt-then-MAC
181 content_type => $content_type,
185 len_real => $len_real,
186 decrypt_len => $decrypt_len,
188 decrypt_data => $decrypt_data,
189 orig_decrypt_data => $decrypt_data
192 return bless $self, $class;
195 #Decrypt using encrypt-then-MAC
200 my $data = $self->data;
202 if($self->version >= VERS_TLS_1_1()) {
203 #TLS1.1+ has an explicit IV. Throw it away
204 $data = substr($data, 16);
207 #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME)
208 $data = substr($data, 0, length($data) - 20);
210 #Find out what the padding byte is
211 my $padval = unpack("C", substr($data, length($data) - 1));
213 #Throw away the padding
214 $data = substr($data, 0, length($data) - ($padval + 1));
216 $self->decrypt_data($data);
217 $self->decrypt_len(length($data));
227 my $data = $self->data;
230 if ($self->version >= VERS_TLS_1_3()) {
231 #8 bytes for a GCM IV
232 $data = substr($data, 8);
234 } elsif ($self->version >= VERS_TLS_1_1()) {
235 #16 bytes for a standard IV
236 $data = substr($data, 16);
238 #Find out what the padding byte is
239 my $padval = unpack("C", substr($data, length($data) - 1));
241 #Throw away the padding
242 $data = substr($data, 0, length($data) - ($padval + 1));
245 #Throw away the MAC or TAG
246 $data = substr($data, 0, length($data) - $mactaglen);
248 $self->decrypt_data($data);
249 $self->decrypt_len(length($data));
254 #Reconstruct the on-the-wire record representation
255 sub reconstruct_record
261 $data = pack('n', $self->len | 0x8000);
263 $data = pack('Cnn', $self->content_type, $self->version, $self->len);
265 $data .= $self->data;
274 return $self->{flight};
279 return $self->{content_type};
284 return $self->{version};
289 return $self->{sslv2};
294 return $self->{len_real};
296 sub orig_decrypt_data
299 return $self->{orig_decrypt_data};
302 #Read/write accessors
307 $self->{decrypt_len} = shift;
309 return $self->{decrypt_len};
315 $self->{data} = shift;
317 return $self->{data};
323 $self->{decrypt_data} = shift;
325 return $self->{decrypt_data};
331 $self->{len} = shift;