int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) { CBB child, name_cbb; if (!CBB_add_u16_length_prefixed(cbb, &child)) { return 0; } STACK_OF(CRYPTO_BUFFER) *names = ssl->client_CA; if (names == NULL) { names = ssl->ctx->client_CA; } if (names == NULL) { return CBB_flush(cbb); } for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(names); i++) { const CRYPTO_BUFFER *name = sk_CRYPTO_BUFFER_value(names, i); if (!CBB_add_u16_length_prefixed(&child, &name_cbb) || !CBB_add_bytes(&name_cbb, CRYPTO_BUFFER_data(name), CRYPTO_BUFFER_len(name))) { return 0; } } return CBB_flush(cbb); }
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; }
static enum ssl_hs_wait_t do_process_client_certificate_verify( SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) { /* Skip this state. */ hs->tls13_state = state_process_channel_id; return ssl_hs_ok; } if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) || !tls13_process_certificate_verify(hs) || !ssl_hash_current_message(hs)) { return ssl_hs_error; } hs->tls13_state = state_process_channel_id; return ssl_hs_read_message; }
int ssl_session_is_resumable(const SSL_HANDSHAKE *hs, const SSL_SESSION *session) { const SSL *const ssl = hs->ssl; return ssl_session_is_context_valid(ssl, session) && /* The session must have been created by the same type of end point as * we're now using it with. */ ssl->server == session->is_server && /* The session must not be expired. */ ssl_session_is_time_valid(ssl, session) && /* Only resume if the session's version matches the negotiated * version. */ ssl->version == session->ssl_version && /* Only resume if the session's cipher matches the negotiated one. */ hs->new_cipher == session->cipher && /* If the session contains a client certificate (either the full * certificate or just the hash) then require that the form of the * certificate matches the current configuration. */ ((sk_CRYPTO_BUFFER_num(session->certs) == 0 && !session->peer_sha256_valid) || session->peer_sha256_valid == ssl->retain_only_sha256_of_client_certs); }
STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert, EVP_PKEY **out_pubkey, uint8_t *out_leaf_sha256, CBS *cbs, CRYPTO_BUFFER_POOL *pool) { *out_pubkey = NULL; STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null(); if (ret == NULL) { *out_alert = SSL_AD_INTERNAL_ERROR; OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; } CBS certificate_list; if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || CBS_len(&certificate) == 0) { *out_alert = SSL_AD_DECODE_ERROR; OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(ret) == 0) { *out_pubkey = ssl_cert_parse_pubkey(&certificate); if (*out_pubkey == NULL) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } /* Retain the hash of the leaf certificate if requested. */ if (out_leaf_sha256 != NULL) { SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, pool); if (buf == NULL) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } if (!sk_CRYPTO_BUFFER_push(ret, buf)) { *out_alert = SSL_AD_INTERNAL_ERROR; CRYPTO_BUFFER_free(buf); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } return ret; err: EVP_PKEY_free(*out_pubkey); *out_pubkey = NULL; sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free); return NULL; }
int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) { SSL *const ssl = hs->ssl; CBS cbs, context, certificate_list; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } const int retain_sha256 = ssl->server && ssl->retain_only_sha256_of_client_certs; int ret = 0; EVP_PKEY *pkey = NULL; STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null(); if (certs == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate, extensions; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || !CBS_get_u16_length_prefixed(&certificate_list, &extensions) || CBS_len(&certificate) == 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 0) { pkey = ssl_cert_parse_pubkey(&certificate); if (pkey == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } /* TLS 1.3 always uses certificate keys for signing thus the correct * keyUsage is enforced. */ if (!ssl_cert_check_digital_signature_key_usage(&certificate)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } if (retain_sha256) { /* Retain the hash of the leaf certificate if requested. */ SHA256(CBS_data(&certificate), CBS_len(&certificate), ssl->s3->new_session->peer_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool); if (buf == NULL || !sk_CRYPTO_BUFFER_push(certs, buf)) { CRYPTO_BUFFER_free(buf); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* Parse out the extensions. */ int have_status_request = 0, have_sct = 0; CBS status_request, sct; const SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_status_request, &have_status_request, &status_request}, {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct}, }; uint8_t alert; if (!ssl_parse_extensions(&extensions, &alert, ext_types, OPENSSL_ARRAY_SIZE(ext_types), 0 /* reject unknown */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } /* All Certificate extensions are parsed, but only the leaf extensions are * stored. */ if (have_status_request) { if (ssl->server || !ssl->ocsp_stapling_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } uint8_t status_type; CBS ocsp_response; if (!CBS_get_u8(&status_request, &status_type) || status_type != TLSEXT_STATUSTYPE_ocsp || !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) || CBS_len(&ocsp_response) == 0 || CBS_len(&status_request) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&ocsp_response, &ssl->s3->new_session->ocsp_response, &ssl->s3->new_session->ocsp_response_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } if (have_sct) { if (ssl->server || !ssl->signed_cert_timestamps_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } if (!ssl_is_sct_list_valid(&sct)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&sct, &ssl->s3->new_session->tlsext_signed_cert_timestamp_list, &ssl->s3->new_session ->tlsext_signed_cert_timestamp_list_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } EVP_PKEY_free(hs->peer_pubkey); hs->peer_pubkey = pkey; pkey = NULL; sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free); ssl->s3->new_session->certs = certs; certs = NULL; if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) { if (!allow_anonymous) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED); goto err; } /* OpenSSL returns X509_V_OK when no certificates are requested. This is * classed by them as a bug, but it's assumed by at least NGINX. */ ssl->s3->new_session->verify_result = X509_V_OK; /* No certificate, so nothing more to do. */ ret = 1; goto err; } ssl->s3->new_session->peer_sha256_valid = retain_sha256; if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result, ssl->s3->new_session->x509_chain)) { goto err; } ret = 1; err: sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free); EVP_PKEY_free(pkey); return ret; }
static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, size_t *out_len, int for_ticket) { CBB cbb, session, child, child2; if (in == NULL || in->cipher == NULL) { return 0; } CBB_zero(&cbb); if (!CBB_init(&cbb, 0) || !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&session, kVersion) || !CBB_add_asn1_uint64(&session, in->ssl_version) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || /* The session ID is irrelevant for a session ticket. */ !CBB_add_bytes(&child, in->session_id, for_ticket ? 0 : in->session_id_length) || !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child, in->master_key, in->master_key_length) || !CBB_add_asn1(&session, &child, kTimeTag) || !CBB_add_asn1_uint64(&child, in->time) || !CBB_add_asn1(&session, &child, kTimeoutTag) || !CBB_add_asn1_uint64(&child, in->timeout)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* The peer certificate is only serialized if the SHA-256 isn't * serialized instead. */ if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) { const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0); if (!CBB_add_asn1(&session, &child, kPeerTag) || !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } /* Although it is OPTIONAL and usually empty, OpenSSL has * historically always encoded the sid_ctx. */ if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->verify_result != X509_V_OK) { if (!CBB_add_asn1(&session, &child, kVerifyResultTag) || !CBB_add_asn1_uint64(&child, in->verify_result)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_hostname) { if (!CBB_add_asn1(&session, &child, kHostNameTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname, strlen(in->tlsext_hostname))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->psk_identity) { if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity, strlen(in->psk_identity))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_tick_lifetime_hint > 0) { if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) || !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_tick && !for_ticket) { if (!CBB_add_asn1(&session, &child, kTicketTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->peer_sha256_valid) { if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->original_handshake_hash_len > 0) { if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->original_handshake_hash, in->original_handshake_hash_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->tlsext_signed_cert_timestamp_list_length > 0) { if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list, in->tlsext_signed_cert_timestamp_list_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->ocsp_response_length > 0) { if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->extended_master_secret) { if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || !CBB_add_u8(&child2, 0xff)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->group_id > 0 && (!CBB_add_asn1(&session, &child, kGroupIDTag) || !CBB_add_asn1_uint64(&child, in->group_id))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* The certificate chain is only serialized if the leaf's SHA-256 isn't * serialized instead. */ if (in->certs != NULL && !in->peer_sha256_valid && sk_CRYPTO_BUFFER_num(in->certs) >= 2) { if (!CBB_add_asn1(&session, &child, kCertChainTag)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) { const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i); if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } } if (in->ticket_age_add_valid) { if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_u32(&child2, in->ticket_age_add)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (!in->is_server) { if (!CBB_add_asn1(&session, &child, kIsServerTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || !CBB_add_u8(&child2, 0x00)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (in->peer_signature_algorithm != 0 && (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) || !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->ticket_max_early_data != 0 && (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) || !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->timeout != in->auth_timeout && (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) || !CBB_add_asn1_uint64(&child, in->auth_timeout))) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (in->early_alpn) { if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) || !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn, in->early_alpn_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } } if (!CBB_finish(&cbb, out_data, out_len)) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } return 1; err: CBB_cleanup(&cbb); return 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; }