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,
29 RT_APPLICATION_DATA, "APPLICATION DATA",
30 RT_HANDSHAKE, "HANDSHAKE",
41 VERS_SSL_LT_3_0 => 767
45 VERS_TLS_1_3, "TLS1.3",
46 VERS_TLS_1_2, "TLS1.2",
47 VERS_TLS_1_1, "TLS1.1",
48 VERS_TLS_1_0, "TLS1.0",
50 VERS_SSL_LT_3_0, "SSL<3"
53 #Class method to extract records from a packet of data
61 my @message_list = ();
70 while (length ($packet) > 0) {
71 print " Record $recnum";
73 print " (server -> client)\n";
75 print " (client -> server)\n";
77 #Get the record header
78 if (length($packet) < TLS_RECORD_HEADER_LENGTH) {
79 print "Partial data : ".length($packet)." bytes\n";
82 ($content_type, $version, $len) = unpack('CnnC*', $packet);
83 $data = substr($packet, 5, $len);
85 print " Content type: ".$record_type{$content_type}."\n";
86 print " Version: $tls_version{$version}\n";
87 print " Length: $len";
88 if ($len == length($data)) {
90 $decrypt_len = $len_real = $len;
92 print " (expected), ".length($data)." (actual)\n";
93 $decrypt_len = $len_real = length($data);
96 my $record = TLSProxy::Record->new(
104 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
105 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
108 if (($server && $server_ccs_seen)
109 || (!$server && $client_ccs_seen)) {
110 if ($version != VERS_TLS_1_3() && $etm) {
111 $record->decryptETM();
117 push @record_list, $record;
119 #Now figure out what messages are contained within this record
120 my @messages = TLSProxy::Message->get_messages($server, $record);
121 push @message_list, @messages;
123 $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
128 return (\@record_list, \@message_list);
133 $server_ccs_seen = 0;
134 $client_ccs_seen = 0;
137 #Class level accessors
142 $server_ccs_seen = shift;
144 return $server_ccs_seen;
150 $client_ccs_seen = shift;
152 return $client_ccs_seen;
154 #Enable/Disable Encrypt-then-MAC
179 content_type => $content_type,
183 len_real => $len_real,
184 decrypt_len => $decrypt_len,
186 decrypt_data => $decrypt_data,
187 orig_decrypt_data => $decrypt_data
190 return bless $self, $class;
193 #Decrypt using encrypt-then-MAC
198 my $data = $self->data;
200 if($self->version >= VERS_TLS_1_1()) {
201 #TLS1.1+ has an explicit IV. Throw it away
202 $data = substr($data, 16);
205 #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME)
206 $data = substr($data, 0, length($data) - 20);
208 #Find out what the padding byte is
209 my $padval = unpack("C", substr($data, length($data) - 1));
211 #Throw away the padding
212 $data = substr($data, 0, length($data) - ($padval + 1));
214 $self->decrypt_data($data);
215 $self->decrypt_len(length($data));
225 my $data = $self->data;
228 if ($self->version >= VERS_TLS_1_3()) {
229 #8 bytes for a GCM IV
230 $data = substr($data, 8);
232 } elsif ($self->version >= VERS_TLS_1_1()) {
233 #16 bytes for a standard IV
234 $data = substr($data, 16);
236 #Find out what the padding byte is
237 my $padval = unpack("C", substr($data, length($data) - 1));
239 #Throw away the padding
240 $data = substr($data, 0, length($data) - ($padval + 1));
243 #Throw away the MAC or TAG
244 $data = substr($data, 0, length($data) - $mactaglen);
246 $self->decrypt_data($data);
247 $self->decrypt_len(length($data));
252 #Reconstruct the on-the-wire record representation
253 sub reconstruct_record
259 $data = pack('n', $self->len | 0x8000);
261 $data = pack('Cnn', $self->content_type, $self->version, $self->len);
263 $data .= $self->data;
272 return $self->{flight};
277 return $self->{content_type};
282 return $self->{version};
287 return $self->{sslv2};
292 return $self->{len_real};
294 sub orig_decrypt_data
297 return $self->{orig_decrypt_data};
300 #Read/write accessors
305 $self->{decrypt_len} = shift;
307 return $self->{decrypt_len};
313 $self->{data} = shift;
315 return $self->{data};
321 $self->{decrypt_data} = shift;
323 return $self->{decrypt_data};
329 $self->{len} = shift;