-# Written by Matt Caswell for the OpenSSL project.
-# ====================================================================
-# Copyright (c) 1998-2015 The OpenSSL Project. All rights reserved.
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-#
-# 3. All advertising materials mentioning features or use of this
-# software must display the following acknowledgment:
-# "This product includes software developed by the OpenSSL Project
-# for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
-#
-# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
-# endorse or promote products derived from this software without
-# prior written permission. For written permission, please contact
-# openssl-core@openssl.org.
-#
-# 5. Products derived from this software may not be called "OpenSSL"
-# nor may "OpenSSL" appear in their names without prior written
-# permission of the OpenSSL Project.
-#
-# 6. Redistributions of any form whatsoever must retain the following
-# acknowledgment:
-# "This product includes software developed by the OpenSSL Project
-# for use in the OpenSSL Toolkit (http://www.openssl.org/)"
-#
-# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
-# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
-# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-# OF THE POSSIBILITY OF SUCH DAMAGE.
-# ====================================================================
-#
-# This product includes cryptographic software written by Eric Young
-# (eay@cryptsoft.com). This product includes software written by Tim
-# Hudson (tjh@cryptsoft.com).
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
use strict;
package TLSProxy::Record;
-my $server_ccs_seen = 0;
-my $client_ccs_seen = 0;
+my $server_encrypting = 0;
+my $client_encrypting = 0;
my $etm = 0;
use constant TLS_RECORD_HEADER_LENGTH => 5;
RT_APPLICATION_DATA => 23,
RT_HANDSHAKE => 22,
RT_ALERT => 21,
- RT_CCS => 20
+ RT_CCS => 20,
+ RT_UNKNOWN => 100
};
my %record_type = (
RT_APPLICATION_DATA, "APPLICATION DATA",
RT_HANDSHAKE, "HANDSHAKE",
RT_ALERT, "ALERT",
- RT_CCS, "CCS"
+ RT_CCS, "CCS",
+ RT_UNKNOWN, "UNKNOWN"
);
use constant {
+ VERS_TLS_1_4 => 773,
+ VERS_TLS_1_3_DRAFT => 32530,
VERS_TLS_1_3 => 772,
VERS_TLS_1_2 => 771,
VERS_TLS_1_1 => 770,
VERS_TLS_1_0 => 769,
- VERS_SSL_3_0 => 768
+ VERS_SSL_3_0 => 768,
+ VERS_SSL_LT_3_0 => 767
};
my %tls_version = (
VERS_TLS_1_2, "TLS1.2",
VERS_TLS_1_1, "TLS1.1",
VERS_TLS_1_0, "TLS1.0",
- VERS_SSL_3_0, "SSL3"
+ VERS_SSL_3_0, "SSL3",
+ VERS_SSL_LT_3_0, "SSL<3"
);
#Class method to extract records from a packet of data
$content_type,
$version,
$len,
+ 0,
$len_real,
$decrypt_len,
substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
);
- if (($server && $server_ccs_seen)
- || (!$server && $client_ccs_seen)) {
- if ($etm) {
+ if (($server && $server_encrypting)
+ || (!$server && $client_encrypting)) {
+ if (!TLSProxy::Proxy->is_tls13() && $etm) {
$record->decryptETM();
} else {
$record->decrypt();
}
+ $record->encrypted(1);
+ }
+
+ if (TLSProxy::Proxy->is_tls13()) {
+ print " Inner content type: "
+ .$record_type{$record->content_type()}."\n";
}
push @record_list, $record;
sub clear
{
- $server_ccs_seen = 0;
- $client_ccs_seen = 0;
+ $server_encrypting = 0;
+ $client_encrypting = 0;
}
#Class level accessors
-sub server_ccs_seen
+sub server_encrypting
{
my $class = shift;
if (@_) {
- $server_ccs_seen = shift;
+ $server_encrypting = shift;
}
- return $server_ccs_seen;
+ return $server_encrypting;
}
-sub client_ccs_seen
+sub client_encrypting
{
my $class = shift;
if (@_) {
- $client_ccs_seen = shift;
+ $client_encrypting= shift;
}
- return $client_ccs_seen;
+ return $client_encrypting;
}
#Enable/Disable Encrypt-then-MAC
sub etm
$content_type,
$version,
$len,
+ $sslv2,
$len_real,
$decrypt_len,
$data,
content_type => $content_type,
version => $version,
len => $len,
+ sslv2 => $sslv2,
len_real => $len_real,
decrypt_len => $decrypt_len,
data => $data,
decrypt_data => $decrypt_data,
- orig_decrypt_data => $decrypt_data
+ orig_decrypt_data => $decrypt_data,
+ encrypted => 0,
+ outer_content_type => RT_APPLICATION_DATA
};
return bless $self, $class;
sub decrypt()
{
my ($self) = shift;
-
+ my $mactaglen = 20;
my $data = $self->data;
- if($self->version >= VERS_TLS_1_1()) {
- #TLS1.1+ has an explicit IV. Throw it away
+ #Throw away any IVs
+ if (TLSProxy::Proxy->is_tls13()) {
+ #A TLS1.3 client, when processing the server's initial flight, could
+ #respond with either an encrypted or an unencrypted alert.
+ if ($self->content_type() == RT_ALERT) {
+ #TODO(TLS1.3): Eventually it is sufficient just to check the record
+ #content type. If an alert is encrypted it will have a record
+ #content type of application data. However we haven't done the
+ #record layer changes yet, so it's a bit more complicated. For now
+ #we will additionally check if the data length is 2 (1 byte for
+ #alert level, 1 byte for alert description). If it is, then this is
+ #an unecrypted alert, so don't try to decrypt
+ return $data if (length($data) == 2);
+ }
+ $mactaglen = 16;
+ } elsif ($self->version >= VERS_TLS_1_1()) {
+ #16 bytes for a standard IV
$data = substr($data, 16);
- }
- #Find out what the padding byte is
- my $padval = unpack("C", substr($data, length($data) - 1));
+ #Find out what the padding byte is
+ my $padval = unpack("C", substr($data, length($data) - 1));
- #Throw away the padding
- $data = substr($data, 0, length($data) - ($padval + 1));
+ #Throw away the padding
+ $data = substr($data, 0, length($data) - ($padval + 1));
+ }
- #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME)
- $data = substr($data, 0, length($data) - 20);
+ #Throw away the MAC or TAG
+ $data = substr($data, 0, length($data) - $mactaglen);
+
+ if (TLSProxy::Proxy->is_tls13()) {
+ #Get the content type
+ my $content_type = unpack("C", substr($data, length($data) - 1));
+ $self->content_type($content_type);
+ $data = substr($data, 0, length($data) - 1);
+ }
$self->decrypt_data($data);
$self->decrypt_len(length($data));
sub reconstruct_record
{
my $self = shift;
+ my $server = shift;
my $data;
+ my $tls13_enc = 0;
+
+ if ($self->sslv2) {
+ $data = pack('n', $self->len | 0x8000);
+ } else {
+ if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
+ $data = pack('Cnn', $self->outer_content_type, $self->version,
+ $self->len + 1);
+ $tls13_enc = 1;
+ } else {
+ $data = pack('Cnn', $self->content_type, $self->version,
+ $self->len);
+ }
- $data = pack('Cnn', $self->content_type, $self->version, $self->len);
+ }
$data .= $self->data;
+ if ($tls13_enc) {
+ $data .= pack('C', $self->content_type);
+ }
+
return $data;
}
my $self = shift;
return $self->{flight};
}
-sub content_type
+sub sslv2
{
my $self = shift;
- return $self->{content_type};
-}
-sub version
-{
- my $self = shift;
- return $self->{version};
+ return $self->{sslv2};
}
sub len_real
{
}
return $self->{len};
}
+sub version
+{
+ my $self = shift;
+ if (@_) {
+ $self->{version} = shift;
+ }
+ return $self->{version};
+}
+sub content_type
+{
+ my $self = shift;
+ if (@_) {
+ $self->{content_type} = shift;
+ }
+ return $self->{content_type};
+}
+sub encrypted
+{
+ my $self = shift;
+ if (@_) {
+ $self->{encrypted} = shift;
+ }
+ return $self->{encrypted};
+}
+sub outer_content_type
+{
+ my $self = shift;
+ if (@_) {
+ $self->{outer_content_type} = shift;
+ }
+ return $self->{outer_content_type};
+}
1;