mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 09:38:19 +00:00
Add basic DTLSv1.3 support
DTLSv1.3 changes the DTLS record format, introducing a completely new header - which is a first for DTLS. We don't currently completely parse this header, as this requires a bit more statekeeping. This will be added in a future revision. This also also has little practical implications.
This commit is contained in:
parent
e7c9fa1f6e
commit
d6c4c510ea
7 changed files with 88 additions and 5 deletions
|
@ -11,6 +11,7 @@ export {
|
||||||
const DTLSv10 = 0xFEFF;
|
const DTLSv10 = 0xFEFF;
|
||||||
# DTLSv11 does not exist
|
# DTLSv11 does not exist
|
||||||
const DTLSv12 = 0xFEFD;
|
const DTLSv12 = 0xFEFD;
|
||||||
|
const DTLSv13 = 0xFEFC;
|
||||||
|
|
||||||
## Mapping between the constants and string values for SSL/TLS versions.
|
## Mapping between the constants and string values for SSL/TLS versions.
|
||||||
const version_strings: table[count] of string = {
|
const version_strings: table[count] of string = {
|
||||||
|
@ -21,7 +22,8 @@ export {
|
||||||
[TLSv12] = "TLSv12",
|
[TLSv12] = "TLSv12",
|
||||||
[TLSv13] = "TLSv13",
|
[TLSv13] = "TLSv13",
|
||||||
[DTLSv10] = "DTLSv10",
|
[DTLSv10] = "DTLSv10",
|
||||||
[DTLSv12] = "DTLSv12"
|
[DTLSv12] = "DTLSv12",
|
||||||
|
[DTLSv13] = "DTLSv13"
|
||||||
} &default=function(i: count):string
|
} &default=function(i: count):string
|
||||||
{
|
{
|
||||||
if ( i/0xFF == 0x7F ) # TLS 1.3 draft
|
if ( i/0xFF == 0x7F ) # TLS 1.3 draft
|
||||||
|
|
|
@ -138,6 +138,31 @@ refine connection SSL_Conn += {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function proc_unified_record(is_orig: bool, ur: UnifiedRecord) : bool
|
||||||
|
%{
|
||||||
|
// we don't have a CCS packet anymore - so let's just assume the connection is established once we have seen a packet from each direction.
|
||||||
|
if ( is_orig )
|
||||||
|
client_state_ = STATE_ENCRYPTED;
|
||||||
|
else
|
||||||
|
server_state_ = STATE_ENCRYPTED;
|
||||||
|
|
||||||
|
if ( client_state_ == STATE_ENCRYPTED && server_state_ == STATE_ENCRYPTED && established_ == false )
|
||||||
|
{
|
||||||
|
established_ = true;
|
||||||
|
if ( ssl_established )
|
||||||
|
zeek::BifEvent::enqueue_ssl_established(zeek_analyzer(), zeek_analyzer()->Conn());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ssl_encrypted_data )
|
||||||
|
{
|
||||||
|
// FIXME: swallow is not quite the correct length, because we are not parsing the entire header
|
||||||
|
zeek::BifEvent::enqueue_ssl_encrypted_data(zeek_analyzer(),
|
||||||
|
zeek_analyzer()->Conn(), is_orig ^ zeek_analyzer()->GetFlipped(), DTLSv13, APPLICATION_DATA, ur->swallow().length());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
refine typeattr SSLRecord += &let {
|
refine typeattr SSLRecord += &let {
|
||||||
|
@ -147,3 +172,7 @@ refine typeattr SSLRecord += &let {
|
||||||
refine typeattr Handshake += &let {
|
refine typeattr Handshake += &let {
|
||||||
proc: bool = $context.connection.proc_handshake(rec, this);
|
proc: bool = $context.connection.proc_handshake(rec, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
refine typeattr UnifiedRecord += &let {
|
||||||
|
proc: bool = $context.connection.proc_unified_record(is_orig, this);
|
||||||
|
};
|
||||||
|
|
|
@ -4,11 +4,37 @@
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
type DTLSPDU(is_orig: bool) = record {
|
type DTLSPDU(is_orig: bool) = record {
|
||||||
records: SSLRecord(is_orig)[] &transient;
|
records: SSLRecordSwitch(is_orig)[] &transient;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SSLRecord(is_orig: bool) = record {
|
# This feels like (another) really dirty hack. DTLS 1.3 introduces a new way in which ciphertext records
|
||||||
content_type: uint8;
|
# can be encoded, using a new unified header, which is completely different from the earlier DTLS headers.
|
||||||
|
# It only is used after the client & server hello - which essentially are the same as in DTLS 1.2 (including
|
||||||
|
# using the same record-layer versions - which is why `dtls_version_ok` underneath does not refer to DTLS 1.3)
|
||||||
|
# The DTLS 1.3 unified header is signaled by the first 3 bits of the first byte being set to `001`, but only
|
||||||
|
# after DTLS 1.3 has been negotiated.
|
||||||
|
type SSLRecordSwitch(is_orig: bool) = record {
|
||||||
|
firstbyte: uint8;
|
||||||
|
|
||||||
|
cont: case $context.connection.choose_record_type(firstbyte) of {
|
||||||
|
false -> rec: SSLRecord(firstbyte, is_orig);
|
||||||
|
true -> unified: UnifiedRecord(firstbyte, is_orig);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type UnifiedRecord(firstbyte: uint8, is_orig: bool) = record {
|
||||||
|
# sequence_number: bytestring &length=(sequence_number_length?2:1);
|
||||||
|
# lets just ignore eveything for now. We have very limited example
|
||||||
|
# data, and it is hard to parse the CID due to variable length.
|
||||||
|
swallow: bytestring &restofdata;
|
||||||
|
} &let {
|
||||||
|
with_cid: bool = ((firstbyte&0x10)==0x10);
|
||||||
|
sequence_number_length: bool = ((firstbyte&0x08)==0x08);
|
||||||
|
lengh_present: bool = ((firstbyte&0x04)==0x04);
|
||||||
|
epoch_low_bits: uint8 = (firstbyte&0x03);
|
||||||
|
};
|
||||||
|
|
||||||
|
type SSLRecord(content_type: uint8, is_orig: bool) = record {
|
||||||
version: uint16;
|
version: uint16;
|
||||||
# the epoch signalizes that a changecipherspec message has been received. Hence, everything with
|
# the epoch signalizes that a changecipherspec message has been received. Hence, everything with
|
||||||
# an epoch > 0 should be encrypted
|
# an epoch > 0 should be encrypted
|
||||||
|
@ -83,4 +109,11 @@ refine connection SSL_Conn += {
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function choose_record_type(firstbyte: uint8): bool
|
||||||
|
%{
|
||||||
|
uint16_t negotiated_version = zeek_analyzer()->GetNegotiatedVersion();
|
||||||
|
if ( negotiated_version == DTLSv13 && ( (firstbyte & 0x20) == 0x20 ) )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
%}
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,6 +77,7 @@ function version_ok(vers : uint16) : bool
|
||||||
case TLSv13:
|
case TLSv13:
|
||||||
case DTLSv10:
|
case DTLSv10:
|
||||||
case DTLSv12:
|
case DTLSv12:
|
||||||
|
case DTLSv13:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -121,7 +122,8 @@ enum SSLVersions {
|
||||||
|
|
||||||
DTLSv10 = 0xFEFF,
|
DTLSv10 = 0xFEFF,
|
||||||
# DTLSv11 does not exist.
|
# DTLSv11 does not exist.
|
||||||
DTLSv12 = 0xFEFD
|
DTLSv12 = 0xFEFD,
|
||||||
|
DTLSv13 = 0xFEFC
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SSLExtensions {
|
enum SSLExtensions {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path ssl
|
||||||
|
#open XXXX-XX-XX-XX-XX-XX
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established ssl_history cert_chain_fps client_cert_chain_fps sni_matches_cert
|
||||||
|
#types time string addr port addr port string string string string bool string string bool string vector[string] vector[string] bool
|
||||||
|
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 10.168.36.147 33714 10.168.36.144 11111 DTLSv13 TLS_AES_128_GCM_SHA256 secp256r1 - F - - T CjCs - - -
|
||||||
|
#close XXXX-XX-XX-XX-XX-XX
|
BIN
testing/btest/Traces/tls/dtls13-wolfssl.pcap
Normal file
BIN
testing/btest/Traces/tls/dtls13-wolfssl.pcap
Normal file
Binary file not shown.
6
testing/btest/scripts/base/protocols/ssl/dtls-13.test
Normal file
6
testing/btest/scripts/base/protocols/ssl/dtls-13.test
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# This tests a normal SSL connection and the log it outputs.
|
||||||
|
|
||||||
|
# @TEST-EXEC: zeek -C -r $TRACES/tls/dtls13-wolfssl.pcap %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff ssl.log
|
||||||
|
# @TEST-EXEC: test ! -f dpd.log
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue