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; }
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; }
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; }
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; }
static CRYPTO_BUFFER *buffer_up_ref(CRYPTO_BUFFER *buffer) { CRYPTO_BUFFER_up_ref(buffer); return buffer; }
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; }
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; }