summaryrefslogtreecommitdiff
path: root/deps/openssl/openssl/util/perl/TLSProxy/Record.pm
diff options
context:
space:
mode:
Diffstat (limited to 'deps/openssl/openssl/util/perl/TLSProxy/Record.pm')
-rw-r--r--deps/openssl/openssl/util/perl/TLSProxy/Record.pm244
1 files changed, 153 insertions, 91 deletions
diff --git a/deps/openssl/openssl/util/perl/TLSProxy/Record.pm b/deps/openssl/openssl/util/perl/TLSProxy/Record.pm
index 786ba0c72b..0a280cb269 100644
--- a/deps/openssl/openssl/util/perl/TLSProxy/Record.pm
+++ b/deps/openssl/openssl/util/perl/TLSProxy/Record.pm
@@ -11,8 +11,8 @@ use TLSProxy::Proxy;
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;
@@ -35,12 +35,13 @@ my %record_type = (
);
use constant {
- 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_LT_3_0 => 767
+ VERS_TLS_1_4 => 0x0305,
+ VERS_TLS_1_3 => 0x0304,
+ VERS_TLS_1_2 => 0x0303,
+ VERS_TLS_1_1 => 0x0302,
+ VERS_TLS_1_0 => 0x0301,
+ VERS_SSL_3_0 => 0x0300,
+ VERS_SSL_LT_3_0 => 0x02ff
};
my %tls_version = (
@@ -62,72 +63,66 @@ sub get_records
my $partial = "";
my @record_list = ();
my @message_list = ();
- my $data;
- my $content_type;
- my $version;
- my $len;
- my $len_real;
- my $decrypt_len;
my $recnum = 1;
while (length ($packet) > 0) {
- print " Record $recnum";
- if ($server) {
- print " (server -> client)\n";
- } else {
- print " (client -> server)\n";
- }
- #Get the record header
- if (length($packet) < TLS_RECORD_HEADER_LENGTH
- || length($packet) < 5 + unpack("n", substr($packet, 3, 2))) {
+ print " Record $recnum ", $server ? "(server -> client)\n"
+ : "(client -> server)\n";
+
+ #Get the record header (unpack can't fail if $packet is too short)
+ my ($content_type, $version, $len) = unpack('Cnn', $packet);
+
+ if (length($packet) < TLS_RECORD_HEADER_LENGTH + ($len // 0)) {
print "Partial data : ".length($packet)." bytes\n";
$partial = $packet;
- $packet = "";
- } else {
- ($content_type, $version, $len) = unpack('CnnC*', $packet);
- $data = substr($packet, 5, $len);
-
- print " Content type: ".$record_type{$content_type}."\n";
- print " Version: $tls_version{$version}\n";
- print " Length: $len";
- if ($len == length($data)) {
- print "\n";
- $decrypt_len = $len_real = $len;
- } else {
- print " (expected), ".length($data)." (actual)\n";
- $decrypt_len = $len_real = length($data);
- }
+ last;
+ }
- my $record = TLSProxy::Record->new(
- $flight,
- $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) {
+ my $data = substr($packet, TLS_RECORD_HEADER_LENGTH, $len);
+
+ print " Content type: ".$record_type{$content_type}."\n";
+ print " Version: $tls_version{$version}\n";
+ print " Length: $len\n";
+
+ my $record = TLSProxy::Record->new(
+ $flight,
+ $content_type,
+ $version,
+ $len,
+ 0,
+ $len, # len_real
+ $len, # decrypt_len
+ $data, # data
+ $data # decrypt_data
+ );
+
+ if ($content_type != RT_CCS
+ && (!TLSProxy::Proxy->is_tls13()
+ || $content_type != RT_ALERT)) {
+ 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;
+ push @record_list, $record;
- #Now figure out what messages are contained within this record
- my @messages = TLSProxy::Message->get_messages($server, $record);
- push @message_list, @messages;
+ #Now figure out what messages are contained within this record
+ my @messages = TLSProxy::Message->get_messages($server, $record);
+ push @message_list, @messages;
- $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
- $recnum++;
- }
+ $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len);
+ $recnum++;
}
return (\@record_list, \@message_list, $partial);
@@ -135,26 +130,26 @@ sub get_records
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
@@ -190,7 +185,9 @@ sub new
data => $data,
decrypt_data => $decrypt_data,
orig_decrypt_data => $decrypt_data,
- sent => 0
+ sent => 0,
+ encrypted => 0,
+ outer_content_type => RT_APPLICATION_DATA
};
return bless $self, $class;
@@ -227,22 +224,44 @@ sub decryptETM
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 unencrypted 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));
@@ -254,9 +273,11 @@ sub decrypt()
sub reconstruct_record
{
my $self = shift;
+ my $server = shift;
my $data;
- if ($self->{sent}) {
+ #We only replay the records in the same direction
+ if ($self->{sent} || ($self->flight & 1) != $server) {
return "";
}
$self->{sent} = 1;
@@ -264,7 +285,14 @@ sub reconstruct_record
if ($self->sslv2) {
$data = pack('n', $self->len | 0x8000);
} else {
- $data = pack('Cnn', $self->content_type, $self->version, $self->len);
+ if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
+ $data = pack('Cnn', $self->outer_content_type, $self->version,
+ $self->len);
+ } else {
+ $data = pack('Cnn', $self->content_type, $self->version,
+ $self->len);
+ }
+
}
$data .= $self->data;
@@ -277,16 +305,6 @@ sub flight
my $self = shift;
return $self->{flight};
}
-sub content_type
-{
- my $self = shift;
- return $self->{content_type};
-}
-sub version
-{
- my $self = shift;
- return $self->{version};
-}
sub sslv2
{
my $self = shift;
@@ -336,4 +354,48 @@ sub len
}
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};
+}
+sub is_fatal_alert
+{
+ my $self = shift;
+ my $server = shift;
+
+ if (($self->{flight} & 1) == $server
+ && $self->{content_type} == TLSProxy::Record::RT_ALERT) {
+ my ($level, $alert) = unpack('CC', $self->decrypt_data);
+ return $alert if ($level == 2);
+ }
+ return 0;
+}
1;