1 | /***************************************************************************
|
---|
2 | * _ _ ____ _
|
---|
3 | * Project ___| | | | _ \| |
|
---|
4 | * / __| | | | |_) | |
|
---|
5 | * | (__| |_| | _ <| |___
|
---|
6 | * \___|\___/|_| \_\_____|
|
---|
7 | *
|
---|
8 | * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
|
---|
9 | *
|
---|
10 | * This software is licensed as described in the file COPYING, which
|
---|
11 | * you should have received as part of this distribution. The terms
|
---|
12 | * are also available at https://curl.se/docs/copyright.html.
|
---|
13 | *
|
---|
14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
---|
15 | * copies of the Software, and permit persons to whom the Software is
|
---|
16 | * furnished to do so, under the terms of the COPYING file.
|
---|
17 | *
|
---|
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
---|
19 | * KIND, either express or implied.
|
---|
20 | *
|
---|
21 | * SPDX-License-Identifier: curl
|
---|
22 | *
|
---|
23 | ***************************************************************************/
|
---|
24 |
|
---|
25 | #include "curl_setup.h"
|
---|
26 |
|
---|
27 | #if defined(ENABLE_QUIC) && \
|
---|
28 | (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
|
---|
29 |
|
---|
30 | #ifdef USE_OPENSSL
|
---|
31 | #include <openssl/err.h>
|
---|
32 | #include "vtls/openssl.h"
|
---|
33 | #elif defined(USE_GNUTLS)
|
---|
34 | #include <gnutls/abstract.h>
|
---|
35 | #include <gnutls/gnutls.h>
|
---|
36 | #include <gnutls/x509.h>
|
---|
37 | #include <gnutls/crypto.h>
|
---|
38 | #include <nettle/sha2.h>
|
---|
39 | #include "vtls/gtls.h"
|
---|
40 | #elif defined(USE_WOLFSSL)
|
---|
41 | #include <wolfssl/options.h>
|
---|
42 | #include <wolfssl/ssl.h>
|
---|
43 | #include <wolfssl/quic.h>
|
---|
44 | #include "vtls/wolfssl.h"
|
---|
45 | #endif
|
---|
46 |
|
---|
47 | #include "urldata.h"
|
---|
48 | #include "curl_trc.h"
|
---|
49 | #include "cfilters.h"
|
---|
50 | #include "multiif.h"
|
---|
51 | #include "vtls/keylog.h"
|
---|
52 | #include "vtls/vtls.h"
|
---|
53 | #include "vquic-tls.h"
|
---|
54 |
|
---|
55 | /* The last 3 #include files should be in this order */
|
---|
56 | #include "curl_printf.h"
|
---|
57 | #include "curl_memory.h"
|
---|
58 | #include "memdebug.h"
|
---|
59 |
|
---|
60 | #ifndef ARRAYSIZE
|
---|
61 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
---|
62 | #endif
|
---|
63 |
|
---|
64 | #ifdef USE_OPENSSL
|
---|
65 | #define QUIC_CIPHERS \
|
---|
66 | "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
|
---|
67 | "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
|
---|
68 | #define QUIC_GROUPS "P-256:X25519:P-384:P-521"
|
---|
69 | #elif defined(USE_GNUTLS)
|
---|
70 | #define QUIC_PRIORITY \
|
---|
71 | "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
|
---|
72 | "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
|
---|
73 | "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
|
---|
74 | "%DISABLE_TLS13_COMPAT_MODE"
|
---|
75 | #elif defined(USE_WOLFSSL)
|
---|
76 | #define QUIC_CIPHERS \
|
---|
77 | "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
|
---|
78 | "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
|
---|
79 | #define QUIC_GROUPS "P-256:P-384:P-521"
|
---|
80 | #endif
|
---|
81 |
|
---|
82 |
|
---|
83 | #ifdef USE_OPENSSL
|
---|
84 |
|
---|
85 | static void keylog_callback(const SSL *ssl, const char *line)
|
---|
86 | {
|
---|
87 | (void)ssl;
|
---|
88 | Curl_tls_keylog_write_line(line);
|
---|
89 | }
|
---|
90 |
|
---|
91 | static CURLcode curl_ossl_init_ctx(struct quic_tls_ctx *ctx,
|
---|
92 | struct Curl_cfilter *cf,
|
---|
93 | struct Curl_easy *data,
|
---|
94 | Curl_vquic_tls_ctx_setup *ctx_setup)
|
---|
95 | {
|
---|
96 | struct ssl_primary_config *conn_config;
|
---|
97 | CURLcode result = CURLE_FAILED_INIT;
|
---|
98 |
|
---|
99 | DEBUGASSERT(!ctx->ssl_ctx);
|
---|
100 | #ifdef USE_OPENSSL_QUIC
|
---|
101 | ctx->ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
|
---|
102 | #else
|
---|
103 | ctx->ssl_ctx = SSL_CTX_new(TLS_method());
|
---|
104 | #endif
|
---|
105 | if(!ctx->ssl_ctx) {
|
---|
106 | result = CURLE_OUT_OF_MEMORY;
|
---|
107 | goto out;
|
---|
108 | }
|
---|
109 | conn_config = Curl_ssl_cf_get_primary_config(cf);
|
---|
110 | if(!conn_config) {
|
---|
111 | result = CURLE_FAILED_INIT;
|
---|
112 | goto out;
|
---|
113 | }
|
---|
114 |
|
---|
115 | if(ctx_setup) {
|
---|
116 | result = ctx_setup(ctx, cf, data);
|
---|
117 | if(result)
|
---|
118 | goto out;
|
---|
119 | }
|
---|
120 |
|
---|
121 | SSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
|
---|
122 |
|
---|
123 | {
|
---|
124 | const char *curves = conn_config->curves ?
|
---|
125 | conn_config->curves : QUIC_GROUPS;
|
---|
126 | if(!SSL_CTX_set1_curves_list(ctx->ssl_ctx, curves)) {
|
---|
127 | failf(data, "failed setting curves list for QUIC: '%s'", curves);
|
---|
128 | return CURLE_SSL_CIPHER;
|
---|
129 | }
|
---|
130 | }
|
---|
131 |
|
---|
132 | #ifndef OPENSSL_IS_BORINGSSL
|
---|
133 | {
|
---|
134 | const char *ciphers13 = conn_config->cipher_list13 ?
|
---|
135 | conn_config->cipher_list13 : QUIC_CIPHERS;
|
---|
136 | if(SSL_CTX_set_ciphersuites(ctx->ssl_ctx, ciphers13) != 1) {
|
---|
137 | failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
|
---|
138 | return CURLE_SSL_CIPHER;
|
---|
139 | }
|
---|
140 | infof(data, "QUIC cipher selection: %s", ciphers13);
|
---|
141 | }
|
---|
142 | #endif
|
---|
143 |
|
---|
144 | /* Open the file if a TLS or QUIC backend has not done this before. */
|
---|
145 | Curl_tls_keylog_open();
|
---|
146 | if(Curl_tls_keylog_enabled()) {
|
---|
147 | SSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
|
---|
148 | }
|
---|
149 |
|
---|
150 | /* OpenSSL always tries to verify the peer, this only says whether it should
|
---|
151 | * fail to connect if the verification fails, or if it should continue
|
---|
152 | * anyway. In the latter case the result of the verification is checked with
|
---|
153 | * SSL_get_verify_result() below. */
|
---|
154 | SSL_CTX_set_verify(ctx->ssl_ctx, conn_config->verifypeer ?
|
---|
155 | SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
|
---|
156 |
|
---|
157 | /* give application a chance to interfere with SSL set up. */
|
---|
158 | if(data->set.ssl.fsslctx) {
|
---|
159 | /* When a user callback is installed to modify the SSL_CTX,
|
---|
160 | * we need to do the full initialization before calling it.
|
---|
161 | * See: #11800 */
|
---|
162 | if(!ctx->x509_store_setup) {
|
---|
163 | result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
|
---|
164 | if(result)
|
---|
165 | goto out;
|
---|
166 | ctx->x509_store_setup = TRUE;
|
---|
167 | }
|
---|
168 | Curl_set_in_callback(data, true);
|
---|
169 | result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
|
---|
170 | data->set.ssl.fsslctxp);
|
---|
171 | Curl_set_in_callback(data, false);
|
---|
172 | if(result) {
|
---|
173 | failf(data, "error signaled by ssl ctx callback");
|
---|
174 | goto out;
|
---|
175 | }
|
---|
176 | }
|
---|
177 | result = CURLE_OK;
|
---|
178 |
|
---|
179 | out:
|
---|
180 | if(result && ctx->ssl_ctx) {
|
---|
181 | SSL_CTX_free(ctx->ssl_ctx);
|
---|
182 | ctx->ssl_ctx = NULL;
|
---|
183 | }
|
---|
184 | return result;
|
---|
185 | }
|
---|
186 |
|
---|
187 | static CURLcode curl_ossl_set_client_cert(struct quic_tls_ctx *ctx,
|
---|
188 | struct Curl_cfilter *cf,
|
---|
189 | struct Curl_easy *data)
|
---|
190 | {
|
---|
191 | SSL_CTX *ssl_ctx = ctx->ssl_ctx;
|
---|
192 | const struct ssl_config_data *ssl_config;
|
---|
193 |
|
---|
194 | ssl_config = Curl_ssl_cf_get_config(cf, data);
|
---|
195 | DEBUGASSERT(ssl_config);
|
---|
196 |
|
---|
197 | if(ssl_config->primary.clientcert ||
|
---|
198 | ssl_config->primary.cert_blob ||
|
---|
199 | ssl_config->cert_type) {
|
---|
200 | return Curl_ossl_set_client_cert(
|
---|
201 | data, ssl_ctx, ssl_config->primary.clientcert,
|
---|
202 | ssl_config->primary.cert_blob, ssl_config->cert_type,
|
---|
203 | ssl_config->key, ssl_config->key_blob,
|
---|
204 | ssl_config->key_type, ssl_config->key_passwd);
|
---|
205 | }
|
---|
206 |
|
---|
207 | return CURLE_OK;
|
---|
208 | }
|
---|
209 |
|
---|
210 | /** SSL callbacks ***/
|
---|
211 |
|
---|
212 | static CURLcode curl_ossl_init_ssl(struct quic_tls_ctx *ctx,
|
---|
213 | struct Curl_easy *data,
|
---|
214 | struct ssl_peer *peer,
|
---|
215 | const char *alpn, size_t alpn_len,
|
---|
216 | void *user_data)
|
---|
217 | {
|
---|
218 | DEBUGASSERT(!ctx->ssl);
|
---|
219 | ctx->ssl = SSL_new(ctx->ssl_ctx);
|
---|
220 |
|
---|
221 | SSL_set_app_data(ctx->ssl, user_data);
|
---|
222 | SSL_set_connect_state(ctx->ssl);
|
---|
223 | #ifndef USE_OPENSSL_QUIC
|
---|
224 | SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
|
---|
225 | #endif
|
---|
226 |
|
---|
227 | if(alpn)
|
---|
228 | SSL_set_alpn_protos(ctx->ssl, (const uint8_t *)alpn, (int)alpn_len);
|
---|
229 |
|
---|
230 | if(peer->sni) {
|
---|
231 | if(!SSL_set_tlsext_host_name(ctx->ssl, peer->sni)) {
|
---|
232 | failf(data, "Failed set SNI");
|
---|
233 | SSL_free(ctx->ssl);
|
---|
234 | ctx->ssl = NULL;
|
---|
235 | return CURLE_QUIC_CONNECT_ERROR;
|
---|
236 | }
|
---|
237 | }
|
---|
238 | return CURLE_OK;
|
---|
239 | }
|
---|
240 |
|
---|
241 | #elif defined(USE_GNUTLS)
|
---|
242 | static int keylog_callback(gnutls_session_t session, const char *label,
|
---|
243 | const gnutls_datum_t *secret)
|
---|
244 | {
|
---|
245 | gnutls_datum_t crandom;
|
---|
246 | gnutls_datum_t srandom;
|
---|
247 |
|
---|
248 | gnutls_session_get_random(session, &crandom, &srandom);
|
---|
249 | if(crandom.size != 32) {
|
---|
250 | return -1;
|
---|
251 | }
|
---|
252 |
|
---|
253 | Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
|
---|
254 | return 0;
|
---|
255 | }
|
---|
256 |
|
---|
257 | static CURLcode curl_gtls_init_ctx(struct quic_tls_ctx *ctx,
|
---|
258 | struct Curl_cfilter *cf,
|
---|
259 | struct Curl_easy *data,
|
---|
260 | struct ssl_peer *peer,
|
---|
261 | const char *alpn, size_t alpn_len,
|
---|
262 | Curl_vquic_tls_ctx_setup *ctx_setup,
|
---|
263 | void *user_data)
|
---|
264 | {
|
---|
265 | struct ssl_primary_config *conn_config;
|
---|
266 | CURLcode result;
|
---|
267 | gnutls_datum_t alpns[5];
|
---|
268 | /* this will need some attention when HTTPS proxy over QUIC get fixed */
|
---|
269 | long * const pverifyresult = &data->set.ssl.certverifyresult;
|
---|
270 | int rc;
|
---|
271 |
|
---|
272 | conn_config = Curl_ssl_cf_get_primary_config(cf);
|
---|
273 | if(!conn_config)
|
---|
274 | return CURLE_FAILED_INIT;
|
---|
275 |
|
---|
276 | DEBUGASSERT(ctx->gtls == NULL);
|
---|
277 | ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
|
---|
278 | if(!ctx->gtls)
|
---|
279 | return CURLE_OUT_OF_MEMORY;
|
---|
280 |
|
---|
281 | result = gtls_client_init(data, conn_config, &data->set.ssl,
|
---|
282 | peer, ctx->gtls, pverifyresult);
|
---|
283 | if(result)
|
---|
284 | return result;
|
---|
285 |
|
---|
286 | gnutls_session_set_ptr(ctx->gtls->session, user_data);
|
---|
287 |
|
---|
288 | if(ctx_setup) {
|
---|
289 | result = ctx_setup(ctx, cf, data);
|
---|
290 | if(result)
|
---|
291 | return result;
|
---|
292 | }
|
---|
293 |
|
---|
294 | rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
|
---|
295 | if(rc < 0) {
|
---|
296 | CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
|
---|
297 | gnutls_strerror(rc));
|
---|
298 | return CURLE_QUIC_CONNECT_ERROR;
|
---|
299 | }
|
---|
300 |
|
---|
301 | /* Open the file if a TLS or QUIC backend has not done this before. */
|
---|
302 | Curl_tls_keylog_open();
|
---|
303 | if(Curl_tls_keylog_enabled()) {
|
---|
304 | gnutls_session_set_keylog_function(ctx->gtls->session, keylog_callback);
|
---|
305 | }
|
---|
306 |
|
---|
307 | /* convert the ALPN string from our arguments to a list of strings
|
---|
308 | * that gnutls wants and will convert internally back to this very
|
---|
309 | * string for sending to the server. nice. */
|
---|
310 | if(alpn) {
|
---|
311 | size_t i, alen = alpn_len;
|
---|
312 | unsigned char *s = (unsigned char *)alpn;
|
---|
313 | unsigned char slen;
|
---|
314 | for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
|
---|
315 | slen = s[0];
|
---|
316 | if(slen >= alen)
|
---|
317 | return CURLE_FAILED_INIT;
|
---|
318 | alpns[i].data = s + 1;
|
---|
319 | alpns[i].size = slen;
|
---|
320 | s += slen + 1;
|
---|
321 | alen -= (size_t)slen + 1;
|
---|
322 | }
|
---|
323 | if(alen) /* not all alpn chars used, wrong format or too many */
|
---|
324 | return CURLE_FAILED_INIT;
|
---|
325 | if(i) {
|
---|
326 | gnutls_alpn_set_protocols(ctx->gtls->session,
|
---|
327 | alpns, (unsigned int)i,
|
---|
328 | GNUTLS_ALPN_MANDATORY);
|
---|
329 | }
|
---|
330 | }
|
---|
331 |
|
---|
332 | return CURLE_OK;
|
---|
333 | }
|
---|
334 | #elif defined(USE_WOLFSSL)
|
---|
335 |
|
---|
336 | #if defined(HAVE_SECRET_CALLBACK)
|
---|
337 | static void keylog_callback(const WOLFSSL *ssl, const char *line)
|
---|
338 | {
|
---|
339 | (void)ssl;
|
---|
340 | Curl_tls_keylog_write_line(line);
|
---|
341 | }
|
---|
342 | #endif
|
---|
343 |
|
---|
344 | static CURLcode curl_wssl_init_ctx(struct quic_tls_ctx *ctx,
|
---|
345 | struct Curl_cfilter *cf,
|
---|
346 | struct Curl_easy *data,
|
---|
347 | Curl_vquic_tls_ctx_setup *ctx_setup)
|
---|
348 | {
|
---|
349 | struct ssl_primary_config *conn_config;
|
---|
350 | CURLcode result = CURLE_FAILED_INIT;
|
---|
351 |
|
---|
352 | conn_config = Curl_ssl_cf_get_primary_config(cf);
|
---|
353 | if(!conn_config) {
|
---|
354 | result = CURLE_FAILED_INIT;
|
---|
355 | goto out;
|
---|
356 | }
|
---|
357 |
|
---|
358 | ctx->ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
|
---|
359 | if(!ctx->ssl_ctx) {
|
---|
360 | result = CURLE_OUT_OF_MEMORY;
|
---|
361 | goto out;
|
---|
362 | }
|
---|
363 |
|
---|
364 | if(ctx_setup) {
|
---|
365 | result = ctx_setup(ctx, cf, data);
|
---|
366 | if(result)
|
---|
367 | goto out;
|
---|
368 | }
|
---|
369 |
|
---|
370 | wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
|
---|
371 |
|
---|
372 | if(wolfSSL_CTX_set_cipher_list(ctx->ssl_ctx, conn_config->cipher_list13 ?
|
---|
373 | conn_config->cipher_list13 :
|
---|
374 | QUIC_CIPHERS) != 1) {
|
---|
375 | char error_buffer[256];
|
---|
376 | ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
|
---|
377 | failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
|
---|
378 | result = CURLE_BAD_FUNCTION_ARGUMENT;
|
---|
379 | goto out;
|
---|
380 | }
|
---|
381 |
|
---|
382 | if(wolfSSL_CTX_set1_groups_list(ctx->ssl_ctx, conn_config->curves ?
|
---|
383 | conn_config->curves :
|
---|
384 | (char *)QUIC_GROUPS) != 1) {
|
---|
385 | failf(data, "wolfSSL failed to set curves");
|
---|
386 | result = CURLE_BAD_FUNCTION_ARGUMENT;
|
---|
387 | goto out;
|
---|
388 | }
|
---|
389 |
|
---|
390 | /* Open the file if a TLS or QUIC backend has not done this before. */
|
---|
391 | Curl_tls_keylog_open();
|
---|
392 | if(Curl_tls_keylog_enabled()) {
|
---|
393 | #if defined(HAVE_SECRET_CALLBACK)
|
---|
394 | wolfSSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
|
---|
395 | #else
|
---|
396 | failf(data, "wolfSSL was built without keylog callback");
|
---|
397 | result = CURLE_NOT_BUILT_IN;
|
---|
398 | goto out;
|
---|
399 | #endif
|
---|
400 | }
|
---|
401 |
|
---|
402 | if(conn_config->verifypeer) {
|
---|
403 | const char * const ssl_cafile = conn_config->CAfile;
|
---|
404 | const char * const ssl_capath = conn_config->CApath;
|
---|
405 |
|
---|
406 | wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
|
---|
407 | if(ssl_cafile || ssl_capath) {
|
---|
408 | /* tell wolfSSL where to find CA certificates that are used to verify
|
---|
409 | the server's certificate. */
|
---|
410 | int rc =
|
---|
411 | wolfSSL_CTX_load_verify_locations_ex(ctx->ssl_ctx, ssl_cafile,
|
---|
412 | ssl_capath,
|
---|
413 | WOLFSSL_LOAD_FLAG_IGNORE_ERR);
|
---|
414 | if(SSL_SUCCESS != rc) {
|
---|
415 | /* Fail if we insist on successfully verifying the server. */
|
---|
416 | failf(data, "error setting certificate verify locations:"
|
---|
417 | " CAfile: %s CApath: %s",
|
---|
418 | ssl_cafile ? ssl_cafile : "none",
|
---|
419 | ssl_capath ? ssl_capath : "none");
|
---|
420 | result = CURLE_SSL_CACERT_BADFILE;
|
---|
421 | goto out;
|
---|
422 | }
|
---|
423 | infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
|
---|
424 | infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
|
---|
425 | }
|
---|
426 | #ifdef CURL_CA_FALLBACK
|
---|
427 | else {
|
---|
428 | /* verifying the peer without any CA certificates won't work so
|
---|
429 | use wolfssl's built-in default as fallback */
|
---|
430 | wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
|
---|
431 | }
|
---|
432 | #endif
|
---|
433 | }
|
---|
434 | else {
|
---|
435 | wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
|
---|
436 | }
|
---|
437 |
|
---|
438 | /* give application a chance to interfere with SSL set up. */
|
---|
439 | if(data->set.ssl.fsslctx) {
|
---|
440 | Curl_set_in_callback(data, true);
|
---|
441 | result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
|
---|
442 | data->set.ssl.fsslctxp);
|
---|
443 | Curl_set_in_callback(data, false);
|
---|
444 | if(result) {
|
---|
445 | failf(data, "error signaled by ssl ctx callback");
|
---|
446 | goto out;
|
---|
447 | }
|
---|
448 | }
|
---|
449 | result = CURLE_OK;
|
---|
450 |
|
---|
451 | out:
|
---|
452 | if(result && ctx->ssl_ctx) {
|
---|
453 | SSL_CTX_free(ctx->ssl_ctx);
|
---|
454 | ctx->ssl_ctx = NULL;
|
---|
455 | }
|
---|
456 | return result;
|
---|
457 | }
|
---|
458 |
|
---|
459 | /** SSL callbacks ***/
|
---|
460 |
|
---|
461 | static CURLcode curl_wssl_init_ssl(struct quic_tls_ctx *ctx,
|
---|
462 | struct Curl_easy *data,
|
---|
463 | struct ssl_peer *peer,
|
---|
464 | const char *alpn, size_t alpn_len,
|
---|
465 | void *user_data)
|
---|
466 | {
|
---|
467 | (void)data;
|
---|
468 | DEBUGASSERT(!ctx->ssl);
|
---|
469 | DEBUGASSERT(ctx->ssl_ctx);
|
---|
470 | ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
|
---|
471 |
|
---|
472 | wolfSSL_set_app_data(ctx->ssl, user_data);
|
---|
473 | wolfSSL_set_connect_state(ctx->ssl);
|
---|
474 | wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
|
---|
475 |
|
---|
476 | if(alpn)
|
---|
477 | wolfSSL_set_alpn_protos(ctx->ssl, (const unsigned char *)alpn,
|
---|
478 | (int)alpn_len);
|
---|
479 |
|
---|
480 | if(peer->sni) {
|
---|
481 | wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
|
---|
482 | peer->sni, (unsigned short)strlen(peer->sni));
|
---|
483 | }
|
---|
484 |
|
---|
485 | return CURLE_OK;
|
---|
486 | }
|
---|
487 | #endif /* defined(USE_WOLFSSL) */
|
---|
488 |
|
---|
489 | CURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
|
---|
490 | struct Curl_cfilter *cf,
|
---|
491 | struct Curl_easy *data,
|
---|
492 | struct ssl_peer *peer,
|
---|
493 | const char *alpn, size_t alpn_len,
|
---|
494 | Curl_vquic_tls_ctx_setup *ctx_setup,
|
---|
495 | void *user_data)
|
---|
496 | {
|
---|
497 | CURLcode result;
|
---|
498 |
|
---|
499 | #ifdef USE_OPENSSL
|
---|
500 | result = curl_ossl_init_ctx(ctx, cf, data, ctx_setup);
|
---|
501 | if(result)
|
---|
502 | return result;
|
---|
503 |
|
---|
504 | result = curl_ossl_set_client_cert(ctx, cf, data);
|
---|
505 | if(result)
|
---|
506 | return result;
|
---|
507 |
|
---|
508 | return curl_ossl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
|
---|
509 | #elif defined(USE_GNUTLS)
|
---|
510 | (void)result;
|
---|
511 | return curl_gtls_init_ctx(ctx, cf, data, peer, alpn, alpn_len,
|
---|
512 | ctx_setup, user_data);
|
---|
513 | #elif defined(USE_WOLFSSL)
|
---|
514 | result = curl_wssl_init_ctx(ctx, cf, data, ctx_setup);
|
---|
515 | if(result)
|
---|
516 | return result;
|
---|
517 |
|
---|
518 | return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
|
---|
519 | #else
|
---|
520 | #error "no TLS lib in used, should not happen"
|
---|
521 | return CURLE_FAILED_INIT;
|
---|
522 | #endif
|
---|
523 | }
|
---|
524 |
|
---|
525 | void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx)
|
---|
526 | {
|
---|
527 | #ifdef USE_OPENSSL
|
---|
528 | if(ctx->ssl)
|
---|
529 | SSL_free(ctx->ssl);
|
---|
530 | if(ctx->ssl_ctx)
|
---|
531 | SSL_CTX_free(ctx->ssl_ctx);
|
---|
532 | #elif defined(USE_GNUTLS)
|
---|
533 | if(ctx->gtls) {
|
---|
534 | if(ctx->gtls->cred)
|
---|
535 | gnutls_certificate_free_credentials(ctx->gtls->cred);
|
---|
536 | if(ctx->gtls->session)
|
---|
537 | gnutls_deinit(ctx->gtls->session);
|
---|
538 | free(ctx->gtls);
|
---|
539 | }
|
---|
540 | #elif defined(USE_WOLFSSL)
|
---|
541 | if(ctx->ssl)
|
---|
542 | wolfSSL_free(ctx->ssl);
|
---|
543 | if(ctx->ssl_ctx)
|
---|
544 | wolfSSL_CTX_free(ctx->ssl_ctx);
|
---|
545 | #endif
|
---|
546 | memset(ctx, 0, sizeof(*ctx));
|
---|
547 | }
|
---|
548 |
|
---|
549 | CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
|
---|
550 | struct Curl_cfilter *cf,
|
---|
551 | struct Curl_easy *data)
|
---|
552 | {
|
---|
553 | #ifdef USE_OPENSSL
|
---|
554 | if(!ctx->x509_store_setup) {
|
---|
555 | CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
|
---|
556 | if(result)
|
---|
557 | return result;
|
---|
558 | ctx->x509_store_setup = TRUE;
|
---|
559 | }
|
---|
560 | #else
|
---|
561 | (void)ctx; (void)cf; (void)data;
|
---|
562 | #endif
|
---|
563 | return CURLE_OK;
|
---|
564 | }
|
---|
565 |
|
---|
566 | CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
|
---|
567 | struct Curl_cfilter *cf,
|
---|
568 | struct Curl_easy *data,
|
---|
569 | struct ssl_peer *peer)
|
---|
570 | {
|
---|
571 | struct ssl_primary_config *conn_config;
|
---|
572 | CURLcode result = CURLE_OK;
|
---|
573 |
|
---|
574 | conn_config = Curl_ssl_cf_get_primary_config(cf);
|
---|
575 | if(!conn_config)
|
---|
576 | return CURLE_FAILED_INIT;
|
---|
577 |
|
---|
578 | if(conn_config->verifyhost) {
|
---|
579 | #ifdef USE_OPENSSL
|
---|
580 | X509 *server_cert;
|
---|
581 | server_cert = SSL_get1_peer_certificate(ctx->ssl);
|
---|
582 | if(!server_cert) {
|
---|
583 | return CURLE_PEER_FAILED_VERIFICATION;
|
---|
584 | }
|
---|
585 | result = Curl_ossl_verifyhost(data, cf->conn, peer, server_cert);
|
---|
586 | X509_free(server_cert);
|
---|
587 | if(result)
|
---|
588 | return result;
|
---|
589 | #elif defined(USE_GNUTLS)
|
---|
590 | result = Curl_gtls_verifyserver(data, ctx->gtls->session,
|
---|
591 | conn_config, &data->set.ssl, peer,
|
---|
592 | data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
|
---|
593 | if(result)
|
---|
594 | return result;
|
---|
595 | #elif defined(USE_WOLFSSL)
|
---|
596 | if(!peer->sni ||
|
---|
597 | wolfSSL_check_domain_name(ctx->ssl, peer->sni) == SSL_FAILURE)
|
---|
598 | return CURLE_PEER_FAILED_VERIFICATION;
|
---|
599 | #endif
|
---|
600 | infof(data, "Verified certificate just fine");
|
---|
601 | }
|
---|
602 | else
|
---|
603 | infof(data, "Skipped certificate verification");
|
---|
604 | #ifdef USE_OPENSSL
|
---|
605 | if(data->set.ssl.certinfo)
|
---|
606 | /* asked to gather certificate info */
|
---|
607 | (void)Curl_ossl_certchain(data, ctx->ssl);
|
---|
608 | #endif
|
---|
609 | return result;
|
---|
610 | }
|
---|
611 |
|
---|
612 |
|
---|
613 | #endif /* !ENABLE_QUIC && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
|
---|