From e85a016521cf2daf613671cd6d03ec380f94810f Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Mon, 22 Apr 2019 23:02:08 +0200 Subject: [PATCH] Parse pre-shared-key extension. No documentation yet... --- scripts/base/init-bare.zeek | 6 ++ src/analyzer/protocol/ssl/events.bif | 3 + .../protocol/ssl/tls-handshake-analyzer.pac | 52 ++++++++++++++++++ .../protocol/ssl/tls-handshake-protocol.pac | 38 +++++++++++++ src/analyzer/protocol/ssl/types.bif | 1 + .../.stdout | 51 ++++++++++++++++- .../Traces/tls/tls13_psk_succesfull.pcap | Bin 0 -> 4088 bytes .../protocols/ssl/tls-extension-events.test | 14 ++++- 8 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 testing/btest/Traces/tls/tls13_psk_succesfull.pcap diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 4575b3a694..cc328cd9aa 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -4170,6 +4170,10 @@ export { SignatureAlgorithm: count; ##< Signature algorithm number }; + type PSKIdentity: record { + identity: string; ##< PSK identity + obfuscated_ticket_age: count; + }; ## Number of non-DTLS frames that can occur in a DTLS connection before ## parsing of the connection is suspended. @@ -4191,6 +4195,8 @@ module GLOBAL; ## directly and then remove this alias. type signature_and_hashalgorithm_vec: vector of SSL::SignatureAndHashAlgorithm; +type psk_identity_vec: vector of SSL::PSKIdentity; + module X509; export { type Certificate: record { diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif index 2ef675554f..774017eb9f 100644 --- a/src/analyzer/protocol/ssl/events.bif +++ b/src/analyzer/protocol/ssl/events.bif @@ -182,6 +182,9 @@ event ssl_extension_signature_algorithm%(c: connection, is_orig: bool, signature ## ssl_rsa_client_pms ssl_server_signature event ssl_extension_key_share%(c: connection, is_orig: bool, curves: index_vec%); +event ssl_extension_pre_shared_key_client_hello%(c: connection, is_orig: bool, identities: psk_identity_vec, binders: string_vec%); +event ssl_extension_pre_shared_key_server_hello%(c: connection, is_orig: bool, selected_identity: count%); + ## 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 5cf250c366..8e0ae84455 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-analyzer.pac @@ -411,6 +411,50 @@ refine connection Handshake_Conn += { return true; %} + function proc_pre_shared_key_server_hello(rec: HandshakeRecord, identities: PSKIdentitiesList, binders: PSKBindersList) : bool + %{ + if ( ! ssl_extension_pre_shared_key_server_hello ) + return true; + + VectorVal* slist = new VectorVal(internal_type("psk_identity_vec")->AsVectorType()); + + if ( identities && identities->identities() ) + { + uint32 i = 0; + for ( auto&& identity : *(identities->identities()) ) + { + RecordVal* el = new RecordVal(BifType::Record::SSL::PSKIdentity); + el->Assign(0, new StringVal(identity->identity().length(), (const char*) identity->identity().data())); + el->Assign(1, val_mgr->GetCount(identity->obfuscated_ticket_age())); + slist->Assign(i++, el); + } + } + + VectorVal* blist = new VectorVal(internal_type("string_vec")->AsVectorType()); + if ( binders && binders->binders() ) + { + uint32 i = 0; + for ( auto&& binder : *(binders->binders()) ) + blist->Assign(i++, new StringVal(binder->binder().length(), (const char*) binder->binder().data())); + } + + BifEvent::generate_ssl_extension_pre_shared_key_client_hello(bro_analyzer(), bro_analyzer()->Conn(), + ${rec.is_orig}, slist, blist); + + return true; + %} + + function proc_pre_shared_key_client_hello(rec: HandshakeRecord, selected_identity: uint16) : bool + %{ + if ( ! ssl_extension_pre_shared_key_client_hello ) + return true; + + BifEvent::generate_ssl_extension_pre_shared_key_server_hello(bro_analyzer(), + bro_analyzer()->Conn(), ${rec.is_orig}, selected_identity); + + return true; + %} + }; refine typeattr ClientHello += &let { @@ -520,6 +564,14 @@ refine typeattr PSKKeyExchangeModes += &let { proc : bool = $context.connection.proc_psk_key_exchange_modes(rec, modes); }; +refine typeattr OfferedPsks += &let { + proc : bool = $context.connection.proc_pre_shared_key_server_hello(rec, identities, binders); +}; + +refine typeattr SelectedPreSharedKeyIdentity += &let { + proc : bool = $context.connection.proc_pre_shared_key_client_hello(rec, selected_identity); +}; + refine typeattr Handshake += &let { proc : bool = $context.connection.proc_handshake(rec.is_orig, rec.msg_type, rec.msg_length); }; diff --git a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac index f141a6e9b0..e3b2b88aeb 100644 --- a/src/analyzer/protocol/ssl/tls-handshake-protocol.pac +++ b/src/analyzer/protocol/ssl/tls-handshake-protocol.pac @@ -778,6 +778,7 @@ type SSLExtension(rec: HandshakeRecord) = record { EXT_KEY_SHARE -> key_share: KeyShare(rec)[] &until($element == 0 || $element != 0); EXT_SUPPORTED_VERSIONS -> supported_versions_selector: SupportedVersionsSelector(rec, data_len)[] &until($element == 0 || $element != 0); EXT_PSK_KEY_EXCHANGE_MODES -> psk_key_exchange_modes: PSKKeyExchangeModes(rec)[] &until($element == 0 || $element != 0); + EXT_PRE_SHARED_KEY -> pre_shared_key: PreSharedKey(rec)[] &until($element == 0 || $element != 0); default -> data: bytestring &restofdata; }; } &length=data_len+4 &exportsourcedata; @@ -864,6 +865,43 @@ type KeyShare(rec: HandshakeRecord) = case rec.msg_type of { default -> other : bytestring &restofdata &transient; }; +type SelectedPreSharedKeyIdentity(rec: HandshakeRecord) = record { + selected_identity: uint16; +}; + +type PSKIdentity() = record { + length: uint16; + identity: bytestring &length=length; + obfuscated_ticket_age: uint32; +}; + +type PSKIdentitiesList() = record { + length: uint16; + identities: PSKIdentity[] &until($input.length() == 0); +} &length=length+2; + +type PSKBinder() = record { + length: uint8; + binder: bytestring &length=length; +}; + +type PSKBindersList() = record { + length: uint16; + binders: PSKBinder[] &until($input.length() == 0); +} &length=length+2; + +type OfferedPsks(rec: HandshakeRecord) = record { + identities: PSKIdentitiesList; + binders: PSKBindersList; +}; + +type PreSharedKey(rec: HandshakeRecord) = case rec.msg_type of { + CLIENT_HELLO -> offered_psks : OfferedPsks(rec); + SERVER_HELLO -> selected_identity : SelectedPreSharedKeyIdentity(rec); + # ... well, we don't parse hello retry requests yet, because I don't have an example of them on the wire. + default -> other : bytestring &restofdata &transient; +}; + type SignatureAlgorithm(rec: HandshakeRecord) = record { length: uint16; supported_signature_algorithms: SignatureAndHashAlgorithm[] &until($input.length() == 0); diff --git a/src/analyzer/protocol/ssl/types.bif b/src/analyzer/protocol/ssl/types.bif index a6f7f069cf..c2bce5a44f 100644 --- a/src/analyzer/protocol/ssl/types.bif +++ b/src/analyzer/protocol/ssl/types.bif @@ -1,5 +1,6 @@ module SSL; type SignatureAndHashAlgorithm: record; +type PSKIdentity: record; module GLOBAL; 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 7347ea650f..a840e43bf4 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 @@ -45,7 +45,7 @@ sha1, dsa sha256, dsa sha384, dsa sha512, dsa -supported_versions(, 192.168.6.240, 139.162.123.134 +supported_versions, 192.168.6.240, 139.162.123.134 TLSv13-draft19 TLSv12 TLSv11 @@ -78,7 +78,7 @@ sha1, dsa sha256, dsa sha384, dsa sha512, dsa -supported_versions(, 192.168.6.240, 139.162.123.134 +supported_versions, 192.168.6.240, 139.162.123.134 TLSv13-draft19 TLSv12 TLSv11 @@ -86,3 +86,50 @@ TLSv10 psk_key_exchange_modes, 192.168.6.240, 139.162.123.134 1 0 +pre_shared_key client hello, 192.168.6.240, 139.162.123.134, [[identity=\x01\xf3\x88\x12\xae\xeb\x13\x01\xed]\xcf\x0b\x8f\xad\xf2\xc1I\x9f-\xfa\xe1\x98\x9f\xb7\x82@\x81Or\x0e\xbe\xfc\xa3\xbc\x8f\x03\x86\xf1\x8e\xae\xd7\xe5\xa2\xee\xf3\xde\xb7\xa5\xf6\\xeb\x18^ICPm!|\x09\xe0NE\xe8\x0f\xda\xf8\xf2\xa8s\x84\x17>\xe5\xd9!\x19\x09\xfe\xdb\xa87\x05\xd7\xd06JG\xeb\xad\xf9\xf8\x13?#\xdc\xe7J\xad\x14\xbfS.\x98\xd8\xd2r\x01\xef\xc5\x0c_\xdf\xc9[7\xa7l\xa7\xa0\xb5\xda\x83\x16\x10\xa1\xdb\xe2$q^enkJEj1}6HAlQOBP)3sP5~B7VWq!cf}aln z2UajEDQ88xTjIbwxyjind70T__l)$V*~v-S;B7j{fF^M26J5|1Xc?Qn1 zf%V~%J#ndl4eOs2^uefRSNb2CE5z7N2RK^ZGl9oHm#d?2pQ5DUAMQaO8*XZH!)JNLjZEAIi z%0R9OWur73);-cPRSQ^=d1A!qhs1<@rkC0>6Rvxj1{!ja#zS!t4{>e4pg~+}&55iQQf9UG?~KDdgC)wwx`)PvNIQ zX;WoWMbjbPgZG5J{6yXzmhlqa4gSQN^P?evH{)$#Ivj?orkbY1P1UdmDx0dH8V;fP zDGcV_8@Q1;3>_icRZ*JnOBzeVn)Z>T&s*z$A9$7 zgvrYfM z9!)dkvFA8Y;8U;WxZ|JaYZ@m0q-<||P;ug%`$hhAL&~ItOT7tO-L0%G3)cLuUu`++ ziXOmn0?ey6t0voh^7y-lSNx)CKQ`xJ{NysXZSO>{{q9}Kb9b5zVBRJz0u_5Gk=CJr51L_ZWoT<8M~m@ z-sP2^HO+UwzjgZlOR6>HVEt|BejDF7)BU%D9oa{X8x8V4oX(`LaevB3okLJ_3gf;& z&0jV|f9kAjb%~C`{xnMUN1e`?a}DL*FyHvhL*~1`Kb^trG$`M$a6p}p`xJvXa`haO z4EvLw!%;M95q_KL`=plR|5E#Q{cz-=>}~HGi|al<|8sqT&w^Rbk2VG@9cfk)&^#vL zY;Q+lzH;}<+6!s-`d+oP{jc=imGBYB@GNyi{G_LX1jj+ou~>0H9e~FagM2F~o~QNg z3x>Xpj>0;+uR!0fQ|g`rwG1Xr$q?OsZ82e$N}u|I!nr9`eC5i>8k@A_ndkm3t3BJ} zCN`b!&nZ+ZEaVp!rCeRM$7z3S(QLE!u$H{9_Z_bYcV*14t=c?k%SUtM<9A2DF1OpP zNcTQn`@sI2o`SuuwQ&I>!Z#^zCXRjga^aS$n$TYZyB79d%^!7l3E#kTCU?HLmmGJZ z)PJ+GzSVwq%p=*M-kJ>?HCJ3`rO#dvcbl)RxLEp~IQUlR?)LVZTP2;%X39^~*wLO7 zUpTq`XjpF7f_T}*_G{k@lBTS<-j;XwLU6Wg=!BQW4ua!5?m6vUct>zH{F|1z-ny3k z|8!U=l(f{}3~3(so(qp!4%DCI9qN0IbT{_%C#Zi2&ZijUqv8B~zttrs82xOuzq{W@ zzc^D43^~|gIQsouhSzD34?0(!R4>MTia{KadOt@R`B}%|D6;y?ync?pDa1iO7@akv zsAoy@`Zr&Bcs*$$ze^sWw13k;r{Va@kb!g>*ze^QTSK451WP))tf}9Z z;5#kVTVll6N^j_!GJft(w=bJZP8#YpT;BToeKj)CAibJ0+SG60K811JKuqzg+Pb+v zBoEe2WqUu5OFr>vn{4FmJ#7Uak?)$;BsH@|%UxR*3Jo(zLul{~_{0BOI zZLVSXclI)5FxD{;`JP)xH?58%MOFnD4EdgoqrX-M*20dcTTiQn1=?B|Y2>{)tOYl! zh4om?x>|4>=gkPq`%W)8>>`W*Nymea4fI<^tB*qW+h*Wznf_WB$n#>%Q+Z;wJk~}$ z@yO$@<(X^9b70)1OOat&q?UgD=jAD$_f(#RS{@rC9-TfTQ6F^LKz$aSa%`I&-DCND oJd`&Y