vquic-tls.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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 curl_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->ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
  83. if(!ctx->ssl_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->ssl_ctx);
  93. if(wolfSSL_CTX_set_cipher_list(ctx->ssl_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->ssl_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->ssl_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->ssl_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->ssl_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 won't work so
  146. use wolfssl's built-in default as fallback */
  147. wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
  148. }
  149. #endif
  150. }
  151. else {
  152. wolfSSL_CTX_set_verify(ctx->ssl_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->ssl_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->ssl_ctx) {
  168. SSL_CTX_free(ctx->ssl_ctx);
  169. ctx->ssl_ctx = NULL;
  170. }
  171. return result;
  172. }
  173. /** SSL callbacks ***/
  174. static CURLcode curl_wssl_init_ssl(struct curl_tls_ctx *ctx,
  175. struct Curl_easy *data,
  176. struct ssl_peer *peer,
  177. const char *alpn, size_t alpn_len,
  178. void *user_data)
  179. {
  180. (void)data;
  181. DEBUGASSERT(!ctx->ssl);
  182. DEBUGASSERT(ctx->ssl_ctx);
  183. ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
  184. wolfSSL_set_app_data(ctx->ssl, user_data);
  185. wolfSSL_set_connect_state(ctx->ssl);
  186. wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
  187. if(alpn)
  188. wolfSSL_set_alpn_protos(ctx->ssl, (const unsigned char *)alpn,
  189. (int)alpn_len);
  190. if(peer->sni) {
  191. wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
  192. peer->sni, (unsigned short)strlen(peer->sni));
  193. }
  194. return CURLE_OK;
  195. }
  196. #endif /* defined(USE_WOLFSSL) */
  197. CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
  198. struct Curl_cfilter *cf,
  199. struct Curl_easy *data,
  200. struct ssl_peer *peer,
  201. const char *alpn, size_t alpn_len,
  202. Curl_vquic_tls_ctx_setup *cb_setup,
  203. void *cb_user_data, void *ssl_user_data)
  204. {
  205. CURLcode result;
  206. #ifdef USE_OPENSSL
  207. (void)result;
  208. return Curl_ossl_ctx_init(&ctx->ossl, cf, data, peer, TRNSPRT_QUIC,
  209. (const unsigned char *)alpn, alpn_len,
  210. cb_setup, cb_user_data, NULL, ssl_user_data);
  211. #elif defined(USE_GNUTLS)
  212. (void)result;
  213. return Curl_gtls_ctx_init(&ctx->gtls, cf, data, peer,
  214. (const unsigned char *)alpn, alpn_len,
  215. cb_setup, cb_user_data, ssl_user_data);
  216. #elif defined(USE_WOLFSSL)
  217. result = curl_wssl_init_ctx(ctx, cf, data, cb_setup, cb_user_data);
  218. if(result)
  219. return result;
  220. return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, ssl_user_data);
  221. #else
  222. #error "no TLS lib in used, should not happen"
  223. return CURLE_FAILED_INIT;
  224. #endif
  225. }
  226. void Curl_vquic_tls_cleanup(struct curl_tls_ctx *ctx)
  227. {
  228. #ifdef USE_OPENSSL
  229. if(ctx->ossl.ssl)
  230. SSL_free(ctx->ossl.ssl);
  231. if(ctx->ossl.ssl_ctx)
  232. SSL_CTX_free(ctx->ossl.ssl_ctx);
  233. #elif defined(USE_GNUTLS)
  234. if(ctx->gtls.cred)
  235. gnutls_certificate_free_credentials(ctx->gtls.cred);
  236. if(ctx->gtls.session)
  237. gnutls_deinit(ctx->gtls.session);
  238. #elif defined(USE_WOLFSSL)
  239. if(ctx->ssl)
  240. wolfSSL_free(ctx->ssl);
  241. if(ctx->ssl_ctx)
  242. wolfSSL_CTX_free(ctx->ssl_ctx);
  243. #endif
  244. memset(ctx, 0, sizeof(*ctx));
  245. }
  246. CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
  247. struct Curl_cfilter *cf,
  248. struct Curl_easy *data)
  249. {
  250. #ifdef USE_OPENSSL
  251. if(!ctx->ossl.x509_store_setup) {
  252. CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ossl.ssl_ctx);
  253. if(result)
  254. return result;
  255. ctx->ossl.x509_store_setup = TRUE;
  256. }
  257. #elif defined(USE_GNUTLS)
  258. if(!ctx->gtls.trust_setup) {
  259. CURLcode result = Curl_gtls_client_trust_setup(cf, data, &ctx->gtls);
  260. if(result)
  261. return result;
  262. }
  263. #else
  264. (void)ctx; (void)cf; (void)data;
  265. #endif
  266. return CURLE_OK;
  267. }
  268. CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
  269. struct Curl_cfilter *cf,
  270. struct Curl_easy *data,
  271. struct ssl_peer *peer)
  272. {
  273. struct ssl_primary_config *conn_config;
  274. CURLcode result = CURLE_OK;
  275. conn_config = Curl_ssl_cf_get_primary_config(cf);
  276. if(!conn_config)
  277. return CURLE_FAILED_INIT;
  278. #ifdef USE_OPENSSL
  279. (void)conn_config;
  280. result = Curl_oss_check_peer_cert(cf, data, &ctx->ossl, peer);
  281. #elif defined(USE_GNUTLS)
  282. if(conn_config->verifyhost) {
  283. result = Curl_gtls_verifyserver(data, ctx->gtls.session,
  284. conn_config, &data->set.ssl, peer,
  285. data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
  286. if(result)
  287. return result;
  288. }
  289. #elif defined(USE_WOLFSSL)
  290. (void)data;
  291. if(conn_config->verifyhost) {
  292. if(peer->sni) {
  293. WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->ssl);
  294. if(wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, NULL)
  295. == WOLFSSL_FAILURE) {
  296. result = CURLE_PEER_FAILED_VERIFICATION;
  297. }
  298. wolfSSL_X509_free(cert);
  299. }
  300. }
  301. #endif
  302. return result;
  303. }
  304. #endif /* !USE_HTTP3 && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */