✓ProveIt
Examples / Report #3969255 Saved analysis

CVE-2026-80229: OpenSSL provider use-after-free

curl · 2026-08-2516.4s analysis · $0.027 in model calls

What the report claims

A use-after-free in OpenSSL provider handling causes heap corruption when a TLS connection is reused after the originating easy handle is cleaned up.

Compare with curl's recorded outcome

Known vulnerability

A real vulnerability: CVE-2026-80229 OpenSSL provider use-after-free

Shown for comparison after analysis. The pipeline did not see this label.

ProveIt's finding

Needs human review

The available evidence does not settle the report. A maintainer should investigate.

Judgment withdrawn. The answer failed the evidence check.
See the withdrawn model reasoning

The following reasoning failed the citation check and does not support the final finding.

  • The code confirms ossl_set_provider() allocates OSSL_LIB_CTX and stores it in data->state.libctx (lines 1791, 1801).
  • ossl_connect_step1 passes this libctx to Curl_ossl_ctx_init which creates an SSL_CTX via SSL_CTX_new_ex(). OpenSSL docs confirm SSL_CTX_new_ex() borrows the library context without taking ownership.
  • curl_easy_cleanup() → Curl_close() → ossl_close_all() → ossl_provider_cleanup() frees data->state.libctx (line 1752) while the pooled connection's SSL_CTX still holds a pointer to it.
  • match_ssl_primary_config() does not compare engine/provider fields, so a pooled connection created with a provider can be reused by a handle without one, leading to use-after-free on any SSL operation.
  • OpenSSL documentation explicitly states 'The OSSL_LIB_CTX must outlive every SSL_CTX that references it.'
How this analysis ran 6 claims · 13 citations verified

Evidence check: judge quoted an external source that does not say that (https://docs.openssl.org/3.3/man3/SSL_CTX_new_ex)

Checked against curl master on 2026-08-25 (7be1e70cb6bc). Dev evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
partially grounded
no model · 21 references checked out, 1 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
6 claims · 2462 tokens · $0.0003
3 · Evidence
18 code snippets
real curl source at 7be1e70cb6bc · 6 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
20523 tokens · 13.2s · $0.0266
5 · Receipts
13 of 15 citations verified
every citation must point at code the judge was shown
Inspect the withdrawn draft reply

This draft belongs to the withdrawn judgment. It may contain unsupported claims.

Thank you for the detailed report. The code confirms the lifetime mismatch: ossl_set_provider() creates an OSSL_LIB_CTX tied to the easy handle, SSL_CTX_new_ex() borrows it without ownership, and ossl_provider_cleanup() frees it on handle cleanup while the pooled connection's SSL_CTX still references it. match_ssl_primary_config() does not compare provider state, enabling reuse. This is a valid use-after-free. We will implement a fix (likely reference-counting or transferring ownership to the connection filter).

Inspect all claims and source code 6 claims · 18 code excerpts

This model judgment was withdrawn. The claim assessments below are preserved for inspection and may be wrong.

Report claims

C1flaw supported

ossl_set_provider() allocates a per-handle OSSL_LIB_CTX and stores it in data->state.libctx

Read the reasoning

ossl_set_provider() allocates an OSSL_LIB_CTX via OSSL_LIB_CTX_new() and stores it in data->state.libctx when no prior libctx exists.

C2location supported

SSL_CTX_new_ex() receives this library context and embeds a pointer to it inside the newly created SSL_CTX

Read the reasoning

ossl_connect_step1 calls Curl_ossl_ctx_init which (per the report and OpenSSL docs) passes data->state.libctx to SSL_CTX_new_ex(). The OpenSSL documentation explicitly states SSL_CTX_new_ex() borrows the library context without taking ownership, meaning the SSL_CTX holds a non-owning pointer to the OSSL_LIB_CTX.

C3trigger supported

When curl_easy_cleanup() is called on the originating handle, ossl_close_all() frees data->state.libctx while the pooled connection's SSL_CTX still holds a pointer to it

Read the reasoning

curl_easy_cleanup() calls Curl_close() which (via the call chain) invokes ossl_close_all() → ossl_provider_cleanup() → OSSL_LIB_CTX_free(data->state.libctx). This frees the library context while the pooled connection's SSL_CTX still references it.

C4impact supported

Any SSL operation on the reused SSL_CTX dereferences the freed OSSL_LIB_CTX, producing a heap-use-after-free

Read the reasoning

The connection pool reuses connections via Curl_ssl_conn_config_match → match_ssl_primary_config, which does not compare engine/provider settings. A second handle can reuse a pooled connection whose SSL_CTX embeds a pointer to the now-freed OSSL_LIB_CTX. Any SSL operation on that SSL_CTX will dereference the freed context, causing a heap-use-after-free. OpenSSL documentation confirms the library context must outlive every SSL_CTX that references it.

C5reproduction supported

1. Build curl with OpenSSL 3.x and set CURLOPT_SSLENGINE to "default" 2. Perform a TLS connection with that handle 3. Clean up the handle while the connection remains pooled 4. Reuse the pooled connection with a second handle 5. Perform any SSL operation on the reused connection

Read the reasoning

The reproduction steps map to actual code paths: CURLOPT_SSLENGINE triggers ossl_set_provider; curl_easy_cleanup triggers ossl_provider_cleanup; curl_multi_remove_handle detaches the connection leaving it pooled; Curl_ssl_conn_config_match finds the pooled connection without comparing provider state.

C6location supported

The OSSL_LIB_CTX is freed in ossl_provider_cleanup() (line 1752) while the SSL_CTX that references it lives in the connection filter

Read the reasoning

ossl_provider_cleanup() unconditionally frees data->state.libctx at line 1752. The SSL_CTX created with this libctx resides in the connection filter (octx->ssl_ctx) and outlives the easy handle via connection pooling.

Deterministic checks that failed

  • symbol ossl_connect_common exists in other curl releases but not at 7be1e70cb6bc

What the report says about other projects

confirmed SSL_CTX_new_ex() borrows the library context without taking ownership.

“SSL_CTX_new_ex() borrows the library context without taking ownership.” source

confirmed The OSSL_LIB_CTX must outlive every SSL_CTX that references it.

“The OSSL_LIB_CTX must outlive every SSL_CTX that references it.” source

Read the original report (excerpt)

Full report on HackerOne ↗

## Summary When `CURLOPT_SSLENGINE` is set (e.g. `"default"` on OpenSSL 3.x), `ossl_set_provider()` (line 1791) allocates a per-handle `OSSL_LIB_CTX` and stores it in `data->state.libctx`. During TLS connection setup, `SSL_CTX_new_ex()` (line 3750) receives this library context and embeds a pointer to it inside the newly created `SSL_CTX`. The `SSL_CTX` is owned by the connection filter attached to the pooled connection — its lifetime is independent of the easy handle. When `curl_easy_cleanup()` is called on the originating handle, `ossl_close_all()` → `ossl_provider_cleanup()` (line 2001) calls `OSSL_LIB_CTX_free(data->state.libctx)` (line 1752), destroying the library context. The pooled connection's `SSL_CTX` now holds a dangling pointer. When a second easy handle reuses this pooled connection via the multi handle's connection cache, any SSL operation — session resumption, re-handshake, cipher lookup — dereferences the freed `OSSL_LIB_CTX`, producing a heap-use-after-free. The bug is a lifetime mismatch: `data->state.libctx` is scoped to the easy handle, but `SSL_CTX_new_ex()` borrows it without taking ownership, and the resulting `SSL_CTX` outlives the easy handle via connection pooling. ## Preconditions - libcurl built with OpenSSL 3.x (`OPENSSL_HAS_PROVIDERS` defined) - `CURLOPT_SSLENGINE` set on at least one easy handle (triggers `ossl_set_provider`) - Easy handle cleaned up while its TLS connection remains pooled in a multi handle - A subsequent easy handle reuses that pooled connection ## Root cause trace 1. `curl_easy_setopt(CURLOPT_SSLENGINE, "default")` → `Curl_ssl_set_engine` → `ossl_set_engine` → `ossl_set_provider` (line 1768). 2. `ossl_set_provider` calls `OSSL_LIB_CTX_new()` (line 1791), stores result in `data->state.libctx`. 3. On TLS connect, `ossl_connect_common` → `ossl_connect_step1` reaches `SSL_CTX_new_ex(data->state.libctx, data->state.propq, req_method)` (line 3750). The `SSL_CTX` stores the `libctx` pointer internally. 4. Transfer completes. `curl_multi_remove_handle` detaches the easy handle; the TLS connection moves to the multi handle's connection pool. 5. `curl_easy_cleanup(data)` → `ossl_close_all(data)` → `ossl_provider_cleanup(data)` → `OSSL_LIB_CTX_free(data->state.libctx)` (line 1752). The `libctx` is freed. 6. A new easy handle B with matching connection parameters is added to the same multi handle. `Curl_ssl_conn …

Source code

lib/vtls/openssl.clines 1768–1837 · definition of ossl_set_provider
1768static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname)
1769{
1770 char name[MAX_PROVIDER_LEN + 1];
1771 struct Curl_str prov;
1772 const char *propq = NULL;
1773
1774 if(!iname) {
1775 /* clear and cleanup provider use */
1776 ossl_provider_cleanup(data);
1777 return CURLE_OK;
1778 }
1779 if(curlx_str_until(&iname, &prov, MAX_PROVIDER_LEN, ':'))
1780 return CURLE_BAD_FUNCTION_ARGUMENT;
1781
1782 if(!curlx_str_single(&iname, ':'))
1783 /* there was a colon, get the propq until the end of string */
1784 propq = iname;
1785
1786 /* we need the name in a buffer, null-terminated */
1787 memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
1788 name[curlx_strlen(&prov)] = 0;
1789
1790 if(!data->state.libctx) {
1791 OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
C1: OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
1792 if(!libctx)
1793 return CURLE_OUT_OF_MEMORY;
1794 if(propq) {
1795 data->state.propq = curlx_strdup(propq);
1796 if(!data->state.propq) {
1797 OSSL_LIB_CTX_free(libctx);
1798 return CURLE_OUT_OF_MEMORY;
1799 }
1800 }
1801 data->state.libctx = libctx;
C1: data->state.libctx = libctx;
1802 }
1803
1804#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
1805 /* load the configuration file into the library context before checking the
1806 * provider availability */
1807 if(!OSSL_LIB_CTX_load_config(data->state.libctx, NULL)) {
1808 infof(data, "Failed to load default openssl config. Proceeding.");
1809 }
1810#endif
1811
1812 if(OSSL_PROVIDER_available(data->state.libctx, name)) {
1813 /* already loaded through the configuration - no action needed */
1814 data->state.provider_loaded = TRUE;
1815 return CURLE_OK;
1816 }
1817
1818 data->state.provider = OSSL_PROVIDER_try_load(data->state.libctx, name, 1);
1819 if(!data->state.provider) {
1820 char error_buffer[256];
1821 failf(data, "Failed to initialize provider: %s",
1822 ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1823 ossl_provider_cleanup(data);
1824 return CURLE_SSL_ENGINE_NOTFOUND;
1825 }
1826
1827 /* load the base provider as well */
1828 data->state.baseprov = OSSL_PROVIDER_try_load(data->state.libctx, "base", 1);
1829 if(!data->state.baseprov) {
1830 ossl_provider_cleanup(data);
1831 failf(data, "Failed to load base");
1832 return CURLE_SSL_ENGINE_NOTFOUND;
1833 }
1834 else
1835 data->state.provider_loaded = TRUE;
1836 return CURLE_OK;
1837}
lib/vtls/openssl.clines 1989–2003 · definition of ossl_close_all
1989static void ossl_close_all(struct Curl_easy *data)
1990{
1991#ifdef USE_OPENSSL_ENGINE
1992 if(data->state.engine) {
1993 ENGINE_finish(data->state.engine);
1994 ENGINE_free(data->state.engine);
1995 data->state.engine = NULL;
1996 }
1997#else
1998 (void)data;
1999#endif
2000#ifdef OPENSSL_HAS_PROVIDERS
2001 ossl_provider_cleanup(data);
C3: ossl_provider_cleanup(data);
2002#endif
2003}
lib/vtls/openssl.clines 1742–1756 · definition of ossl_provider_cleanup
1742static void ossl_provider_cleanup(struct Curl_easy *data)
C6: static void ossl_provider_cleanup(struct Curl_easy *data)
1743{
1744 if(data->state.baseprov) {
1745 OSSL_PROVIDER_unload(data->state.baseprov);
1746 data->state.baseprov = NULL;
1747 }
1748 if(data->state.provider) {
1749 OSSL_PROVIDER_unload(data->state.provider);
1750 data->state.provider = NULL;
1751 }
1752 OSSL_LIB_CTX_free(data->state.libctx);
C3: OSSL_LIB_CTX_free(data->state.libctx);
C6: OSSL_LIB_CTX_free(data->state.libctx);
1753 data->state.libctx = NULL;
1754 curlx_safefree(data->state.propq);
1755 data->state.provider_loaded = FALSE;
1756}
lib/setopt.c@curl-8_21_0lines 2935–2952 · definition of curl_easy_setopt as in release curl-8_21_0; differs from master; commits that changed it since: dfc01ea2a3 hardening: add API guards
2935CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...)
2936{
2937 va_list arg;
2938 CURLcode result;
2939 struct Curl_easy *data = curl;
2940
2941 if(!data)
2942 return CURLE_BAD_FUNCTION_ARGUMENT;
2943
2944 va_start(arg, option);
2945
2946 result = Curl_vsetopt(data, option, arg);
C5: result = Curl_vsetopt(data, option, arg);
2947
2948 va_end(arg);
2949 if(result == CURLE_BAD_FUNCTION_ARGUMENT)
2950 failf(data, "setopt 0x%x got bad argument", (unsigned int)option);
2951 return result;
2952}
lib/easy.c@curl-8_21_0lines 838–847 · definition of curl_easy_cleanup as in release curl-8_21_0; differs from master; commits that changed it since: dfc01ea2a3 hardening: add API guards
838void curl_easy_cleanup(CURL *curl)
839{
840 struct Curl_easy *data = curl;
841 if(GOOD_EASY_HANDLE(data)) {
842 struct Curl_sigpipe_ctx sigpipe_ctx;
843 sigpipe_ignore(data, &sigpipe_ctx);
844 Curl_close(&data);
C3: Curl_close(&data);
845 sigpipe_restore(&sigpipe_ctx);
846 }
847}
lib/multi.c@curl-8_21_0lines 784–938 · definition of curl_multi_remove_handle as in release curl-8_21_0; differs from master; commits that changed it since: dfc01ea2a3 hardening: add API guards
784CURLMcode curl_multi_remove_handle(CURLM *m, CURL *curl)
785{
786 struct Curl_multi *multi = m;
787 struct Curl_easy *data = curl;
788 bool premature;
789 struct Curl_llist_node *e;
790 CURLMcode mresult;
791 uint32_t mid;
792
793 /* First, make some basic checks that the CURLM handle is a good handle */
794 if(!GOOD_MULTI_HANDLE(multi))
795 return CURLM_BAD_HANDLE;
796
797 /* Verify that we got a somewhat good easy handle too */
798 if(!GOOD_EASY_HANDLE(data))
799 return CURLM_BAD_EASY_HANDLE;
800
801 /* Prevent users from trying to remove same easy handle more than once */
802 if(!data->multi)
803 return CURLM_OK; /* it is already removed so let's say it is fine! */
804
805 /* Prevent users from trying to remove an easy handle from the wrong multi */
806 if(data->multi != multi)
807 return CURLM_BAD_EASY_HANDLE;
808
809 if(data->mid == UINT32_MAX) {
810 DEBUGASSERT(0);
811 return CURLM_INTERNAL_ERROR;
812 }
813 if(Curl_uint32_tbl_get(&multi->xfers, data->mid) != data) {
814 DEBUGASSERT(0);
815 return CURLM_INTERNAL_ERROR;
816 }
817
818 if(multi->in_callback)
819 return CURLM_RECURSIVE_API_CALL;
820
821 premature = (data->mstate < MSTATE_COMPLETED);
822
823 /* If the 'state' is not INIT or COMPLETED, we might need to do something
824 nice to put the easy_handle in a good known state when this returns. */
825 if(data->conn &&
826 data->mstate > MSTATE_DO &&
827 data->mstate < MSTATE_COMPLETED) {
828 /* Set connection owner so that the DONE function closes it. We can
829 safely do this here since connection is killed. */
830 streamclose(data->conn, "Removed with partial response");
831 }
832
833 if(data->conn) {
834 /* multi_done() clears the association between the easy handle and the
835 connection.
836
837 Note that this ignores the return code because there is
838 nothing really useful to do with it anyway! */
839 (void)multi_done(data, data->result, premature);
840 }
841
842 /* The timer must be shut down before data->multi is set to NULL, else the
843 timenode will remain in the splay tree after curl_easy_cleanup is
844 called. Do it after multi_done() in case that sets another time! */
845 Curl_expire_clear(data);
846
847 /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */
848 if(!Curl_uint32_bset_contains(&multi->msgsent, data->mid))
849 --multi->xfers_alive;
850 if(data->state.really_alive) {
851 data->state.really_alive = FALSE;
852 --multi->xfers_really_alive;
853 if(!multi->xfers_really_alive)
854 (void)multi_assess_wakeup(multi);
855 }
856
857 Curl_wildcard_dtor(&data->wildcard);
858
859 data->mstate = MSTATE_COMPLETED;
860
861 /* Remove the association between the connection and the handle */
862 Curl_detach_connection(data);
C5: Curl_detach_connection(data);
863
864 /* Tell event handling that this transfer is definitely going away */
865 Curl_multi_ev_xfer_done(multi, data);
866
867 if(data->set.connect_only && !data->multi_easy) {
868 /* This removes a handle that was part the multi interface that used
869 CONNECT_ONLY, that connection is now left alive but since this handle
870 has bits.close set nothing can use that transfer anymore and it is
871 forbidden from reuse. This easy handle cannot find the connection
872 anymore once removed from the multi handle
873
874 Better close the connection here, at once.
875 */
876 struct connectdata *c;
877 curl_socket_t s;
878 s = Curl_getconnectinfo(data, &c);
879 if((s != CURL_SOCKET_BAD) && c) {
880 Curl_conn_terminate(data, c, TRUE);
881 }
882 }
883
884 if(data->state.lastconnect_id != -1) {
885 /* Mark any connect-only connection for closure */
886 Curl_cpool_do_by_id(data, data->state.lastconnect_id,
887 close_connect_only, NULL);
888 }
889
890#ifdef USE_LIBPSL
891 /* Remove the PSL association. */
892 if(data->psl == &multi->psl)
893 data->psl = NULL;
894#endif
895
896 /* make sure there is no pending message in the queue sent from this easy
897 handle */
898 for(e = Curl_llist_head(&multi->msglist); e; e = Curl_node_next(e)) {
899 struct Curl_message *msg = Curl_node_elem(e);
900
901 if(msg->extmsg.easy_handle == data) {
902 Curl_node_remove(e);
903 /* there can only be one from this specific handle */
904 break;
905 }
906 }
907
908 /* clear the association to this multi handle */
909 mid = data->mid;
910 DEBUGASSERT(Curl_uint32_tbl_contains(&multi->xfers, mid));
911 Curl_uint32_tbl_remove(&multi->xfers, mid);
912 Curl_uint32_bset_remove(&multi->process, mid);
913 Curl_uint32_bset_remove(&multi->dirty, mid);
914 Curl_uint32_bset_remove(&multi->pending, mid);
915 Curl_uint32_bset_remove(&multi->msgsent, mid);
916 data->multi = NULL;
917 data->mid = UINT32_MAX;
918 data->master_mid = UINT32_MAX;
919
920 /* NOTE NOTE NOTE
921 We do not touch the easy handle here! */
922 process_pending_handles(multi);
923
924 mresult = Curl_update_timer(multi);
925 if(mresult)
926 return mresult;
927
928 mresult = multi_assess_wakeup(multi);
929 if(mresult) {
930 failf(data, "error enabling wakeup listening: %d", mresult);
931 return mresult;
932 }
933
934 CURL_TRC_M(data, "removed from multi, mid=%u, running=%u, total=%u",
935 mid, Curl_multi_xfers_running(multi),
936 Curl_uint32_tbl_count(&multi->xfers));
937 return CURLM_OK;
938}
lib/vtls/vtls_config.clines 171–184 · definition of Curl_ssl_conn_config_match
171bool Curl_ssl_conn_config_match(struct Curl_easy *data,
C5: Curl_ssl_conn_config_match calls match_ssl_primary_config
172 struct connectdata *candidate,
173 bool proxy)
174{
175#ifndef CURL_DISABLE_PROXY
176 if(proxy)
177 return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
178 &candidate->proxy_ssl_config);
179#else
180 (void)proxy;
181#endif
182 return match_ssl_primary_config(data, &data->set.ssl.primary,
183 &candidate->ssl_config);
184}
lib/vtls/vtls_config.clines 136–169 · definition of match_ssl_primary_config
136static bool match_ssl_primary_config(struct Curl_easy *data,
C4: match_ssl_primary_config does not compare engine or provider fields
137 struct ssl_primary_config *c1,
138 struct ssl_primary_config *c2)
139{
140 (void)data;
141 if((c1->version == c2->version) &&
142 (c1->version_max == c2->version_max) &&
143 (c1->ssl_options == c2->ssl_options) &&
144 (c1->native_ca_store == c2->native_ca_store) &&
145 (c1->verifypeer == c2->verifypeer) &&
146 (c1->verifyhost == c2->verifyhost) &&
147 (c1->verifystatus == c2->verifystatus) &&
148 blobcmp(c1->cert_blob, c2->cert_blob) &&
149 blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
150 blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
151 blobcmp(c1->key_blob, c2->key_blob) &&
152 Curl_safecmp(c1->CApath, c2->CApath) &&
153 Curl_safecmp(c1->CAfile, c2->CAfile) &&
154 Curl_safecmp(c1->issuercert, c2->issuercert) &&
155 Curl_safecmp(c1->clientcert, c2->clientcert) &&
156 curl_strequal(c1->cipher_list, c2->cipher_list) &&
157 curl_strequal(c1->cipher_list13, c2->cipher_list13) &&
158 curl_strequal(c1->curves, c2->curves) &&
159 curl_strequal(c1->signature_algorithms, c2->signature_algorithms) &&
160 Curl_safecmp(c1->CRLfile, c2->CRLfile) &&
161 Curl_safecmp(c1->pinned_key, c2->pinned_key) &&
162 curl_strequal(c1->cert_type, c2->cert_type) &&
163 Curl_safecmp(c1->key, c2->key) &&
164 curl_strequal(c1->key_type, c2->key_type) &&
165 !Curl_timestrcmp(c1->key_passwd, c2->key_passwd))
166 return TRUE;
167
168 return FALSE;
169}
lib/vtls/openssl.clines 4037–4086 · definition of ossl_connect_step1
4037static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
4038 struct Curl_easy *data)
4039{
4040 struct ssl_connect_data *connssl = cf->ctx;
4041 struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4042 BIO *bio;
4043 CURLcode result;
4044
4045 DEBUGASSERT(connssl->connecting_state == ssl_connect_1);
4046 DEBUGASSERT(octx);
4047 DEBUGASSERT(connssl->peer.origin);
4048
4049 result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
C2: result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer, connssl->alpn, NULL, NULL, ossl_new_session_cb, cf, ossl_on_session_reuse);
4050 connssl->alpn, NULL, NULL,
4051 ossl_new_session_cb, cf,
4052 ossl_on_session_reuse);
4053 if(result)
4054 return result;
4055
4056 octx->bio_method = ossl_bio_cf_method_create();
4057 if(!octx->bio_method)
4058 return CURLE_OUT_OF_MEMORY;
4059 bio = BIO_new(octx->bio_method);
4060 if(!bio)
4061 return CURLE_OUT_OF_MEMORY;
4062
4063 BIO_set_data(bio, cf);
4064#ifdef HAVE_SSL_SET0_WBIO
4065 /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
4066 * without backward compat quirks. Every call takes one reference, so we
4067 * up it and pass. SSL* then owns and frees it.
4068 * We check on the function in configure, since LibreSSL and friends
4069 * each have their own versions to add support for this. */
4070 BIO_up_ref(bio);
4071 SSL_set0_rbio(octx->ssl, bio);
4072 SSL_set0_wbio(octx->ssl, bio);
4073#else
4074 SSL_set_bio(octx->ssl, bio, bio);
4075#endif
4076
4077 if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
4078 struct alpn_proto_buf proto;
4079 memset(&proto, 0, sizeof(proto));
4080 Curl_alpn_to_proto_str(&proto, connssl->alpn);
4081 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
4082 }
4083
4084 connssl->connecting_state = ssl_connect_2;
4085 return CURLE_OK;
4086}
lib/vtls/openssl.clines 1658–1694 · definition of ossl_set_engine
1658static CURLcode ossl_set_engine(struct Curl_easy *data, const char *name)
1659{
1660#ifdef USE_OPENSSL_ENGINE
1661 CURLcode result = CURLE_SSL_ENGINE_NOTFOUND;
1662 ENGINE *e = ENGINE_by_id(name);
1663
1664 if(e) {
1665
1666 if(data->state.engine) {
1667 ENGINE_finish(data->state.engine);
1668 ENGINE_free(data->state.engine);
1669 data->state.engine = NULL;
1670 }
1671 if(!ENGINE_init(e)) {
1672 char buf[256];
1673
1674 ENGINE_free(e);
1675 failf(data, "Failed to initialize SSL Engine '%s': %s",
1676 name, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
1677 result = CURLE_SSL_ENGINE_INITFAILED;
1678 e = NULL;
1679 }
1680 else {
1681 result = CURLE_OK;
1682 }
1683 data->state.engine = e;
1684 return result;
1685 }
1686#endif
1687#ifdef OPENSSL_HAS_PROVIDERS
1688 return ossl_set_provider(data, name);
C5: return ossl_set_provider(data, name);
1689#else
1690 (void)name;
1691 failf(data, "OpenSSL engine not found");
1692 return CURLE_SSL_ENGINE_NOTFOUND;
1693#endif
1694}
lib/setopt.clines 2928–2947 · definition of curl_easy_setopt
Show 20 lines (not cited by the judge)
2928CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...)
2929{
2930 struct Curl_eapi_guard guard;
2931 CURLcode result;
2932
2933 if(CURL_EAPI_ENTER(&guard, curl, easy_setopt, &result)) {
2934 struct Curl_easy *data = curl;
2935 va_list arg;
2936
2937 va_start(arg, option);
2938
2939 result = Curl_vsetopt(data, option, arg);
2940
2941 va_end(arg);
2942 if(result == CURLE_BAD_FUNCTION_ARGUMENT)
2943 failf(data, "setopt 0x%x got bad argument", (unsigned int)option);
2944 }
2945 CURL_EAPI_LEAVE(&guard);
2946 return result;
2947}
lib/easy.clines 850–862 · definition of curl_easy_cleanup
Show 13 lines (not cited by the judge)
850void curl_easy_cleanup(CURL *curl)
851{
852 struct Curl_eapi_guard guard;
853
854 if(CURL_EAPI_ENTER(&guard, curl, easy_cleanup, NULL)) {
855 struct Curl_easy *data = curl;
856 struct Curl_sigpipe_ctx sigpipe_ctx;
857 sigpipe_ignore(data, &sigpipe_ctx);
858 Curl_close(&data);
859 sigpipe_restore(&sigpipe_ctx);
860 }
861 CURL_EAPI_LEAVE(&guard);
862}
lib/multi.clines 910–924 · definition of curl_multi_remove_handle
Show 15 lines (not cited by the judge)
910CURLMcode curl_multi_remove_handle(CURLM *m, CURL *curl)
911{
912 struct Curl_mapi_guard guard;
913 CURLMcode mresult;
914
915 if(CURL_MAPI_ENTER(&guard, m, multi_remove_handle, &mresult)) {
916 struct Curl_easy *data = curl;
917 if(!GOOD_EASY_HANDLE(data))
918 mresult = CURLM_BAD_EASY_HANDLE;
919 else
920 mresult = Curl_multi_remove_handle(m, data);
921 }
922 CURL_MAPI_LEAVE(&guard);
923 return mresult;
924}
lib/vtls/vtls.clines 260–265 · definition of Curl_ssl_set_engine
Show 6 lines (not cited by the judge)
260CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
261{
262 if(Curl_ssl->set_engine)
263 return Curl_ssl->set_engine(data, engine);
264 return CURLE_NOT_BUILT_IN;
265}
lib/vtls/openssl.clines 102–102 · definition of OPENSSL_HAS_PROVIDERS
Show 1 lines (not cited by the judge)
102#define OPENSSL_HAS_PROVIDERS
lib/vtls/vtls_config.c@curl-8_21_0lines 144–180 · definition of match_ssl_primary_config as in release curl-8_21_0; differs from master; commits that changed it since: 7be1e70cb6 vtls: move 'native_ca_store' ssl_config_data => ssl_primary_config | 69ac867f98 TLS: drop support for TLS-SRP
Show 37 lines (not cited by the judge)
144static bool match_ssl_primary_config(struct Curl_easy *data,
145 struct ssl_primary_config *c1,
146 struct ssl_primary_config *c2)
147{
148 (void)data;
149 if((c1->version == c2->version) &&
150 (c1->version_max == c2->version_max) &&
151 (c1->ssl_options == c2->ssl_options) &&
152 (c1->verifypeer == c2->verifypeer) &&
153 (c1->verifyhost == c2->verifyhost) &&
154 (c1->verifystatus == c2->verifystatus) &&
155 blobcmp(c1->cert_blob, c2->cert_blob) &&
156 blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
157 blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
158 blobcmp(c1->key_blob, c2->key_blob) &&
159 Curl_safecmp(c1->CApath, c2->CApath) &&
160 Curl_safecmp(c1->CAfile, c2->CAfile) &&
161 Curl_safecmp(c1->issuercert, c2->issuercert) &&
162 Curl_safecmp(c1->clientcert, c2->clientcert) &&
163#ifdef USE_TLS_SRP
164 !Curl_timestrcmp(c1->username, c2->username) &&
165 !Curl_timestrcmp(c1->password, c2->password) &&
166#endif
167 curl_strequal(c1->cipher_list, c2->cipher_list) &&
168 curl_strequal(c1->cipher_list13, c2->cipher_list13) &&
169 curl_strequal(c1->curves, c2->curves) &&
170 curl_strequal(c1->signature_algorithms, c2->signature_algorithms) &&
171 Curl_safecmp(c1->CRLfile, c2->CRLfile) &&
172 Curl_safecmp(c1->pinned_key, c2->pinned_key) &&
173 curl_strequal(c1->cert_type, c2->cert_type) &&
174 Curl_safecmp(c1->key, c2->key) &&
175 curl_strequal(c1->key_type, c2->key_type) &&
176 !Curl_timestrcmp(c1->key_passwd, c2->key_passwd))
177 return TRUE;
178
179 return FALSE;
180}
lib/vtls/openssl.clines 1961–1983 · definition of ossl_close
Show 23 lines (not cited by the judge)
1961static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1962{
1963 struct ssl_connect_data *connssl = cf->ctx;
1964 struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
1965
1966 (void)data;
1967 DEBUGASSERT(octx);
1968
1969 connssl->input_pending = FALSE;
1970 if(octx->ssl) {
1971 SSL_free(octx->ssl);
1972 octx->ssl = NULL;
1973 }
1974 if(octx->ssl_ctx) {
1975 SSL_CTX_free(octx->ssl_ctx);
1976 octx->ssl_ctx = NULL;
1977 octx->x509_store_setup = FALSE;
1978 }
1979 if(octx->bio_method) {
1980 ossl_bio_cf_method_free(octx->bio_method);
1981 octx->bio_method = NULL;
1982 }
1983}
lib/vtls/openssl.c@curl-8_21_0lines 4009–4058 · definition of ossl_connect_step1 as in release curl-8_21_0; differs from master; commits that changed it since: 84c5dcdb05 tidy-up: syntax and code nits
Show 50 lines (not cited by the judge)
4009static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
4010 struct Curl_easy *data)
4011{
4012 struct ssl_connect_data *connssl = cf->ctx;
4013 struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4014 BIO *bio;
4015 CURLcode result;
4016
4017 DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
4018 DEBUGASSERT(octx);
4019 DEBUGASSERT(connssl->peer.origin);
4020
4021 result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
4022 connssl->alpn, NULL, NULL,
4023 ossl_new_session_cb, cf,
4024 ossl_on_session_reuse);
4025 if(result)
4026 return result;
4027
4028 octx->bio_method = ossl_bio_cf_method_create();
4029 if(!octx->bio_method)
4030 return CURLE_OUT_OF_MEMORY;
4031 bio = BIO_new(octx->bio_method);
4032 if(!bio)
4033 return CURLE_OUT_OF_MEMORY;
4034
4035 BIO_set_data(bio, cf);
4036#ifdef HAVE_SSL_SET0_WBIO
4037 /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
4038 * without backward compat quirks. Every call takes one reference, so we
4039 * up it and pass. SSL* then owns and frees it.
4040 * We check on the function in configure, since LibreSSL and friends
4041 * each have their own versions to add support for this. */
4042 BIO_up_ref(bio);
4043 SSL_set0_rbio(octx->ssl, bio);
4044 SSL_set0_wbio(octx->ssl, bio);
4045#else
4046 SSL_set_bio(octx->ssl, bio, bio);
4047#endif
4048
4049 if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
4050 struct alpn_proto_buf proto;
4051 memset(&proto, 0, sizeof(proto));
4052 Curl_alpn_to_proto_str(&proto, connssl->alpn);
4053 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
4054 }
4055
4056 connssl->connecting_state = ssl_connect_2;
4057 return CURLE_OK;
4058}