Skip to content
/ bro Public
forked from zeek/zeek

Commit

Permalink
TLS 1.3 support.
Browse files Browse the repository at this point in the history
Well, at least -draft-16, and we don't quite parse all extensions yet
(not that there is that much left to parse).
  • Loading branch information
0xxon committed Oct 7, 2016
1 parent 14c119c commit fdef28c
Show file tree
Hide file tree
Showing 23 changed files with 449 additions and 83 deletions.
13 changes: 12 additions & 1 deletion scripts/base/protocols/ssl/consts.bro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export {
const TLSv10 = 0x0301;
const TLSv11 = 0x0302;
const TLSv12 = 0x0303;
const TLSv13 = 0x0304;

const DTLSv10 = 0xFEFF;
# DTLSv11 does not exist
Expand All @@ -18,9 +19,16 @@ export {
[TLSv10] = "TLSv10",
[TLSv11] = "TLSv11",
[TLSv12] = "TLSv12",
[TLSv13] = "TLSv13",
[DTLSv10] = "DTLSv10",
[DTLSv12] = "DTLSv12"
} &default=function(i: count):string { return fmt("unknown-%d", i); };
} &default=function(i: count):string
{
if ( i/0xFF == 0x7F ) # TLS 1.3 draft
return fmt("TLSv13-draft%d", i % 0x7F );

return fmt("unknown-%d", i);
};

## TLS content types:
const CHANGE_CIPHER_SPEC = 20;
Expand All @@ -39,6 +47,8 @@ export {
const SERVER_HELLO = 2;
const HELLO_VERIFY_REQUEST = 3; # RFC 6347
const SESSION_TICKET = 4; # RFC 5077
const HELLO_RETRY_REQUEST = 6; # draft-ietf-tls-tls13-16
const ENCRYPTED_EXTENSIONS = 8; # draft-ietf-tls-tls13-16
const CERTIFICATE = 11;
const SERVER_KEY_EXCHANGE = 12;
const CERTIFICATE_REQUEST = 13;
Expand All @@ -49,6 +59,7 @@ export {
const CERTIFICATE_URL = 21; # RFC 3546
const CERTIFICATE_STATUS = 22; # RFC 3546
const SUPPLEMENTAL_DATA = 23; # RFC 4680
const KEY_UPDATE = 24; # draft-ietf-tls-tls13-16

## Mapping between numeric codes and human readable strings for alert
## levels.
Expand Down
66 changes: 65 additions & 1 deletion scripts/base/protocols/ssl/main.bro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
##! Base SSL analysis script. This script logs information about the SSL/TLS
##! handshaking and encryption establishment process.

@load base/frameworks/notice/weird
@load ./consts

module SSL;
Expand All @@ -16,7 +17,9 @@ export {
uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
## SSL/TLS version that the server offered.
## Numeric SSL/TLS version that the server chose.
version_num: count &optional;
## SSL/TLS version that the server chose.
version: string &log &optional;
## SSL/TLS cipher suite that the server chose.
cipher: string &log &optional;
Expand All @@ -40,6 +43,13 @@ export {
## by the client. This value is used to determine if a session
## is being resumed. It's not logged.
client_key_exchange_seen: bool &default=F;
## Count to track if the server already sent an application data
## packet fot TLS 1.3. Used to track when a session was established.
server_appdata: count &default=0;
## Flag to track if the client already sent an application data
## packet fot TLS 1.3. Used to track when a session was established.
client_appdata: bool &default=F;

## Last alert that was seen during the connection.
last_alert: string &log &optional;
## Next protocol the server chose using the application layer
Expand Down Expand Up @@ -183,6 +193,7 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, server_
{
set_session(c);

c$ssl$version_num = version;
c$ssl$version = version_strings[version];
c$ssl$cipher = cipher_desc[cipher];

Expand All @@ -197,6 +208,15 @@ event ssl_server_curve(c: connection, curve: count) &priority=5
c$ssl$curve = ec_curves[curve];
}

event ssl_extension_key_share(c: connection, is_orig: bool, curves: index_vec)
{
if ( is_orig || |curves| != 1 )
return;

set_session(c);
c$ssl$curve = ec_curves[curves[0]];
}

event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) &priority=5
{
set_session(c);
Expand Down Expand Up @@ -282,6 +302,50 @@ event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &pr
}
}

event ssl_application_data(c: connection, is_orig: bool, length: count)
{
set_session(c);

if ( ! c$ssl?$version || c$ssl$established )
return;

if ( c$ssl$version_num/0xFF != 0x7F && c$ssl$version_num != TLSv13 )
{
local wi = Weird::Info($ts=network_time(), $name="ssl_early_application_data", $uid=c$uid, $id=c$id);
Weird::weird(wi);
return;
}

if ( is_orig )
{
c$ssl$client_appdata = T;
return;
}

if ( c$ssl$client_appdata && c$ssl$server_appdata == 0 )
{
# something went wrong in the handshake here - we can't say if it was established. Just abort.
return;
}
else if ( ! c$ssl$client_appdata && c$ssl$server_appdata == 0 )
{
c$ssl$server_appdata = 1;
return;
}
else if ( c$ssl$client_appdata && c$ssl$server_appdata == 1 )
{
# wait for one more packet before we believe it was established. This one could be an encrypted alert.
c$ssl$server_appdata = 2;
return;
}
else if ( c$ssl$client_appdata && c$ssl$server_appdata == 2 )
{
set_ssl_established(c);
event ssl_established(c);
return;
}
}

event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=5
{
Expand Down
1 change: 1 addition & 0 deletions src/analyzer/protocol/ssl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ bro_plugin_begin(Bro SSL)
bro_plugin_cc(SSL.cc DTLS.cc Plugin.cc)
bro_plugin_bif(types.bif)
bro_plugin_bif(events.bif)
bro_plugin_bif(functions.bif)
bro_plugin_pac(tls-handshake.pac tls-handshake-protocol.pac tls-handshake-analyzer.pac ssl-defs.pac
proc-client-hello.pac
proc-server-hello.pac
Expand Down
7 changes: 7 additions & 0 deletions src/analyzer/protocol/ssl/SSL.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ void SSL_Analyzer::EndpointEOF(bool is_orig)
handshake_interp->FlowEOF(is_orig);
}

void SSL_Analyzer::StartEncryption()
{
interp->startEncryption(true);
interp->startEncryption(false);
interp->setEstablished();
}

void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
{
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
Expand Down
3 changes: 3 additions & 0 deletions src/analyzer/protocol/ssl/SSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class SSL_Analyzer : public tcp::TCP_ApplicationAnalyzer {

void SendHandshake(const u_char* begin, const u_char* end, bool orig);

// tell the analyzer that encryption has started.
void StartEncryption();

// Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig);

Expand Down
53 changes: 46 additions & 7 deletions src/analyzer/protocol/ssl/events.bif
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, client
## :bro:id:`SSL::version_strings` table maps them to descriptive names.
##
## possible_ts: The current time as sent by the server. Note that SSL/TLS does
## not require clocks to be set correctly, so treat with care.
## not require clocks to be set correctly, so treat with care. This value
## is not sent in TLSv1.3.
##
## session_id: The session ID as sent back by the server (if any).
## session_id: The session ID as sent back by the server (if any). This value is not
## sent in TLSv1.3.
##
## server_random: The random value sent by the server. For version 2 connections,
## the connection-id is returned.
Expand All @@ -56,7 +58,8 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, client
## them to descriptive names.
##
## comp_method: The compression method chosen by the client. The values are
## standardized as part of the SSL/TLS protocol.
## standardized as part of the SSL/TLS protocol. This value is not
## sent in TLSv1.3.
##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
## ssl_session_ticket_handshake x509_certificate ssl_server_curve
Expand All @@ -83,7 +86,7 @@ event ssl_server_hello%(c: connection, version: count, possible_ts: time, server
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## ssl_session_ticket_handshake ssl_extension_ec_point_formats
## ssl_extension_elliptic_curves ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name ssl_extension_signature_algorithm
## ssl_extension_server_name ssl_extension_signature_algorithm ssl_extension_key_share
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);

## Generated for an SSL/TLS Elliptic Curves extension. This TLS extension is
Expand All @@ -100,6 +103,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_ec_point_formats ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name ssl_server_curve ssl_extension_signature_algorithm
## ssl_extension_key_share
event ssl_extension_elliptic_curves%(c: connection, is_orig: bool, curves: index_vec%);

## Generated for an SSL/TLS Supported Point Formats extension. This TLS extension
Expand All @@ -117,6 +121,7 @@ event ssl_extension_elliptic_curves%(c: connection, is_orig: bool, curves: index
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name ssl_server_curve ssl_extension_signature_algorithm
## ssl_extension_key_share
event ssl_extension_ec_point_formats%(c: connection, is_orig: bool, point_formats: index_vec%);

## Generated for an Signature Algorithms extension. This TLS extension
Expand All @@ -133,9 +138,25 @@ event ssl_extension_ec_point_formats%(c: connection, is_orig: bool, point_format
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name ssl_server_curve
## ssl_extension_server_name ssl_server_curve ssl_extension_key_share
event ssl_extension_signature_algorithm%(c: connection, is_orig: bool, signature_algorithms: signature_and_hashalgorithm_vec%);

## Generated for a Key Share extension. This TLS extension is defined in TLS1.3-draft16
## and seht by the client and the server in the initial handshake. It gives the list of
## named groups supported by the client and chosen by the server.
##
## c: The connection.
##
## is_orig: True if event is raised for originator side of the connection.
##
## curves: List of supported/chosen named groups.
##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name ssl_server_curve
event ssl_extension_key_share%(c: connection, is_orig: bool, curves: index_vec%);

## Generated if a named curve is chosen by the server for an SSL/TLS connection.
## The curve is sent by the server in the ServerKeyExchange message as defined
## in :rfc:`4492`, in case an ECDH or ECDHE cipher suite is chosen.
Expand All @@ -147,7 +168,7 @@ event ssl_extension_signature_algorithm%(c: connection, is_orig: bool, signature
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_application_layer_protocol_negotiation
## ssl_extension_server_name
## ssl_extension_server_name ssl_extension_key_share
event ssl_server_curve%(c: connection, curve: count%);

## Generated if a server uses a DH-anon or DHE cipher suite. This event contains
Expand Down Expand Up @@ -182,7 +203,7 @@ event ssl_dh_server_params%(c: connection, p: string, q: string, Ys: string%);
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_ec_point_formats
## ssl_extension_server_name
## ssl_extension_server_name ssl_extension_key_share
event ssl_extension_application_layer_protocol_negotiation%(c: connection, is_orig: bool, protocols: string_vec%);

## Generated for an SSL/TLS Server Name extension. This SSL/TLS extension is
Expand All @@ -201,6 +222,7 @@ event ssl_extension_application_layer_protocol_negotiation%(c: connection, is_or
## ssl_session_ticket_handshake ssl_extension
## ssl_extension_elliptic_curves ssl_extension_ec_point_formats
## ssl_extension_application_layer_protocol_negotiation
## ssl_extension_key_share
event ssl_extension_server_name%(c: connection, is_orig: bool, names: string_vec%);

## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
Expand Down Expand Up @@ -284,6 +306,23 @@ event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count,
## ssl_alert ssl_encrypted_data
event ssl_heartbeat%(c: connection, is_orig: bool, length: count, heartbeat_type: count, payload_length: count, payload: string%);

## Generated for non-handshake SSL/TLS application_data messages that are sent before
## full encryption starts. For TLS 1.2 and lower, this event should not be raised. For TLS 1.3,
## it is used by Bro internally to determine if the connection has been completely setup.
## This is necessary as TLS 1.3 does not have CCS anymore.
##
## c: The connection.
##
## is_orig: True if event is raised for originator side of the connection.
##
## content_type: message type as reported by TLS session layer.
##
## length: length of the entire heartbeat message.
##
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
## ssl_alert ssl_heartbeat
event ssl_application_data%(c: connection, is_orig: bool, length: count%);

## Generated for SSL/TLS messages that are sent after session encryption
## started.
##
Expand Down
16 changes: 16 additions & 0 deletions src/analyzer/protocol/ssl/functions.bif
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

%%{
#include "analyzer/protocol/ssl/SSL.h"
%%}

## Sets if the SSL analyzer should consider the connection established (handshake
## finished succesfully).
##
## c: The SSL connection.
function set_ssl_established%(c: connection%): any
%{
analyzer::Analyzer* sa = c->FindAnalyzer("SSL");
if ( sa )
static_cast<analyzer::ssl::SSL_Analyzer*>(sa)->StartEncryption();
return 0;
%}
14 changes: 12 additions & 2 deletions src/analyzer/protocol/ssl/ssl-defs.pac
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,16 @@ function to_string_val(data : uint8[]) : StringVal

function version_ok(vers : uint16) : bool
%{
if ( vers >> 8 == 0x7F ) // 1.3 draft
return true;

switch ( vers ) {
case SSLv20:
case SSLv30:
case TLSv10:
case TLSv11:
case TLSv12:
case TLSv13:
case DTLSv10:
case DTLSv12:
return true;
Expand All @@ -88,7 +92,7 @@ using std::string;
#include "events.bif.h"
%}

# a maximum of 100k for one record seems safe
# a maximum of 100k for one record seems safe
let MAX_DTLS_HANDSHAKE_RECORD: uint32 = 100000;

enum ContentType {
Expand All @@ -112,6 +116,8 @@ enum SSLVersions {
TLSv10 = 0x0301,
TLSv11 = 0x0302,
TLSv12 = 0x0303,
TLSv13 = 0x0304,
TLSv13_draft = 0x7F00, # the second byte actually defines the draft.

DTLSv10 = 0xFEFF,
# DTLSv11 does not exist.
Expand Down Expand Up @@ -139,7 +145,11 @@ enum SSLExtensions {
EXT_STATUS_REQUEST_V2 = 17,
EXT_SIGNED_CERTIFICATE_TIMESTAMP = 18,
EXT_SESSIONTICKET_TLS = 35,
EXT_EXTENDED_RANDOM = 40,
EXT_KEY_SHARE = 40,
EXT_PRE_SHARED_KEY = 41,
EXT_EARLY_DATA = 42,
EXT_SUPPORTED_VERSIONS = 43,
EXT_COOKIE = 44,
EXT_NEXT_PROTOCOL_NEGOTIATION = 13172,
EXT_ORIGIN_BOUND_CERTIFICATES = 13175,
EXT_ENCRYPTED_CLIENT_CERTIFICATES = 13180,
Expand Down
Loading

0 comments on commit fdef28c

Please sign in to comment.