diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index 2855dd7fe9..3fb565b8aa 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -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 diff --git a/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac b/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac index a4f4f94c6f..7f4eb2ba3c 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac @@ -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(logid.begin())), + ((double)timestamp)/1000, + ha, + new StringVal(digitally_signed_signature.length(), reinterpret_cast(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); +}; diff --git a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac index da01a27f1d..65da41e0db 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac @@ -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; diff --git a/testing/btest/Baseline/scripts.base.protocols.ssl.signed_certificate_timestamp/.stdout b/testing/btest/Baseline/scripts.base.protocols.ssl.signed_certificate_timestamp/.stdout new file mode 100644 index 0000000000..abed68df42 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ssl.signed_certificate_timestamp/.stdout @@ -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] diff --git a/testing/btest/Traces/tls/signed_certificate_timestamp.pcap b/testing/btest/Traces/tls/signed_certificate_timestamp.pcap new file mode 100644 index 0000000000..50efed9cea Binary files /dev/null and b/testing/btest/Traces/tls/signed_certificate_timestamp.pcap differ diff --git a/testing/btest/scripts/base/protocols/ssl/signed_certificate_timestamp.test b/testing/btest/scripts/base/protocols/ssl/signed_certificate_timestamp.test new file mode 100644 index 0000000000..80a041c316 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ssl/signed_certificate_timestamp.test @@ -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; + }