);
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_LT_3_0 => 767
+ VERS_TLS_1_4 => 0x0305,
+ VERS_TLS_1_3_DRAFT => 0x7f14,
+ 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 = (
if (($server && $server_encrypting)
|| (!$server && $client_encrypting)) {
- if ($version != VERS_TLS_1_3() && $etm) {
+ 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;
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;
my $data = $self->data;
#Throw away any IVs
- if ($self->version >= VERS_TLS_1_3()) {
- #8 bytes for a GCM IV
- $data = substr($data, 8);
+ 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
#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 {
- $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 + 1);
+ $tls13_enc = 1;
+ } else {
+ $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
-{
- my $self = shift;
- return $self->{content_type};
-}
sub sslv2
{
my $self = 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;