84b90d2014-05-04Martin Nilsson #pike __REAL_VERSION__ #pragma strict_types #require constant(SSL.Cipher)
4ceceb2014-05-05Henrik Grubbström (Grubba) //! Client-side connection state.
3c859d2015-02-25Martin Nilsson #include "tls.h"
f1ab082015-02-24Martin Nilsson 
a2d1fd2014-05-15Martin Nilsson import "."; import Constants; inherit Connection;
ec23732014-05-04Martin Nilsson 
41ed982014-05-05Martin Nilsson //! A few storage variables for client certificate handling on the client side. array(int) client_cert_types;
2d40602014-05-16Martin Nilsson array(string(8bit)) client_cert_distinguished_names;
41ed982014-05-05Martin Nilsson 
423a552014-08-01Henrik Grubbström (Grubba) protected string _sprintf(int t) { if (t == 'O') return sprintf("SSL.ClientConnection(%s)", describe_state()); }
ad4a8e2015-03-30Martin Nilsson protected Packet client_hello(string(8bit)|void server_name, array(Packet)|void early_data)
ec23732014-05-04Martin Nilsson {
7d55002014-11-24Martin Nilsson  Buffer struct = Buffer();
ec23732014-05-04Martin Nilsson  /* Build client_hello message */ client_version = version;
0cf7f72017-12-11Martin Nilsson  // Clamp version to TLS 1.2. 1.3 and later are negotiated using // supported versions extension.
6809612017-12-12Martin Nilsson  struct->add_int(min(client_version, PROTOCOL_TLS_1_2), 2);
ec23732014-05-04Martin Nilsson  // The first four bytes of the client_random is specified to be the // timestamp on the client side. This is to guard against bad random // generators, where a client could produce the same random numbers // if the seed is reused. This argument is flawed, since a broken // random generator will make the connection insecure anyways. The // standard explicitly allows these bytes to not be correct, so // sending random data instead is safer and reduces client // fingerprinting. client_random = context->random(32);
1a43772014-11-25Martin Nilsson  struct->add(client_random);
73d2192014-11-24Martin Nilsson  struct->add_hstring(session->identity || "", 1);
ec23732014-05-04Martin Nilsson 
2658342015-02-18Martin Nilsson  array(int) cipher_suites = context->preferred_suites;
2ed01a2014-05-23Henrik Grubbström (Grubba)  if ((state & CONNECTION_handshaking) && !secure_renegotiation) {
ec23732014-05-04Martin Nilsson  // Initial handshake. // Use the backward-compat way of asking for
ad4a8e2015-03-30Martin Nilsson  // support for secure renegotiation.
ec23732014-05-04Martin Nilsson  cipher_suites += ({ TLS_empty_renegotiation_info_scsv });
0e21bb2014-07-06Henrik Grubbström (Grubba) 
6809612017-12-12Martin Nilsson  if (client_version < max(@context->supported_versions)) {
0e21bb2014-07-06Henrik Grubbström (Grubba)  // Negotiating a version lower than the max supported version. //
28e57a2015-04-25Henrik Grubbström (Grubba)  // RFC 7507 4:
0e21bb2014-07-06Henrik Grubbström (Grubba)  // If a client sends a ClientHello.client_version containing a lower // value than the latest (highest-valued) version supported by the // client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite value
28e57a2015-04-25Henrik Grubbström (Grubba)  // in ClientHello.cipher_suites; see Section 6 for security // considerations for this recommendation. (The client SHOULD put // TLS_FALLBACK_SCSV after all cipher suites that it actually intends // to negotiate.)
0e21bb2014-07-06Henrik Grubbström (Grubba)  cipher_suites += ({ TLS_fallback_scsv }); }
ec23732014-05-04Martin Nilsson  } SSL3_DEBUG_MSG("Client ciphers:\n%s",
a2d1fd2014-05-15Martin Nilsson  fmt_cipher_suites(cipher_suites));
2658342015-02-18Martin Nilsson  struct->add_int_array(cipher_suites, 2, 2); array(int) compression_methods;
cdf0cb2014-12-03Henrik Grubbström (Grubba)  if (client_version >= PROTOCOL_TLS_1_3) { // TLS 1.3 (draft 3) does not allow any compression. compression_methods = ({ COMPRESSION_null }); } else { compression_methods = context->preferred_compressors; }
16ce052014-11-25Martin Nilsson  struct->add_int_array(compression_methods, 1, 1);
ec23732014-05-04Martin Nilsson 
7d55002014-11-24Martin Nilsson  Buffer extensions = Buffer();
ec23732014-05-04Martin Nilsson 
7d55002014-11-24Martin Nilsson  void ext(int id, int condition, function(void:Buffer) code)
73d3fe2014-05-10Martin Nilsson  {
473bf12015-09-24Martin Nilsson  if(context->extensions[id] && condition)
73d3fe2014-05-10Martin Nilsson  {
3917072014-11-24Martin Nilsson  extensions->add_int(id, 2);
9a2ee22014-11-24Martin Nilsson  extensions->add_hstring(code(), 2);
73d3fe2014-05-10Martin Nilsson  } };
0cf7f72017-12-11Martin Nilsson  ext (EXTENSION_supported_versions, client_version >= PROTOCOL_TLS_1_3) { Buffer versions = Buffer();
6809612017-12-12Martin Nilsson  foreach(context->supported_versions;; ProtocolVersion v)
0cf7f72017-12-11Martin Nilsson  v->add_int(v, 2); return versions; };
73d3fe2014-05-10Martin Nilsson  ext (EXTENSION_renegotiation_info, secure_renegotiation) {
ec23732014-05-04Martin Nilsson  // RFC 5746 3.4: // The client MUST include either an empty "renegotiation_info" // extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling // cipher suite value in the ClientHello. Including both is NOT // RECOMMENDED.
73d2192014-11-24Martin Nilsson  return Buffer()->add_hstring(client_verify_data, 1);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
14f8162014-12-15Henrik Grubbström (Grubba)  ext (EXTENSION_elliptic_curves, sizeof(context->ecc_curves)||sizeof(context->ffdhe_groups)) {
ec23732014-05-04Martin Nilsson  // RFC 4492 5.1: // The extensions SHOULD be sent along with any ClientHello message // that proposes ECC cipher suites.
9a2ee22014-11-24Martin Nilsson  Buffer curves = Buffer();
ec23732014-05-04Martin Nilsson  foreach(context->ecc_curves, int curve) {
3917072014-11-24Martin Nilsson  curves->add_int(curve, 2);
ec23732014-05-04Martin Nilsson  }
14f8162014-12-15Henrik Grubbström (Grubba)  // FFDHE draft 4 3: // The compatible client that wants to be able to negotiate // strong FFDHE SHOULD send a "Supported Groups" extension // (identified by type elliptic_curves(10) in [RFC4492]) in the // ClientHello, and include a list of known FFDHE groups in the // extension data, ordered from most preferred to least preferred. // // NB: The ffdhe_groups in the context has the smallest group first, // so we reverse it here in case the server actually follows // our priority order. foreach(reverse(context->ffdhe_groups), int group) { curves->add_int(group, 2); } // FIXME: FFDHE draft 4 6.1: // More subtly, clients MAY interleave preferences between ECDHE // and FFDHE groups, for example if stronger groups are // preferred regardless of cost, but weaker groups are // acceptable, the Supported Groups extension could consist of: // <ffdhe8192,secp384p1,ffdhe3072,secp256r1>. In this example, // with the same CipherSuite offered as the previous example, a // server configured to respect client preferences and with // support for all listed groups SHOULD select // TLS_DHE_RSA_WITH_AES_128_CBC_SHA with ffdhe8192. A server // configured to respect client preferences and with support for // only secp384p1 and ffdhe3072 SHOULD select // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA with secp384p1.
9a2ee22014-11-24Martin Nilsson  return Buffer()->add_hstring(curves, 2);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
73d3fe2014-05-10Martin Nilsson  ext (EXTENSION_ec_point_formats, sizeof(context->ecc_curves)) {
9a2ee22014-11-24Martin Nilsson  Buffer point = Buffer();
3917072014-11-24Martin Nilsson  point->add_int(POINT_uncompressed, 1);
9a2ee22014-11-24Martin Nilsson  return Buffer()->add_hstring(point, 1);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson  // We always attempt to enable the heartbeat extension.
73d3fe2014-05-10Martin Nilsson  ext (EXTENSION_heartbeat, 1) {
ec23732014-05-04Martin Nilsson  // RFC 6420
3917072014-11-24Martin Nilsson  return Buffer()->add_int(HEARTBEAT_MODE_peer_allowed_to_send, 1);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
473bf12015-09-24Martin Nilsson  ext (EXTENSION_encrypt_then_mac, 1) {
162bc22015-11-06Henrik Grubbström (Grubba)  // RFC 7366
7d55002014-11-24Martin Nilsson  return Buffer();
0fddf02014-06-29Henrik Grubbström (Grubba)  };
1b04c72015-02-22Henrik Grubbström (Grubba)  ext (EXTENSION_extended_master_secret,
44c4dc2015-09-02Martin Nilsson  context->extended_master_secret &&
6809612017-12-12Martin Nilsson  ( has_value(context->supported_versions, PROTOCOL_TLS_1_0) || has_value(context->supported_versions, PROTOCOL_TLS_1_1) || has_value(context->supported_versions, PROTOCOL_TLS_1_2) )) {
1b04c72015-02-22Henrik Grubbström (Grubba)  // draft-ietf-tls-session-hash
6809612017-12-12Martin Nilsson  // NB: This extension is implicit in TLS 1.3 and N/A in SSL.
1b04c72015-02-22Henrik Grubbström (Grubba)  return Buffer(); };
73d3fe2014-05-10Martin Nilsson  ext (EXTENSION_signature_algorithms, client_version >= PROTOCOL_TLS_1_2) {
ec23732014-05-04Martin Nilsson  // RFC 5246 7.4.1.4.1: // If the client supports only the default hash and signature algorithms // (listed in this section), it MAY omit the signature_algorithms // extension. If the client does not support the default algorithms, or // supports other hash and signature algorithms (and it is willing to // use them for verifying messages sent by the server, i.e., server // certificates and server key exchange), it MUST send the // signature_algorithms extension, listing the algorithms it is willing // to accept. // We list all hashes and signature formats that we support.
73d2192014-11-24Martin Nilsson  return Buffer()->add_hstring(get_signature_algorithms(), 2);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
6542d42014-06-09Martin Nilsson  ext (EXTENSION_server_name, !!server_name)
ec23732014-05-04Martin Nilsson  {
7d55002014-11-24Martin Nilsson  Buffer hostname = Buffer();
3917072014-11-24Martin Nilsson  hostname->add_int(0, 1); // name_time host_name(0)
73d2192014-11-24Martin Nilsson  hostname->add_hstring(server_name, 2); // hostname
6542d42014-06-09Martin Nilsson 
9a2ee22014-11-24Martin Nilsson  return Buffer()->add_hstring(hostname, 2);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
95ad6e2016-07-15Henrik Grubbström (Grubba)  ext (EXTENSION_session_ticket, 1) { // RFC 4507 and RFC 5077. if (session->ticket_expiry_time < time(1)) { session->ticket = UNDEFINED; session->ticket_expiry_time = 0; } SSL3_DEBUG_MSG("SSL.ClientConnection: Sending ticket %O.\n", session->ticket); // NB: RFC 4507 and RFC 5077 differ in encoding here. // Apparently no implementations actually followed // the RFC 4507 encoding. return Buffer()->add(session->ticket || ""); };
bf53f32015-07-06Henrik Grubbström (Grubba)  ext (EXTENSION_application_layer_protocol_negotiation, !!(context->advertised_protocols))
ec23732014-05-04Martin Nilsson  {
16ce052014-11-25Martin Nilsson  return Buffer()->add_string_array(context->advertised_protocols, 1, 2);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson  // When the client HELLO packet data is in the range 256-511 bytes // f5 SSL terminators will intepret it as SSL2 requiring an // additional 8k of data, which will cause the connection to hang. // The solution is to pad the package to more than 511 bytes using a // dummy exentsion. // Reference: draft-agl-tls-padding int packet_size = sizeof(struct)+sizeof(extensions)+2;
73d3fe2014-05-10Martin Nilsson  ext (EXTENSION_padding, packet_size>255 && packet_size<512)
ec23732014-05-04Martin Nilsson  { int padding = max(0, 512-packet_size-4);
938d512014-05-16Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection: Adding %d bytes of padding.\n",
ec23732014-05-04Martin Nilsson  padding);
1a43772014-11-25Martin Nilsson  return Buffer()->add("\0"*padding);
73d3fe2014-05-10Martin Nilsson  };
ec23732014-05-04Martin Nilsson 
f72a412015-01-05Henrik Grubbström (Grubba)  ext(EXTENSION_early_data, early_data && sizeof(early_data)) { SSL3_DEBUG_MSG("SSL.ClientConnection: Adding %d packets of early data.\n", sizeof(early_data)); Buffer buf = Buffer(); foreach(early_data, Packet p) {
3f605c2015-03-31Martin Nilsson  p->send(buf);
f72a412015-01-05Henrik Grubbström (Grubba)  } return buf; };
8cad0e2016-04-28Henrik Grubbström (Grubba)  // NB: WebSphere Application Server 7.0 doesn't like having an // empty extension last, so don't put any such extensions // in the list here. // cf https://bugs.chromium.org/p/chromium/issues/detail?id=363583#c17
e428892014-10-15Henrik Grubbström (Grubba)  if(sizeof(extensions) && (version >= PROTOCOL_TLS_1_0))
9a2ee22014-11-24Martin Nilsson  struct->add_hstring(extensions, 2);
ec23732014-05-04Martin Nilsson 
d8de2e2014-11-24Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection: Client hello: %q\n", struct);
610f2f2015-01-29Henrik Grubbström (Grubba)  Packet ret = handshake_packet(HANDSHAKE_client_hello, struct); if (version > PROTOCOL_TLS_1_0) { // For maximum interoperability, it seems having // version TLS 1.0 at the packet level is best. // // From Xiaoyin Liu <xiaoyin.l@outlook.com> on // the TLS mailing list 2015-01-21: // // (1) Number of sites scanned: 1,000,001 // (2) Number of DNS Error: 45,402 // (3) Number of sites that refuse TCP connection on port 443 // (RST, timeout): 289,334 // (4) Number of sites that fail sending ServerHello in all 4 // attempts: 238,846 // (5) Number of sites that are tolerant to (TLS1.3, TLS1.3): // 397,152 (93.1%) // (6) Number of sites that need to fallback to (TLS1.0, TLS1.3): // 22,461 (5.3%) // (7) Number of sites that need to fallback to (TLS1.0, TLS1.2): // 6,352 (1.5%) // (8) Number of sites that need to fallback to (TLS1.0, TLS1.0): // 454 (0.1%) ret->protocol_version = PROTOCOL_TLS_1_0; } return ret;
ec23732014-05-04Martin Nilsson }
ad4a8e2015-03-30Martin Nilsson protected Packet finished_packet(string(8bit) sender)
d2e2852014-05-04Henrik Grubbström (Grubba) { SSL3_DEBUG_MSG("Sending finished_packet, with sender=\""+sender+"\"\n" ); // We're the client. client_verify_data = hash_messages(sender); return handshake_packet(HANDSHAKE_finished, client_verify_data); }
ad4a8e2015-03-30Martin Nilsson protected Packet client_key_exchange_packet()
41ed982014-05-05Martin Nilsson {
a125c22015-01-25Henrik Grubbström (Grubba)  Stdio.Buffer packet_data = Stdio.Buffer();
0aaedc2015-02-01Henrik Grubbström (Grubba)  if (!ke) { ke = session->cipher_spec->ke_factory(context, session, this, client_version); if (!ke->init_client()) { send_packet(alert(ALERT_fatal, ALERT_handshake_failure, "Invalid KEX.\n")); return 0; } }
a125c22015-01-25Henrik Grubbström (Grubba)  string(8bit) premaster_secret = ke->client_key_exchange_packet(packet_data, version); if (!premaster_secret) {
3046e62014-12-13Henrik Grubbström (Grubba)  send_packet(alert(ALERT_fatal, ALERT_handshake_failure,
41ed982014-05-05Martin Nilsson  "Invalid KEX.\n")); return 0; }
a125c22015-01-25Henrik Grubbström (Grubba)  derive_master_secret(premaster_secret);
41ed982014-05-05Martin Nilsson 
a125c22015-01-25Henrik Grubbström (Grubba)  return handshake_packet(HANDSHAKE_client_key_exchange, packet_data);
41ed982014-05-05Martin Nilsson }
172d6c2014-11-23Henrik Grubbström (Grubba) //! Initialize a new @[ClientConnection]. //! //! @param ctx //! @[Context] to use. //! //! @param server_name //! Optional host name of the server. //! //! @param session //! Optional @[Session] to resume. protected void create(Context ctx, string(8bit)|void server_name, Session|void session)
84b90d2014-05-04Martin Nilsson { ::create(ctx);
d2e2852014-05-04Henrik Grubbström (Grubba)  handshake_state = STATE_wait_for_hello;
2dc0d62015-03-28Henrik Grubbström (Grubba)  if (session && (!server_name || session->server_name == server_name)) { // Reuse the session. this_program::session = session; } else { this_program::session = Session(); this_program::session->server_name = server_name;
14f8162014-12-15Henrik Grubbström (Grubba)  this_program::session->ffdhe_groups = ctx->ffdhe_groups; }
b6be942015-01-07Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  // Pre-TLS 1.3. SSL3_DEBUG_MSG("CLIENT: TLS <= 1.2 handshake.\n"); send_packet(client_hello(server_name));
5e6d4e2014-05-04Henrik Grubbström (Grubba) }
5c41912014-08-24Henrik Grubbström (Grubba) //! Renegotiate the connection (client initiated). //! //! Sends a @[client_hello] to force a new round of handshaking. void send_renegotiate() {
c22fcb2015-09-13Henrik Grubbström (Grubba)  if (!context->enable_renegotiation) { error("Renegotiation disabled in context.\n"); }
fbc3d02015-03-28Henrik Grubbström (Grubba)  send_packet(client_hello(session->server_name), PRI_application);
5c41912014-08-24Henrik Grubbström (Grubba) }
ae22f52015-01-09Henrik Grubbström (Grubba) protected int send_certs() { /* Send Certificate, ClientKeyExchange, CertificateVerify and * ChangeCipherSpec as appropriate, and then Finished. */ CertificatePair cert;
b4e9422015-01-09Henrik Grubbström (Grubba)  /* Only send a certificate if it's been requested. */
ae22f52015-01-09Henrik Grubbström (Grubba)  if(client_cert_types) { SSL3_DEBUG_MSG("Searching for a suitable client certificate...\n"); // Okay, we have a list of certificate types and DN:s that are // acceptable to the remote server. We should weed out the certs // we have so that we only send certificates that match what they // want. SSL3_DEBUG_MSG("All certs: %O\n" "distinguished_names: %O\n", context->get_certificates(), client_cert_distinguished_names); array(CertificatePair) certs = context->find_cert_issuer(client_cert_distinguished_names) || ({}); certs = [array(CertificatePair)] filter(certs,
3167482015-01-27Martin Nilsson  lambda(CertificatePair cp) { // Is the certificate type supported? if( !has_value(client_cert_types, cp->cert_type) ) return 0; // Are the individual hash and sign algorithms in the // certificate chain supported? foreach(cp->sign_algs, [int cert_hash, int cert_sign]) { int match; foreach(session->signature_algorithms, [int hash, int sign]) { if( hash==cert_hash && sign==cert_sign ) { match = 1; break; } } if( !match ) return 0; } return 1; });
ae22f52015-01-09Henrik Grubbström (Grubba)  if (sizeof(certs)) { SSL3_DEBUG_MSG("Found %d matching client certs.\n", sizeof(certs)); cert = certs[0]; session->private_key = cert->key; session->certificate_chain = cert->certs; send_packet(certificate_packet(session->certificate_chain)); } else { SSL3_DEBUG_MSG("No suitable client certificate found.\n"); send_packet(certificate_packet(({}))); } }
f1ab082015-02-24Martin Nilsson  COND_FATAL(!session->has_required_certificates(), ALERT_unexpected_message, "Certificate message missing.\n");
ae22f52015-01-09Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  Packet key_exchange = client_key_exchange_packet();
ae22f52015-01-09Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  if (key_exchange) { send_packet(key_exchange); }
5321c22015-01-18Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  if(cert) { // We sent a certificate, so we should send the verification. send_packet(certificate_verify_packet());
8401262015-01-17Henrik Grubbström (Grubba)  }
ae22f52015-01-09Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  send_packet(change_cipher_packet());
ae22f52015-01-09Henrik Grubbström (Grubba)  if(version == PROTOCOL_SSL_3_0) send_packet(finished_packet("CLNT"));
8401262015-01-17Henrik Grubbström (Grubba)  else if(version >= PROTOCOL_TLS_1_0) {
ae22f52015-01-09Henrik Grubbström (Grubba)  send_packet(finished_packet("client finished"));
8401262015-01-17Henrik Grubbström (Grubba)  }
ae22f52015-01-09Henrik Grubbström (Grubba)  // NB: The server direction hash will be calculated // when we've received the server finished packet. if (context->heartbleed_probe && session->heartbeat_mode == HEARTBEAT_MODE_peer_allowed_to_send) { // Probe for the Heartbleed vulnerability (CVE-2014-0160). send_packet(heartbleed_packet()); } return 0; }
72a2d02015-01-06Henrik Grubbström (Grubba) void new_cipher_states() { SSL3_DEBUG_MSG("CLIENT: master: %O\n", session->master_secret); array(State) res = session->new_client_states(this, client_random, server_random, version);
1604ca2015-01-10Henrik Grubbström (Grubba)  pending_read_state += ({ res[0] }); pending_write_state += ({ res[1] });
72a2d02015-01-06Henrik Grubbström (Grubba) }
ad4a8e2015-03-30Martin Nilsson protected int(-1..0) got_certificate_request(Buffer input)
c6d6ea2015-01-15Henrik Grubbström (Grubba) { SSL3_DEBUG_MSG("SSL.ClientConnection: CERTIFICATE_REQUEST\n"); // It is a fatal handshake_failure alert for an anonymous server to // request client authentication.
0fd7982015-01-16Henrik Grubbström (Grubba)  // // RFC 5246 7.4.4: // A non-anonymous server can optionally request a certificate from // the client, if appropriate for the selected cipher suite.
f1ab082015-02-24Martin Nilsson  COND_FATAL(session->cipher_spec->signature_alg == SIGNATURE_anonymous, ALERT_handshake_failure, "Anonymous server requested authentication by certificate.\n");
c6d6ea2015-01-15Henrik Grubbström (Grubba)  client_cert_types = input->read_int_array(1, 1); client_cert_distinguished_names = ({}); if (version >= PROTOCOL_TLS_1_2) { // TLS 1.2 has var_uint_array of hash and sign pairs here. string bytes = input->read_hstring(2);
f1ab082015-02-24Martin Nilsson  COND_FATAL(sizeof(bytes)&1, ALERT_handshake_failure, "Odd number of bytes in supported_signature_algorithms.\n");
c6d6ea2015-01-15Henrik Grubbström (Grubba)  // Pairs of <hash_alg, signature_alg>. session->signature_algorithms = ((array(int))bytes)/2; SSL3_DEBUG_MSG("New signature_algorithms:\n"+ fmt_signature_pairs(session->signature_algorithms)); } Stdio.Buffer s = input->read_hbuffer(2); while(sizeof(s))
cdb6ae2015-01-27Martin Nilsson  client_cert_distinguished_names += ({ s->read_hstring(2) }); SSL3_DEBUG_MSG("Got %O potential certificate names.", sizeof(client_cert_distinguished_names));
c6d6ea2015-01-15Henrik Grubbström (Grubba) 
fb02972015-03-30Martin Nilsson  COND_FATAL(sizeof(input), ALERT_handshake_failure, "Badly formed Certificate Request.\n");
380b842015-03-29Henrik Grubbström (Grubba) 
c6d6ea2015-01-15Henrik Grubbström (Grubba)  return 0; }
95ad6e2016-07-15Henrik Grubbström (Grubba) protected int(-1..1) got_new_session_ticket(Buffer input) { COND_FATAL(!tickets_enabled, ALERT_handshake_failure, "Unexpected session ticket.\n"); // Make sure that we only get one ticket. tickets_enabled = 3; int lifetime_hint = input->read_int(4); string(8bit) ticket = input->read_hstring(2); SSL3_DEBUG_MSG("SSL.ClientConnection: Got ticket %O (%d seconds).\n", ticket, lifetime_hint); COND_FATAL(!sizeof(ticket), ALERT_handshake_failure, "Empty ticket.\n"); if (!lifetime_hint) { // Unspecified lifetime. Handle as one hour. lifetime_hint = 3600; } session->ticket = ticket; session->ticket_expiry_time = lifetime_hint + time(1); return 0; }
184dcf2016-08-14Henrik Grubbström (Grubba) //! Do handshake processing.
5e6d4e2014-05-04Henrik Grubbström (Grubba) //!
184dcf2016-08-14Henrik Grubbström (Grubba) //! @param type //! One of HANDSHAKE_*. //! @param input //! The contents of the packet. //! @param raw //! The raw packet received (needed for supporting SSLv2 hello messages). //! //! @returns //! This function returns: //! @int //! @value 0 //! If handshaking is in progress. //! @value 1 //! If handshaking has completed. //! @value -1 //! If a fatal error occurred. //! @endint //! //! It uses the @[send_packet()] function to transmit packets.
af9ae22015-03-30Martin Nilsson int(-1..1) handle_handshake(int type, Buffer input, Stdio.Buffer raw)
5e6d4e2014-05-04Henrik Grubbström (Grubba) { #ifdef SSL3_PROFILING addRecord(type,0); #endif #ifdef SSL3_DEBUG_HANDSHAKE_STATE
938d512014-05-16Martin Nilsson  werror("SSL.ClientConnection: state %s, type %s\n",
5e6d4e2014-05-04Henrik Grubbström (Grubba)  fmt_constant(handshake_state, "STATE"), fmt_constant(type, "HANDSHAKE")); werror("sizeof(data)="+sizeof(data)+"\n"); #endif
95ad6e2016-07-15Henrik Grubbström (Grubba) #if 0 // Not compatible with session tickets...
aed1a32015-04-11Henrik Grubbström (Grubba)  // Enforce packet ordering.
f1ab082015-02-24Martin Nilsson  COND_FATAL(type <= previous_handshake, ALERT_unexpected_message, "Invalid handshake packet order.\n");
b9909a2015-01-06Henrik Grubbström (Grubba)  previous_handshake = type;
95ad6e2016-07-15Henrik Grubbström (Grubba) #endif
b9909a2015-01-06Henrik Grubbström (Grubba) 
5e6d4e2014-05-04Henrik Grubbström (Grubba)  switch(handshake_state) { default: error( "Internal error\n" );
d2e2852014-05-04Henrik Grubbström (Grubba)  case STATE_wait_for_hello:
a239312015-04-15Martin Nilsson  add_handshake_message(raw);
dbb7fc2015-01-12Henrik Grubbström (Grubba)  switch(type) { default:
f1ab082015-02-24Martin Nilsson  COND_FATAL(1, ALERT_unexpected_message, "Expected server hello.\n"); break;
dbb7fc2015-01-12Henrik Grubbström (Grubba)  case HANDSHAKE_server_hello:
938d512014-05-16Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection: SERVER_HELLO\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
ca99532015-02-25Martin Nilsson  string(8bit) session_id;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  int cipher_suite, compression_method;
3917072014-11-24Martin Nilsson  version = [int(0x300..0x300)|ProtocolVersion]input->read_int(2); server_random = input->read(32);
ca99532015-02-25Martin Nilsson  session_id = input->read_hstring(1);
3917072014-11-24Martin Nilsson  cipher_suite = input->read_int(2); compression_method = input->read_int(1);
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
6809612017-12-12Martin Nilsson  if( !has_value(context->supported_versions, version) ) { SSL3_DEBUG_MSG("Unsupported version of SSL: %s (Requested {%s}).\n", fmt_version(version), fmt_version(context->supported_versions[*])*","); version = client_version; COND_FATAL(1, ALERT_protocol_version, "Unsupported version.\n"); } SSL3_DEBUG_MSG("Selecting version %s.\n", fmt_version(version));
5e6d4e2014-05-04Henrik Grubbström (Grubba)  if( !has_value(context->preferred_suites, cipher_suite) || !has_value(context->preferred_compressors, compression_method) || !session->is_supported_suite(cipher_suite, ~0, version)) { // The server tried to trick us to use some other cipher suite // or compression method than we wanted
f1ab082015-02-24Martin Nilsson  version = client_version; // FIXME: Do we need this? COND_FATAL(1, ALERT_handshake_failure, "Server selected bad suite.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  }
21c2222018-04-17Martin Nilsson  SSL3_DEBUG_MSG("Server selected suite %s.\n", fmt_cipher_suite(cipher_suite));
f1ab082015-02-24Martin Nilsson  COND_FATAL(!session->set_cipher_suite(cipher_suite, version, context->signature_algorithms, 512), ALERT_handshake_failure, "Unsupported or obsolete cipher suite.\n"); COND_FATAL(version >= PROTOCOL_TLS_1_3 && compression_method!=COMPRESSION_null, ALERT_insufficient_security, "Compression not supported in TLS 1.3 and later.\n");
cf9f152014-10-13Martin Nilsson 
5e6d4e2014-05-04Henrik Grubbström (Grubba)  session->set_compression_method(compression_method);
cf9f152014-10-13Martin Nilsson 
d2e2852014-05-04Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("STATE_wait_for_hello: received hello\n"
5e6d4e2014-05-04Henrik Grubbström (Grubba)  "version = %s\n"
ca99532015-02-25Martin Nilsson  "session_id=%O\n"
e9eef52017-10-07Martin Nilsson  "cipher suite: 0x%x\n"
5e6d4e2014-05-04Henrik Grubbström (Grubba)  "compression method: %O\n", fmt_version(version),
ca99532015-02-25Martin Nilsson  session_id, cipher_suite, compression_method);
5e6d4e2014-05-04Henrik Grubbström (Grubba)  int missing_secure_renegotiation = secure_renegotiation;
cca26f2014-05-11Martin Nilsson  if (sizeof(input)) {
88efab2014-11-24Martin Nilsson  Stdio.Buffer extensions = input->read_hbuffer(2);
6f2eed2014-07-10Martin Nilsson  multiset(int) remote_extensions = (<>);
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
cca26f2014-05-11Martin Nilsson  while (sizeof(extensions)) {
3917072014-11-24Martin Nilsson  int extension_type = extensions->read_int(2);
7d55002014-11-24Martin Nilsson  Buffer extension_data =
3917072014-11-24Martin Nilsson  Buffer(extensions->read_hstring(2));
938d512014-05-16Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection->handle_handshake: "
5e6d4e2014-05-04Henrik Grubbström (Grubba)  "Got extension %s.\n", fmt_constant(extension_type, "EXTENSION"));
f1ab082015-02-24Martin Nilsson  COND_FATAL(remote_extensions[extension_type], ALERT_decode_error, "Same extension sent twice.\n"); remote_extensions[extension_type] = 1;
6f2eed2014-07-10Martin Nilsson 
473bf12015-09-24Martin Nilsson  if( !context->extensions[extension_type] ) { SSL3_DEBUG_MSG("Ignored extension %O (%d bytes)\n", extension_type, sizeof(extension_data)); continue; }
5e6d4e2014-05-04Henrik Grubbström (Grubba)  switch(extension_type) { case EXTENSION_renegotiation_info:
3917072014-11-24Martin Nilsson  string renegotiated_connection = extension_data->read_hstring(1);
f1ab082015-02-24Martin Nilsson  // RFC 5746 3.5: (secure_renegotiation) // The client MUST then verify that the first half of the // "renegotiated_connection" field is equal to the saved // client_verify_data value, and the second half is equal // to the saved server_verify_data value. If they are not, // the client MUST abort the handshake. // // RFC 5746 4.2: (!secure_renegotiation) // When the ServerHello is received, the client MUST // verify that it does not contain the // "renegotiation_info" extension. If it does, the client // MUST abort the handshake. (Because the server has // already indicated it does not support secure // renegotiation, the only way that this can happen is if // the server is broken or there is an attack.) COND_FATAL((renegotiated_connection != (client_verify_data + server_verify_data)) || (!(state & CONNECTION_handshaking) && !secure_renegotiation), ALERT_handshake_failure, "Invalid renegotiation data.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  secure_renegotiation = 1; missing_secure_renegotiation = 0; break; case EXTENSION_ec_point_formats: array(int) ecc_point_formats =
16ce052014-11-25Martin Nilsson  extension_data->read_int_array(1, 1);
5e6d4e2014-05-04Henrik Grubbström (Grubba)  // NB: We only support the uncompressed point format for now. if (has_value(ecc_point_formats, POINT_uncompressed)) { session->ecc_point_format = POINT_uncompressed; } else { // Not a supported point format. session->ecc_point_format = -1; }
2102132016-04-11Martin Nilsson  break; case EXTENSION_elliptic_curves: /* This is only supposed to be included in ClientHello, but some * servers send it anyway, and other SSLs ignore it. */ break;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  case EXTENSION_server_name: break;
bf53f32015-07-06Henrik Grubbström (Grubba)  case EXTENSION_application_layer_protocol_negotiation: array(string(8bit)) selected_prot = extension_data->read_string_array(1, 2); COND_FATAL((!context->advertised_protocols || (sizeof(selected_prot) != 1) || !has_value(context->advertised_protocols, selected_prot[0])), ALERT_handshake_failure, "Invalid ALPN.\n"); application_protocol = selected_prot[0]; break;
95ad6e2016-07-15Henrik Grubbström (Grubba)  case EXTENSION_session_ticket: COND_FATAL(sizeof(extension_data), ALERT_handshake_failure, "Invalid server session ticket extension.\n"); SSL3_DEBUG_MSG("SSL.ClientConnection: Server supports tickets.\n"); tickets_enabled = 1; break;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  case EXTENSION_heartbeat: { int hb_mode;
f1ab082015-02-24Martin Nilsson  // RFC 6520 2: // Upon reception of an unknown mode, an error Alert // message using illegal_parameter as its // AlertDescription MUST be sent in response. COND_FATAL(!sizeof(extension_data) || !(hb_mode = extension_data->read_int(1)) || sizeof(extension_data) || ((hb_mode != HEARTBEAT_MODE_peer_allowed_to_send) && (hb_mode != HEARTBEAT_MODE_peer_not_allowed_to_send)), ALERT_illegal_parameter, "Invalid heartbeat extension.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("heartbeat extension: %s\n", fmt_constant(hb_mode, "HEARTBEAT_MODE")); session->heartbeat_mode = [int(0..1)]hb_mode; } break;
1b04c72015-02-22Henrik Grubbström (Grubba)  case EXTENSION_extended_master_secret: {
f1ab082015-02-24Martin Nilsson  COND_FATAL(sizeof(extension_data) ||
6809612017-12-12Martin Nilsson  (min(@context->supported_versions) >= PROTOCOL_TLS_1_3),
f1ab082015-02-24Martin Nilsson  ALERT_illegal_parameter, "Extended-master-secret: Invalid extension.\n");
1b04c72015-02-22Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("Extended-master-secret: Enabled.\n"); session->extended_master_secret = 1; }
0cf7f72017-12-11Martin Nilsson  break; case EXTENSION_supported_versions: { COND_FATAL(sizeof(extension_data)!=2, ALERT_illegal_parameter, "Illegal size of supported version extension.\n"); version = extension_data->read_int16();
6809612017-12-12Martin Nilsson  COND_FATAL( !has_value(context->supported_versions, version),
0cf7f72017-12-11Martin Nilsson  ALERT_illegal_parameter, "Received version not offered.\n"); } break;
1b04c72015-02-22Henrik Grubbström (Grubba) 
0fddf02014-06-29Henrik Grubbström (Grubba)  case EXTENSION_encrypt_then_mac: { if (context->encrypt_then_mac) {
f1ab082015-02-24Martin Nilsson  COND_FATAL(sizeof(extension_data), ALERT_illegal_parameter, "Encrypt-then-MAC: Invalid extension.\n"); COND_FATAL(((sizeof(CIPHER_SUITES[cipher_suite]) == 3) &&
25b0422014-06-29Henrik Grubbström (Grubba)  (< CIPHER_rc4, CIPHER_rc4_40 >)[CIPHER_SUITES[cipher_suite][1]]) || ((sizeof(CIPHER_SUITES[cipher_suite]) == 4) &&
f1ab082015-02-24Martin Nilsson  (CIPHER_SUITES[cipher_suite][3] != MODE_cbc)), ALERT_illegal_parameter, "Encrypt-then-MAC: Invalid for selected suite.\n");
0fddf02014-06-29Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("Encrypt-then-MAC: Enabled.\n"); session->encrypt_then_mac = 1; break; } /* We didn't request the extension, so complain loudly. */ } /* FALL_THROUGH */
5e6d4e2014-05-04Henrik Grubbström (Grubba)  default: // RFC 5246 7.4.1.4: // If a client receives an extension type in ServerHello // that it did not request in the associated ClientHello, it // MUST abort the handshake with an unsupported_extension
2102132016-04-11Martin Nilsson  // fatal alert. SSL3_DEBUG_MSG("Unrequested extension %s.\n", fmt_constant(extension_type, "EXTENSION"));
f1ab082015-02-24Martin Nilsson  COND_FATAL(1, ALERT_unsupported_extension, "Unrequested extension.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  } } }
3167482015-01-27Martin Nilsson 
95ad6e2016-07-15Henrik Grubbström (Grubba)  if (session->ticket && !tickets_enabled) { // The server has stopped supporting session tickets? // Make sure not to compare the server-generated // session id with the one that we may have generated. session_id = ""; }
f1ab082015-02-24Martin Nilsson  // RFC 5746 3.5: // When a ServerHello is received, the client MUST verify that the // "renegotiation_info" extension is present; if it is not, the // client MUST abort the handshake. COND_FATAL(missing_secure_renegotiation, ALERT_handshake_failure, "Missing secure renegotiation extension.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
ca99532015-02-25Martin Nilsson  if ((session_id == session->identity) && sizeof(session_id)) { SSL3_DEBUG_MSG("Resuming session %O.\n", session_id);
8401262015-01-17Henrik Grubbström (Grubba) 
ad2ac42017-12-09Martin Nilsson  new_cipher_states(); send_packet(change_cipher_packet());
fab1c62014-11-22Henrik Grubbström (Grubba) 
95ad6e2016-07-15Henrik Grubbström (Grubba)  if (tickets_enabled) { handshake_state = STATE_wait_for_ticket; // Expect the ticket before the CC. expect_change_cipher--; } else { handshake_state = STATE_wait_for_finish; }
fab1c62014-11-22Henrik Grubbström (Grubba)  reuse = 1; break; }
95ad6e2016-07-15Henrik Grubbström (Grubba)  if ((session_id == "") && tickets_enabled) { // Generate a session identifier. // NB: We currently do NOT support resumption based on an // empty session id and a HANDSHAKE_new_session_ticket. // We thus need a non-empty session id when we use // this new session for resumption. We don't care much // about the value (as long as it is non-empty), as // a compliant server will return either the value we // provided, or the empty string. session_id = "RESUMPTION_TICKET"; }
ca99532015-02-25Martin Nilsson  session->identity = session_id;
ad2ac42017-12-09Martin Nilsson  handshake_state = STATE_wait_for_peer;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  break; } break;
d2e2852014-05-04Henrik Grubbström (Grubba)  case STATE_wait_for_peer:
a239312015-04-15Martin Nilsson  add_handshake_message(raw);
5e6d4e2014-05-04Henrik Grubbström (Grubba)  switch(type) { default:
f1ab082015-02-24Martin Nilsson  COND_FATAL(1, ALERT_unexpected_message, "Unexpected server message.\n"); break;
aed1a32015-04-11Henrik Grubbström (Grubba)  /* FIXME: HANDSHAKE_encrypted_extensions */
5e6d4e2014-05-04Henrik Grubbström (Grubba)  case HANDSHAKE_certificate: {
aed1a32015-04-11Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("SSL.ClientConnection: Certificate received\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
3ab9b12014-07-16Martin Nilsson  // we're anonymous, so no certificate is requred. if(ke && ke->anonymous) break;
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
0a6d7b2015-01-26Martin Nilsson  if( !handle_certificates(input) )
3ab9b12014-07-16Martin Nilsson  return -1;
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
3ab9b12014-07-16Martin Nilsson  certificate_state = CERT_received; break;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  } case HANDSHAKE_server_key_exchange: {
fe62212015-04-06Henrik Grubbström (Grubba)  COND_FATAL(version >= PROTOCOL_TLS_1_3, ALERT_unexpected_message, "Unexpected server message.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  if (ke) error("KE!\n");
0aaedc2015-02-01Henrik Grubbström (Grubba)  ke = session->cipher_spec->ke_factory(context, session, this, client_version);
f1ab082015-02-24Martin Nilsson  COND_FATAL(!ke->init_server() || (ke->got_server_key_exchange(input, client_random, server_random) < 0), ALERT_handshake_failure, "Verification of ServerKeyExchange failed.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  break; } case HANDSHAKE_certificate_request:
c6d6ea2015-01-15Henrik Grubbström (Grubba)  return got_certificate_request(input);
5e6d4e2014-05-04Henrik Grubbström (Grubba)  case HANDSHAKE_server_hello_done:
938d512014-05-16Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection: SERVER_HELLO_DONE\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
fe62212015-04-06Henrik Grubbström (Grubba)  COND_FATAL(version >= PROTOCOL_TLS_1_3, ALERT_unexpected_message, "Unexpected server message.\n");
ae22f52015-01-09Henrik Grubbström (Grubba)  if (send_certs()) return -1;
95ad6e2016-07-15Henrik Grubbström (Grubba)  if (tickets_enabled) { handshake_state = STATE_wait_for_ticket; // Expect the ticket before the CC. expect_change_cipher--; } else { handshake_state = STATE_wait_for_finish; }
5e6d4e2014-05-04Henrik Grubbström (Grubba)  break; } break;
0fd7982015-01-16Henrik Grubbström (Grubba)  case STATE_wait_for_verify: if (version < PROTOCOL_TLS_1_3) { error("Waiting for verify in %s.\n", fmt_version(version)); } switch(type) { default:
f1ab082015-02-24Martin Nilsson  COND_FATAL(1, ALERT_unexpected_message, "Unexpected server message.\n"); break;
0fd7982015-01-16Henrik Grubbström (Grubba)  case HANDSHAKE_certificate_request:
a239312015-04-15Martin Nilsson  add_handshake_message(raw);
0fd7982015-01-16Henrik Grubbström (Grubba)  return got_certificate_request(input); case HANDSHAKE_certificate_verify: SSL3_DEBUG_MSG("SSL.ClientConnection: CERTIFICATE_VERIFY\n");
f1ab082015-02-24Martin Nilsson  COND_FATAL(version < PROTOCOL_TLS_1_3, ALERT_unexpected_message, "Unexpected server message.\n");
0fd7982015-01-16Henrik Grubbström (Grubba)  SSL3_DEBUG_MSG("SERVER: handshake_messages: %d bytes.\n", sizeof(handshake_messages));
5321c22015-01-18Henrik Grubbström (Grubba)  if (validate_certificate_verify(input, SIGN_server_certificate_verify) < 0) {
0fd7982015-01-16Henrik Grubbström (Grubba)  return -1; }
a239312015-04-15Martin Nilsson  add_handshake_message(raw);
0fd7982015-01-16Henrik Grubbström (Grubba)  handshake_state = STATE_wait_for_finish; break; } break;
95ad6e2016-07-15Henrik Grubbström (Grubba)  case STATE_wait_for_ticket: { COND_FATAL(type != HANDSHAKE_new_session_ticket, ALERT_unexpected_message, "Expected new session ticket.\n"); SSL3_DEBUG_MSG("SSL.ClientConnection: NEW_SESSION_TICKET\n"); add_handshake_message(raw); // Expect CC. expect_change_cipher++; handshake_state = STATE_wait_for_finish; return got_new_session_ticket(input); } break;
d2e2852014-05-04Henrik Grubbström (Grubba)  case STATE_wait_for_finish:
5e6d4e2014-05-04Henrik Grubbström (Grubba)  {
f1ab082015-02-24Martin Nilsson  COND_FATAL(type != HANDSHAKE_finished, ALERT_unexpected_message, "Expected handshake finished.\n");
8b43472014-07-16Martin Nilsson 
938d512014-05-16Martin Nilsson  SSL3_DEBUG_MSG("SSL.ClientConnection: FINISHED\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  string my_digest; if (version == PROTOCOL_SSL_3_0) {
3917072014-11-24Martin Nilsson  server_verify_data = input->read(36);
8b43472014-07-16Martin Nilsson  my_digest = hash_messages("SRVR");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  } else if (version >= PROTOCOL_TLS_1_0) {
3917072014-11-24Martin Nilsson  server_verify_data = input->read(12);
8b43472014-07-16Martin Nilsson  my_digest = hash_messages("server finished");
5e6d4e2014-05-04Henrik Grubbström (Grubba)  }
f1ab082015-02-24Martin Nilsson  COND_FATAL(my_digest != server_verify_data, ALERT_unexpected_message, "Digests differ.\n");
5e6d4e2014-05-04Henrik Grubbström (Grubba) 
8401262015-01-17Henrik Grubbström (Grubba)  if (reuse || (version >= PROTOCOL_TLS_1_3)) {
a239312015-04-15Martin Nilsson  add_handshake_message(raw);
af9ae22015-03-30Martin Nilsson  /* Second hash includes this message, the first doesn't */
fab1c62014-11-22Henrik Grubbström (Grubba)  if(version == PROTOCOL_SSL_3_0) send_packet(finished_packet("CLNT"));
8401262015-01-17Henrik Grubbström (Grubba)  else if(version <= PROTOCOL_TLS_1_2)
fab1c62014-11-22Henrik Grubbström (Grubba)  send_packet(finished_packet("client finished"));
ad2ac42017-12-09Martin Nilsson  if (context->heartbleed_probe &&
fab1c62014-11-22Henrik Grubbström (Grubba)  session->heartbeat_mode == HEARTBEAT_MODE_peer_allowed_to_send) { // Probe for the Heartbleed vulnerability (CVE-2014-0160). send_packet(heartbleed_packet()); } }
c6dc3b2014-11-25Henrik Grubbström (Grubba)  // Handshake hash is calculated for both directions above. handshake_messages = 0;
8401262015-01-17Henrik Grubbström (Grubba)  handshake_state = STATE_handshake_finished;
5e6d4e2014-05-04Henrik Grubbström (Grubba)  return 1; // We're done shaking hands } }
3167482015-01-27Martin Nilsson 
5e6d4e2014-05-04Henrik Grubbström (Grubba)  return 0; }