mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Spicy TLS: raise ssl_established event for TLS 1.3
This commit is contained in:
parent
061dc73e8f
commit
3f91557c3e
3 changed files with 41 additions and 20 deletions
|
@ -67,5 +67,6 @@ uses_seh = "uses_seh"
|
|||
[default.extend-words]
|
||||
caf = "caf"
|
||||
helo = "helo"
|
||||
inout = "inout"
|
||||
# Seems we use this in the management framework
|
||||
requestor = "requestor"
|
||||
|
|
|
@ -25,8 +25,9 @@ on TLS::NewSessionTicket -> event ssl_session_ticket_handshake($conn, self.ticke
|
|||
|
||||
on TLS::PlaintextRecord::ccs -> event ssl_change_cipher_spec($conn, $is_orig);
|
||||
on TLS::PlaintextRecord::ccs if ( msg.context().ccs_seen == 2 ) -> event ssl_established($conn);
|
||||
on TLS::PlaintextRecord::appdata if ( self.encrypted == False ) -> event ssl_plaintext_data($conn, TLS::get_direction(sh), msg.record_version, content_type, self.length);
|
||||
on TLS::PlaintextRecord::appdata if ( self.encrypted == True ) -> event ssl_encrypted_data($conn, TLS::get_direction(sh), msg.record_version, content_type, self.length);
|
||||
on TLS::PlaintextRecord::trigger_one if ( sh.both_sides_encrypted_first_time == True ) -> event ssl_established($conn);
|
||||
on TLS::PlaintextRecord::trigger_two if ( self.encrypted == False ) -> event ssl_plaintext_data($conn, TLS::get_direction(sh), msg.record_version, content_type, self.length);
|
||||
on TLS::PlaintextRecord::trigger_two if ( self.encrypted == True ) -> event ssl_encrypted_data($conn, TLS::get_direction(sh), msg.record_version, content_type, self.length);
|
||||
|
||||
on TLS::Handshake_message -> event ssl_handshake_message($conn, TLS::get_direction(sh), self.msg_type, self.length);
|
||||
|
||||
|
|
|
@ -568,6 +568,7 @@ type Share = unit {
|
|||
# var skipping: bool;
|
||||
var client_encrypted: bool;
|
||||
var server_encrypted: bool;
|
||||
var both_sides_encrypted_first_time: bool;
|
||||
|
||||
on %init {
|
||||
self.ccs_seen = 0;
|
||||
|
@ -578,6 +579,7 @@ type Share = unit {
|
|||
self.flip_already_alerted = False;
|
||||
self.server_encrypted = False;
|
||||
self.client_encrypted = False;
|
||||
self.both_sides_encrypted_first_time = False;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -588,7 +590,7 @@ function get_encrypted(sh: Share) : bool {
|
|||
return sh.server_encrypted;
|
||||
}
|
||||
|
||||
function startEncryption(handshakesink: sink, alertsink: sink, inout sh: Share) {
|
||||
function startEncryption(inout handshakesink: sink, inout alertsink: sink, inout sh: Share) {
|
||||
local old_state: bool;
|
||||
|
||||
if ( get_direction(sh) ) {
|
||||
|
@ -605,19 +607,19 @@ function startEncryption(handshakesink: sink, alertsink: sink, inout sh: Share)
|
|||
print "Closing sink";
|
||||
handshakesink.close();
|
||||
alertsink.close();
|
||||
sh.ccs_seen++; # do we need this?
|
||||
|
||||
if ( sh.client_encrypted && sh.server_encrypted ) {
|
||||
print "Encrypted first time";
|
||||
sh.both_sides_encrypted_first_time = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This function is called several times in certain circumstances.
|
||||
# If it is called twice, it is first called due to the supported_versions
|
||||
# field in the server hello - and then again due to the outer version in
|
||||
# the server hello. So - once we have a version here, let's just stick
|
||||
# with it.
|
||||
# If it is called twice, it is first called due to the outer version in
|
||||
# the server hello - and then again due to the supported_versions
|
||||
# field in the server hello.
|
||||
function set_version(version: uint16, inout sh: Share) : bool {
|
||||
if ( sh.parsed_version != UNKNOWN_VERSION )
|
||||
return False;
|
||||
|
||||
sh.parsed_version = version;
|
||||
if ( version == TLSv13 || version/0xFF == 0x7F )
|
||||
sh.tls_13 = True;
|
||||
|
@ -698,7 +700,10 @@ type DTLSRecordFragment = unit(content_type: uint8, handshakesink: sink, alertsi
|
|||
|
||||
type PlaintextRecord = unit(content_type: uint8, handshakesink: sink, alertsink: sink, inout msg: Message, inout sh: Share) {
|
||||
length: uint16;
|
||||
var encrypted: bool = determine_encryption_on(self, handshakesink, alertsink, msg, sh);
|
||||
var encrypted: bool;
|
||||
# convenient triggers to hang stuff in the evt file from. Two of them for event ordering :)
|
||||
trigger_one: bytes &size=0;
|
||||
trigger_two: bytes &size=0;
|
||||
switch ( ContentType(content_type) ) {
|
||||
ContentType::handshake -> : bytes &size=self.length -> handshakesink;
|
||||
ContentType::application_data -> {
|
||||
|
@ -717,6 +722,10 @@ type PlaintextRecord = unit(content_type: uint8, handshakesink: sink, alertsink:
|
|||
print "Unhandled content type", content_type;
|
||||
}
|
||||
|
||||
on length {
|
||||
self.encrypted = determine_encryption_on(self, content_type, handshakesink, alertsink, msg, sh);
|
||||
}
|
||||
|
||||
on ccs {
|
||||
# I know this looks a bit weird. Basically - in TLS 1.3, CCS is meaningless
|
||||
# fluff that just is used to pretend to TLS 1.2 devices listening in that
|
||||
|
@ -726,8 +735,14 @@ type PlaintextRecord = unit(content_type: uint8, handshakesink: sink, alertsink:
|
|||
if ( sh.tls_13 )
|
||||
return;
|
||||
|
||||
print "CCS accepted";
|
||||
sh.ccs_seen++; # used in TLS.evt
|
||||
startEncryption(handshakesink, alertsink, sh);
|
||||
}
|
||||
on trigger_two {
|
||||
if ( sh.both_sides_encrypted_first_time )
|
||||
sh.both_sides_encrypted_first_time = False;
|
||||
}
|
||||
};
|
||||
|
||||
## So - this falls a bit under the envelope of dirty hack - but I don't
|
||||
|
@ -750,7 +765,7 @@ type PlaintextRecord = unit(content_type: uint8, handshakesink: sink, alertsink:
|
|||
## a bit of context here - we can't really say when we get the first packet
|
||||
## that uses the final cryptographic key material - and will contain content
|
||||
## data. We just don't have that information available in TLS 1.3 anymore.
|
||||
function determine_encryption_on(pr: PlaintextRecord, handshakesink: sink, alertsink: sink, inout msg: Message, inout sh: Share) : bool {
|
||||
function determine_encryption_on(pr: PlaintextRecord, content_type: uint8, handshakesink: sink, alertsink: sink, inout msg: Message, inout sh: Share) : bool {
|
||||
if ( get_encrypted(sh) )
|
||||
return True;
|
||||
|
||||
|
@ -758,6 +773,9 @@ function determine_encryption_on(pr: PlaintextRecord, handshakesink: sink, alert
|
|||
if ( pr.length == 0 )
|
||||
return False;
|
||||
|
||||
if ( content_type != 23 ) # application_data
|
||||
return False;
|
||||
|
||||
## in theory, we should check for TLS13 or draft-TLS13 instead of doing the reverse.
|
||||
## But - people use weird version numbers. And all of those weird version numbers are
|
||||
## some sort of TLS1.3. So - let's do it this way round instead.
|
||||
|
@ -896,7 +914,7 @@ type ClientHello = unit(len: uint64, msg: Message, inout sh: Share) {
|
|||
}
|
||||
};
|
||||
|
||||
# Draft versions of TLS 1.3 had a diffent server hello - distinguish here
|
||||
# Draft versions of TLS 1.3 had a different server hello - distinguish here
|
||||
type ServerHelloChoice = unit(len: uint64, msg: Message, inout sh: Share) {
|
||||
direction_check: DirectionCheck(sh, False); # should be sent by responder
|
||||
sv : bitfield(16) {
|
||||
|
@ -907,8 +925,8 @@ type ServerHelloChoice = unit(len: uint64, msg: Message, inout sh: Share) {
|
|||
var parsed_version: uint16;
|
||||
|
||||
switch ( self.parsed_version ) {
|
||||
TLSv13, TLSv13_draft, 0x7F00 -> : ServerHelloOneThree(len, msg, sh, self.sv.server_version);
|
||||
* -> : ServerHello(len, msg, sh, self.sv.server_version);
|
||||
TLSv13, TLSv13_draft, 0x7F00 -> sh_one_three : ServerHelloOneThree(len, msg, sh, self.sv.server_version);
|
||||
* -> sh_normal : ServerHello(len, msg, sh, self.sv.server_version);
|
||||
};
|
||||
|
||||
on sv {
|
||||
|
@ -927,7 +945,7 @@ type ServerHelloChoice = unit(len: uint64, msg: Message, inout sh: Share) {
|
|||
}
|
||||
};
|
||||
|
||||
# Draft versions of TLS 1.3 had a diffent server hello.
|
||||
# Draft versions of TLS 1.3 had a different server hello.
|
||||
type ServerHelloOneThree = unit(len: uint64, msg: Message, inout sh: Share, server_version: uint16) {
|
||||
random_bytes: bytes &size=32;
|
||||
gmt_unix_time: uint32 &parse-from=self.random_bytes;
|
||||
|
@ -986,7 +1004,7 @@ type Extension = unit(inout sh: Share, client_hello: bool) {
|
|||
};
|
||||
|
||||
on code {
|
||||
print "Extension", self.code;
|
||||
print "Extension", self.code, client_hello;
|
||||
}
|
||||
on unknown {
|
||||
print "Unknown extension", self.code;
|
||||
|
@ -1050,11 +1068,12 @@ type SupportedVersions = unit(sh: Share) {
|
|||
versions: uint16[self.length/2];
|
||||
};
|
||||
|
||||
# If the server sends it, this is the authorative version. Set it.
|
||||
# If the server sends it, this is the authoritative version. Set it.
|
||||
type OneSupportedVersion = unit(inout sh: Share) {
|
||||
version: uint16;
|
||||
|
||||
on version {
|
||||
print "Setting version to ", self.version;
|
||||
set_version(self.version, sh);
|
||||
}
|
||||
};
|
||||
|
@ -1086,7 +1105,7 @@ type ClientHelloKeyShare = unit(sh: Share) {
|
|||
};
|
||||
|
||||
type KeyShare = unit(client_hello: bool, sh: Share, length: uint16) {
|
||||
switch (client_hello ) {
|
||||
switch (client_hello) {
|
||||
True -> client_hello_keyshare : ClientHelloKeyShare(sh);
|
||||
False -> server_hello_keyshare : ServerHelloKeyShareChoice(sh, length);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue