Пример #1
0
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL *ssl,
                                                            SSL_HANDSHAKE *hs,
                                                            int is_first_run) {
  /* Don't send CertificateVerify if there is no certificate. */
  if (!ssl_has_certificate(ssl)) {
    hs->state = state_send_client_finished;
    return ssl_hs_ok;
  }

  switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
    case ssl_private_key_success:
      hs->state = state_send_client_finished;
      return ssl_hs_write_message;

    case ssl_private_key_retry:
      hs->state = state_complete_client_certificate_verify;
      return ssl_hs_private_key_operation;

    case ssl_private_key_failure:
      return ssl_hs_error;
  }

  assert(0);
  return ssl_hs_error;
}
Пример #2
0
int ssl_add_cert_chain(SSL *ssl, CBB *cbb) {
  if (!ssl_has_certificate(ssl)) {
    return CBB_add_u24(cbb, 0);
  }

  CBB certs;
  if (!CBB_add_u24_length_prefixed(cbb, &certs)) {
    goto err;
  }

  STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain;
  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain); i++) {
    CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(chain, i);
    CBB child;
    if (!CBB_add_u24_length_prefixed(&certs, &child) ||
        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
                       CRYPTO_BUFFER_len(buffer)) ||
        !CBB_flush(&certs)) {
      goto err;
    }
  }

  return CBB_flush(cbb);

err:
  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
  return 0;
}
Пример #3
0
int ssl_on_certificate_selected(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  if (!ssl_has_certificate(ssl)) {
    /* Nothing to do. */
    return 1;
  }

  if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl)) {
    return 0;
  }

  CBS leaf;
  CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0), &leaf);

  EVP_PKEY_free(hs->local_pubkey);
  hs->local_pubkey = ssl_cert_parse_pubkey(&leaf);
  return hs->local_pubkey != NULL;
}
Пример #4
0
static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
                                                     SSL_HANDSHAKE *hs) {
  if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
    hs->state = state_send_server_finished;
    return ssl_hs_ok;
  }

  if (!ssl_has_certificate(ssl)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
    return ssl_hs_error;
  }

  if (!tls13_prepare_certificate(ssl)) {
    return ssl_hs_error;
  }

  hs->state = state_send_server_certificate_verify;
  return ssl_hs_write_message;
}
Пример #5
0
int tls13_prepare_certificate(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  CBB cbb, body, certificate_list;
  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
      /* The request context is always empty in the handshake. */
      !CBB_add_u8(&body, 0) ||
      !CBB_add_u24_length_prefixed(&body, &certificate_list)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    goto err;
  }

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

    return 1;
  }

  CERT *cert = ssl->cert;
  CBB leaf, extensions;
  if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
      !ssl_add_cert_to_cbb(&leaf, cert->x509_leaf) ||
      !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    goto err;
  }

  if (hs->scts_requested &&
      ssl->ctx->signed_cert_timestamp_list_length != 0) {
    CBB contents;
    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
        !CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list,
                       ssl->ctx->signed_cert_timestamp_list_length) ||
        !CBB_flush(&extensions)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      goto err;
    }
  }

  if (hs->ocsp_stapling_requested &&
      ssl->ocsp_response != NULL) {
    CBB contents, ocsp_response;
    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) ||
        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
        !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
        !CBB_add_u24_length_prefixed(&contents, &ocsp_response) ||
        !CBB_add_bytes(&ocsp_response, CRYPTO_BUFFER_data(ssl->ocsp_response),
                       CRYPTO_BUFFER_len(ssl->ocsp_response)) ||
        !CBB_flush(&extensions)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      goto err;
    }
  }

  for (size_t i = 0; i < sk_X509_num(cert->x509_chain); i++) {
    CBB child;
    if (!CBB_add_u24_length_prefixed(&certificate_list, &child) ||
        !ssl_add_cert_to_cbb(&child, sk_X509_value(cert->x509_chain, i)) ||
        !CBB_add_u16(&certificate_list, 0 /* no extensions */)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      goto err;
    }
  }

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

  return 1;

err:
  CBB_cleanup(&cbb);
  return 0;
}
Пример #6
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;
}