diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 586decbad5..d5b7fa12fa 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -3009,6 +3009,23 @@ export { }; } +module SSL; +export { + type SignatureAndHashAlgorithm: record { + HashAlgorithm: count; ##< Hash algorithm number + SignatureAlgorithm: count; ##< Signature algorithm number + }; +} + +module GLOBAL; + +## A vector of Signature and Hash Algorithms. +## +## .. todo:: We need this type definition only for declaring builtin functions +## via ``bifcl``. We should extend ``bifcl`` to understand composite types +## directly and then remove this alias. +type signature_and_hashalgorithm_vec: vector of SSL::SignatureAndHashAlgorithm; + module X509; export { type Certificate: record { diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index c8825057fa..fa9f9a2788 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -57,6 +57,27 @@ export { [2] = "fatal", } &default=function(i: count):string { return fmt("unknown-%d", i); }; + ## Mapping between numeric codes and human readable strings for hash + ## algorithms. + const hash_algorithms: table[count] of string = { + [0] = "none", + [1] = "md5", + [2] = "sha1", + [3] = "sha224", + [4] = "sha256", + [5] = "sha384", + [6] = "sha512", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + + ## Mapping between numeric codes and human readable strings for signature + ## algorithms. + const signature_algorithms: table[count] of string = { + [0] = "anonymous", + [1] = "rsa", + [2] = "dsa", + [3] = "ecdsa", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + ## Mapping between numeric codes and human readable strings for alert ## descriptions. const alert_descriptions: table[count] of string = { diff --git a/src/analyzer/protocol/ssl/CMakeLists.txt b/src/analyzer/protocol/ssl/CMakeLists.txt index c8008da4d6..006a04b862 100644 --- a/src/analyzer/protocol/ssl/CMakeLists.txt +++ b/src/analyzer/protocol/ssl/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI 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_pac(tls-handshake.pac tls-handshake-protocol.pac tls-handshake-analyzer.pac ssl-defs.pac proc-client-hello.pac diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index 18704d25ec..4d8b65821d 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -83,7 +83,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_server_name ssl_extension_signature_algorithm event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); ## Generated for an SSL/TLS Elliptic Curves extension. This TLS extension is @@ -99,7 +99,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello ## 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_server_name ssl_server_curve ssl_extension_signature_algorithm 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 @@ -116,9 +116,26 @@ event ssl_extension_elliptic_curves%(c: connection, is_orig: bool, curves: index ## .. 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_signature_algorithm event ssl_extension_ec_point_formats%(c: connection, is_orig: bool, point_formats: index_vec%); +## Generated for an Signature Algorithms extension. This TLS extension +## is defined in :rfc:`5246` and sent by the client in the initial +## handshake. It gives the list of signature and hash algorithms supported by the +## client. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## signature_algorithms: List of supported signature and hash algorithm pairs. +## +## .. 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_signature_algorithm%(c: connection, is_orig: bool, signature_algorithms: signature_and_hashalgorithm_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. diff --git a/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac b/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac index 17432fa5cb..092ad5b59f 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac @@ -102,6 +102,30 @@ refine connection Handshake_Conn += { return true; %} + function proc_signature_algorithm(rec: HandshakeRecord, supported_signature_algorithms: SignatureAndHashAlgorithm[]) : bool + %{ + RecordType* rt = BifType::Record::SSL::SignatureAndHashAlgorithm; + VectorType* vt = new VectorType(rt); + + VectorVal* slist = new VectorVal(vt); + Unref(vt); // not consumed, VectorVal refs. + + if ( supported_signature_algorithms ) + { + for ( unsigned int i = 0; i < supported_signature_algorithms->size(); ++i ) + { + RecordVal* el = new RecordVal(rt); + el->Assign(0, new Val((*supported_signature_algorithms)[i]->HashAlgorithm(), TYPE_COUNT)); + el->Assign(1, new Val((*supported_signature_algorithms)[i]->SignatureAlgorithm(), TYPE_COUNT)); + slist->Assign(i, el); + } + } + + BifEvent::generate_ssl_extension_signature_algorithm(bro_analyzer(), bro_analyzer()->Conn(), ${rec.is_orig}, slist); + + return true; + %} + function proc_apnl(rec: HandshakeRecord, protocols: ProtocolName[]) : bool %{ VectorVal* plist = new VectorVal(internal_type("string_vec")->AsVectorType()); @@ -247,6 +271,10 @@ refine typeattr EllipticCurves += &let { proc : bool = $context.connection.proc_elliptic_curves(rec, elliptic_curve_list); }; +refine typeattr SignatureAlgorithm += &let { + proc : bool = $context.connection.proc_signature_algorithm(rec, supported_signature_algorithms); +} + refine typeattr ApplicationLayerProtocolNegotiationExtension += &let { proc : bool = $context.connection.proc_apnl(rec, protocol_name_list); }; diff --git a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac index 3b65e63ee7..e0c63f73d3 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac @@ -458,6 +458,7 @@ type SSLExtension(rec: HandshakeRecord) = record { EXT_EC_POINT_FORMATS -> ec_point_formats: EcPointFormats(rec)[] &until($element == 0 || $element != 0); # 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); default -> data: bytestring &restofdata; }; } &length=data_len+4 &exportsourcedata; @@ -501,6 +502,16 @@ type EcPointFormats(rec: HandshakeRecord) = record { point_format_list: uint8[length]; }; +type SignatureAndHashAlgorithm() = record { + HashAlgorithm: uint8; + SignatureAlgorithm: uint8; +} + +type SignatureAlgorithm(rec: HandshakeRecord) = record { + length: uint16; + supported_signature_algorithms: SignatureAndHashAlgorithm[] &until($input.length() == 0); +} + type EllipticCurves(rec: HandshakeRecord) = record { length: uint16; elliptic_curve_list: uint16[length/2]; diff --git a/src/analyzer/protocol/ssl/tls-handshake.pac b/src/analyzer/protocol/ssl/tls-handshake.pac index a3c45fa492..3bc03eeddb 100644 --- a/src/analyzer/protocol/ssl/tls-handshake.pac +++ b/src/analyzer/protocol/ssl/tls-handshake.pac @@ -3,6 +3,11 @@ %include binpac.pac %include bro.pac +%extern{ +#include "types.bif.h" +#include "events.bif.h" +%} + analyzer TLSHandshake withcontext { connection: Handshake_Conn; flow: Handshake_Flow; diff --git a/testing/btest/Baseline/scripts.base.protocols.ssl.tls-extension-events/.stdout b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-extension-events/.stdout index 8305175edb..c9434d9ddd 100644 --- a/testing/btest/Baseline/scripts.base.protocols.ssl.tls-extension-events/.stdout +++ b/testing/btest/Baseline/scripts.base.protocols.ssl.tls-extension-events/.stdout @@ -6,6 +6,15 @@ secp521r1 Point formats, 192.168.4.149, 74.125.239.152, T uncompressed ALPN, 192.168.4.149, 74.125.239.152, [spdy/3, spdy/3.1, http/1.1] +signature_algorithm, 192.168.4.149, 74.125.239.152 +sha256, rsa +sha384, rsa +sha1, rsa +sha256, ecdsa +sha384, ecdsa +sha1, ecdsa +sha256, dsa +sha1, dsa Point formats, 192.168.4.149, 74.125.239.152, F uncompressed ansiX962_compressed_prime diff --git a/testing/btest/scripts/base/protocols/ssl/tls-extension-events.test b/testing/btest/scripts/base/protocols/ssl/tls-extension-events.test index a2db2afe95..261a698833 100644 --- a/testing/btest/scripts/base/protocols/ssl/tls-extension-events.test +++ b/testing/btest/scripts/base/protocols/ssl/tls-extension-events.test @@ -24,3 +24,12 @@ event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) { print "server_name", c$id$orig_h, c$id$resp_h, names; } + +event ssl_extension_signature_algorithm(c: connection, is_orig: bool, signature_algorithms: vector of SSL::SignatureAndHashAlgorithm) + { + print "signature_algorithm", c$id$orig_h, c$id$resp_h; + for ( i in signature_algorithms) + { + print SSL::hash_algorithms[signature_algorithms[i]$HashAlgorithm], SSL::signature_algorithms[signature_algorithms[i]$SignatureAlgorithm]; + } + }