2
0

vquic-tls.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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. #include "curl_setup.h"
  25. #if defined(USE_HTTP3) && \
  26. (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
  27. #ifdef USE_OPENSSL
  28. #include <openssl/err.h>
  29. #include "vtls/openssl.h"
  30. #elif defined(USE_GNUTLS)
  31. #include <gnutls/abstract.h>
  32. #include <gnutls/gnutls.h>
  33. #include <gnutls/x509.h>
  34. #include <gnutls/crypto.h>
  35. #include <nettle/sha2.h>
  36. #include "vtls/gtls.h"
  37. #elif defined(USE_WOLFSSL)
  38. #include <wolfssl/options.h>
  39. #include <wolfssl/ssl.h>
  40. #include <wolfssl/quic.h>
  41. #include "vtls/wolfssl.h"
  42. #endif
  43. #include "urldata.h"
  44. #include "curl_trc.h"
  45. #include "cfilters.h"
  46. #include "multiif.h"
  47. #include "vtls/keylog.h"
  48. #include "vtls/vtls.h"
  49. #include "vtls/vtls_scache.h"
  50. #include "vquic-tls.h"
  51. /* The last 3 #include files should be in this order */
  52. #include "curl_printf.h"
  53. #include "curl_memory.h"
  54. #include "memdebug.h"
  55. #ifndef ARRAYSIZE
  56. #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
  57. #endif
  58. #if defined(USE_WOLFSSL)
  59. #define QUIC_CIPHERS \
  60. "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
  61. "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
  62. #define QUIC_GROUPS "P-256:P-384:P-521"
  63. #if defined(HAVE_SECRET_CALLBACK)
  64. static void keylog_callback(const WOLFSSL *ssl, const char *line)
  65. {
  66. (void)ssl;
  67. Curl_tls_keylog_write_line(line);
  68. }
  69. #endif
  70. static CURLcode wssl_init_ctx(struct curl_tls_ctx *ctx,
  71. struct Curl_cfilter *cf,
  72. struct Curl_easy *data,
  73. Curl_vquic_tls_ctx_setup *cb_setup,
  74. void *cb_user_data)
  75. {
  76. struct ssl_primary_config *conn_config;
  77. CURLcode result = CURLE_FAILED_INIT;
  78. conn_config = Curl_ssl_cf_get_primary_config(cf);
  79. if(!conn_config) {
  80. result = CURLE_FAILED_INIT;
  81. goto out;
  82. }
  83. ctx->wssl.ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
  84. if(!ctx->wssl.ctx) {
  85. result = CURLE_OUT_OF_MEMORY;
  86. goto out;
  87. }
  88. if(cb_setup) {
  89. result = cb_setup(cf, data, cb_user_data);
  90. if(result)
  91. goto out;
  92. }
  93. wolfSSL_CTX_set_default_verify_paths(ctx->wssl.ctx);
  94. if(wolfSSL_CTX_set_cipher_list(ctx->wssl.ctx, conn_config->cipher_list13 ?
  95. conn_config->cipher_list13 :
  96. QUIC_CIPHERS) != 1) {
  97. char error_buffer[256];
  98. ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
  99. failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
  100. result = CURLE_BAD_FUNCTION_ARGUMENT;
  101. goto out;
  102. }
  103. if(wolfSSL_CTX_set1_groups_list(ctx->wssl.ctx, conn_config->curves ?
  104. conn_config->curves :
  105. (char *)QUIC_GROUPS) != 1) {
  106. failf(data, "wolfSSL failed to set curves");
  107. result = CURLE_BAD_FUNCTION_ARGUMENT;
  108. goto out;
  109. }
  110. /* Open the file if a TLS or QUIC backend has not done this before. */
  111. Curl_tls_keylog_open();
  112. if(Curl_tls_keylog_enabled()) {
  113. #if defined(HAVE_SECRET_CALLBACK)
  114. wolfSSL_CTX_set_keylog_callback(ctx->wssl.ctx, keylog_callback);
  115. #else
  116. failf(data, "wolfSSL was built without keylog callback");
  117. result = CURLE_NOT_BUILT_IN;
  118. goto out;
  119. #endif
  120. }
  121. if(conn_config->verifypeer) {
  122. const char * const ssl_cafile = conn_config->CAfile;
  123. const char * const ssl_capath = conn_config->CApath;
  124. wolfSSL_CTX_set_verify(ctx->wssl.ctx, SSL_VERIFY_PEER, NULL);
  125. if(ssl_cafile || ssl_capath) {
  126. /* tell wolfSSL where to find CA certificates that are used to verify
  127. the server's certificate. */
  128. int rc =
  129. wolfSSL_CTX_load_verify_locations_ex(ctx->wssl.ctx, ssl_cafile,
  130. ssl_capath,
  131. WOLFSSL_LOAD_FLAG_IGNORE_ERR);
  132. if(SSL_SUCCESS != rc) {
  133. /* Fail if we insist on successfully verifying the server. */
  134. failf(data, "error setting certificate verify locations:"
  135. " CAfile: %s CApath: %s",
  136. ssl_cafile ? ssl_cafile : "none",
  137. ssl_capath ? ssl_capath : "none");
  138. result = CURLE_SSL_CACERT_BADFILE;
  139. goto out;
  140. }
  141. infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
  142. infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
  143. }
  144. #ifdef CURL_CA_FALLBACK
  145. else {
  146. /* verifying the peer without any CA certificates will not work so
  147. use wolfSSL's built-in default as fallback */
  148. wolfSSL_CTX_set_default_verify_paths(ctx->wssl.ctx);
  149. }
  150. #endif
  151. }
  152. else {
  153. wolfSSL_CTX_set_verify(ctx->wssl.ctx, SSL_VERIFY_NONE, NULL);
  154. }
  155. /* give application a chance to interfere with SSL set up. */
  156. if(data->set.ssl.fsslctx) {
  157. Curl_set_in_callback(data, TRUE);
  158. result = (*data->set.ssl.fsslctx)(data, ctx->wssl.ctx,
  159. data->set.ssl.fsslctxp);
  160. Curl_set_in_callback(data, FALSE);
  161. if(result) {
  162. failf(data, "error signaled by ssl ctx callback");
  163. goto out;
  164. }
  165. }
  166. result = CURLE_OK;
  167. out:
  168. if(result && ctx->wssl.ctx) {
  169. SSL_CTX_free(ctx->wssl.ctx);
  170. ctx->wssl.ctx = NULL;
  171. }
  172. return result;
  173. }
  174. /** SSL callbacks ***/
  175. static CURLcode wssl_init_ssl(struct curl_tls_ctx *ctx,
  176. struct Curl_cfilter *cf,
  177. struct Curl_easy *data,
  178. struct ssl_peer *peer,
  179. const char *alpn, size_t alpn_len,
  180. void *user_data)
  181. {
  182. struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
  183. DEBUGASSERT(!ctx->wssl.handle);
  184. DEBUGASSERT(ctx->wssl.ctx);
  185. ctx->wssl.handle = wolfSSL_new(ctx->wssl.ctx);
  186. wolfSSL_set_app_data(ctx->wssl.handle, user_data);
  187. wolfSSL_set_connect_state(ctx->wssl.handle);
  188. wolfSSL_set_quic_use_legacy_codepoint(ctx->wssl.handle, 0);
  189. if(alpn)
  190. wolfSSL_set_alpn_protos(ctx->wssl.handle, (const unsigned char *)alpn,
  191. (unsigned int)alpn_len);
  192. if(peer->sni) {
  193. wolfSSL_UseSNI(ctx->wssl.handle, WOLFSSL_SNI_HOST_NAME,
  194. peer->sni, (unsigned short)strlen(peer->sni));
  195. }
  196. if(ssl_config->primary.cache_session) {
  197. (void)Curl_wssl_setup_session(cf, data, &ctx->wssl, peer->scache_key);
  198. }
  199. return CURLE_OK;
  200. }
  201. #endif /* defined(USE_WOLFSSL) */
  202. CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
  203. struct Curl_cfilter *cf,
  204. struct Curl_easy *data,
  205. struct ssl_peer *peer,
  206. const char *alpn, size_t alpn_len,
  207. Curl_vquic_tls_ctx_setup *cb_setup,
  208. void *cb_user_data, void *ssl_user_data,
  209. Curl_vquic_session_reuse_cb *session_reuse_cb)
  210. {
  211. char tls_id[80];
  212. CURLcode result;
  213. #ifdef USE_OPENSSL
  214. Curl_ossl_version(tls_id, sizeof(tls_id));
  215. #elif defined(USE_GNUTLS)
  216. Curl_gtls_version(tls_id, sizeof(tls_id));
  217. #elif defined(USE_WOLFSSL)
  218. Curl_wssl_version(tls_id, sizeof(tls_id));
  219. #else
  220. #error "no TLS lib in used, should not happen"
  221. return CURLE_FAILED_INIT;
  222. #endif
  223. (void)session_reuse_cb;
  224. result = Curl_ssl_peer_init(peer, cf, tls_id, TRNSPRT_QUIC);
  225. if(result)
  226. return result;
  227. #ifdef USE_OPENSSL
  228. (void)result;
  229. return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer,
  230. (const unsigned char *)alpn, alpn_len,
  231. cb_setup, cb_user_data, NULL, ssl_user_data);
  232. #elif defined(USE_GNUTLS)
  233. return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
  234. (const unsigned char *)alpn, alpn_len,
  235. cb_setup, cb_user_data, ssl_user_data,
  236. session_reuse_cb);
  237. #elif defined(USE_WOLFSSL)
  238. result = wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
  239. if(result)
  240. return result;
  241. (void)session_reuse_cb;
  242. return wssl_init_ssl(ctx, cf, data, peer, alpn, alpn_len, ssl_user_data);
  243. #else
  244. #error "no TLS lib in used, should not happen"
  245. return CURLE_FAILED_INIT;
  246. #endif
  247. }
  248. void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
  249. {
  250. #ifdef USE_OPENSSL
  251. if(ctx->ossl.ssl)
  252. SSL_free(ctx->ossl.ssl);
  253. if(ctx->ossl.ssl_ctx)
  254. SSL_CTX_free(ctx->ossl.ssl_ctx);
  255. #elif defined(USE_GNUTLS)
  256. if(ctx->gtls.session)
  257. gnutls_deinit(ctx->gtls.session);
  258. Curl_gtls_shared_creds_free(&ctx->gtls.shared_creds);
  259. #elif defined(USE_WOLFSSL)
  260. if(ctx->wssl.handle)
  261. wolfSSL_free(ctx->wssl.handle);
  262. if(ctx->wssl.ctx)
  263. wolfSSL_CTX_free(ctx->wssl.ctx);
  264. #endif
  265. memset(ctx, 0, sizeof(*ctx));
  266. }
  267. CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
  268. struct Curl_cfilter *cf,
  269. struct Curl_easy *data)
  270. {
  271. #ifdef USE_OPENSSL
  272. if(!ctx->ossl.x509_store_setup) {
  273. CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ossl.ssl_ctx);
  274. if(result)
  275. return result;
  276. ctx->ossl.x509_store_setup = TRUE;
  277. }
  278. #elif defined(USE_WOLFSSL)
  279. if(!ctx->wssl.x509_store_setup) {
  280. CURLcode result = Curl_wssl_setup_x509_store(cf, data, &ctx->wssl);
  281. if(result)
  282. return result;
  283. }
  284. #elif defined(USE_GNUTLS)
  285. if(!ctx->gtls.shared_creds->trust_setup) {
  286. CURLcode result = Curl_gtls_client_trust_setup(cf, data, &ctx->gtls);
  287. if(result)
  288. return result;
  289. }
  290. #else
  291. (void)ctx; (void)cf; (void)data;
  292. #endif
  293. return CURLE_OK;
  294. }
  295. CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
  296. struct Curl_cfilter *cf,
  297. struct Curl_easy *data,
  298. struct ssl_peer *peer)
  299. {
  300. struct ssl_primary_config *conn_config;
  301. CURLcode result = CURLE_OK;
  302. conn_config = Curl_ssl_cf_get_primary_config(cf);
  303. if(!conn_config)
  304. return CURLE_FAILED_INIT;
  305. #ifdef USE_OPENSSL
  306. (void)conn_config;
  307. result = Curl_oss_check_peer_cert(cf, data, &ctx->ossl, peer);
  308. #elif defined(USE_GNUTLS)
  309. if(conn_config->verifyhost) {
  310. result = Curl_gtls_verifyserver(data, ctx->gtls.session,
  311. conn_config, &data->set.ssl, peer,
  312. data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
  313. if(result)
  314. return result;
  315. }
  316. #elif defined(USE_WOLFSSL)
  317. (void)data;
  318. if(conn_config->verifyhost) {
  319. if(peer->sni) {
  320. WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.handle);
  321. if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
  322. == WOLFSSL_FAILURE) {
  323. result = CURLE_PEER_FAILED_VERIFICATION;
  324. }
  325. wolfSSL_X509_free(cert);
  326. }
  327. }
  328. #endif
  329. /* on error, remove any session we might have in the pool */
  330. if(result)
  331. Curl_ssl_scache_remove_all(cf, data, peer->scache_key);
  332. return result;
  333. }
  334. #endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */