1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> |
9 | * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. |
10 | * |
11 | * This software is licensed as described in the file COPYING, which |
12 | * you should have received as part of this distribution. The terms |
13 | * are also available at https://curl.haxx.se/docs/copyright.html. |
14 | * |
15 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
16 | * copies of the Software, and permit persons to whom the Software is |
17 | * furnished to do so, under the terms of the COPYING file. |
18 | * |
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
20 | * KIND, either express or implied. |
21 | * |
22 | ***************************************************************************/ |
23 | |
24 | /* |
25 | * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code |
26 | * but vtls.c should ever call or use these functions. |
27 | * |
28 | */ |
29 | |
30 | #include "curl_setup.h" |
31 | |
32 | #ifdef USE_MBEDTLS |
33 | |
34 | #include <mbedtls/version.h> |
35 | #if MBEDTLS_VERSION_NUMBER >= 0x02040000 |
36 | #include <mbedtls/net_sockets.h> |
37 | #else |
38 | #include <mbedtls/net.h> |
39 | #endif |
40 | #include <mbedtls/ssl.h> |
41 | #include <mbedtls/certs.h> |
42 | #include <mbedtls/x509.h> |
43 | |
44 | #include <mbedtls/error.h> |
45 | #include <mbedtls/entropy.h> |
46 | #include <mbedtls/ctr_drbg.h> |
47 | #include <mbedtls/sha256.h> |
48 | |
49 | #include "urldata.h" |
50 | #include "sendf.h" |
51 | #include "inet_pton.h" |
52 | #include "mbedtls.h" |
53 | #include "vtls.h" |
54 | #include "parsedate.h" |
55 | #include "connect.h" /* for the connect timeout */ |
56 | #include "select.h" |
57 | #include "multiif.h" |
58 | #include "polarssl_threadlock.h" |
59 | |
60 | /* The last 3 #include files should be in this order */ |
61 | #include "curl_printf.h" |
62 | #include "curl_memory.h" |
63 | #include "memdebug.h" |
64 | |
65 | struct ssl_backend_data { |
66 | mbedtls_ctr_drbg_context ctr_drbg; |
67 | mbedtls_entropy_context entropy; |
68 | mbedtls_ssl_context ssl; |
69 | int server_fd; |
70 | mbedtls_x509_crt cacert; |
71 | mbedtls_x509_crt clicert; |
72 | mbedtls_x509_crl crl; |
73 | mbedtls_pk_context pk; |
74 | mbedtls_ssl_config config; |
75 | const char *protocols[3]; |
76 | }; |
77 | |
78 | #define BACKEND connssl->backend |
79 | |
80 | /* apply threading? */ |
81 | #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) |
82 | #define THREADING_SUPPORT |
83 | #endif |
84 | |
85 | #if defined(THREADING_SUPPORT) |
86 | static mbedtls_entropy_context ts_entropy; |
87 | |
88 | static int entropy_init_initialized = 0; |
89 | |
90 | /* start of entropy_init_mutex() */ |
91 | static void entropy_init_mutex(mbedtls_entropy_context *ctx) |
92 | { |
93 | /* lock 0 = entropy_init_mutex() */ |
94 | Curl_polarsslthreadlock_lock_function(0); |
95 | if(entropy_init_initialized == 0) { |
96 | mbedtls_entropy_init(ctx); |
97 | entropy_init_initialized = 1; |
98 | } |
99 | Curl_polarsslthreadlock_unlock_function(0); |
100 | } |
101 | /* end of entropy_init_mutex() */ |
102 | |
103 | /* start of entropy_func_mutex() */ |
104 | static int entropy_func_mutex(void *data, unsigned char *output, size_t len) |
105 | { |
106 | int ret; |
107 | /* lock 1 = entropy_func_mutex() */ |
108 | Curl_polarsslthreadlock_lock_function(1); |
109 | ret = mbedtls_entropy_func(data, output, len); |
110 | Curl_polarsslthreadlock_unlock_function(1); |
111 | |
112 | return ret; |
113 | } |
114 | /* end of entropy_func_mutex() */ |
115 | |
116 | #endif /* THREADING_SUPPORT */ |
117 | |
118 | /* Define this to enable lots of debugging for mbedTLS */ |
119 | #undef MBEDTLS_DEBUG |
120 | |
121 | #ifdef MBEDTLS_DEBUG |
122 | static void mbed_debug(void *context, int level, const char *f_name, |
123 | int line_nb, const char *line) |
124 | { |
125 | struct Curl_easy *data = NULL; |
126 | |
127 | if(!context) |
128 | return; |
129 | |
130 | data = (struct Curl_easy *)context; |
131 | |
132 | infof(data, "%s" , line); |
133 | (void) level; |
134 | } |
135 | #else |
136 | #endif |
137 | |
138 | /* ALPN for http2? */ |
139 | #ifdef USE_NGHTTP2 |
140 | # undef HAS_ALPN |
141 | # ifdef MBEDTLS_SSL_ALPN |
142 | # define HAS_ALPN |
143 | # endif |
144 | #endif |
145 | |
146 | |
147 | /* |
148 | * profile |
149 | */ |
150 | static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = |
151 | { |
152 | /* Hashes from SHA-1 and above */ |
153 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | |
154 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | |
155 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | |
156 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | |
157 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | |
158 | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), |
159 | 0xFFFFFFF, /* Any PK alg */ |
160 | 0xFFFFFFF, /* Any curve */ |
161 | 1024, /* RSA min key len */ |
162 | }; |
163 | |
164 | /* See https://tls.mbed.org/discussions/generic/ |
165 | howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der |
166 | */ |
167 | #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) |
168 | #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) |
169 | |
170 | #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ |
171 | RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) |
172 | |
173 | static Curl_recv mbed_recv; |
174 | static Curl_send mbed_send; |
175 | |
176 | static CURLcode mbedtls_version_from_curl(int *mbedver, long version) |
177 | { |
178 | switch(version) { |
179 | case CURL_SSLVERSION_TLSv1_0: |
180 | *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; |
181 | return CURLE_OK; |
182 | case CURL_SSLVERSION_TLSv1_1: |
183 | *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; |
184 | return CURLE_OK; |
185 | case CURL_SSLVERSION_TLSv1_2: |
186 | *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; |
187 | return CURLE_OK; |
188 | case CURL_SSLVERSION_TLSv1_3: |
189 | break; |
190 | } |
191 | return CURLE_SSL_CONNECT_ERROR; |
192 | } |
193 | |
194 | static CURLcode |
195 | set_ssl_version_min_max(struct connectdata *conn, int sockindex) |
196 | { |
197 | struct Curl_easy *data = conn->data; |
198 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
199 | int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; |
200 | int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; |
201 | long ssl_version = SSL_CONN_CONFIG(version); |
202 | long ssl_version_max = SSL_CONN_CONFIG(version_max); |
203 | CURLcode result = CURLE_OK; |
204 | |
205 | switch(ssl_version) { |
206 | case CURL_SSLVERSION_DEFAULT: |
207 | case CURL_SSLVERSION_TLSv1: |
208 | ssl_version = CURL_SSLVERSION_TLSv1_0; |
209 | break; |
210 | } |
211 | |
212 | switch(ssl_version_max) { |
213 | case CURL_SSLVERSION_MAX_NONE: |
214 | case CURL_SSLVERSION_MAX_DEFAULT: |
215 | ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; |
216 | break; |
217 | } |
218 | |
219 | result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); |
220 | if(result) { |
221 | failf(data, "unsupported min version passed via CURLOPT_SSLVERSION" ); |
222 | return result; |
223 | } |
224 | result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); |
225 | if(result) { |
226 | failf(data, "unsupported max version passed via CURLOPT_SSLVERSION" ); |
227 | return result; |
228 | } |
229 | |
230 | mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, |
231 | mbedtls_ver_min); |
232 | mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, |
233 | mbedtls_ver_max); |
234 | |
235 | return result; |
236 | } |
237 | |
238 | static CURLcode |
239 | mbed_connect_step1(struct connectdata *conn, |
240 | int sockindex) |
241 | { |
242 | struct Curl_easy *data = conn->data; |
243 | struct ssl_connect_data* connssl = &conn->ssl[sockindex]; |
244 | const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); |
245 | const bool verifypeer = SSL_CONN_CONFIG(verifypeer); |
246 | const char * const ssl_capath = SSL_CONN_CONFIG(CApath); |
247 | char * const ssl_cert = SSL_SET_OPTION(cert); |
248 | const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); |
249 | const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : |
250 | conn->host.name; |
251 | const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; |
252 | int ret = -1; |
253 | char errorbuf[128]; |
254 | errorbuf[0] = 0; |
255 | |
256 | /* mbedTLS only supports SSLv3 and TLSv1 */ |
257 | if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { |
258 | failf(data, "mbedTLS does not support SSLv2" ); |
259 | return CURLE_SSL_CONNECT_ERROR; |
260 | } |
261 | |
262 | #ifdef THREADING_SUPPORT |
263 | entropy_init_mutex(&ts_entropy); |
264 | mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); |
265 | |
266 | ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, |
267 | &ts_entropy, NULL, 0); |
268 | if(ret) { |
269 | #ifdef MBEDTLS_ERROR_C |
270 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
271 | #endif /* MBEDTLS_ERROR_C */ |
272 | failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n" , |
273 | -ret, errorbuf); |
274 | } |
275 | #else |
276 | mbedtls_entropy_init(&BACKEND->entropy); |
277 | mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); |
278 | |
279 | ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, |
280 | &BACKEND->entropy, NULL, 0); |
281 | if(ret) { |
282 | #ifdef MBEDTLS_ERROR_C |
283 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
284 | #endif /* MBEDTLS_ERROR_C */ |
285 | failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n" , |
286 | -ret, errorbuf); |
287 | } |
288 | #endif /* THREADING_SUPPORT */ |
289 | |
290 | /* Load the trusted CA */ |
291 | mbedtls_x509_crt_init(&BACKEND->cacert); |
292 | |
293 | if(ssl_cafile) { |
294 | ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile); |
295 | |
296 | if(ret<0) { |
297 | #ifdef MBEDTLS_ERROR_C |
298 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
299 | #endif /* MBEDTLS_ERROR_C */ |
300 | failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s" , |
301 | ssl_cafile, -ret, errorbuf); |
302 | |
303 | if(verifypeer) |
304 | return CURLE_SSL_CACERT_BADFILE; |
305 | } |
306 | } |
307 | |
308 | if(ssl_capath) { |
309 | ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath); |
310 | |
311 | if(ret<0) { |
312 | #ifdef MBEDTLS_ERROR_C |
313 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
314 | #endif /* MBEDTLS_ERROR_C */ |
315 | failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s" , |
316 | ssl_capath, -ret, errorbuf); |
317 | |
318 | if(verifypeer) |
319 | return CURLE_SSL_CACERT_BADFILE; |
320 | } |
321 | } |
322 | |
323 | /* Load the client certificate */ |
324 | mbedtls_x509_crt_init(&BACKEND->clicert); |
325 | |
326 | if(ssl_cert) { |
327 | ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert); |
328 | |
329 | if(ret) { |
330 | #ifdef MBEDTLS_ERROR_C |
331 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
332 | #endif /* MBEDTLS_ERROR_C */ |
333 | failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s" , |
334 | ssl_cert, -ret, errorbuf); |
335 | |
336 | return CURLE_SSL_CERTPROBLEM; |
337 | } |
338 | } |
339 | |
340 | /* Load the client private key */ |
341 | mbedtls_pk_init(&BACKEND->pk); |
342 | |
343 | if(SSL_SET_OPTION(key)) { |
344 | ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), |
345 | SSL_SET_OPTION(key_passwd)); |
346 | if(ret == 0 && !(mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA) || |
347 | mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_ECKEY))) |
348 | ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; |
349 | |
350 | if(ret) { |
351 | #ifdef MBEDTLS_ERROR_C |
352 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
353 | #endif /* MBEDTLS_ERROR_C */ |
354 | failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s" , |
355 | SSL_SET_OPTION(key), -ret, errorbuf); |
356 | |
357 | return CURLE_SSL_CERTPROBLEM; |
358 | } |
359 | } |
360 | |
361 | /* Load the CRL */ |
362 | mbedtls_x509_crl_init(&BACKEND->crl); |
363 | |
364 | if(ssl_crlfile) { |
365 | ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile); |
366 | |
367 | if(ret) { |
368 | #ifdef MBEDTLS_ERROR_C |
369 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
370 | #endif /* MBEDTLS_ERROR_C */ |
371 | failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s" , |
372 | ssl_crlfile, -ret, errorbuf); |
373 | |
374 | return CURLE_SSL_CRL_BADFILE; |
375 | } |
376 | } |
377 | |
378 | infof(data, "mbedTLS: Connecting to %s:%ld\n" , hostname, port); |
379 | |
380 | mbedtls_ssl_config_init(&BACKEND->config); |
381 | |
382 | mbedtls_ssl_init(&BACKEND->ssl); |
383 | if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { |
384 | failf(data, "mbedTLS: ssl_init failed" ); |
385 | return CURLE_SSL_CONNECT_ERROR; |
386 | } |
387 | ret = mbedtls_ssl_config_defaults(&BACKEND->config, |
388 | MBEDTLS_SSL_IS_CLIENT, |
389 | MBEDTLS_SSL_TRANSPORT_STREAM, |
390 | MBEDTLS_SSL_PRESET_DEFAULT); |
391 | if(ret) { |
392 | failf(data, "mbedTLS: ssl_config failed" ); |
393 | return CURLE_SSL_CONNECT_ERROR; |
394 | } |
395 | |
396 | /* new profile with RSA min key len = 1024 ... */ |
397 | mbedtls_ssl_conf_cert_profile(&BACKEND->config, |
398 | &mbedtls_x509_crt_profile_fr); |
399 | |
400 | switch(SSL_CONN_CONFIG(version)) { |
401 | case CURL_SSLVERSION_DEFAULT: |
402 | case CURL_SSLVERSION_TLSv1: |
403 | mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, |
404 | MBEDTLS_SSL_MINOR_VERSION_1); |
405 | infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n" ); |
406 | break; |
407 | case CURL_SSLVERSION_SSLv3: |
408 | mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, |
409 | MBEDTLS_SSL_MINOR_VERSION_0); |
410 | mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, |
411 | MBEDTLS_SSL_MINOR_VERSION_0); |
412 | infof(data, "mbedTLS: Set SSL version to SSLv3\n" ); |
413 | break; |
414 | case CURL_SSLVERSION_TLSv1_0: |
415 | case CURL_SSLVERSION_TLSv1_1: |
416 | case CURL_SSLVERSION_TLSv1_2: |
417 | case CURL_SSLVERSION_TLSv1_3: |
418 | { |
419 | CURLcode result = set_ssl_version_min_max(conn, sockindex); |
420 | if(result != CURLE_OK) |
421 | return result; |
422 | break; |
423 | } |
424 | default: |
425 | failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION" ); |
426 | return CURLE_SSL_CONNECT_ERROR; |
427 | } |
428 | |
429 | mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); |
430 | |
431 | mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, |
432 | &BACKEND->ctr_drbg); |
433 | mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], |
434 | mbedtls_net_send, |
435 | mbedtls_net_recv, |
436 | NULL /* rev_timeout() */); |
437 | |
438 | mbedtls_ssl_conf_ciphersuites(&BACKEND->config, |
439 | mbedtls_ssl_list_ciphersuites()); |
440 | |
441 | #if defined(MBEDTLS_SSL_RENEGOTIATION) |
442 | mbedtls_ssl_conf_renegotiation(&BACKEND->config, |
443 | MBEDTLS_SSL_RENEGOTIATION_ENABLED); |
444 | #endif |
445 | |
446 | #if defined(MBEDTLS_SSL_SESSION_TICKETS) |
447 | mbedtls_ssl_conf_session_tickets(&BACKEND->config, |
448 | MBEDTLS_SSL_SESSION_TICKETS_DISABLED); |
449 | #endif |
450 | |
451 | /* Check if there's a cached ID we can/should use here! */ |
452 | if(SSL_SET_OPTION(primary.sessionid)) { |
453 | void *old_session = NULL; |
454 | |
455 | Curl_ssl_sessionid_lock(conn); |
456 | if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { |
457 | ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session); |
458 | if(ret) { |
459 | Curl_ssl_sessionid_unlock(conn); |
460 | failf(data, "mbedtls_ssl_set_session returned -0x%x" , -ret); |
461 | return CURLE_SSL_CONNECT_ERROR; |
462 | } |
463 | infof(data, "mbedTLS re-using session\n" ); |
464 | } |
465 | Curl_ssl_sessionid_unlock(conn); |
466 | } |
467 | |
468 | mbedtls_ssl_conf_ca_chain(&BACKEND->config, |
469 | &BACKEND->cacert, |
470 | &BACKEND->crl); |
471 | |
472 | if(SSL_SET_OPTION(key)) { |
473 | mbedtls_ssl_conf_own_cert(&BACKEND->config, |
474 | &BACKEND->clicert, &BACKEND->pk); |
475 | } |
476 | if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) { |
477 | /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* |
478 | the name to set in the SNI extension. So even if curl connects to a |
479 | host specified as an IP address, this function must be used. */ |
480 | failf(data, "couldn't set hostname in mbedTLS" ); |
481 | return CURLE_SSL_CONNECT_ERROR; |
482 | } |
483 | |
484 | #ifdef HAS_ALPN |
485 | if(conn->bits.tls_enable_alpn) { |
486 | const char **p = &BACKEND->protocols[0]; |
487 | #ifdef USE_NGHTTP2 |
488 | if(data->set.httpversion >= CURL_HTTP_VERSION_2) |
489 | *p++ = NGHTTP2_PROTO_VERSION_ID; |
490 | #endif |
491 | *p++ = ALPN_HTTP_1_1; |
492 | *p = NULL; |
493 | /* this function doesn't clone the protocols array, which is why we need |
494 | to keep it around */ |
495 | if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config, |
496 | &BACKEND->protocols[0])) { |
497 | failf(data, "Failed setting ALPN protocols" ); |
498 | return CURLE_SSL_CONNECT_ERROR; |
499 | } |
500 | for(p = &BACKEND->protocols[0]; *p; ++p) |
501 | infof(data, "ALPN, offering %s\n" , *p); |
502 | } |
503 | #endif |
504 | |
505 | #ifdef MBEDTLS_DEBUG |
506 | /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ |
507 | mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data); |
508 | /* - 0 No debug |
509 | * - 1 Error |
510 | * - 2 State change |
511 | * - 3 Informational |
512 | * - 4 Verbose |
513 | */ |
514 | mbedtls_debug_set_threshold(4); |
515 | #endif |
516 | |
517 | /* give application a chance to interfere with mbedTLS set up. */ |
518 | if(data->set.ssl.fsslctx) { |
519 | ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config, |
520 | data->set.ssl.fsslctxp); |
521 | if(ret) { |
522 | failf(data, "error signaled by ssl ctx callback" ); |
523 | return ret; |
524 | } |
525 | } |
526 | |
527 | connssl->connecting_state = ssl_connect_2; |
528 | |
529 | return CURLE_OK; |
530 | } |
531 | |
532 | static CURLcode |
533 | mbed_connect_step2(struct connectdata *conn, |
534 | int sockindex) |
535 | { |
536 | int ret; |
537 | struct Curl_easy *data = conn->data; |
538 | struct ssl_connect_data* connssl = &conn->ssl[sockindex]; |
539 | const mbedtls_x509_crt *peercert; |
540 | const char * const pinnedpubkey = SSL_IS_PROXY() ? |
541 | data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : |
542 | data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; |
543 | |
544 | conn->recv[sockindex] = mbed_recv; |
545 | conn->send[sockindex] = mbed_send; |
546 | |
547 | ret = mbedtls_ssl_handshake(&BACKEND->ssl); |
548 | |
549 | if(ret == MBEDTLS_ERR_SSL_WANT_READ) { |
550 | connssl->connecting_state = ssl_connect_2_reading; |
551 | return CURLE_OK; |
552 | } |
553 | else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { |
554 | connssl->connecting_state = ssl_connect_2_writing; |
555 | return CURLE_OK; |
556 | } |
557 | else if(ret) { |
558 | char errorbuf[128]; |
559 | errorbuf[0] = 0; |
560 | #ifdef MBEDTLS_ERROR_C |
561 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
562 | #endif /* MBEDTLS_ERROR_C */ |
563 | failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s" , |
564 | -ret, errorbuf); |
565 | return CURLE_SSL_CONNECT_ERROR; |
566 | } |
567 | |
568 | infof(data, "mbedTLS: Handshake complete, cipher is %s\n" , |
569 | mbedtls_ssl_get_ciphersuite(&BACKEND->ssl) |
570 | ); |
571 | |
572 | ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl); |
573 | |
574 | if(!SSL_CONN_CONFIG(verifyhost)) |
575 | /* Ignore hostname errors if verifyhost is disabled */ |
576 | ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; |
577 | |
578 | if(ret && SSL_CONN_CONFIG(verifypeer)) { |
579 | if(ret & MBEDTLS_X509_BADCERT_EXPIRED) |
580 | failf(data, "Cert verify failed: BADCERT_EXPIRED" ); |
581 | |
582 | else if(ret & MBEDTLS_X509_BADCERT_REVOKED) |
583 | failf(data, "Cert verify failed: BADCERT_REVOKED" ); |
584 | |
585 | else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) |
586 | failf(data, "Cert verify failed: BADCERT_CN_MISMATCH" ); |
587 | |
588 | else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) |
589 | failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED" ); |
590 | |
591 | else if(ret & MBEDTLS_X509_BADCERT_FUTURE) |
592 | failf(data, "Cert verify failed: BADCERT_FUTURE" ); |
593 | |
594 | return CURLE_PEER_FAILED_VERIFICATION; |
595 | } |
596 | |
597 | peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl); |
598 | |
599 | if(peercert && data->set.verbose) { |
600 | const size_t bufsize = 16384; |
601 | char *buffer = malloc(bufsize); |
602 | |
603 | if(!buffer) |
604 | return CURLE_OUT_OF_MEMORY; |
605 | |
606 | if(mbedtls_x509_crt_info(buffer, bufsize, "* " , peercert) > 0) |
607 | infof(data, "Dumping cert info:\n%s\n" , buffer); |
608 | else |
609 | infof(data, "Unable to dump certificate information.\n" ); |
610 | |
611 | free(buffer); |
612 | } |
613 | |
614 | if(pinnedpubkey) { |
615 | int size; |
616 | CURLcode result; |
617 | mbedtls_x509_crt *p; |
618 | unsigned char pubkey[PUB_DER_MAX_BYTES]; |
619 | |
620 | if(!peercert || !peercert->raw.p || !peercert->raw.len) { |
621 | failf(data, "Failed due to missing peer certificate" ); |
622 | return CURLE_SSL_PINNEDPUBKEYNOTMATCH; |
623 | } |
624 | |
625 | p = calloc(1, sizeof(*p)); |
626 | |
627 | if(!p) |
628 | return CURLE_OUT_OF_MEMORY; |
629 | |
630 | mbedtls_x509_crt_init(p); |
631 | |
632 | /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der |
633 | needs a non-const key, for now. |
634 | https://github.com/ARMmbed/mbedtls/issues/396 */ |
635 | if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { |
636 | failf(data, "Failed copying peer certificate" ); |
637 | mbedtls_x509_crt_free(p); |
638 | free(p); |
639 | return CURLE_SSL_PINNEDPUBKEYNOTMATCH; |
640 | } |
641 | |
642 | size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); |
643 | |
644 | if(size <= 0) { |
645 | failf(data, "Failed copying public key from peer certificate" ); |
646 | mbedtls_x509_crt_free(p); |
647 | free(p); |
648 | return CURLE_SSL_PINNEDPUBKEYNOTMATCH; |
649 | } |
650 | |
651 | /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ |
652 | result = Curl_pin_peer_pubkey(data, |
653 | pinnedpubkey, |
654 | &pubkey[PUB_DER_MAX_BYTES - size], size); |
655 | if(result) { |
656 | mbedtls_x509_crt_free(p); |
657 | free(p); |
658 | return result; |
659 | } |
660 | |
661 | mbedtls_x509_crt_free(p); |
662 | free(p); |
663 | } |
664 | |
665 | #ifdef HAS_ALPN |
666 | if(conn->bits.tls_enable_alpn) { |
667 | const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl); |
668 | |
669 | if(next_protocol) { |
670 | infof(data, "ALPN, server accepted to use %s\n" , next_protocol); |
671 | #ifdef USE_NGHTTP2 |
672 | if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, |
673 | NGHTTP2_PROTO_VERSION_ID_LEN) && |
674 | !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { |
675 | conn->negnpn = CURL_HTTP_VERSION_2; |
676 | } |
677 | else |
678 | #endif |
679 | if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && |
680 | !next_protocol[ALPN_HTTP_1_1_LENGTH]) { |
681 | conn->negnpn = CURL_HTTP_VERSION_1_1; |
682 | } |
683 | } |
684 | else { |
685 | infof(data, "ALPN, server did not agree to a protocol\n" ); |
686 | } |
687 | Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? |
688 | BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); |
689 | } |
690 | #endif |
691 | |
692 | connssl->connecting_state = ssl_connect_3; |
693 | infof(data, "SSL connected\n" ); |
694 | |
695 | return CURLE_OK; |
696 | } |
697 | |
698 | static CURLcode |
699 | mbed_connect_step3(struct connectdata *conn, |
700 | int sockindex) |
701 | { |
702 | CURLcode retcode = CURLE_OK; |
703 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
704 | struct Curl_easy *data = conn->data; |
705 | |
706 | DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); |
707 | |
708 | if(SSL_SET_OPTION(primary.sessionid)) { |
709 | int ret; |
710 | mbedtls_ssl_session *our_ssl_sessionid; |
711 | void *old_ssl_sessionid = NULL; |
712 | |
713 | our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); |
714 | if(!our_ssl_sessionid) |
715 | return CURLE_OUT_OF_MEMORY; |
716 | |
717 | mbedtls_ssl_session_init(our_ssl_sessionid); |
718 | |
719 | ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); |
720 | if(ret) { |
721 | if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) |
722 | mbedtls_ssl_session_free(our_ssl_sessionid); |
723 | free(our_ssl_sessionid); |
724 | failf(data, "mbedtls_ssl_get_session returned -0x%x" , -ret); |
725 | return CURLE_SSL_CONNECT_ERROR; |
726 | } |
727 | |
728 | /* If there's already a matching session in the cache, delete it */ |
729 | Curl_ssl_sessionid_lock(conn); |
730 | if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) |
731 | Curl_ssl_delsessionid(conn, old_ssl_sessionid); |
732 | |
733 | retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); |
734 | Curl_ssl_sessionid_unlock(conn); |
735 | if(retcode) { |
736 | mbedtls_ssl_session_free(our_ssl_sessionid); |
737 | free(our_ssl_sessionid); |
738 | failf(data, "failed to store ssl session" ); |
739 | return retcode; |
740 | } |
741 | } |
742 | |
743 | connssl->connecting_state = ssl_connect_done; |
744 | |
745 | return CURLE_OK; |
746 | } |
747 | |
748 | static ssize_t mbed_send(struct connectdata *conn, int sockindex, |
749 | const void *mem, size_t len, |
750 | CURLcode *curlcode) |
751 | { |
752 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
753 | int ret = -1; |
754 | |
755 | ret = mbedtls_ssl_write(&BACKEND->ssl, |
756 | (unsigned char *)mem, len); |
757 | |
758 | if(ret < 0) { |
759 | *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? |
760 | CURLE_AGAIN : CURLE_SEND_ERROR; |
761 | ret = -1; |
762 | } |
763 | |
764 | return ret; |
765 | } |
766 | |
767 | static void Curl_mbedtls_close_all(struct Curl_easy *data) |
768 | { |
769 | (void)data; |
770 | } |
771 | |
772 | static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) |
773 | { |
774 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
775 | mbedtls_pk_free(&BACKEND->pk); |
776 | mbedtls_x509_crt_free(&BACKEND->clicert); |
777 | mbedtls_x509_crt_free(&BACKEND->cacert); |
778 | mbedtls_x509_crl_free(&BACKEND->crl); |
779 | mbedtls_ssl_config_free(&BACKEND->config); |
780 | mbedtls_ssl_free(&BACKEND->ssl); |
781 | mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg); |
782 | #ifndef THREADING_SUPPORT |
783 | mbedtls_entropy_free(&BACKEND->entropy); |
784 | #endif /* THREADING_SUPPORT */ |
785 | } |
786 | |
787 | static ssize_t mbed_recv(struct connectdata *conn, int num, |
788 | char *buf, size_t buffersize, |
789 | CURLcode *curlcode) |
790 | { |
791 | struct ssl_connect_data *connssl = &conn->ssl[num]; |
792 | int ret = -1; |
793 | ssize_t len = -1; |
794 | |
795 | memset(buf, 0, buffersize); |
796 | ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf, |
797 | buffersize); |
798 | |
799 | if(ret <= 0) { |
800 | if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) |
801 | return 0; |
802 | |
803 | *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? |
804 | CURLE_AGAIN : CURLE_RECV_ERROR; |
805 | return -1; |
806 | } |
807 | |
808 | len = ret; |
809 | |
810 | return len; |
811 | } |
812 | |
813 | static void Curl_mbedtls_session_free(void *ptr) |
814 | { |
815 | mbedtls_ssl_session_free(ptr); |
816 | free(ptr); |
817 | } |
818 | |
819 | static size_t Curl_mbedtls_version(char *buffer, size_t size) |
820 | { |
821 | #ifdef MBEDTLS_VERSION_C |
822 | /* if mbedtls_version_get_number() is available it is better */ |
823 | unsigned int version = mbedtls_version_get_number(); |
824 | return msnprintf(buffer, size, "mbedTLS/%u.%u.%u" , version>>24, |
825 | (version>>16)&0xff, (version>>8)&0xff); |
826 | #else |
827 | return msnprintf(buffer, size, "mbedTLS/%s" , MBEDTLS_VERSION_STRING); |
828 | #endif |
829 | } |
830 | |
831 | static CURLcode Curl_mbedtls_random(struct Curl_easy *data, |
832 | unsigned char *entropy, size_t length) |
833 | { |
834 | #if defined(MBEDTLS_CTR_DRBG_C) |
835 | int ret = -1; |
836 | char errorbuf[128]; |
837 | mbedtls_entropy_context ctr_entropy; |
838 | mbedtls_ctr_drbg_context ctr_drbg; |
839 | mbedtls_entropy_init(&ctr_entropy); |
840 | mbedtls_ctr_drbg_init(&ctr_drbg); |
841 | errorbuf[0] = 0; |
842 | |
843 | ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, |
844 | &ctr_entropy, NULL, 0); |
845 | |
846 | if(ret) { |
847 | #ifdef MBEDTLS_ERROR_C |
848 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
849 | #endif /* MBEDTLS_ERROR_C */ |
850 | failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n" , |
851 | -ret, errorbuf); |
852 | } |
853 | else { |
854 | ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); |
855 | |
856 | if(ret) { |
857 | #ifdef MBEDTLS_ERROR_C |
858 | mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); |
859 | #endif /* MBEDTLS_ERROR_C */ |
860 | failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n" , |
861 | -ret, errorbuf); |
862 | } |
863 | } |
864 | |
865 | mbedtls_ctr_drbg_free(&ctr_drbg); |
866 | mbedtls_entropy_free(&ctr_entropy); |
867 | |
868 | return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; |
869 | #elif defined(MBEDTLS_HAVEGE_C) |
870 | mbedtls_havege_state hs; |
871 | mbedtls_havege_init(&hs); |
872 | mbedtls_havege_random(&hs, entropy, length); |
873 | mbedtls_havege_free(&hs); |
874 | return CURLE_OK; |
875 | #else |
876 | return CURLE_NOT_BUILT_IN; |
877 | #endif |
878 | } |
879 | |
880 | static CURLcode |
881 | mbed_connect_common(struct connectdata *conn, |
882 | int sockindex, |
883 | bool nonblocking, |
884 | bool *done) |
885 | { |
886 | CURLcode retcode; |
887 | struct Curl_easy *data = conn->data; |
888 | struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
889 | curl_socket_t sockfd = conn->sock[sockindex]; |
890 | timediff_t timeout_ms; |
891 | int what; |
892 | |
893 | /* check if the connection has already been established */ |
894 | if(ssl_connection_complete == connssl->state) { |
895 | *done = TRUE; |
896 | return CURLE_OK; |
897 | } |
898 | |
899 | if(ssl_connect_1 == connssl->connecting_state) { |
900 | /* Find out how much more time we're allowed */ |
901 | timeout_ms = Curl_timeleft(data, NULL, TRUE); |
902 | |
903 | if(timeout_ms < 0) { |
904 | /* no need to continue if time already is up */ |
905 | failf(data, "SSL connection timeout" ); |
906 | return CURLE_OPERATION_TIMEDOUT; |
907 | } |
908 | retcode = mbed_connect_step1(conn, sockindex); |
909 | if(retcode) |
910 | return retcode; |
911 | } |
912 | |
913 | while(ssl_connect_2 == connssl->connecting_state || |
914 | ssl_connect_2_reading == connssl->connecting_state || |
915 | ssl_connect_2_writing == connssl->connecting_state) { |
916 | |
917 | /* check allowed time left */ |
918 | timeout_ms = Curl_timeleft(data, NULL, TRUE); |
919 | |
920 | if(timeout_ms < 0) { |
921 | /* no need to continue if time already is up */ |
922 | failf(data, "SSL connection timeout" ); |
923 | return CURLE_OPERATION_TIMEDOUT; |
924 | } |
925 | |
926 | /* if ssl is expecting something, check if it's available. */ |
927 | if(connssl->connecting_state == ssl_connect_2_reading |
928 | || connssl->connecting_state == ssl_connect_2_writing) { |
929 | |
930 | curl_socket_t writefd = ssl_connect_2_writing == |
931 | connssl->connecting_state?sockfd:CURL_SOCKET_BAD; |
932 | curl_socket_t readfd = ssl_connect_2_reading == |
933 | connssl->connecting_state?sockfd:CURL_SOCKET_BAD; |
934 | |
935 | what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, |
936 | nonblocking ? 0 : (time_t)timeout_ms); |
937 | if(what < 0) { |
938 | /* fatal error */ |
939 | failf(data, "select/poll on SSL socket, errno: %d" , SOCKERRNO); |
940 | return CURLE_SSL_CONNECT_ERROR; |
941 | } |
942 | else if(0 == what) { |
943 | if(nonblocking) { |
944 | *done = FALSE; |
945 | return CURLE_OK; |
946 | } |
947 | else { |
948 | /* timeout */ |
949 | failf(data, "SSL connection timeout" ); |
950 | return CURLE_OPERATION_TIMEDOUT; |
951 | } |
952 | } |
953 | /* socket is readable or writable */ |
954 | } |
955 | |
956 | /* Run transaction, and return to the caller if it failed or if |
957 | * this connection is part of a multi handle and this loop would |
958 | * execute again. This permits the owner of a multi handle to |
959 | * abort a connection attempt before step2 has completed while |
960 | * ensuring that a client using select() or epoll() will always |
961 | * have a valid fdset to wait on. |
962 | */ |
963 | retcode = mbed_connect_step2(conn, sockindex); |
964 | if(retcode || (nonblocking && |
965 | (ssl_connect_2 == connssl->connecting_state || |
966 | ssl_connect_2_reading == connssl->connecting_state || |
967 | ssl_connect_2_writing == connssl->connecting_state))) |
968 | return retcode; |
969 | |
970 | } /* repeat step2 until all transactions are done. */ |
971 | |
972 | if(ssl_connect_3 == connssl->connecting_state) { |
973 | retcode = mbed_connect_step3(conn, sockindex); |
974 | if(retcode) |
975 | return retcode; |
976 | } |
977 | |
978 | if(ssl_connect_done == connssl->connecting_state) { |
979 | connssl->state = ssl_connection_complete; |
980 | conn->recv[sockindex] = mbed_recv; |
981 | conn->send[sockindex] = mbed_send; |
982 | *done = TRUE; |
983 | } |
984 | else |
985 | *done = FALSE; |
986 | |
987 | /* Reset our connect state machine */ |
988 | connssl->connecting_state = ssl_connect_1; |
989 | |
990 | return CURLE_OK; |
991 | } |
992 | |
993 | static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn, |
994 | int sockindex, bool *done) |
995 | { |
996 | return mbed_connect_common(conn, sockindex, TRUE, done); |
997 | } |
998 | |
999 | |
1000 | static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) |
1001 | { |
1002 | CURLcode retcode; |
1003 | bool done = FALSE; |
1004 | |
1005 | retcode = mbed_connect_common(conn, sockindex, FALSE, &done); |
1006 | if(retcode) |
1007 | return retcode; |
1008 | |
1009 | DEBUGASSERT(done); |
1010 | |
1011 | return CURLE_OK; |
1012 | } |
1013 | |
1014 | /* |
1015 | * return 0 error initializing SSL |
1016 | * return 1 SSL initialized successfully |
1017 | */ |
1018 | static int Curl_mbedtls_init(void) |
1019 | { |
1020 | return Curl_polarsslthreadlock_thread_setup(); |
1021 | } |
1022 | |
1023 | static void Curl_mbedtls_cleanup(void) |
1024 | { |
1025 | (void)Curl_polarsslthreadlock_thread_cleanup(); |
1026 | } |
1027 | |
1028 | static bool Curl_mbedtls_data_pending(const struct connectdata *conn, |
1029 | int sockindex) |
1030 | { |
1031 | const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; |
1032 | return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0; |
1033 | } |
1034 | |
1035 | static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, |
1036 | size_t inputlen, |
1037 | unsigned char *sha256sum, |
1038 | size_t sha256len UNUSED_PARAM) |
1039 | { |
1040 | (void)sha256len; |
1041 | #if MBEDTLS_VERSION_NUMBER < 0x02070000 |
1042 | mbedtls_sha256(input, inputlen, sha256sum, 0); |
1043 | #else |
1044 | /* returns 0 on success, otherwise failure */ |
1045 | if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) |
1046 | return CURLE_BAD_FUNCTION_ARGUMENT; |
1047 | #endif |
1048 | return CURLE_OK; |
1049 | } |
1050 | |
1051 | static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, |
1052 | CURLINFO info UNUSED_PARAM) |
1053 | { |
1054 | (void)info; |
1055 | return &BACKEND->ssl; |
1056 | } |
1057 | |
1058 | const struct Curl_ssl Curl_ssl_mbedtls = { |
1059 | { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ |
1060 | |
1061 | SSLSUPP_CA_PATH | |
1062 | SSLSUPP_PINNEDPUBKEY | |
1063 | SSLSUPP_SSL_CTX, |
1064 | |
1065 | sizeof(struct ssl_backend_data), |
1066 | |
1067 | Curl_mbedtls_init, /* init */ |
1068 | Curl_mbedtls_cleanup, /* cleanup */ |
1069 | Curl_mbedtls_version, /* version */ |
1070 | Curl_none_check_cxn, /* check_cxn */ |
1071 | Curl_none_shutdown, /* shutdown */ |
1072 | Curl_mbedtls_data_pending, /* data_pending */ |
1073 | Curl_mbedtls_random, /* random */ |
1074 | Curl_none_cert_status_request, /* cert_status_request */ |
1075 | Curl_mbedtls_connect, /* connect */ |
1076 | Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */ |
1077 | Curl_mbedtls_get_internals, /* get_internals */ |
1078 | Curl_mbedtls_close, /* close_one */ |
1079 | Curl_mbedtls_close_all, /* close_all */ |
1080 | Curl_mbedtls_session_free, /* session_free */ |
1081 | Curl_none_set_engine, /* set_engine */ |
1082 | Curl_none_set_engine_default, /* set_engine_default */ |
1083 | Curl_none_engines_list, /* engines_list */ |
1084 | Curl_none_false_start, /* false_start */ |
1085 | Curl_none_md5sum, /* md5sum */ |
1086 | Curl_mbedtls_sha256sum /* sha256sum */ |
1087 | }; |
1088 | |
1089 | #endif /* USE_MBEDTLS */ |
1090 | |