###################################################################### # Handshake Protocols (7.) ###################################################################### enum HandshakeType { HELLO_REQUEST = 0, CLIENT_HELLO = 1, SERVER_HELLO = 2, HELLO_VERIFY_REQUEST = 3, # DTLS SESSION_TICKET = 4, # RFC 5077 CERTIFICATE = 11, SERVER_KEY_EXCHANGE = 12, CERTIFICATE_REQUEST = 13, SERVER_HELLO_DONE = 14, CERTIFICATE_VERIFY = 15, CLIENT_KEY_EXCHANGE = 16, FINISHED = 20, CERTIFICATE_URL = 21, # RFC 3546 CERTIFICATE_STATUS = 22, # RFC 3546 }; ###################################################################### # V3 Handshake Protocol (7.) ###################################################################### type HandshakeRecord(is_orig: bool) = record { msg_type: uint8; msg_length: uint24; rec: Handshake(this); } &length=(to_int()(msg_length) + 4); type Handshake(rec: HandshakeRecord) = case rec.msg_type of { HELLO_REQUEST -> hello_request : HelloRequest(rec); CLIENT_HELLO -> client_hello : ClientHello(rec); SERVER_HELLO -> server_hello : ServerHelloChoice(rec); HELLO_VERIFY_REQUEST -> hello_verify_request : HelloVerifyRequest(rec); SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec); CERTIFICATE -> certificate : Certificate(rec); SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec); CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec); SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec); CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec); CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec); FINISHED -> finished : Finished(rec); CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient; CERTIFICATE_STATUS -> certificate_status : CertificateStatus(rec); default -> unknown_handshake : UnknownHandshake(rec, rec.is_orig); } type HandshakePDU(is_orig: bool) = record { records: HandshakeRecord(is_orig)[] &transient; } &byteorder = bigendian; type UnknownHandshake(hs: HandshakeRecord, is_orig: bool) = record { data : bytestring &restofdata &transient; }; ###################################################################### # V3 Hello Request (7.4.1.1.) ###################################################################### # Hello Request is empty type HelloRequest(rec: HandshakeRecord) = record { direction_check : DirectionCheck(false, rec); # should be sent by responder }; ###################################################################### # V3 Client Hello (7.4.1.2.) ###################################################################### type ClientHello(rec: HandshakeRecord) = record { direction_check : DirectionCheck(true, rec); # should be sent by originator client_version : uint16; gmt_unix_time : uint32; random_bytes : bytestring &length = 28; session_len : uint8; session_id : uint8[session_len]; dtls_cookie: case client_version of { DTLSv10, DTLSv12 -> cookie: ClientHelloCookie(rec); default -> nothing: bytestring &length=0; }; csuit_len : uint16; # &check(csuit_len > 1 && csuit_len % 2 == 0); csuits : uint16[csuit_len/2]; cmeth_len : uint8; # &check(cmeth_len > 0); cmeths : uint8[cmeth_len]; # This weirdness is to deal with the possible existence or absence # of the following fields. ext_len: uint16[] &until($element == 0 || $element != 0); extensions : SSLExtension(rec)[] &until($input.length() == 0); }; type ClientHelloCookie(rec: HandshakeRecord) = record { cookie_len : uint8; cookie : bytestring &length = cookie_len; }; ###################################################################### # V3 Server Hello (7.4.1.3.) ###################################################################### # TLS 1.3 server hello is different from earlier versions. Trick around a # bit, route 1.3 requests to a different record than earlier. type ServerHelloChoice(rec: HandshakeRecord) = record { direction_check : DirectionCheck(false, rec); # should be sent by responder server_version0 : uint8; server_version1 : uint8; hello: case parsed_version of { TLSv13, TLSv13_draft -> hello13: ServerHello13(rec, server_version); default -> helloclassic: ServerHello(rec, server_version); } &requires(server_version) &requires(parsed_version); } &let { server_version : uint16 = (server_version0 << 8) | server_version1; parsed_version : uint16 = case server_version0 of { 0x7F -> 0x7F00; # map any draft version to 00 default -> server_version; }; version_set : bool = $context.connection.set_version(server_version); }; type ServerHello(rec: HandshakeRecord, server_version: uint16) = record { random_bytes : bytestring &length = 32; session_len : uint8; session_id : uint8[session_len]; cipher_suite : uint16[1]; compression_method : uint8; # This weirdness is to deal with the possible existence or absence # of the following fields. ext_len: uint16[] &until($element == 0 || $element != 0); extensions : SSLExtension(rec)[] &until($input.length() == 0); } &let { cipher_set : bool = $context.connection.set_cipher(cipher_suite[0]); }; type ServerHello13(rec: HandshakeRecord, server_version: uint16) = record { random : bytestring &length = 32; cipher_suite : uint16[1]; ext_len: uint16[] &until($element == 0 || $element != 0); extensions : SSLExtension(rec)[] &until($input.length() == 0); } &let { cipher_set : bool = $context.connection.set_cipher(cipher_suite[0]); }; # Used to check if originator/responder are reversed for this connection type DirectionCheck(desired: bool, rec: HandshakeRecord) = record { } &let { proc : bool = $context.connection.check_flipped(desired, rec.is_orig); }; ###################################################################### # DTLS Hello Verify Request ###################################################################### type HelloVerifyRequest(rec: HandshakeRecord) = record { version: uint16; cookie_length: uint8; cookie: bytestring &length=cookie_length; }; ###################################################################### # V3 Server Certificate (7.4.2.) ###################################################################### type X509Certificate = record { length : uint24; certificate : bytestring &length = to_int()(length); }; type Certificate(rec: HandshakeRecord) = record { length : uint24; certificates : X509Certificate[] &until($input.length() == 0); } &length = to_int()(length)+3; # OCSP Stapling type CertificateStatus(rec: HandshakeRecord) = record { status_type: uint8; # 1 = ocsp, everything else is undefined length : uint24; response: bytestring &restofdata; }; ###################################################################### # V3 Server Key Exchange Message (7.4.3.) ###################################################################### # The server key exchange contains the server public key exchange values, and a # signature over those values for non-anonymous exchanges. The server key # exchange messages is only sent for ECDHE, ECDH-anon, DHE, and DH-anon cipher # suites. type ServerKeyExchange(rec: HandshakeRecord) = case $context.connection.chosen_cipher() of { # ECDHE suites TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_RC4_128_SHA, TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, TLS_ECDHE_PSK_WITH_NULL_SHA, TLS_ECDHE_PSK_WITH_NULL_SHA256, TLS_ECDHE_PSK_WITH_NULL_SHA384, TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CCM, TLS_ECDHE_ECDSA_WITH_AES_256_CCM, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> ecdhe_server_key_exchange : EcdheServerKeyExchange(rec); # ECDH-anon suites TLS_ECDH_ANON_WITH_NULL_SHA, TLS_ECDH_ANON_WITH_RC4_128_SHA, TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ANON_WITH_AES_128_CBC_SHA, TLS_ECDH_ANON_WITH_AES_256_CBC_SHA # ECDH non-anon suites do not send a ServerKeyExchange -> ecdh_anon_server_key_exchange : EcdhAnonServerKeyExchange(rec); # DHE suites TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_DSS_WITH_DES_CBC_SHA, TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, TLS_DHE_DSS_WITH_RC4_128_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD, TLS_DHE_DSS_WITH_AES_128_CBC_RMD, TLS_DHE_DSS_WITH_AES_256_CBC_RMD, TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD, TLS_DHE_RSA_WITH_AES_128_CBC_RMD, TLS_DHE_RSA_WITH_AES_256_CBC_RMD, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_PSK_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, TLS_DHE_PSK_WITH_AES_128_CBC_SHA, TLS_DHE_PSK_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_SEED_CBC_SHA, TLS_DHE_RSA_WITH_SEED_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, TLS_DHE_PSK_WITH_NULL_SHA256, TLS_DHE_PSK_WITH_NULL_SHA384, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256, TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_CCM, TLS_DHE_RSA_WITH_AES_256_CCM, TLS_DHE_RSA_WITH_AES_128_CCM_8, TLS_DHE_RSA_WITH_AES_256_CCM_8, TLS_DHE_PSK_WITH_AES_128_CCM, TLS_DHE_PSK_WITH_AES_256_CCM, TLS_PSK_DHE_WITH_AES_128_CCM_8, TLS_PSK_DHE_WITH_AES_256_CCM_8, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> dhe_server_key_exchange : DheServerKeyExchange(rec); # DH-anon suites TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5, TLS_DH_ANON_WITH_RC4_128_MD5, TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_ANON_WITH_DES_CBC_SHA, TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA, TLS_DH_ANON_WITH_AES_128_CBC_SHA, TLS_DH_ANON_WITH_AES_256_CBC_SHA, TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_ANON_WITH_AES_128_CBC_SHA256, TLS_DH_ANON_WITH_AES_256_CBC_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA, TLS_DH_ANON_WITH_SEED_CBC_SHA, TLS_DH_ANON_WITH_AES_128_GCM_SHA256, TLS_DH_ANON_WITH_AES_256_GCM_SHA384, TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256, TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384, TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256, TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384, TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384 # DH non-anon suites do not send a ServerKeyExchange -> dh_anon_server_key_exchange : DhAnonServerKeyExchange(rec); default -> key : bytestring &restofdata &transient; }; # Parse an ECDHE ServerKeyExchange message, which contains a signature over the # parameters. Parsing explicit curve parameters from the server is not # currently supported. type EcdheServerKeyExchange(rec: HandshakeRecord) = record { curve_type: uint8; named_curve: case curve_type of { NAMED_CURVE -> params: ServerECDHParamsAndSignature; default -> data: bytestring &restofdata &transient; }; signature: case curve_type of { NAMED_CURVE -> signed_params: ServerKeyExchangeSignature; default -> nothing: bytestring &length=0; }; }; type ServerKeyExchangeSignature = record { alg: case uses_signature_and_hashalgorithm of { true -> algorithm: SignatureAndHashAlgorithm; false -> nothing: bytestring &length=0; } &requires(uses_signature_and_hashalgorithm); signature_length: uint16; signature: bytestring &length=signature_length; } &let { uses_signature_and_hashalgorithm : bool = ($context.connection.chosen_version() > TLSv11) && ($context.connection.chosen_version() != DTLSv10); }; # Parse an ECDH-anon ServerKeyExchange message, which does not contain a # signature over the parameters. Parsing explicit curve parameters from the # server is not currently supported. type EcdhAnonServerKeyExchange(rec: HandshakeRecord) = record { curve_type: uint8; named_curve: case curve_type of { NAMED_CURVE -> params: ServerECDHParamsAndSignature; default -> data: bytestring &restofdata &transient; }; }; type ServerECDHParamsAndSignature() = record { curve: uint16; point_length: uint8; point: bytestring &length=point_length; }; # Parse a DHE ServerKeyExchange message, which contains a signature over the # parameters. type DheServerKeyExchange(rec: HandshakeRecord) = record { dh_p_length: uint16; dh_p: bytestring &length=dh_p_length; dh_g_length: uint16; dh_g: bytestring &length=dh_g_length; dh_Ys_length: uint16; dh_Ys: bytestring &length=dh_Ys_length; signed_params: ServerKeyExchangeSignature; }; # Parse a DH-anon ServerKeyExchange message, which does not contain a # signature over the parameters. type DhAnonServerKeyExchange(rec: HandshakeRecord) = record { dh_p_length: uint16; dh_p: bytestring &length=dh_p_length; dh_g_length: uint16; dh_g: bytestring &length=dh_g_length; dh_Ys_length: uint16; dh_Ys: bytestring &length=dh_Ys_length; data: bytestring &restofdata &transient; }; ###################################################################### # V3 Certificate Request (7.4.4.) ###################################################################### type CertificateAuthorities = record { certificate_authority_len: uint16; certificate_authority: bytestring &length=certificate_authority_len; }; type CertificateAuthoritiesContainer = record { certificate_authorities: CertificateAuthorities[] &until($input.length() == 0); }; # For now, ignore Certificate Request Details; just eat up message. type CertificateRequest(rec: HandshakeRecord) = record { certificate_types_len: uint8; certificate_types: uint8[certificate_types_len]; alg: case uses_signature_and_hashalgorithm of { true -> supported_signature_algorithms: SignatureAlgorithm(rec); false -> nothing: bytestring &length=0; } &requires(uses_signature_and_hashalgorithm); certificate_authorities_len: uint16; certificate_authorities: CertificateAuthoritiesContainer &length=certificate_authorities_len; cont : bytestring &restofdata &transient; } &let { uses_signature_and_hashalgorithm : bool = ($context.connection.chosen_version() > TLSv11) && ($context.connection.chosen_version() != DTLSv10); }; ###################################################################### # V3 Server Hello Done (7.4.5.) ###################################################################### # Server Hello Done is empty type ServerHelloDone(rec: HandshakeRecord) = empty; ###################################################################### # V3 Client Certificate (7.4.6.) ###################################################################### # Client Certificate is identical to Server Certificate; # no further definition here ###################################################################### # V3 Client Key Exchange Message (7.4.7.) ###################################################################### # Parse a ClientKeyExchange message. For RSA cipher suites, this consists of an # encrypted pre-master secret. For DH, DH-anon, and DHE cipher suites, this # consists of the client public finite-field Diffie-Hellman value. For ECDH, # ECDH-anon, and ECDHE cipher suites, this consists of the client public # elliptic curve point. type ClientKeyExchange(rec: HandshakeRecord) = case $context.connection.chosen_cipher() of { # RSA suites TLS_RSA_WITH_NULL_MD5, TLS_RSA_WITH_NULL_SHA, TLS_RSA_EXPORT_WITH_RC4_40_MD5, TLS_RSA_WITH_RC4_128_MD5, TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, TLS_RSA_WITH_IDEA_CBC_SHA, TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_NULL_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_RSA_EXPORT1024_WITH_RC4_56_MD5, TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, TLS_RSA_WITH_3DES_EDE_CBC_RMD, TLS_RSA_WITH_AES_128_CBC_RMD, TLS_RSA_WITH_AES_256_CBC_RMD, TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, TLS_RSA_PSK_WITH_RC4_128_SHA, TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, TLS_RSA_PSK_WITH_AES_128_CBC_SHA, TLS_RSA_PSK_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_SEED_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, TLS_RSA_PSK_WITH_NULL_SHA256, TLS_RSA_PSK_WITH_NULL_SHA384, TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_RSA_WITH_ARIA_128_CBC_SHA256, TLS_RSA_WITH_ARIA_256_CBC_SHA384, TLS_RSA_WITH_ARIA_128_GCM_SHA256, TLS_RSA_WITH_ARIA_256_GCM_SHA384, TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, TLS_RSA_WITH_AES_128_CCM, TLS_RSA_WITH_AES_256_CCM, TLS_RSA_WITH_AES_128_CCM_8, TLS_RSA_WITH_AES_256_CCM_8 -> rsa_client_key_exchange: RsaClientKeyExchange(rec); #ECHDE TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ANON_WITH_NULL_SHA, TLS_ECDH_ANON_WITH_RC4_128_SHA, TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ANON_WITH_AES_128_CBC_SHA, TLS_ECDH_ANON_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_RC4_128_SHA, TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, TLS_ECDHE_PSK_WITH_NULL_SHA, TLS_ECDHE_PSK_WITH_NULL_SHA256, TLS_ECDHE_PSK_WITH_NULL_SHA384, TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CCM, TLS_ECDHE_ECDSA_WITH_AES_256_CCM, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> ecdh_client_key_exchange : EcdhClientKeyExchange(rec); # DHE suites TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_DSS_WITH_DES_CBC_SHA, TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, TLS_DHE_DSS_WITH_RC4_128_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD, TLS_DHE_DSS_WITH_AES_128_CBC_RMD, TLS_DHE_DSS_WITH_AES_256_CBC_RMD, TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD, TLS_DHE_RSA_WITH_AES_128_CBC_RMD, TLS_DHE_RSA_WITH_AES_256_CBC_RMD, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_PSK_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, TLS_DHE_PSK_WITH_AES_128_CBC_SHA, TLS_DHE_PSK_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_SEED_CBC_SHA, TLS_DHE_RSA_WITH_SEED_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, TLS_DHE_PSK_WITH_NULL_SHA256, TLS_DHE_PSK_WITH_NULL_SHA384, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256, TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_CCM, TLS_DHE_RSA_WITH_AES_256_CCM, TLS_DHE_RSA_WITH_AES_128_CCM_8, TLS_DHE_RSA_WITH_AES_256_CCM_8, TLS_DHE_PSK_WITH_AES_128_CCM, TLS_DHE_PSK_WITH_AES_256_CCM, TLS_PSK_DHE_WITH_AES_128_CCM_8, TLS_PSK_DHE_WITH_AES_256_CCM_8, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, # DH-anon suites TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5, TLS_DH_ANON_WITH_RC4_128_MD5, TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_ANON_WITH_DES_CBC_SHA, TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA, TLS_DH_ANON_WITH_AES_128_CBC_SHA, TLS_DH_ANON_WITH_AES_256_CBC_SHA, TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_ANON_WITH_AES_128_CBC_SHA256, TLS_DH_ANON_WITH_AES_256_CBC_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA, TLS_DH_ANON_WITH_SEED_CBC_SHA, TLS_DH_ANON_WITH_AES_128_GCM_SHA256, TLS_DH_ANON_WITH_AES_256_GCM_SHA384, TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256, TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384, TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256, TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384, TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256, TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384 -> dh_server_key_exchange : DhClientKeyExchange(rec); default -> key : bytestring &restofdata &transient; }; type RsaClientKeyExchange(rec: HandshakeRecord) = record { rsa_pms : bytestring &restofdata; }; type DhClientKeyExchange(rec: HandshakeRecord) = record { dh_Yc : bytestring &restofdata; }; type EcdhClientKeyExchange(rec: HandshakeRecord) = record { point : bytestring &restofdata; }; ###################################################################### # V3 Certificate Verify (7.4.8.) ###################################################################### # For now, ignore Certificate Verify; just eat up the message. type CertificateVerify(rec: HandshakeRecord) = record { cont : bytestring &restofdata &transient; }; ###################################################################### # V3 Finished (7.4.9.) ###################################################################### # The finished messages are always sent after encryption is in effect, # so we will not be able to read those messages. type Finished(rec: HandshakeRecord) = record { cont : bytestring &restofdata &transient; }; type SessionTicketHandshake(rec: HandshakeRecord) = record { ticket_lifetime_hint: uint32; data: bytestring &restofdata; }; ###################################################################### # TLS Extensions ###################################################################### type SSLExtension(rec: HandshakeRecord) = record { type: uint16; data_len: uint16; # Pretty code ahead. Deal with the fact that perhaps extensions are # not really present and we do not want to fail because of that. ext: case type of { EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> apnl: ApplicationLayerProtocolNegotiationExtension(rec)[] &until($element == 0 || $element != 0); EXT_ELLIPTIC_CURVES -> elliptic_curves: EllipticCurves(rec)[] &until($element == 0 || $element != 0); 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); EXT_SIGNED_CERTIFICATE_TIMESTAMP -> certificate_timestamp: SignedCertificateTimestampList(rec)[] &until($element == 0 || $element != 0); EXT_KEY_SHARE -> key_share: KeyShare(rec, this)[] &until($element == 0 || $element != 0); EXT_KEY_SHARE_OLD -> key_share_old: KeyShare(rec, this)[] &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; %include tls-handshake-signed_certificate_timestamp.pac type SupportedVersionsSelector(rec: HandshakeRecord, data_len: uint16) = case ( rec.is_orig ^ $context.connection.flipped() ) of { true -> a: SupportedVersions(rec); false -> b: OneSupportedVersion(rec); } type SupportedVersions(rec: HandshakeRecord) = record { length: uint8; versions: uint16[] &until($input.length() == 0); } &length=length+1; # If the server sends it, this is the authoritative version. Set it. type OneSupportedVersion(rec: HandshakeRecord) = record { version: uint16; } &let { version_set : bool = $context.connection.set_version(version); }; type PSKKeyExchangeModes(rec: HandshakeRecord) = record { length: uint8; modes: uint8[] &until($input.length() == 0); } &length=length+1; type ServerNameHostName() = record { length: uint16; host_name: bytestring &length=length; }; type ServerName() = record { name_type: uint8; # has to be 0 for host-name name: case name_type of { 0 -> host_name: ServerNameHostName; default -> data : bytestring &restofdata &transient; # unknown name }; }; type ServerNameExt(rec: HandshakeRecord) = record { length: uint16; server_names: ServerName[] &until($input.length() == 0); } &length=length+2; # Do not parse for now. Structure is correct, but only contains asn.1 data that we would not use further. #type OcspStatusRequest(rec: HandshakeRecord) = record { # responder_id_list_length: uint16; # responder_id_list: bytestring &length=responder_id_list_length; # request_extensions_length: uint16; # request_extensions: bytestring &length=request_extensions_length; #}; # #type StatusRequest(rec: HandshakeRecord) = record { # status_type: uint8; # 1 -> ocsp # req: case status_type of { # 1 -> ocsp_status_request: OcspStatusRequest(rec); # default -> data : bytestring &restofdata &transient; # unknown # }; #}; type EcPointFormats(rec: HandshakeRecord) = record { length: uint8; point_format_list: uint8[length]; }; type KeyShareEntry() = record { namedgroup : uint16; key_exchange_length : uint16; key_exchange: bytestring &length=key_exchange_length &transient; }; type ServerHelloKeyShare(rec: HandshakeRecord) = record { keyshare : KeyShareEntry; }; type HelloRetryRequestKeyShare(rec: HandshakeRecord) = record { namedgroup : uint16; }; type ServerHelloKeyShareChoice(rec: HandshakeRecord, ext: SSLExtension) = case (ext.data_len) of { 2 -> hrr : HelloRetryRequestKeyShare(rec); default -> server : ServerHelloKeyShare(rec); }; type ClientHelloKeyShare(rec: HandshakeRecord) = record { length: uint16; keyshares : KeyShareEntry[] &until($input.length() == 0); } &length=(length+2); type KeyShare(rec: HandshakeRecord, ext: SSLExtension) = case rec.msg_type of { CLIENT_HELLO -> client_hello_keyshare : ClientHelloKeyShare(rec); SERVER_HELLO -> server_hello_keyshare : ServerHelloKeyShareChoice(rec, ext); # in old traces, theoretically hello retry requests might show up as a separate type here. # If this happens, just ignore the extension - we do not have any example traffic for this. # And it will not happen in anything speaking TLS 1.3, or not completely ancient drafts of it. 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); } &length=length+2; type EllipticCurves(rec: HandshakeRecord) = record { length: uint16; elliptic_curve_list: uint16[length/2]; }; type ProtocolName() = record { length: uint8; name: bytestring &length=length; }; type ApplicationLayerProtocolNegotiationExtension(rec: HandshakeRecord) = record { length: uint16; protocol_name_list: ProtocolName[] &until($input.length() == 0); } &length=length+2; refine connection Handshake_Conn += { %member{ uint32 chosen_cipher_; uint16 chosen_version_; uint16 record_version_; bytestring client_random_; bytestring server_random_; uint32 gmt_unix_time_; bool flipped_; bool already_alerted_; %} %init{ flipped_ = false; already_alerted_ = false; chosen_cipher_ = NO_CHOSEN_CIPHER; chosen_version_ = UNKNOWN_VERSION; record_version_ = 0; gmt_unix_time_ = 0; %} %cleanup{ client_random_.free(); server_random_.free(); %} function chosen_cipher() : int %{ return chosen_cipher_; %} function set_cipher(cipher: uint32) : bool %{ chosen_cipher_ = cipher; return true; %} function chosen_version() : uint16 %{ return chosen_version_; %} # This function is called several times in certain circumstances. # If it is called twice, it is first called due to the supported_versions # field in the server hello - and then again due to the outer version in # the server hello. So - once we have a version here, let's just stick # with it. function set_version(version: uint16) : bool %{ if ( chosen_version_ != UNKNOWN_VERSION ) return false; chosen_version_ = version; return true; %} function check_flipped(desired: bool, is_orig: bool) : bool %{ if ( flipped_ ) { if ( desired == is_orig ) { // well, I guess we get to flip it back - and alert on this flipped_ = false; zeek::BifEvent::enqueue_ssl_connection_flipped(zeek_analyzer(), zeek_analyzer()->Conn()); if ( ! already_alerted_ ) { already_alerted_ = true; zeek_analyzer()->Weird("SSL_unclear_connection_direction"); } } } else { if ( desired != is_orig ) { flipped_ = true; zeek::BifEvent::enqueue_ssl_connection_flipped(zeek_analyzer(), zeek_analyzer()->Conn()); } } return true; %} function flipped() : bool %{ return flipped_; %} function record_version() : uint16 %{ return record_version_; %} function set_record_version(version: uint16) : bool %{ record_version_ = version; return true; %} function client_random() : bytestring %{ return client_random_; %} function set_client_random(client_random: bytestring) : bool %{ client_random_.free(); client_random_.init(client_random.data(), client_random.length()); return true; %} function server_random() : bytestring %{ return server_random_; %} function set_server_random(server_random: bytestring) : bool %{ server_random_.free(); server_random_.init(server_random.data(), server_random.length()); return true; %} function gmt_unix_time() : uint32 %{ return gmt_unix_time_; %} function set_gmt_unix_time(ts: uint32) : bool %{ gmt_unix_time_ = ts; return true; %} };