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_encrypting = 0;
15 my $client_encrypting = 0;
18 use constant TLS_RECORD_HEADER_LENGTH => 5;
22 RT_APPLICATION_DATA => 23,
30 RT_APPLICATION_DATA, "APPLICATION DATA",
31 RT_HANDSHAKE, "HANDSHAKE",
39 VERS_TLS_1_3_DRAFT => 32530,
45 VERS_SSL_LT_3_0 => 767
49 VERS_TLS_1_3, "TLS1.3",
50 VERS_TLS_1_2, "TLS1.2",
51 VERS_TLS_1_1, "TLS1.1",
52 VERS_TLS_1_0, "TLS1.0",
54 VERS_SSL_LT_3_0, "SSL<3"
57 #Class method to extract records from a packet of data
65 my @message_list = ();
74 while (length ($packet) > 0) {
75 print " Record $recnum";
77 print " (server -> client)\n";
79 print " (client -> server)\n";
81 #Get the record header
82 if (length($packet) < TLS_RECORD_HEADER_LENGTH) {
83 print "Partial data : ".length($packet)." bytes\n";
86 ($content_type, $version, $len) = unpack('CnnC*', $packet);
87 $data = substr($packet, 5, $len);
89 print " Content type: ".$record_type{$content_type}."\n";
90 print " Version: $tls_version{$version}\n";
91 print " Length: $len";
92 if ($len == length($data)) {
94 $decrypt_len = $len_real = $len;
96 print " (expected), ".length($data)." (actual)\n";
97 $decrypt_len = $len_real = length($data);
100 my $record = TLSProxy::Record->new(
108 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
109 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
112 if (($server && $server_encrypting)
113 || (!$server && $client_encrypting)) {
114 if (!TLSProxy::Proxy->is_tls13() && $etm) {
115 $record->decryptETM();
119 $record->encrypted(1);
122 if (TLSProxy::Proxy->is_tls13()) {
123 print " Inner content type: "
124 .$record_type{$record->content_type()}."\n";
127 push @record_list, $record;
129 #Now figure out what messages are contained within this record
130 my @messages = TLSProxy::Message->get_messages($server, $record);
131 push @message_list, @messages;
133 $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
138 return (\@record_list, \@message_list);
143 $server_encrypting = 0;
144 $client_encrypting = 0;
147 #Class level accessors
148 sub server_encrypting
152 $server_encrypting = shift;
154 return $server_encrypting;
156 sub client_encrypting
160 $client_encrypting= shift;
162 return $client_encrypting;
164 #Enable/Disable Encrypt-then-MAC
189 content_type => $content_type,
193 len_real => $len_real,
194 decrypt_len => $decrypt_len,
196 decrypt_data => $decrypt_data,
197 orig_decrypt_data => $decrypt_data,
199 outer_content_type => RT_APPLICATION_DATA
202 return bless $self, $class;
205 #Decrypt using encrypt-then-MAC
210 my $data = $self->data;
212 if($self->version >= VERS_TLS_1_1()) {
213 #TLS1.1+ has an explicit IV. Throw it away
214 $data = substr($data, 16);
217 #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME)
218 $data = substr($data, 0, length($data) - 20);
220 #Find out what the padding byte is
221 my $padval = unpack("C", substr($data, length($data) - 1));
223 #Throw away the padding
224 $data = substr($data, 0, length($data) - ($padval + 1));
226 $self->decrypt_data($data);
227 $self->decrypt_len(length($data));
237 my $data = $self->data;
240 if (TLSProxy::Proxy->is_tls13()) {
241 #A TLS1.3 client, when processing the server's initial flight, could
242 #respond with either an encrypted or an unencrypted alert.
243 if ($self->content_type() == RT_ALERT) {
244 #TODO(TLS1.3): Eventually it is sufficient just to check the record
245 #content type. If an alert is encrypted it will have a record
246 #content type of application data. However we haven't done the
247 #record layer changes yet, so it's a bit more complicated. For now
248 #we will additionally check if the data length is 2 (1 byte for
249 #alert level, 1 byte for alert description). If it is, then this is
250 #an unecrypted alert, so don't try to decrypt
251 return $data if (length($data) == 2);
254 } elsif ($self->version >= VERS_TLS_1_1()) {
255 #16 bytes for a standard IV
256 $data = substr($data, 16);
258 #Find out what the padding byte is
259 my $padval = unpack("C", substr($data, length($data) - 1));
261 #Throw away the padding
262 $data = substr($data, 0, length($data) - ($padval + 1));
265 #Throw away the MAC or TAG
266 $data = substr($data, 0, length($data) - $mactaglen);
268 if (TLSProxy::Proxy->is_tls13()) {
269 #Get the content type
270 my $content_type = unpack("C", substr($data, length($data) - 1));
271 $self->content_type($content_type);
272 $data = substr($data, 0, length($data) - 1);
275 $self->decrypt_data($data);
276 $self->decrypt_len(length($data));
281 #Reconstruct the on-the-wire record representation
282 sub reconstruct_record
290 $data = pack('n', $self->len | 0x8000);
292 if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
293 $data = pack('Cnn', $self->outer_content_type, $self->version,
297 $data = pack('Cnn', $self->content_type, $self->version,
302 $data .= $self->data;
305 $data .= pack('C', $self->content_type);
315 return $self->{flight};
320 return $self->{sslv2};
325 return $self->{len_real};
327 sub orig_decrypt_data
330 return $self->{orig_decrypt_data};
333 #Read/write accessors
338 $self->{decrypt_len} = shift;
340 return $self->{decrypt_len};
346 $self->{data} = shift;
348 return $self->{data};
354 $self->{decrypt_data} = shift;
356 return $self->{decrypt_data};
362 $self->{len} = shift;
370 $self->{version} = shift;
372 return $self->{version};
378 $self->{content_type} = shift;
380 return $self->{content_type};
386 $self->{encrypted} = shift;
388 return $self->{encrypted};
390 sub outer_content_type
394 $self->{outer_content_type} = shift;
396 return $self->{outer_content_type};