rustls.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Jacob Hoffman-Andrews,
  9. * <[email protected]>
  10. * Copyright (C) kpcyrd, <[email protected]>
  11. * Copyright (C) Daniel McCarney, <[email protected]>
  12. *
  13. * This software is licensed as described in the file COPYING, which
  14. * you should have received as part of this distribution. The terms
  15. * are also available at https://curl.se/docs/copyright.html.
  16. *
  17. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  18. * copies of the Software, and permit persons to whom the Software is
  19. * furnished to do so, under the terms of the COPYING file.
  20. *
  21. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  22. * KIND, either express or implied.
  23. *
  24. * SPDX-License-Identifier: curl
  25. *
  26. ***************************************************************************/
  27. #include "../curl_setup.h"
  28. #ifdef USE_RUSTLS
  29. #include <rustls.h>
  30. #include "../curlx/fopen.h"
  31. #include "../curlx/inet_pton.h"
  32. #include "../curlx/strerr.h"
  33. #include "../urldata.h"
  34. #include "../sendf.h"
  35. #include "vtls.h"
  36. #include "vtls_int.h"
  37. #include "rustls.h"
  38. #include "keylog.h"
  39. #include "cipher_suite.h"
  40. #include "x509asn1.h"
  41. /* The last #include files should be: */
  42. #include "../curl_memory.h"
  43. #include "../memdebug.h"
  44. struct rustls_ssl_backend_data
  45. {
  46. const struct rustls_client_config *config;
  47. struct rustls_connection *conn;
  48. size_t plain_out_buffered;
  49. BIT(data_in_pending);
  50. BIT(sent_shutdown);
  51. };
  52. /* For a given rustls_result error code, return the best-matching CURLcode. */
  53. static CURLcode map_error(const rustls_result r)
  54. {
  55. if(rustls_result_is_cert_error(r)) {
  56. return CURLE_PEER_FAILED_VERIFICATION;
  57. }
  58. switch(r) {
  59. case RUSTLS_RESULT_OK:
  60. return CURLE_OK;
  61. case RUSTLS_RESULT_NULL_PARAMETER:
  62. return CURLE_BAD_FUNCTION_ARGUMENT;
  63. default:
  64. return CURLE_RECV_ERROR;
  65. }
  66. }
  67. static void
  68. rustls_failf(struct Curl_easy *data, const rustls_result rr, const char *msg)
  69. {
  70. char errorbuf[STRERROR_LEN];
  71. size_t errorlen;
  72. rustls_error(rr, errorbuf, sizeof(errorbuf), &errorlen);
  73. failf(data, "%s: %.*s", msg, (int)errorlen, errorbuf);
  74. }
  75. static bool
  76. cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
  77. {
  78. const struct ssl_connect_data *ctx = cf->ctx;
  79. struct rustls_ssl_backend_data *backend;
  80. (void)data;
  81. DEBUGASSERT(ctx && ctx->backend);
  82. backend = (struct rustls_ssl_backend_data *)ctx->backend;
  83. return backend->data_in_pending;
  84. }
  85. struct io_ctx {
  86. struct Curl_cfilter *cf;
  87. struct Curl_easy *data;
  88. };
  89. static int
  90. read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
  91. {
  92. const struct io_ctx *io_ctx = userdata;
  93. struct ssl_connect_data *const connssl = io_ctx->cf->ctx;
  94. CURLcode result;
  95. int ret = 0;
  96. size_t nread;
  97. result = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
  98. (char *)buf, len, &nread);
  99. if(result) {
  100. nread = 0;
  101. /* !checksrc! disable ERRNOVAR 4 */
  102. if(CURLE_AGAIN == result)
  103. ret = EAGAIN;
  104. else
  105. ret = EINVAL;
  106. }
  107. else if(nread == 0)
  108. connssl->peer_closed = TRUE;
  109. *out_n = (uintptr_t)nread;
  110. CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next recv(len=%zu) -> %d, %zu",
  111. (size_t)len, result, nread);
  112. return ret;
  113. }
  114. static int
  115. write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
  116. {
  117. const struct io_ctx *io_ctx = userdata;
  118. CURLcode result;
  119. int ret = 0;
  120. size_t nwritten;
  121. result = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
  122. (const char *)buf, len, FALSE, &nwritten);
  123. if(result) {
  124. nwritten = 0;
  125. if(CURLE_AGAIN == result)
  126. ret = EAGAIN;
  127. else
  128. ret = EINVAL;
  129. }
  130. *out_n = (uintptr_t)nwritten;
  131. CURL_TRC_CF(io_ctx->data, io_ctx->cf, "cf->next send(len=%zu) -> %d, %zu",
  132. len, result, nwritten);
  133. return ret;
  134. }
  135. static ssize_t tls_recv_more(struct Curl_cfilter *cf,
  136. struct Curl_easy *data, CURLcode *err)
  137. {
  138. const struct ssl_connect_data *const connssl = cf->ctx;
  139. struct rustls_ssl_backend_data *const backend =
  140. (struct rustls_ssl_backend_data *)connssl->backend;
  141. struct io_ctx io_ctx;
  142. size_t tls_bytes_read = 0;
  143. rustls_io_result io_error;
  144. rustls_result rresult = 0;
  145. io_ctx.cf = cf;
  146. io_ctx.data = data;
  147. io_error = rustls_connection_read_tls(backend->conn, read_cb, &io_ctx,
  148. &tls_bytes_read);
  149. if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
  150. *err = CURLE_AGAIN;
  151. return -1;
  152. }
  153. else if(io_error) {
  154. char buffer[STRERROR_LEN];
  155. failf(data, "reading from socket: %s",
  156. curlx_strerror(io_error, buffer, sizeof(buffer)));
  157. *err = CURLE_RECV_ERROR;
  158. return -1;
  159. }
  160. rresult = rustls_connection_process_new_packets(backend->conn);
  161. if(rresult != RUSTLS_RESULT_OK) {
  162. rustls_failf(data, rresult, "rustls_connection_process_new_packets");
  163. *err = map_error(rresult);
  164. return -1;
  165. }
  166. backend->data_in_pending = TRUE;
  167. *err = CURLE_OK;
  168. return (ssize_t)tls_bytes_read;
  169. }
  170. /*
  171. * Filter receive method implementation. `plainbuf` and `plainlen`
  172. * are always not NULL/0.
  173. */
  174. static CURLcode
  175. cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  176. char *plainbuf, size_t plainlen, size_t *pnread)
  177. {
  178. const struct ssl_connect_data *const connssl = cf->ctx;
  179. struct rustls_ssl_backend_data *const backend =
  180. (struct rustls_ssl_backend_data *)connssl->backend;
  181. struct rustls_connection *rconn = NULL;
  182. CURLcode result = CURLE_OK;
  183. size_t n = 0;
  184. rustls_result rresult = 0;
  185. bool eof = FALSE;
  186. DEBUGASSERT(backend);
  187. *pnread = 0;
  188. rconn = backend->conn;
  189. while(*pnread < plainlen) {
  190. if(!backend->data_in_pending) {
  191. if(tls_recv_more(cf, data, &result) < 0) {
  192. if(result != CURLE_AGAIN) {
  193. goto out;
  194. }
  195. result = CURLE_OK;
  196. break;
  197. }
  198. }
  199. rresult = rustls_connection_read(rconn,
  200. (uint8_t *)plainbuf + *pnread,
  201. plainlen - *pnread,
  202. &n);
  203. if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
  204. backend->data_in_pending = FALSE;
  205. }
  206. else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
  207. failf(data, "rustls: peer closed TCP connection "
  208. "without first closing TLS connection");
  209. result = CURLE_RECV_ERROR;
  210. goto out;
  211. }
  212. else if(rresult != RUSTLS_RESULT_OK) {
  213. /* n always equals 0 in this case, do not need to check it */
  214. rustls_failf(data, rresult, "rustls_connection_read");
  215. result = CURLE_RECV_ERROR;
  216. goto out;
  217. }
  218. else if(n == 0) {
  219. /* n == 0 indicates clean EOF, but we may have read some other
  220. plaintext bytes before we reached this. Break out of the loop
  221. so we can figure out whether to return success or EOF. */
  222. eof = TRUE;
  223. break;
  224. }
  225. else {
  226. *pnread += n;
  227. }
  228. }
  229. if(!eof && !*pnread) {
  230. result = CURLE_AGAIN;
  231. }
  232. out:
  233. CURL_TRC_CF(data, cf, "rustls_recv(len=%zu) -> %d, %zu",
  234. plainlen, result, *pnread);
  235. return result;
  236. }
  237. static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data,
  238. struct rustls_connection *rconn)
  239. {
  240. struct io_ctx io_ctx;
  241. rustls_io_result io_error;
  242. size_t tlswritten = 0;
  243. size_t tlswritten_total = 0;
  244. io_ctx.cf = cf;
  245. io_ctx.data = data;
  246. while(rustls_connection_wants_write(rconn)) {
  247. io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
  248. &tlswritten);
  249. if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
  250. CURL_TRC_CF(data, cf, "cf_send: EAGAIN after %zu bytes",
  251. tlswritten_total);
  252. return CURLE_AGAIN;
  253. }
  254. else if(io_error) {
  255. char buffer[STRERROR_LEN];
  256. failf(data, "writing to socket: %s",
  257. curlx_strerror(io_error, buffer, sizeof(buffer)));
  258. return CURLE_SEND_ERROR;
  259. }
  260. if(tlswritten == 0) {
  261. failf(data, "EOF in swrite");
  262. return CURLE_SEND_ERROR;
  263. }
  264. CURL_TRC_CF(data, cf, "cf_send: wrote %zu TLS bytes", tlswritten);
  265. tlswritten_total += tlswritten;
  266. }
  267. return CURLE_OK;
  268. }
  269. /*
  270. * On each call:
  271. * - Copy `plainlen` bytes into Rustls' plaintext input buffer (if > 0).
  272. * - Fully drain Rustls' plaintext output buffer into the socket until
  273. * we get either an error or EAGAIN/EWOULDBLOCK.
  274. *
  275. * it is okay to call this function with plainbuf == NULL and plainlen == 0.
  276. * In that case, it will not read anything into Rustls' plaintext input buffer.
  277. * It will only drain Rustls' plaintext output buffer into the socket.
  278. */
  279. static CURLcode
  280. cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  281. const void *plainbuf, size_t plainlen, size_t *pnwritten)
  282. {
  283. const struct ssl_connect_data *const connssl = cf->ctx;
  284. struct rustls_ssl_backend_data *const backend =
  285. (struct rustls_ssl_backend_data *)connssl->backend;
  286. struct rustls_connection *rconn = NULL;
  287. size_t plainwritten = 0;
  288. const unsigned char *buf = plainbuf;
  289. CURLcode result = CURLE_OK;
  290. size_t blen = plainlen;
  291. DEBUGASSERT(backend);
  292. *pnwritten = 0;
  293. rconn = backend->conn;
  294. DEBUGASSERT(rconn);
  295. CURL_TRC_CF(data, cf, "cf_send(len=%zu)", plainlen);
  296. /* If a previous send blocked, we already added its plain bytes
  297. * to rustsls and must not do that again. Flush the TLS bytes and,
  298. * if successful, deduct the previous plain bytes from the current
  299. * send. */
  300. if(backend->plain_out_buffered) {
  301. result = cr_flush_out(cf, data, rconn);
  302. CURL_TRC_CF(data, cf, "cf_send: flushing %zu previously added bytes -> %d",
  303. backend->plain_out_buffered, result);
  304. if(result)
  305. return result;
  306. if(blen > backend->plain_out_buffered) {
  307. blen -= backend->plain_out_buffered;
  308. buf += backend->plain_out_buffered;
  309. }
  310. else
  311. blen = 0;
  312. *pnwritten += (ssize_t)backend->plain_out_buffered;
  313. backend->plain_out_buffered = 0;
  314. }
  315. if(blen > 0) {
  316. rustls_result rresult;
  317. CURL_TRC_CF(data, cf, "cf_send: adding %zu plain bytes to Rustls", blen);
  318. rresult = rustls_connection_write(rconn, buf, blen, &plainwritten);
  319. if(rresult != RUSTLS_RESULT_OK) {
  320. rustls_failf(data, rresult, "rustls_connection_write");
  321. result = CURLE_WRITE_ERROR;
  322. goto out;
  323. }
  324. else if(plainwritten == 0) {
  325. failf(data, "rustls_connection_write: EOF");
  326. result = CURLE_WRITE_ERROR;
  327. goto out;
  328. }
  329. }
  330. result = cr_flush_out(cf, data, rconn);
  331. if(result) {
  332. if(CURLE_AGAIN == result) {
  333. /* The TLS bytes may have been partially written, but we fail the
  334. * complete send() and remember how much we already added to Rustls. */
  335. backend->plain_out_buffered = plainwritten;
  336. if(*pnwritten) {
  337. result = CURLE_OK;
  338. }
  339. }
  340. goto out;
  341. }
  342. else
  343. *pnwritten += (ssize_t)plainwritten;
  344. out:
  345. CURL_TRC_CF(data, cf, "rustls_send(len=%zu) -> %d, %zd",
  346. plainlen, result, *pnwritten);
  347. return result;
  348. }
  349. /* A server certificate verify callback for Rustls that always returns
  350. RUSTLS_RESULT_OK, or in other words disable certificate verification. */
  351. static uint32_t
  352. cr_verify_none(void *userdata,
  353. const rustls_verify_server_cert_params *params)
  354. {
  355. (void)userdata;
  356. (void)params;
  357. return RUSTLS_RESULT_OK;
  358. }
  359. static int
  360. read_file_into(const char *filename,
  361. struct dynbuf *out)
  362. {
  363. FILE *f = curlx_fopen(filename, FOPEN_READTEXT);
  364. if(!f) {
  365. return 0;
  366. }
  367. for(;;) {
  368. uint8_t buf[256];
  369. const size_t rr = fread(buf, 1, sizeof(buf), f);
  370. if((!rr && !feof(f)) ||
  371. curlx_dyn_addn(out, buf, rr)) {
  372. curlx_fclose(f);
  373. return 0;
  374. }
  375. if(rr < sizeof(buf))
  376. break;
  377. }
  378. return curlx_fclose(f) == 0;
  379. }
  380. static void
  381. cr_get_selected_ciphers(struct Curl_easy *data,
  382. const char *ciphers12,
  383. const char *ciphers13,
  384. const struct rustls_supported_ciphersuite **selected,
  385. size_t *selected_size)
  386. {
  387. const size_t supported_len = *selected_size;
  388. const size_t default_len = rustls_default_crypto_provider_ciphersuites_len();
  389. const struct rustls_supported_ciphersuite *entry = NULL;
  390. const char *ciphers = ciphers12;
  391. size_t count = 0, default13_count = 0, i, j;
  392. const char *ptr, *end;
  393. DEBUGASSERT(default_len <= supported_len);
  394. if(!ciphers13) {
  395. /* Add default TLSv1.3 ciphers to selection */
  396. for(j = 0; j < default_len; j++) {
  397. entry = rustls_default_crypto_provider_ciphersuites_get(j);
  398. if(rustls_supported_ciphersuite_protocol_version(entry) !=
  399. RUSTLS_TLS_VERSION_TLSV1_3)
  400. continue;
  401. selected[count++] = entry;
  402. }
  403. default13_count = count;
  404. if(!ciphers)
  405. ciphers = "";
  406. }
  407. else
  408. ciphers = ciphers13;
  409. add_ciphers:
  410. for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
  411. uint16_t id = Curl_cipher_suite_walk_str(&ptr, &end);
  412. /* Check if cipher is supported */
  413. if(id) {
  414. for(i = 0; i < supported_len; i++) {
  415. entry = rustls_default_crypto_provider_ciphersuites_get(i);
  416. if(rustls_supported_ciphersuite_get_suite(entry) == id)
  417. break;
  418. }
  419. if(i == supported_len)
  420. id = 0;
  421. }
  422. if(!id) {
  423. if(ptr[0] != '\0')
  424. infof(data, "rustls: unknown cipher in list: \"%.*s\"",
  425. (int) (end - ptr), ptr);
  426. continue;
  427. }
  428. /* No duplicates allowed (so selected cannot overflow) */
  429. for(i = 0; i < count && selected[i] != entry; i++);
  430. if(i < count) {
  431. if(i >= default13_count)
  432. infof(data, "rustls: duplicate cipher in list: \"%.*s\"",
  433. (int) (end - ptr), ptr);
  434. continue;
  435. }
  436. selected[count++] = entry;
  437. }
  438. if(ciphers == ciphers13 && ciphers12) {
  439. ciphers = ciphers12;
  440. goto add_ciphers;
  441. }
  442. if(!ciphers12) {
  443. /* Add default TLSv1.2 ciphers to selection */
  444. for(j = 0; j < default_len; j++) {
  445. entry = rustls_default_crypto_provider_ciphersuites_get(j);
  446. if(rustls_supported_ciphersuite_protocol_version(entry) ==
  447. RUSTLS_TLS_VERSION_TLSV1_3)
  448. continue;
  449. /* No duplicates allowed (so selected cannot overflow) */
  450. for(i = 0; i < count && selected[i] != entry; i++);
  451. if(i < count)
  452. continue;
  453. selected[count++] = entry;
  454. }
  455. }
  456. *selected_size = count;
  457. }
  458. static void
  459. cr_keylog_log_cb(struct rustls_str label,
  460. const uint8_t *client_random, size_t client_random_len,
  461. const uint8_t *secret, size_t secret_len)
  462. {
  463. char clabel[KEYLOG_LABEL_MAXLEN];
  464. (void)client_random_len;
  465. DEBUGASSERT(client_random_len == CLIENT_RANDOM_SIZE);
  466. /* Turning a "rustls_str" into a null delimited "c" string */
  467. curl_msnprintf(clabel, sizeof(clabel), "%.*s", (int)label.len, label.data);
  468. Curl_tls_keylog_write(clabel, client_random, secret, secret_len);
  469. }
  470. static CURLcode
  471. init_config_builder(struct Curl_easy *data,
  472. const struct ssl_primary_config *conn_config,
  473. struct rustls_client_config_builder **config_builder)
  474. {
  475. const struct rustls_supported_ciphersuite **cipher_suites = NULL;
  476. struct rustls_crypto_provider_builder *custom_provider_builder = NULL;
  477. const struct rustls_crypto_provider *custom_provider = NULL;
  478. uint16_t tls_versions[2] = {
  479. RUSTLS_TLS_VERSION_TLSV1_2,
  480. RUSTLS_TLS_VERSION_TLSV1_3,
  481. };
  482. size_t tls_versions_len = 2;
  483. size_t cipher_suites_len =
  484. rustls_default_crypto_provider_ciphersuites_len();
  485. CURLcode result = CURLE_OK;
  486. rustls_result rr;
  487. switch(conn_config->version) {
  488. case CURL_SSLVERSION_DEFAULT:
  489. case CURL_SSLVERSION_TLSv1:
  490. case CURL_SSLVERSION_TLSv1_0:
  491. case CURL_SSLVERSION_TLSv1_1:
  492. case CURL_SSLVERSION_TLSv1_2:
  493. break;
  494. case CURL_SSLVERSION_TLSv1_3:
  495. tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
  496. tls_versions_len = 1;
  497. break;
  498. default:
  499. failf(data, "rustls: unsupported minimum TLS version value");
  500. result = CURLE_BAD_FUNCTION_ARGUMENT;
  501. goto cleanup;
  502. }
  503. switch(conn_config->version_max) {
  504. case CURL_SSLVERSION_MAX_DEFAULT:
  505. case CURL_SSLVERSION_MAX_NONE:
  506. case CURL_SSLVERSION_MAX_TLSv1_3:
  507. break;
  508. case CURL_SSLVERSION_MAX_TLSv1_2:
  509. if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) {
  510. tls_versions_len = 1;
  511. break;
  512. }
  513. FALLTHROUGH();
  514. case CURL_SSLVERSION_MAX_TLSv1_1:
  515. case CURL_SSLVERSION_MAX_TLSv1_0:
  516. default:
  517. failf(data, "rustls: unsupported maximum TLS version value");
  518. result = CURLE_BAD_FUNCTION_ARGUMENT;
  519. goto cleanup;
  520. }
  521. #ifdef USE_ECH
  522. if(ECH_ENABLED(data)) {
  523. tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
  524. tls_versions_len = 1;
  525. infof(data, "rustls: ECH enabled, forcing TLSv1.3");
  526. }
  527. #endif /* USE_ECH */
  528. cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
  529. if(!cipher_suites) {
  530. result = CURLE_OUT_OF_MEMORY;
  531. goto cleanup;
  532. }
  533. cr_get_selected_ciphers(data,
  534. conn_config->cipher_list,
  535. conn_config->cipher_list13,
  536. cipher_suites, &cipher_suites_len);
  537. if(cipher_suites_len == 0) {
  538. failf(data, "rustls: no supported cipher in list");
  539. result = CURLE_SSL_CIPHER;
  540. goto cleanup;
  541. }
  542. rr = rustls_crypto_provider_builder_new_from_default(
  543. &custom_provider_builder);
  544. if(rr != RUSTLS_RESULT_OK) {
  545. rustls_failf(data, rr,
  546. "failed to create crypto provider builder from default");
  547. result = CURLE_SSL_CIPHER;
  548. goto cleanup;
  549. }
  550. rr =
  551. rustls_crypto_provider_builder_set_cipher_suites(
  552. custom_provider_builder,
  553. cipher_suites,
  554. cipher_suites_len);
  555. if(rr != RUSTLS_RESULT_OK) {
  556. rustls_failf(data, rr,
  557. "failed to set ciphersuites for crypto provider builder");
  558. result = CURLE_SSL_CIPHER;
  559. goto cleanup;
  560. }
  561. rr = rustls_crypto_provider_builder_build(
  562. custom_provider_builder, &custom_provider);
  563. if(rr != RUSTLS_RESULT_OK) {
  564. rustls_failf(data, rr, "failed to build custom crypto provider");
  565. result = CURLE_SSL_CIPHER;
  566. goto cleanup;
  567. }
  568. rr = rustls_client_config_builder_new_custom(custom_provider,
  569. tls_versions,
  570. tls_versions_len,
  571. config_builder);
  572. if(rr != RUSTLS_RESULT_OK) {
  573. rustls_failf(data, rr, "failed to create client config builder");
  574. result = CURLE_SSL_CIPHER;
  575. goto cleanup;
  576. }
  577. cleanup:
  578. if(cipher_suites) {
  579. free(cipher_suites);
  580. }
  581. if(custom_provider_builder) {
  582. rustls_crypto_provider_builder_free(custom_provider_builder);
  583. }
  584. if(custom_provider) {
  585. rustls_crypto_provider_free(custom_provider);
  586. }
  587. return result;
  588. }
  589. static void
  590. init_config_builder_alpn(struct Curl_easy *data,
  591. const struct ssl_connect_data *connssl,
  592. struct rustls_client_config_builder *config_builder) {
  593. struct alpn_proto_buf proto;
  594. rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
  595. size_t i;
  596. for(i = 0; i < connssl->alpn->count; ++i) {
  597. alpn[i].data = (const uint8_t *)connssl->alpn->entries[i];
  598. alpn[i].len = strlen(connssl->alpn->entries[i]);
  599. }
  600. rustls_client_config_builder_set_alpn_protocols(config_builder, alpn,
  601. connssl->alpn->count);
  602. Curl_alpn_to_proto_str(&proto, connssl->alpn);
  603. infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
  604. }
  605. static CURLcode
  606. init_config_builder_verifier_crl(
  607. struct Curl_easy *data,
  608. const struct ssl_primary_config *conn_config,
  609. struct rustls_web_pki_server_cert_verifier_builder *builder)
  610. {
  611. CURLcode result = CURLE_OK;
  612. struct dynbuf crl_contents;
  613. rustls_result rr;
  614. curlx_dyn_init(&crl_contents, DYN_CRLFILE_SIZE);
  615. if(!read_file_into(conn_config->CRLfile, &crl_contents)) {
  616. failf(data, "rustls: failed to read revocation list file");
  617. result = CURLE_SSL_CRL_BADFILE;
  618. goto cleanup;
  619. }
  620. rr = rustls_web_pki_server_cert_verifier_builder_add_crl(
  621. builder,
  622. curlx_dyn_uptr(&crl_contents),
  623. curlx_dyn_len(&crl_contents));
  624. if(rr != RUSTLS_RESULT_OK) {
  625. rustls_failf(data, rr, "failed to parse revocation list");
  626. result = CURLE_SSL_CRL_BADFILE;
  627. goto cleanup;
  628. }
  629. cleanup:
  630. curlx_dyn_free(&crl_contents);
  631. return result;
  632. }
  633. static CURLcode
  634. init_config_builder_verifier(struct Curl_easy *data,
  635. struct rustls_client_config_builder *builder,
  636. const struct ssl_primary_config *conn_config,
  637. const struct curl_blob *ca_info_blob,
  638. const char * const ssl_cafile) {
  639. const struct rustls_root_cert_store *roots = NULL;
  640. struct rustls_root_cert_store_builder *roots_builder = NULL;
  641. struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL;
  642. struct rustls_server_cert_verifier *server_cert_verifier = NULL;
  643. rustls_result rr = RUSTLS_RESULT_OK;
  644. CURLcode result = CURLE_OK;
  645. roots_builder = rustls_root_cert_store_builder_new();
  646. if(ca_info_blob) {
  647. rr = rustls_root_cert_store_builder_add_pem(roots_builder,
  648. ca_info_blob->data,
  649. ca_info_blob->len,
  650. 1);
  651. if(rr != RUSTLS_RESULT_OK) {
  652. rustls_failf(data, rr, "failed to parse trusted certificates from blob");
  653. result = CURLE_SSL_CACERT_BADFILE;
  654. goto cleanup;
  655. }
  656. }
  657. else if(ssl_cafile) {
  658. rr = rustls_root_cert_store_builder_load_roots_from_file(roots_builder,
  659. ssl_cafile,
  660. 1);
  661. if(rr != RUSTLS_RESULT_OK) {
  662. rustls_failf(data, rr, "failed to load trusted certificates");
  663. result = CURLE_SSL_CACERT_BADFILE;
  664. goto cleanup;
  665. }
  666. }
  667. rr = rustls_root_cert_store_builder_build(roots_builder, &roots);
  668. if(rr != RUSTLS_RESULT_OK) {
  669. rustls_failf(data, rr, "failed to build trusted root certificate store");
  670. result = CURLE_SSL_CACERT_BADFILE;
  671. if(result) {
  672. goto cleanup;
  673. }
  674. }
  675. verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots);
  676. if(conn_config->CRLfile) {
  677. result = init_config_builder_verifier_crl(data,
  678. conn_config,
  679. verifier_builder);
  680. if(result) {
  681. goto cleanup;
  682. }
  683. }
  684. rr = rustls_web_pki_server_cert_verifier_builder_build(
  685. verifier_builder, &server_cert_verifier);
  686. if(rr != RUSTLS_RESULT_OK) {
  687. rustls_failf(data, rr, "failed to build certificate verifier");
  688. result = CURLE_SSL_CACERT_BADFILE;
  689. goto cleanup;
  690. }
  691. rustls_client_config_builder_set_server_verifier(builder,
  692. server_cert_verifier);
  693. cleanup:
  694. if(roots_builder) {
  695. rustls_root_cert_store_builder_free(roots_builder);
  696. }
  697. if(roots) {
  698. rustls_root_cert_store_free(roots);
  699. }
  700. if(verifier_builder) {
  701. rustls_web_pki_server_cert_verifier_builder_free(verifier_builder);
  702. }
  703. if(server_cert_verifier) {
  704. rustls_server_cert_verifier_free(server_cert_verifier);
  705. }
  706. return result;
  707. }
  708. static CURLcode
  709. init_config_builder_platform_verifier(
  710. struct Curl_easy *data,
  711. struct rustls_client_config_builder *builder)
  712. {
  713. struct rustls_server_cert_verifier *server_cert_verifier = NULL;
  714. CURLcode result = CURLE_OK;
  715. rustls_result rr;
  716. rr = rustls_platform_server_cert_verifier(&server_cert_verifier);
  717. if(rr != RUSTLS_RESULT_OK) {
  718. rustls_failf(data, rr, "failed to create platform certificate verifier");
  719. result = CURLE_SSL_CACERT_BADFILE;
  720. goto cleanup;
  721. }
  722. rustls_client_config_builder_set_server_verifier(builder,
  723. server_cert_verifier);
  724. cleanup:
  725. if(server_cert_verifier) {
  726. rustls_server_cert_verifier_free(server_cert_verifier);
  727. }
  728. return result;
  729. }
  730. static CURLcode
  731. init_config_builder_keylog(struct Curl_easy *data,
  732. struct rustls_client_config_builder *builder)
  733. {
  734. rustls_result rr;
  735. Curl_tls_keylog_open();
  736. if(!Curl_tls_keylog_enabled()) {
  737. return CURLE_OK;
  738. }
  739. rr = rustls_client_config_builder_set_key_log(builder,
  740. cr_keylog_log_cb,
  741. NULL);
  742. if(rr != RUSTLS_RESULT_OK) {
  743. rustls_failf(data, rr, "rustls_client_config_builder_set_key_log");
  744. Curl_tls_keylog_close();
  745. return map_error(rr);
  746. }
  747. return CURLE_OK;
  748. }
  749. static CURLcode
  750. init_config_builder_client_auth(struct Curl_easy *data,
  751. const struct ssl_primary_config *conn_config,
  752. const struct ssl_config_data *ssl_config,
  753. struct rustls_client_config_builder *builder)
  754. {
  755. struct dynbuf cert_contents;
  756. struct dynbuf key_contents;
  757. rustls_result rr;
  758. const struct rustls_certified_key *certified_key = NULL;
  759. CURLcode result = CURLE_OK;
  760. if(conn_config->clientcert && !ssl_config->key) {
  761. failf(data, "rustls: must provide key with certificate '%s'",
  762. conn_config->clientcert);
  763. return CURLE_SSL_CERTPROBLEM;
  764. }
  765. else if(!conn_config->clientcert && ssl_config->key) {
  766. failf(data, "rustls: must provide certificate with key '%s'",
  767. ssl_config->key);
  768. return CURLE_SSL_CERTPROBLEM;
  769. }
  770. curlx_dyn_init(&cert_contents, DYN_CERTFILE_SIZE);
  771. curlx_dyn_init(&key_contents, DYN_KEYFILE_SIZE);
  772. if(!read_file_into(conn_config->clientcert, &cert_contents)) {
  773. failf(data, "rustls: failed to read client certificate file: '%s'",
  774. conn_config->clientcert);
  775. result = CURLE_SSL_CERTPROBLEM;
  776. goto cleanup;
  777. }
  778. if(!read_file_into(ssl_config->key, &key_contents)) {
  779. failf(data, "rustls: failed to read key file: '%s'", ssl_config->key);
  780. result = CURLE_SSL_CERTPROBLEM;
  781. goto cleanup;
  782. }
  783. rr = rustls_certified_key_build(curlx_dyn_uptr(&cert_contents),
  784. curlx_dyn_len(&cert_contents),
  785. curlx_dyn_uptr(&key_contents),
  786. curlx_dyn_len(&key_contents),
  787. &certified_key);
  788. if(rr != RUSTLS_RESULT_OK) {
  789. rustls_failf(data, rr, "rustls: failed to build certified key");
  790. result = CURLE_SSL_CERTPROBLEM;
  791. goto cleanup;
  792. }
  793. rr = rustls_certified_key_keys_match(certified_key);
  794. if(rr != RUSTLS_RESULT_OK) {
  795. rustls_failf(data,
  796. rr,
  797. "rustls: client certificate and keypair files do not match:");
  798. result = CURLE_SSL_CERTPROBLEM;
  799. goto cleanup;
  800. }
  801. rr = rustls_client_config_builder_set_certified_key(builder,
  802. &certified_key,
  803. 1);
  804. if(rr != RUSTLS_RESULT_OK) {
  805. rustls_failf(data, rr, "rustls: failed to set certified key");
  806. result = CURLE_SSL_CERTPROBLEM;
  807. goto cleanup;
  808. }
  809. cleanup:
  810. curlx_dyn_free(&cert_contents);
  811. curlx_dyn_free(&key_contents);
  812. if(certified_key) {
  813. rustls_certified_key_free(certified_key);
  814. }
  815. return result;
  816. }
  817. #ifdef USE_ECH
  818. static CURLcode
  819. init_config_builder_ech(struct Curl_easy *data,
  820. const struct ssl_connect_data *connssl,
  821. struct rustls_client_config_builder *builder)
  822. {
  823. const rustls_hpke *hpke = rustls_supported_hpke();
  824. unsigned char *ech_config = NULL;
  825. size_t ech_config_len = 0;
  826. struct Curl_dns_entry *dns = NULL;
  827. struct Curl_https_rrinfo *rinfo = NULL;
  828. CURLcode result = CURLE_OK;
  829. rustls_result rr;
  830. if(!hpke) {
  831. failf(data,
  832. "rustls: ECH unavailable, rustls-ffi built without "
  833. "HPKE compatible crypto provider");
  834. result = CURLE_SSL_CONNECT_ERROR;
  835. goto cleanup;
  836. }
  837. if(data->set.str[STRING_ECH_PUBLIC]) {
  838. failf(data, "rustls: ECH outername not supported");
  839. result = CURLE_SSL_CONNECT_ERROR;
  840. goto cleanup;
  841. }
  842. if(data->set.tls_ech == CURLECH_GREASE) {
  843. rr = rustls_client_config_builder_enable_ech_grease(builder, hpke);
  844. if(rr != RUSTLS_RESULT_OK) {
  845. rustls_failf(data, rr, "rustls: failed to configure ECH GREASE");
  846. result = CURLE_SSL_CONNECT_ERROR;
  847. goto cleanup;
  848. }
  849. return CURLE_OK;
  850. }
  851. if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
  852. const char *b64 = data->set.str[STRING_ECH_CONFIG];
  853. size_t decode_result;
  854. if(!b64) {
  855. infof(data, "rustls: ECHConfig from command line empty");
  856. result = CURLE_SSL_CONNECT_ERROR;
  857. goto cleanup;
  858. }
  859. /* rustls-ffi expects the raw TLS encoded ECHConfigList bytes */
  860. decode_result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
  861. if(decode_result || !ech_config) {
  862. infof(data, "rustls: cannot base64 decode ECHConfig from command line");
  863. result = CURLE_SSL_CONNECT_ERROR;
  864. goto cleanup;
  865. }
  866. }
  867. else {
  868. if(connssl->peer.hostname) {
  869. dns = Curl_dnscache_get(data, connssl->peer.hostname,
  870. connssl->peer.port, data->conn->ip_version);
  871. }
  872. if(!dns) {
  873. failf(data, "rustls: ECH requested but no DNS info available");
  874. result = CURLE_SSL_CONNECT_ERROR;
  875. goto cleanup;
  876. }
  877. rinfo = dns->hinfo;
  878. if(!rinfo || !rinfo->echconfiglist) {
  879. failf(data, "rustls: ECH requested but no ECHConfig available");
  880. result = CURLE_SSL_CONNECT_ERROR;
  881. goto cleanup;
  882. }
  883. ech_config = rinfo->echconfiglist;
  884. ech_config_len = rinfo->echconfiglist_len;
  885. }
  886. rr = rustls_client_config_builder_enable_ech(builder,
  887. ech_config,
  888. ech_config_len,
  889. hpke);
  890. if(rr != RUSTLS_RESULT_OK) {
  891. rustls_failf(data, rr, "rustls: failed to configure ECH");
  892. result = CURLE_SSL_CONNECT_ERROR;
  893. goto cleanup;
  894. }
  895. cleanup:
  896. /* if we base64 decoded, we can free now */
  897. if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) {
  898. free(ech_config);
  899. }
  900. if(dns) {
  901. Curl_resolv_unlink(data, &dns);
  902. }
  903. return result;
  904. }
  905. #endif /* USE_ECH */
  906. static CURLcode
  907. cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
  908. struct rustls_ssl_backend_data *const backend)
  909. {
  910. const struct ssl_connect_data *connssl = cf->ctx;
  911. const struct ssl_primary_config *conn_config =
  912. Curl_ssl_cf_get_primary_config(cf);
  913. struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
  914. struct rustls_connection *rconn = NULL;
  915. struct rustls_client_config_builder *config_builder = NULL;
  916. const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
  917. const char * const ssl_cafile =
  918. /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
  919. (ca_info_blob ? NULL : conn_config->CAfile);
  920. CURLcode result = CURLE_OK;
  921. rustls_result rr;
  922. DEBUGASSERT(backend);
  923. rconn = backend->conn;
  924. result = init_config_builder(data, conn_config, &config_builder);
  925. if(result != CURLE_OK) {
  926. return result;
  927. }
  928. if(connssl->alpn) {
  929. init_config_builder_alpn(data, connssl, config_builder);
  930. }
  931. if(!conn_config->verifypeer) {
  932. rustls_client_config_builder_dangerous_set_certificate_verifier(
  933. config_builder, cr_verify_none);
  934. }
  935. else if(ssl_config->native_ca_store) {
  936. result = init_config_builder_platform_verifier(data, config_builder);
  937. if(result != CURLE_OK) {
  938. rustls_client_config_builder_free(config_builder);
  939. return result;
  940. }
  941. }
  942. else if(ca_info_blob || ssl_cafile) {
  943. result = init_config_builder_verifier(data,
  944. config_builder,
  945. conn_config,
  946. ca_info_blob,
  947. ssl_cafile);
  948. if(result != CURLE_OK) {
  949. rustls_client_config_builder_free(config_builder);
  950. return result;
  951. }
  952. }
  953. if(conn_config->clientcert || ssl_config->key) {
  954. result = init_config_builder_client_auth(data,
  955. conn_config,
  956. ssl_config,
  957. config_builder);
  958. if(result != CURLE_OK) {
  959. rustls_client_config_builder_free(config_builder);
  960. return result;
  961. }
  962. }
  963. #ifdef USE_ECH
  964. if(ECH_ENABLED(data)) {
  965. result = init_config_builder_ech(data, connssl, config_builder);
  966. if(result != CURLE_OK && data->set.tls_ech & CURLECH_HARD) {
  967. rustls_client_config_builder_free(config_builder);
  968. return result;
  969. }
  970. }
  971. #endif /* USE_ECH */
  972. result = init_config_builder_keylog(data, config_builder);
  973. if(result != CURLE_OK) {
  974. rustls_client_config_builder_free(config_builder);
  975. return result;
  976. }
  977. rr = rustls_client_config_builder_build(
  978. config_builder,
  979. &backend->config);
  980. if(rr != RUSTLS_RESULT_OK) {
  981. rustls_failf(data, rr, "failed to build client config");
  982. rustls_client_config_builder_free(config_builder);
  983. rustls_client_config_free(backend->config);
  984. return CURLE_SSL_CONNECT_ERROR;
  985. }
  986. DEBUGASSERT(rconn == NULL);
  987. rr = rustls_client_connection_new(backend->config,
  988. connssl->peer.hostname,
  989. &rconn);
  990. if(rr != RUSTLS_RESULT_OK) {
  991. rustls_failf(data, rr, "rustls_client_connection_new");
  992. return CURLE_COULDNT_CONNECT;
  993. }
  994. DEBUGASSERT(rconn);
  995. rustls_connection_set_userdata(rconn, backend);
  996. backend->conn = rconn;
  997. return result;
  998. }
  999. static void
  1000. cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
  1001. const struct rustls_connection *rconn)
  1002. {
  1003. struct ssl_connect_data *const connssl = cf->ctx;
  1004. const uint8_t *protocol = NULL;
  1005. size_t len = 0;
  1006. rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
  1007. Curl_alpn_set_negotiated(cf, data, connssl, protocol, len);
  1008. }
  1009. /* Given an established network connection, do a TLS handshake.
  1010. *
  1011. * This function will set `*done` to true once the handshake is complete.
  1012. * This function never reads the value of `*done*`.
  1013. */
  1014. static CURLcode
  1015. cr_connect(struct Curl_cfilter *cf,
  1016. struct Curl_easy *data, bool *done)
  1017. {
  1018. struct ssl_connect_data *const connssl = cf->ctx;
  1019. const struct rustls_ssl_backend_data *const backend =
  1020. (struct rustls_ssl_backend_data *)connssl->backend;
  1021. const struct rustls_connection *rconn = NULL;
  1022. CURLcode tmperr = CURLE_OK;
  1023. int result;
  1024. bool wants_read;
  1025. bool wants_write;
  1026. DEBUGASSERT(backend);
  1027. CURL_TRC_CF(data, cf, "cr_connect, state=%d", connssl->state);
  1028. *done = FALSE;
  1029. if(!backend->conn) {
  1030. result = cr_init_backend(cf, data,
  1031. (struct rustls_ssl_backend_data *)connssl->backend);
  1032. CURL_TRC_CF(data, cf, "cr_connect, init backend -> %d", result);
  1033. if(result != CURLE_OK) {
  1034. return result;
  1035. }
  1036. connssl->state = ssl_connection_negotiating;
  1037. }
  1038. rconn = backend->conn;
  1039. /* Read/write data until the handshake is done or the socket would block. */
  1040. for(;;) {
  1041. /*
  1042. * Connection has been established according to Rustls. Set send/recv
  1043. * handlers, and update the state machine.
  1044. */
  1045. connssl->io_need = CURL_SSL_IO_NEED_NONE;
  1046. if(!rustls_connection_is_handshaking(rconn)) {
  1047. /* Rustls claims it is no longer handshaking *before* it has
  1048. * send its FINISHED message off. We attempt to let it write
  1049. * one more time. Oh my.
  1050. */
  1051. size_t nwritten;
  1052. cr_set_negotiated_alpn(cf, data, rconn);
  1053. tmperr = cr_send(cf, data, NULL, 0, &nwritten);
  1054. if(tmperr == CURLE_AGAIN) {
  1055. connssl->io_need = CURL_SSL_IO_NEED_SEND;
  1056. return CURLE_OK;
  1057. }
  1058. else if(tmperr != CURLE_OK) {
  1059. return tmperr;
  1060. }
  1061. /* REALLY Done with the handshake. */
  1062. {
  1063. const uint16_t proto =
  1064. rustls_connection_get_protocol_version(rconn);
  1065. const rustls_str ciphersuite_name =
  1066. rustls_connection_get_negotiated_ciphersuite_name(rconn);
  1067. const rustls_str kex_group_name =
  1068. rustls_connection_get_negotiated_key_exchange_group_name(rconn);
  1069. const char *ver = "TLS version unknown";
  1070. if(proto == RUSTLS_TLS_VERSION_TLSV1_3)
  1071. ver = "TLSv1.3";
  1072. if(proto == RUSTLS_TLS_VERSION_TLSV1_2)
  1073. ver = "TLSv1.2";
  1074. infof(data,
  1075. "rustls: handshake complete, %s, ciphersuite: %.*s, "
  1076. "key exchange group: %.*s",
  1077. ver,
  1078. (int) ciphersuite_name.len,
  1079. ciphersuite_name.data,
  1080. (int) kex_group_name.len,
  1081. kex_group_name.data);
  1082. }
  1083. if(data->set.ssl.certinfo) {
  1084. size_t num_certs = 0;
  1085. size_t i;
  1086. while(rustls_connection_get_peer_certificate(rconn, (int)num_certs)) {
  1087. num_certs++;
  1088. }
  1089. result = Curl_ssl_init_certinfo(data, (int)num_certs);
  1090. if(result)
  1091. return result;
  1092. for(i = 0; i < num_certs; i++) {
  1093. const rustls_certificate *cert;
  1094. const unsigned char *der_data;
  1095. size_t der_len;
  1096. rustls_result rresult = RUSTLS_RESULT_OK;
  1097. cert = rustls_connection_get_peer_certificate(rconn, i);
  1098. DEBUGASSERT(cert); /* Should exist since we counted already */
  1099. rresult = rustls_certificate_get_der(cert, &der_data, &der_len);
  1100. if(rresult != RUSTLS_RESULT_OK) {
  1101. char errorbuf[255];
  1102. size_t errorlen;
  1103. rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
  1104. failf(data,
  1105. "Failed getting DER of server certificate #%zu: %.*s", i,
  1106. (int)errorlen, errorbuf);
  1107. return map_error(rresult);
  1108. }
  1109. {
  1110. const char *beg;
  1111. const char *end;
  1112. beg = (const char *)der_data;
  1113. end = (const char *)(der_data + der_len);
  1114. result = Curl_extract_certinfo(data, (int)i, beg, end);
  1115. if(result)
  1116. return result;
  1117. }
  1118. }
  1119. }
  1120. connssl->state = ssl_connection_complete;
  1121. *done = TRUE;
  1122. return CURLE_OK;
  1123. }
  1124. connssl->connecting_state = ssl_connect_2;
  1125. wants_read = rustls_connection_wants_read(rconn);
  1126. wants_write = rustls_connection_wants_write(rconn) ||
  1127. backend->plain_out_buffered;
  1128. DEBUGASSERT(wants_read || wants_write);
  1129. if(wants_write) {
  1130. size_t nwritten;
  1131. CURL_TRC_CF(data, cf, "rustls_connection wants us to write_tls.");
  1132. tmperr = cr_send(cf, data, NULL, 0, &nwritten);
  1133. if(tmperr == CURLE_AGAIN) {
  1134. CURL_TRC_CF(data, cf, "writing would block");
  1135. connssl->io_need = CURL_SSL_IO_NEED_SEND;
  1136. return CURLE_OK;
  1137. }
  1138. else if(tmperr != CURLE_OK) {
  1139. return tmperr;
  1140. }
  1141. }
  1142. if(wants_read) {
  1143. CURL_TRC_CF(data, cf, "rustls_connection wants us to read_tls.");
  1144. if(tls_recv_more(cf, data, &tmperr) < 0) {
  1145. if(tmperr == CURLE_AGAIN) {
  1146. CURL_TRC_CF(data, cf, "reading would block");
  1147. connssl->io_need = CURL_SSL_IO_NEED_RECV;
  1148. return CURLE_OK;
  1149. }
  1150. else if(tmperr == CURLE_RECV_ERROR) {
  1151. return CURLE_SSL_CONNECT_ERROR;
  1152. }
  1153. else {
  1154. return tmperr;
  1155. }
  1156. }
  1157. }
  1158. }
  1159. /* We should never fall through the loop. We should return either because
  1160. the handshake is done or because we cannot read/write without blocking. */
  1161. DEBUGASSERT(FALSE);
  1162. }
  1163. static void *
  1164. cr_get_internals(struct ssl_connect_data *connssl,
  1165. CURLINFO info)
  1166. {
  1167. struct rustls_ssl_backend_data *backend =
  1168. (struct rustls_ssl_backend_data *)connssl->backend;
  1169. (void)info;
  1170. DEBUGASSERT(backend);
  1171. return backend->conn;
  1172. }
  1173. static CURLcode
  1174. cr_shutdown(struct Curl_cfilter *cf,
  1175. struct Curl_easy *data,
  1176. const bool send_shutdown, bool *done)
  1177. {
  1178. struct ssl_connect_data *connssl = cf->ctx;
  1179. struct rustls_ssl_backend_data *backend =
  1180. (struct rustls_ssl_backend_data *)connssl->backend;
  1181. CURLcode result = CURLE_OK;
  1182. size_t i, nread = 0, nwritten;
  1183. DEBUGASSERT(backend);
  1184. if(!backend->conn || cf->shutdown) {
  1185. *done = TRUE;
  1186. goto out;
  1187. }
  1188. connssl->io_need = CURL_SSL_IO_NEED_NONE;
  1189. *done = FALSE;
  1190. if(!backend->sent_shutdown) {
  1191. /* do this only once */
  1192. backend->sent_shutdown = TRUE;
  1193. if(send_shutdown) {
  1194. rustls_connection_send_close_notify(backend->conn);
  1195. }
  1196. }
  1197. result = cr_send(cf, data, NULL, 0, &nwritten);
  1198. if(result) {
  1199. if(result == CURLE_AGAIN) {
  1200. connssl->io_need = CURL_SSL_IO_NEED_SEND;
  1201. result = CURLE_OK;
  1202. goto out;
  1203. }
  1204. DEBUGASSERT(result);
  1205. CURL_TRC_CF(data, cf, "shutdown send failed: %d", result);
  1206. goto out;
  1207. }
  1208. for(i = 0; i < 10; ++i) {
  1209. char buf[1024];
  1210. result = cr_recv(cf, data, buf, (int)sizeof(buf), &nread);
  1211. if(result)
  1212. break;
  1213. }
  1214. if(result == CURLE_AGAIN) {
  1215. connssl->io_need = CURL_SSL_IO_NEED_RECV;
  1216. result = CURLE_OK;
  1217. }
  1218. else if(result) {
  1219. DEBUGASSERT(result);
  1220. CURL_TRC_CF(data, cf, "shutdown, error: %d", result);
  1221. }
  1222. else if(nread == 0) {
  1223. /* We got the close notify alert and are done. */
  1224. *done = TRUE;
  1225. }
  1226. out:
  1227. cf->shutdown = (result || *done);
  1228. return result;
  1229. }
  1230. static void
  1231. cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  1232. {
  1233. const struct ssl_connect_data *connssl = cf->ctx;
  1234. struct rustls_ssl_backend_data *backend =
  1235. (struct rustls_ssl_backend_data *)connssl->backend;
  1236. (void)data;
  1237. DEBUGASSERT(backend);
  1238. if(backend->conn) {
  1239. rustls_connection_free(backend->conn);
  1240. backend->conn = NULL;
  1241. }
  1242. if(backend->config) {
  1243. rustls_client_config_free(backend->config);
  1244. backend->config = NULL;
  1245. }
  1246. }
  1247. static size_t cr_version(char *buffer, size_t size)
  1248. {
  1249. const struct rustls_str ver = rustls_version();
  1250. return curl_msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data);
  1251. }
  1252. static CURLcode
  1253. cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length)
  1254. {
  1255. rustls_result rresult = 0;
  1256. (void)data;
  1257. rresult =
  1258. rustls_default_crypto_provider_random(entropy, length);
  1259. return map_error(rresult);
  1260. }
  1261. static void cr_cleanup(void)
  1262. {
  1263. Curl_tls_keylog_close();
  1264. }
  1265. const struct Curl_ssl Curl_ssl_rustls = {
  1266. { CURLSSLBACKEND_RUSTLS, "rustls" },
  1267. SSLSUPP_CAINFO_BLOB | /* supports */
  1268. SSLSUPP_HTTPS_PROXY |
  1269. SSLSUPP_CIPHER_LIST |
  1270. SSLSUPP_TLS13_CIPHERSUITES |
  1271. SSLSUPP_CERTINFO |
  1272. SSLSUPP_ECH,
  1273. sizeof(struct rustls_ssl_backend_data),
  1274. NULL, /* init */
  1275. cr_cleanup, /* cleanup */
  1276. cr_version, /* version */
  1277. cr_shutdown, /* shutdown */
  1278. cr_data_pending, /* data_pending */
  1279. cr_random, /* random */
  1280. NULL, /* cert_status_request */
  1281. cr_connect, /* connect */
  1282. Curl_ssl_adjust_pollset, /* adjust_pollset */
  1283. cr_get_internals, /* get_internals */
  1284. cr_close, /* close_one */
  1285. NULL, /* close_all */
  1286. NULL, /* set_engine */
  1287. NULL, /* set_engine_default */
  1288. NULL, /* engines_list */
  1289. NULL, /* sha256sum */
  1290. cr_recv, /* recv decrypted data */
  1291. cr_send, /* send data to encrypt */
  1292. NULL, /* get_channel_binding */
  1293. };
  1294. #endif /* USE_RUSTLS */