Beispiel #1
0
static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  CBB cbb, body, extensions;
  uint16_t group_id;
  if (!ssl->method->init_message(ssl, &cbb, &body,
                                 SSL3_MT_HELLO_RETRY_REQUEST) ||
      !CBB_add_u16(&body, ssl->version) ||
      !tls1_get_shared_group(hs, &group_id) ||
      !CBB_add_u16_length_prefixed(&body, &extensions) ||
      !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
      !CBB_add_u16(&extensions, 2 /* length */) ||
      !CBB_add_u16(&extensions, group_id) ||
      !ssl_add_message_cbb(ssl, &cbb)) {
    CBB_cleanup(&cbb);
    return ssl_hs_error;
  }

  hs->tls13_state = state_process_second_client_hello;
  return ssl_hs_flush_and_read_message;
}
Beispiel #2
0
static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
  /* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
   * client makes several connections before getting a renewal. */
  static const int kNumTickets = 2;

  SSL *const ssl = hs->ssl;
  /* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
   * session ticket. */
  if (!hs->accept_psk_mode) {
    hs->tls13_state = state_done;
    return ssl_hs_ok;
  }

  SSL_SESSION *session = ssl->s3->new_session;
  CBB cbb;
  CBB_zero(&cbb);

  for (int i = 0; i < kNumTickets; i++) {
    if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
      goto err;
    }

    CBB body, ticket, extensions;
    if (!ssl->method->init_message(ssl, &cbb, &body,
                                   SSL3_MT_NEW_SESSION_TICKET) ||
        !CBB_add_u32(&body, session->timeout) ||
        !CBB_add_u32(&body, session->ticket_age_add) ||
        !CBB_add_u16_length_prefixed(&body, &ticket) ||
        !ssl_encrypt_ticket(ssl, &ticket, session) ||
        !CBB_add_u16_length_prefixed(&body, &extensions)) {
      goto err;
    }

    if (ssl->ctx->enable_early_data) {
      session->ticket_max_early_data = kMaxEarlyDataAccepted;

      CBB early_data_info;
      if (!CBB_add_u16(&extensions, TLSEXT_TYPE_ticket_early_data_info) ||
          !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
          !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
          !CBB_flush(&extensions)) {
        goto err;
      }
    }

    /* Add a fake extension. See draft-davidben-tls-grease-01. */
    if (!CBB_add_u16(&extensions,
                     ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
        !CBB_add_u16(&extensions, 0 /* empty */)) {
      goto err;
    }

    if (!ssl_add_message_cbb(ssl, &cbb)) {
      goto err;
    }
  }

  hs->session_tickets_sent++;
  hs->tls13_state = state_done;
  return ssl_hs_flush;

err:
  CBB_cleanup(&cbb);
  return ssl_hs_error;
}
Beispiel #3
0
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;

  /* Send a ServerHello. */
  CBB cbb, body, extensions;
  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
      !CBB_add_u16(&body, ssl->version) ||
      !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
      !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
      !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
      !CBB_add_u16_length_prefixed(&body, &extensions) ||
      !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
      !ssl_ext_key_share_add_serverhello(hs, &extensions)) {
    goto err;
  }

  if (ssl->s3->short_header) {
    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_short_header) ||
        !CBB_add_u16(&extensions, 0 /* empty extension */)) {
      goto err;
    }
  }

  if (!ssl_add_message_cbb(ssl, &cbb)) {
    goto err;
  }

  /* Derive and enable the handshake traffic secrets. */
  if (!tls13_derive_handshake_secrets(hs) ||
      !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
                             hs->hash_len) ||
      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
                             hs->hash_len)) {
    goto err;
  }

  /* Send EncryptedExtensions. */
  if (!ssl->method->init_message(ssl, &cbb, &body,
                                 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
      !ssl_add_serverhello_tlsext(hs, &body) ||
      !ssl_add_message_cbb(ssl, &cbb)) {
    goto err;
  }

  /* Determine whether to request a client certificate. */
  hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
  /* CertificateRequest may only be sent in non-resumption handshakes. */
  if (ssl->s3->session_reused) {
    hs->cert_request = 0;
  }

  /* Send a CertificateRequest, if necessary. */
  if (hs->cert_request) {
    CBB sigalgs_cbb;
    if (!ssl->method->init_message(ssl, &cbb, &body,
                                   SSL3_MT_CERTIFICATE_REQUEST) ||
        !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
      goto err;
    }

    const uint16_t *sigalgs;
    size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
    if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
      goto err;
    }

    for (size_t i = 0; i < num_sigalgs; i++) {
      if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
        goto err;
      }
    }

    if (!ssl_add_client_CA_list(ssl, &body) ||
        !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
        !ssl_add_message_cbb(ssl, &cbb)) {
      goto err;
    }
  }

  /* Send the server Certificate message, if necessary. */
  if (!ssl->s3->session_reused) {
    if (!ssl_has_certificate(ssl)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
      goto err;
    }

    if (!tls13_add_certificate(hs)) {
      goto err;
    }

    hs->tls13_state = state_send_server_certificate_verify;
    return ssl_hs_ok;
  }

  hs->tls13_state = state_send_server_finished;
  return ssl_hs_ok;

err:
  CBB_cleanup(&cbb);
  return ssl_hs_error;
}
Beispiel #4
0
static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  /* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case
   * the client makes several connections before getting a renewal. */
  static const int kNumTickets = 2;

  SSL_SESSION *session = hs->new_session;
  CBB cbb;
  CBB_zero(&cbb);

  /* Rebase the session timestamp so that it is measured from ticket
   * issuance. */
  ssl_session_rebase_time(ssl, session);

  for (int i = 0; i < kNumTickets; i++) {
    if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
      goto err;
    }
    session->ticket_age_add_valid = 1;

    CBB body, ticket, extensions;
    if (!ssl->method->init_message(ssl, &cbb, &body,
                                   SSL3_MT_NEW_SESSION_TICKET) ||
        !CBB_add_u32(&body, session->timeout) ||
        !CBB_add_u32(&body, session->ticket_age_add) ||
        !CBB_add_u16_length_prefixed(&body, &ticket) ||
        !ssl_encrypt_ticket(ssl, &ticket, session) ||
        !CBB_add_u16_length_prefixed(&body, &extensions)) {
      goto err;
    }

    if (ssl->cert->enable_early_data) {
      session->ticket_max_early_data = kMaxEarlyDataAccepted;

      CBB early_data_info;
      if (!CBB_add_u16(&extensions, TLSEXT_TYPE_ticket_early_data_info) ||
          !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
          !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
          !CBB_flush(&extensions)) {
        goto err;
      }
    }

    /* Add a fake extension. See draft-davidben-tls-grease-01. */
    if (!CBB_add_u16(&extensions,
                     ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
        !CBB_add_u16(&extensions, 0 /* empty */)) {
      goto err;
    }

    if (!ssl_add_message_cbb(ssl, &cbb)) {
      goto err;
    }
  }

  return 1;

err:
  CBB_cleanup(&cbb);
  return 0;
}