예제 #1
0
CERT *ssl_cert_dup(CERT *cert) {
  CERT *ret = OPENSSL_malloc(sizeof(CERT));
  if (ret == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  OPENSSL_memset(ret, 0, sizeof(CERT));

  ret->chain = sk_CRYPTO_BUFFER_deep_copy(cert->chain, buffer_up_ref,
                                          CRYPTO_BUFFER_free);

  if (cert->privatekey != NULL) {
    EVP_PKEY_up_ref(cert->privatekey);
    ret->privatekey = cert->privatekey;
  }

  ret->key_method = cert->key_method;
  ret->x509_method = cert->x509_method;

  if (cert->sigalgs != NULL) {
    ret->sigalgs =
        BUF_memdup(cert->sigalgs, cert->num_sigalgs * sizeof(cert->sigalgs[0]));
    if (ret->sigalgs == NULL) {
      goto err;
    }
  }
  ret->num_sigalgs = cert->num_sigalgs;

  ret->cert_cb = cert->cert_cb;
  ret->cert_cb_arg = cert->cert_cb_arg;

  ret->x509_method->cert_dup(ret, cert);

  if (cert->signed_cert_timestamp_list != NULL) {
    CRYPTO_BUFFER_up_ref(cert->signed_cert_timestamp_list);
    ret->signed_cert_timestamp_list = cert->signed_cert_timestamp_list;
  }

  if (cert->ocsp_response != NULL) {
    CRYPTO_BUFFER_up_ref(cert->ocsp_response);
    ret->ocsp_response = cert->ocsp_response;
  }

  ret->sid_ctx_length = cert->sid_ctx_length;
  OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));

  ret->enable_early_data = cert->enable_early_data;

  return ret;

err:
  ssl_cert_free(ret);
  return NULL;
}
예제 #2
0
X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) {
  if (CRYPTO_BUFFER_len(buf) > LONG_MAX) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
    return 0;
  }

  X509 *x509 = X509_new();
  if (x509 == NULL) {
    return NULL;
  }

  x509->cert_info->enc.alias_only_on_next_parse = 1;

  const uint8_t *inp = CRYPTO_BUFFER_data(buf);
  X509 *x509p = x509;
  X509 *ret = d2i_X509(&x509p, &inp, CRYPTO_BUFFER_len(buf));
  if (ret == NULL ||
      inp - CRYPTO_BUFFER_data(buf) != (ptrdiff_t)CRYPTO_BUFFER_len(buf)) {
    X509_free(x509p);
    return NULL;
  }
  assert(x509p == x509);
  assert(ret == x509);

  CRYPTO_BUFFER_up_ref(buf);
  ret->buf = buf;

  return ret;
}
예제 #3
0
int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
  switch (check_leaf_cert_and_privkey(buffer, cert->privatekey)) {
    case leaf_cert_and_privkey_error:
      return 0;
    case leaf_cert_and_privkey_mismatch:
      /* don't fail for a cert/key mismatch, just free current private key
       * (when switching to a different cert & key, first this function should
       * be used, then |ssl_set_pkey|. */
      EVP_PKEY_free(cert->privatekey);
      cert->privatekey = NULL;
      break;
    case leaf_cert_and_privkey_ok:
      break;
  }

  cert->x509_method->cert_flush_cached_leaf(cert);

  if (cert->chain != NULL) {
    CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
    sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
    CRYPTO_BUFFER_up_ref(buffer);
    return 1;
  }

  cert->chain = sk_CRYPTO_BUFFER_new_null();
  if (cert->chain == NULL) {
    return 0;
  }

  if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
    sk_CRYPTO_BUFFER_free(cert->chain);
    cert->chain = NULL;
    return 0;
  }
  CRYPTO_BUFFER_up_ref(buffer);

  return 1;
}
예제 #4
0
static int cert_set_chain_and_key(
    CERT *cert, CRYPTO_BUFFER *const *certs, size_t num_certs,
    EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) {
  if (num_certs == 0 ||
      (privkey == NULL && privkey_method == NULL)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
    return 0;
  }

  if (privkey != NULL && privkey_method != NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD);
    return 0;
  }

  switch (check_leaf_cert_and_privkey(certs[0], privkey)) {
    case leaf_cert_and_privkey_error:
      return 0;
    case leaf_cert_and_privkey_mismatch:
      OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_AND_PRIVATE_KEY_MISMATCH);
      return 0;
    case leaf_cert_and_privkey_ok:
      break;
  }

  STACK_OF(CRYPTO_BUFFER) *certs_sk = sk_CRYPTO_BUFFER_new_null();
  if (certs_sk == NULL) {
    return 0;
  }

  for (size_t i = 0; i < num_certs; i++) {
    if (!sk_CRYPTO_BUFFER_push(certs_sk, certs[i])) {
      sk_CRYPTO_BUFFER_pop_free(certs_sk, CRYPTO_BUFFER_free);
      return 0;
    }
    CRYPTO_BUFFER_up_ref(certs[i]);
  }

  EVP_PKEY_free(cert->privatekey);
  cert->privatekey = privkey;
  if (privkey != NULL) {
    EVP_PKEY_up_ref(privkey);
  }
  cert->key_method = privkey_method;

  sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
  cert->chain = certs_sk;

  return 1;
}
예제 #5
0
static CRYPTO_BUFFER *buffer_up_ref(CRYPTO_BUFFER *buffer) {
  CRYPTO_BUFFER_up_ref(buffer);
  return buffer;
}
예제 #6
0
SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
  SSL_SESSION *new_session = ssl_session_new(session->x509_method);
  if (new_session == NULL) {
    goto err;
  }

  new_session->is_server = session->is_server;
  new_session->ssl_version = session->ssl_version;
  new_session->sid_ctx_length = session->sid_ctx_length;
  OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);

  /* Copy the key material. */
  new_session->master_key_length = session->master_key_length;
  OPENSSL_memcpy(new_session->master_key, session->master_key,
         session->master_key_length);
  new_session->cipher = session->cipher;

  /* Copy authentication state. */
  if (session->psk_identity != NULL) {
    new_session->psk_identity = BUF_strdup(session->psk_identity);
    if (new_session->psk_identity == NULL) {
      goto err;
    }
  }
  if (session->certs != NULL) {
    new_session->certs = sk_CRYPTO_BUFFER_new_null();
    if (new_session->certs == NULL) {
      goto err;
    }
    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
      CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
      if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
        goto err;
      }
      CRYPTO_BUFFER_up_ref(buffer);
    }
  }

  if (!session->x509_method->session_dup(new_session, session)) {
    goto err;
  }

  new_session->verify_result = session->verify_result;

  new_session->ocsp_response_length = session->ocsp_response_length;
  if (session->ocsp_response != NULL) {
    new_session->ocsp_response = BUF_memdup(session->ocsp_response,
                                            session->ocsp_response_length);
    if (new_session->ocsp_response == NULL) {
      goto err;
    }
  }

  new_session->tlsext_signed_cert_timestamp_list_length =
      session->tlsext_signed_cert_timestamp_list_length;
  if (session->tlsext_signed_cert_timestamp_list != NULL) {
    new_session->tlsext_signed_cert_timestamp_list =
        BUF_memdup(session->tlsext_signed_cert_timestamp_list,
                   session->tlsext_signed_cert_timestamp_list_length);
    if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
      goto err;
    }
  }

  OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
                 SHA256_DIGEST_LENGTH);
  new_session->peer_sha256_valid = session->peer_sha256_valid;

  if (session->tlsext_hostname != NULL) {
    new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
    if (new_session->tlsext_hostname == NULL) {
      goto err;
    }
  }

  new_session->peer_signature_algorithm = session->peer_signature_algorithm;

  new_session->timeout = session->timeout;
  new_session->auth_timeout = session->auth_timeout;
  new_session->time = session->time;

  /* Copy non-authentication connection properties. */
  if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
    new_session->session_id_length = session->session_id_length;
    OPENSSL_memcpy(new_session->session_id, session->session_id,
                   session->session_id_length);

    new_session->group_id = session->group_id;

    OPENSSL_memcpy(new_session->original_handshake_hash,
                   session->original_handshake_hash,
                   session->original_handshake_hash_len);
    new_session->original_handshake_hash_len =
        session->original_handshake_hash_len;
    new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
    new_session->ticket_age_add = session->ticket_age_add;
    new_session->ticket_max_early_data = session->ticket_max_early_data;
    new_session->extended_master_secret = session->extended_master_secret;

    if (session->early_alpn != NULL) {
      new_session->early_alpn =
          BUF_memdup(session->early_alpn, session->early_alpn_len);
      if (new_session->early_alpn == NULL) {
        goto err;
      }
    }
    new_session->early_alpn_len = session->early_alpn_len;
  }

  /* Copy the ticket. */
  if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
    if (session->tlsext_tick != NULL) {
      new_session->tlsext_tick =
          BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
      if (new_session->tlsext_tick == NULL) {
        goto err;
      }
    }
    new_session->tlsext_ticklen = session->tlsext_ticklen;
  }

  /* The new_session does not get a copy of the ex_data. */

  new_session->not_resumable = 1;
  return new_session;

err:
  SSL_SESSION_free(new_session);
  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
  return 0;
}
예제 #7
0
static int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
  CBS cert_cbs;
  CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs);
  EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
  if (pubkey == NULL) {
    return 0;
  }

  if (!is_key_type_supported(pubkey->type)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
    EVP_PKEY_free(pubkey);
    return 0;
  }

  /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
   * certificates, so sanity-check the key usage extension. */
  if (pubkey->type == EVP_PKEY_EC &&
      !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
    EVP_PKEY_free(pubkey);
    return 0;
  }

  if (cert->privatekey != NULL) {
    /* Sanity-check that the private key and the certificate match, unless the
     * key is opaque (in case of, say, a smartcard). */
    if (!EVP_PKEY_is_opaque(cert->privatekey) &&
        !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) {
      /* don't fail for a cert/key mismatch, just free current private key
       * (when switching to a different cert & key, first this function should
       * be used, then ssl_set_pkey */
      EVP_PKEY_free(cert->privatekey);
      cert->privatekey = NULL;
      /* clear error queue */
      ERR_clear_error();
    }
  }

  EVP_PKEY_free(pubkey);

  ssl_cert_flush_cached_x509_leaf(cert);

  if (cert->chain != NULL) {
    CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
    sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
    CRYPTO_BUFFER_up_ref(buffer);
    return 1;
  }

  cert->chain = sk_CRYPTO_BUFFER_new_null();
  if (cert->chain == NULL) {
    return 0;
  }

  if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
    sk_CRYPTO_BUFFER_free(cert->chain);
    cert->chain = NULL;
    return 0;
  }
  CRYPTO_BUFFER_up_ref(buffer);

  return 1;
}