# Copyright (c) 2024 by the Zeek Project. See LICENSE for details.

protocol analyzer SSL over TCP:
	parse with SSL::Message;

protocol analyzer DTLS over UDP:
	parse with SSL::DTLSMessage;

import SSL;
import zeek;
import spicy;

on SSL::ClientHello -> event ssl_client_hello($conn, self.client_version, msg.record_version, cast<time>(self.random.gmt_unix_time), self.random.random_bytes, self.session_id, self.cipher_suites, self.compression_methods);
on SSL::SSL2ClientHello -> event ssl_client_hello($conn, self.client_version, 0, cast<time>(0), self.challenge, self.session_id, self.ciphers, vector<uint16>());

on SSL::ServerHello -> event ssl_server_hello($conn, server_version, msg.record_version, cast<time>(self.gmt_unix_time), self.random_bytes, self.session_id, self.cipher_suite, self.compression_method);
on SSL::ServerHelloOneThree -> event ssl_server_hello($conn, server_version, msg.record_version, cast<time>(self.gmt_unix_time), self.random_bytes, "", self.cipher_suite, 0);
on SSL::SSL2ServerHello::conn_id_data -> event ssl_server_hello($conn, self.server_version, 0, cast<time>(0), b"", self.conn_id_data, self.ciphers[0], 0);

on SSL::EllipticCurveList -> event ssl_extension_elliptic_curves($conn, SSL::get_direction(sh), self.elliptic_curve_list);

on SSL::EcPointsFormat_extension -> event ssl_extension_ec_point_formats($conn, SSL::get_direction(sh), self.ec_point_format_list);

on SSL::ServerNameList -> event ssl_extension_server_name($conn, SSL::get_direction(sh), self.server_name_list);

on SSL::NewSessionTicket -> event ssl_session_ticket_handshake($conn, self.ticket_lifetime_hint, self.ticket);

on SSL::PlaintextRecord::ccs -> event ssl_change_cipher_spec($conn, $is_orig);
# weird trigger for event ordering
on SSL::PlaintextRecord::trigger_zero if ( content_type == 23 && sh.tls_13 == True && ( sh.established == False || sh.both_sides_encrypted_first_time ) ) -> event ssl_probable_encrypted_handshake_message($conn, SSL::get_direction(sh), self.length);
on SSL::PlaintextRecord::trigger_one if ( sh.both_sides_encrypted_first_time == True && content_type != 20 ) -> event ssl_established($conn);
on SSL::PlaintextRecord::trigger_two if ( self.encrypted == False ) -> event ssl_plaintext_data($conn, SSL::get_direction(sh), msg.record_version, content_type, self.length);
on SSL::PlaintextRecord::trigger_two if ( self.encrypted == True ) -> event ssl_encrypted_data($conn, SSL::get_direction(sh), msg.record_version, content_type, self.length);

on SSL::SSL2ClientMasterKey::%init -> event ssl_established($conn);

on SSL::Extension -> event ssl_extension($conn, SSL::get_direction(sh), self.code, self.raw);

on SSL::Handshake_message -> event ssl_handshake_message($conn, SSL::get_direction(sh), self.msg_type, self.length);

on SSL::SignatureAlgorithms -> event ssl_extension_signature_algorithm($conn, SSL::get_direction(sh), self.supported_signature_algorithms_converted);

on SSL::ServerHelloKeyShare -> event ssl_extension_key_share($conn, SSL::get_direction(sh), vector<uint16>(self.keyshare.namedgroup,));

on SSL::HelloRetryRequestKeyShare -> event ssl_extension_key_share($conn, SSL::get_direction(sh), vector<uint16>(self.namedgroup,));

on SSL::ClientHelloKeyShare -> event ssl_extension_key_share($conn, SSL::get_direction(sh), self.named_groups);

on SSL::OfferedPsks -> event ssl_extension_pre_shared_key_client_hello($conn, SSL::get_direction(sh), self.identities, self.binders);

on SSL::SelectedPreSharedKeyIdentity -> event ssl_extension_pre_shared_key_server_hello($conn, SSL::get_direction(sh), self.selected_identity);

on SSL::ServerECDHParamsAndSignature -> event ssl_ecdh_server_params($conn, self.curve, self.point);

on SSL::DheServerKeyExchange -> event ssl_dh_server_params($conn, self.dh_p, self.dh_g, self.dh_Ys);

on SSL::DhAnonServerKeyExchange -> event ssl_dh_server_params($conn, self.dh_p, self.dh_g, self.dh_Ys);

on SSL::ServerKeyExchangeSignature if ( self?.algorithm ) -> event ssl_server_signature($conn, tuple(self.algorithm.hash, self.algorithm.signature), self.signature);

# just use nonsense values for no algorithm. Same as in the old analyzer
on SSL::ServerKeyExchangeSignature if ( ! self?.algorithm ) -> event ssl_server_signature($conn, tuple(256, 256), self.signature);

on SSL::EcdhClientKeyExchange -> event ssl_ecdh_client_params($conn, self.point);

on SSL::DhClientKeyExchange -> event ssl_dh_client_params($conn, self.dh_Yc);

on SSL::RsaClientKeyExchange -> event ssl_rsa_client_pms($conn, self.rsa_pms);

on SSL::ProtocolNameList -> event ssl_extension_application_layer_protocol_negotiation($conn, SSL::get_direction(sh), self.protocol_name_list);

on SSL::SignedCertificateTimestamp -> event ssl_extension_signed_certificate_timestamp($conn, SSL::get_direction(sh), self.version, self.logid, self.timestamp, tuple(self.digitally_signed_algorithms.hash, self.digitally_signed_algorithms.signature), self.digitally_signed_signature);

on SSL::SupportedVersions -> event ssl_extension_supported_versions($conn, SSL::get_direction(sh), self.versions);

on SSL::OneSupportedVersion -> event ssl_extension_supported_versions($conn, SSL::get_direction(sh), vector<uint16>(self.version,));

on SSL::PSKKeyExchangeModes -> event ssl_extension_psk_key_exchange_modes($conn, SSL::get_direction(sh), self.modes);

on SSL::Alert_message -> event ssl_alert($conn, SSL::get_direction(sh), self.level, self.description);

on SSL::Heartbeat -> event ssl_heartbeat($conn, SSL::get_direction(sh), length, self.tpe, self.payload_length, self.data);

on SSL::CertificateStatus -> event ssl_stapled_ocsp($conn, $is_orig, self.response);

on SSL::CertificateRequest if ( SSL::uses_signature_and_hashalgorithm(sh) ) -> event ssl_certificate_request($conn, SSL::get_direction(sh), self.certificate_types, self.supported_signature_algorithms.supported_signature_algorithms_converted, self.certificate_authorities);
on SSL::CertificateRequest if ( ! SSL::uses_signature_and_hashalgorithm(sh) ) -> event ssl_certificate_request($conn, SSL::get_direction(sh), self.certificate_types, SSL::create_empty_sigmature_algorithms(), self.certificate_authorities);

on SSL::DirectionCheck if ( self.was_flipped ) -> event ssl_connection_flipped($conn);
