diff --git a/lib/vquic/cf-ngtcp2-cmn.c b/lib/vquic/cf-ngtcp2-cmn.c index 419c52009a..a86960c91c 100644 --- a/lib/vquic/cf-ngtcp2-cmn.c +++ b/lib/vquic/cf-ngtcp2-cmn.c @@ -649,8 +649,8 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) quic_tp_len = (size_t)tplen; } #endif - Curl_ossl_add_session(cf, data, ctx->ssl_peer.scache_key, ssl_sessionid, - SSL_version(ssl), "h3", quic_tp, quic_tp_len); + Curl_ossl_add_session(cf, data, &ctx->tls.ossl, ctx->ssl_peer.scache_key, + ssl_sessionid, "h3", quic_tp, quic_tp_len); } return 0; } diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index ed401fe0d8..cd8d43523a 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -2632,9 +2632,9 @@ static CURLcode ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, struct Curl_easy *data, + struct ossl_ctx *octx, const char *ssl_peer_key, SSL_SESSION *session, - int ietf_tls_id, const char *alpn, unsigned char *quic_tp, size_t quic_tp_len) @@ -2651,6 +2651,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, size_t der_session_size; unsigned char *der_session_ptr; size_t earlydata_max = 0; + int ietf_tls_id = SSL_version(octx->ssl); der_session_size = i2d_SSL_SESSION(session, NULL); if(der_session_size == 0) { @@ -2688,6 +2689,9 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, earlydata_max, qtp_clone, quic_tp_len, &sc_session); der_session_buf = NULL; /* took ownership of sdata */ +#ifdef USE_APPLE_SECTRUST + sc_session->sectrust_verified = octx->sectrust_verified; +#endif if(!result) { result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session); /* took ownership of `sc_session` */ @@ -2708,8 +2712,9 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) if(cf) { struct Curl_easy *data = CF_DATA_CURRENT(cf); struct ssl_connect_data *connssl = cf->ctx; - Curl_ossl_add_session(cf, data, connssl->peer.scache_key, ssl_sessionid, - SSL_version(ssl), connssl->negotiated.alpn, NULL, 0); + struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; + Curl_ossl_add_session(cf, data, octx, connssl->peer.scache_key, + ssl_sessionid, connssl->negotiated.alpn, NULL, 0); } return 0; } @@ -3353,7 +3358,12 @@ static CURLcode ossl_init_session_and_alpns( } else { if(conn_cfg->verifypeer && - (SSL_get_verify_result(octx->ssl) != X509_V_OK)) { + (SSL_get_verify_result(octx->ssl) != X509_V_OK) +#ifdef USE_APPLE_SECTRUST + /* if sectrust is used and verified the session before */ + && (!ssl_config->native_ca_store || !scs->sectrust_verified) +#endif + ) { /* Session was from unverified connection, cannot reuse here */ SSL_set_session(octx->ssl, NULL); infof(data, "SSL session not peer verified, not reusing"); @@ -3362,6 +3372,9 @@ static CURLcode ossl_init_session_and_alpns( infof(data, "SSL reusing session with ALPN '%s'", scs->alpn ? scs->alpn : "-"); octx->reused_session = TRUE; +#ifdef USE_APPLE_SECTRUST + octx->sectrust_session = scs->sectrust_verified; +#endif infof(data, "SSL verify result: %lx", (unsigned long)SSL_get_verify_result(octx->ssl)); #ifdef HAVE_OPENSSL_EARLYDATA @@ -4671,13 +4684,13 @@ static CURLcode ossl_chain_get_der(struct Curl_cfilter *cf, static CURLcode ossl_apple_verify(struct Curl_cfilter *cf, struct Curl_easy *data, struct ossl_ctx *octx, - struct ssl_peer *peer, - bool *pverified) + struct ssl_peer *peer) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ossl_certs_ctx chain; CURLcode result; + octx->sectrust_verified = FALSE; memset(&chain, 0, sizeof(chain)); chain.sk = SSL_get_peer_cert_chain(octx->ssl); chain.num_certs = chain.sk ? sk_X509_num(chain.sk) : 0; @@ -4689,8 +4702,11 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf, result = CURLE_PEER_FAILED_VERIFICATION; } else { - /* when session was reused, there is no peer cert chain */ - *pverified = FALSE; + /* When session was reused, there is no peer cert chain. + * We trust it if it came from a SecTrust verified TLS. */ + CURL_TRC_CF(data, cf, "session reused, sectrust_session=%d", + octx->sectrust_session); + octx->sectrust_verified = (bool)octx->sectrust_session; return CURLE_OK; } } @@ -4717,12 +4733,12 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf, if(!result && ocsp_missing && conn_config->verifystatus && !octx->reused_session) { /* verified, but OCSP stapling is required and server sent none */ - *pverified = TRUE; + octx->sectrust_verified = TRUE; failf(data, "No OCSP response received"); return CURLE_SSL_INVALIDCERTSTATUS; } } - *pverified = !result; + octx->sectrust_verified = !result; return result; } #endif /* USE_APPLE_SECTRUST */ @@ -4739,9 +4755,6 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, long ossl_verify; X509 *server_cert; bool verified = FALSE; -#if !defined(OPENSSL_NO_OCSP) && defined(USE_APPLE_SECTRUST) - bool sectrust_verified = FALSE; -#endif if(data->set.ssl.certinfo && !octx->reused_session) { /* asked to gather certificate info. Reused sessions do not have cert @@ -4789,15 +4802,13 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, /* we verify using Apple SecTrust *unless* OpenSSL already verified. * This may happen if the application intercepted the OpenSSL callback * and installed its own. */ - result = ossl_apple_verify(cf, data, octx, peer, &verified); + result = ossl_apple_verify(cf, data, octx, peer); if(result && (result != CURLE_PEER_FAILED_VERIFICATION)) goto out; /* unexpected error */ - if(verified) { + if(octx->sectrust_verified) { infof(data, "SSL certificate verified via Apple SecTrust."); ssl_config->certverifyresult = X509_V_OK; -#ifndef OPENSSL_NO_OCSP - sectrust_verified = TRUE; -#endif + verified = TRUE; } } #endif @@ -4816,9 +4827,9 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, #ifndef OPENSSL_NO_OCSP if(conn_config->verifystatus && #ifdef USE_APPLE_SECTRUST - !sectrust_verified && /* already verified via apple sectrust, cannot - * verifystate via OpenSSL in that case as it - * does not have the trust anchors */ + !octx->sectrust_verified && /* already verified via sectrust, cannot + * verifystate via OpenSSL in that case as it + * does not have the trust anchors */ #endif !octx->reused_session) { /* do not do this after Session ID reuse */ diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h index 53ab60528f..1daeef50df 100644 --- a/lib/vtls/openssl.h +++ b/lib/vtls/openssl.h @@ -129,6 +129,10 @@ struct ossl_ctx { BIT(x509_store_setup); /* x509 store has been set up */ BIT(store_is_empty); /* no certs/paths/blobs in x509 store */ BIT(reused_session); /* session-ID was reused for this */ +#ifdef USE_APPLE_SECTRUST + BIT(sectrust_verified); /* peer was verified by sectrust */ + BIT(sectrust_session); /* session from sectrust verified peer */ +#endif }; size_t Curl_ossl_version(char *buffer, size_t size); @@ -182,9 +186,9 @@ CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf, */ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, struct Curl_easy *data, + struct ossl_ctx *octx, const char *ssl_peer_key, SSL_SESSION *session, - int ietf_tls_id, const char *alpn, unsigned char *quic_tp, size_t quic_tp_len); diff --git a/lib/vtls/vtls_scache.h b/lib/vtls/vtls_scache.h index effb1d8f96..fc4eb9ef51 100644 --- a/lib/vtls/vtls_scache.h +++ b/lib/vtls/vtls_scache.h @@ -131,6 +131,7 @@ struct Curl_ssl_session { const unsigned char *quic_tp; /* Optional QUIC transport param bytes */ size_t quic_tp_len; /* number of bytes in quic_tp */ struct Curl_llist_node list; /* internal storage handling */ + BIT(sectrust_verified); /* session comes from sectrust verified TLS */ }; /* Create a `session` instance. Does NOT need locking. diff --git a/lib/vtls/vtls_spack.c b/lib/vtls/vtls_spack.c index 9cbdecc901..e572e923f5 100644 --- a/lib/vtls/vtls_spack.c +++ b/lib/vtls/vtls_spack.c @@ -38,6 +38,7 @@ #define CURL_SPACK_ALPN 0x05 #define CURL_SPACK_EARLYDATA 0x06 #define CURL_SPACK_QUICTP 0x07 +#define CURL_SPACK_SECTRUST 0x08 static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b) { @@ -218,6 +219,9 @@ CURLcode Curl_ssl_session_pack(struct Curl_easy *data, if(!result) result = spack_enc32(buf, (uint32_t)s->earlydata_max); } + if(!result && s->sectrust_verified) { + result = spack_enc8(buf, CURL_SPACK_SECTRUST); + } if(!result && s->quic_tp && s->quic_tp_len) { result = spack_enc8(buf, CURL_SPACK_QUICTP); if(!result) @@ -303,6 +307,9 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data, goto out; s->valid_until = (curl_off_t)val64; break; + case CURL_SPACK_SECTRUST: + s->sectrust_verified = TRUE; + break; default: /* unknown tag */ result = CURLE_READ_ERROR; goto out;