vquic-tls.c 11 KB

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