Add support for the signed_certificate_timestamp TLS extension.

This commit is contained in:
Johanna Amann 2017-02-03 11:23:49 -08:00
parent 9db27a6d60
commit 3882ba6fbf
6 changed files with 73 additions and 2 deletions

View file

@ -192,7 +192,7 @@ event ssl_dh_server_params%(c: connection, p: string, q: string, Ys: string%);
## the initial handshake. It contains the list of client supported application
## protocols by the client or the server, respectively.
##
## At the moment it is mostly used to negotiate the use of SPDY / HTTP2-drafts.
## At the moment it is mostly used to negotiate the use of SPDY / HTTP2.
##
## c: The connection.
##
@ -225,6 +225,27 @@ event ssl_extension_application_layer_protocol_negotiation%(c: connection, is_or
## ssl_extension_key_share
event ssl_extension_server_name%(c: connection, is_orig: bool, names: string_vec%);
## Generated for the signed_certificate_timestamp TLS extension as defined in
## :rfc:`6962`. The extension is used to transmit signed proofs that are
## used for Certificate Transparency.
##
## c: The connection.
##
## is_orig: True if event is raised for originator side of the connection.
##
## version: the version of the protocol to which the SCT conforms. Always
## should be 0 (representing version 1)
##
## logid: 32 bit key id
##
## timestamp: the current NTP Time
##
## signature_and_hashalgorithm: signature and hash algorithm used for the
## digitally_signed struct
##
## signature: signature part of the digitally_signed struct
event ssl_extension_signed_certificate_timestamp%(c: connection, is_orig: bool, version: count, logid: string, timestamp: time, signature_and_hashalgorithm: SSL::SignatureAndHashAlgorithm, signature: string%);
## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
## an unencrypted handshake, and Bro extracts as much information out of that
## as it can. This event signals the time when an SSL/TLS has finished the

View file

@ -231,6 +231,24 @@ refine connection Handshake_Conn += {
return true;
%}
function proc_signedcertificatetimestamp(rec: HandshakeRecord, version: uint8, logid: const_bytestring, timestamp: uint64, digitally_signed_algorithms: SignatureAndHashAlgorithm, digitally_signed_signature: const_bytestring) : bool
%{
RecordVal* ha = new RecordVal(BifType::Record::SSL::SignatureAndHashAlgorithm);
ha->Assign(0, new Val(digitally_signed_algorithms->HashAlgorithm(), TYPE_COUNT));
ha->Assign(1, new Val(digitally_signed_algorithms->SignatureAlgorithm(), TYPE_COUNT));
BifEvent::generate_ssl_extension_signed_certificate_timestamp(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig},
version,
new StringVal(logid.length(), reinterpret_cast<const char*>(logid.begin())),
((double)timestamp)/1000,
ha,
new StringVal(digitally_signed_signature.length(), reinterpret_cast<const char*>(digitally_signed_signature.begin()))
);
return true;
%}
function proc_dh_server_key_exchange(rec: HandshakeRecord, p: bytestring, g: bytestring, Ys: bytestring) : bool
%{
BifEvent::generate_ssl_dh_server_params(bro_analyzer(),
@ -251,7 +269,6 @@ refine connection Handshake_Conn += {
return true;
%}
};
refine typeattr ClientHello += &let {
@ -333,3 +350,6 @@ refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(rec.is_orig, rec.msg_type, rec.msg_length);
};
refine typeattr SignedCertificateTimestamp += &let {
proc : bool = $context.connection.proc_signedcertificatetimestamp(rec, version, logid, timestamp, digitally_signed_algorithms, digitally_signed_signature);
};

View file

@ -485,11 +485,31 @@ type SSLExtension(rec: HandshakeRecord) = record {
# EXT_STATUS_REQUEST -> status_request: StatusRequest(rec)[] &until($element == 0 || $element != 0);
EXT_SERVER_NAME -> server_name: ServerNameExt(rec)[] &until($element == 0 || $element != 0);
EXT_SIGNATURE_ALGORITHMS -> signature_algorithm: SignatureAlgorithm(rec)[] &until($element == 0 || $element != 0);
EXT_SIGNED_CERTIFICATE_TIMESTAMP -> certificate_timestamp: SignedCertificateTimestampList(rec)[] &until($element == 0 || $element != 0);
EXT_KEY_SHARE -> key_share: KeyShare(rec)[] &until($element == 0 || $element != 0);
default -> data: bytestring &restofdata;
};
} &length=data_len+4 &exportsourcedata;
type SignedCertificateTimestampList(rec: HandshakeRecord) = record {
length: uint16;
SCTs: SignedCertificateTimestamp(rec)[] &until($input.length() == 0);
} &length=length+2;
type SignedCertificateTimestamp(rec: HandshakeRecord) = record {
# before - framing
length: uint16;
# from here: SignedCertificateTimestamp
version: uint8;
logid: bytestring &length=32;
timestamp: uint64;
extensions_length: uint16; # extensions are not actually defined yet, so we cannot parse them
extensions: bytestring &length=extensions_length;
digitally_signed_algorithms: SignatureAndHashAlgorithm;
digitally_signed_signature_length: uint16;
digitally_signed_signature: bytestring &length=digitally_signed_signature_length;
} &length=length+2;
type ServerNameHostName() = record {
length: uint16;
host_name: bytestring &length=length;

View file

@ -0,0 +1,3 @@
0, 1406997753.366, [HashAlgorithm=4, SignatureAlgorithm=3]
0, 1407002457.456, [HashAlgorithm=4, SignatureAlgorithm=3]
0, 1410299366.023, [HashAlgorithm=4, SignatureAlgorithm=3]

View file

@ -0,0 +1,7 @@
# @TEST-EXEC: bro -r $TRACES/tls/signed_certificate_timestamp.pcap %INPUT
# @TEST-EXEC: btest-diff .stdout
event ssl_extension_signed_certificate_timestamp(c: connection, is_orig: bool, version: count, logid: string, timestamp: time, signature_and_hashalgorithm: SSL::SignatureAndHashAlgorithm, signature: string)
{
print version, timestamp, signature_and_hashalgorithm;
}