1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
9 * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
25 * Source file for all mbedTSL-specific code for the TLS/SSL layer. No code
26 * but vtls.c should ever call or use these functions.
30 #include "curl_setup.h"
34 #include <mbedtls/net.h>
35 #include <mbedtls/ssl.h>
36 #include <mbedtls/certs.h>
37 #include <mbedtls/x509.h>
38 #include <mbedtls/version.h>
40 #include <mbedtls/error.h>
41 #include <mbedtls/entropy.h>
42 #include <mbedtls/ctr_drbg.h>
43 #include <mbedtls/sha256.h>
47 #include "inet_pton.h"
50 #include "parsedate.h"
51 #include "connect.h" /* for the connect timeout */
54 #include "polarssl_threadlock.h"
56 #define _MPRINTF_REPLACE /* use our functions only */
57 #include <curl/mprintf.h>
58 #include "curl_memory.h"
59 /* The last #include file should be: */
62 /* apply threading? */
63 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
64 #define THREADING_SUPPORT
67 #if defined(THREADING_SUPPORT)
68 static mbedtls_entropy_context entropy;
70 static int entropy_init_initialized = 0;
72 /* start of entropy_init_mutex() */
73 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
75 /* lock 0 = entropy_init_mutex() */
76 Curl_polarsslthreadlock_lock_function(0);
77 if(entropy_init_initialized == 0) {
78 mbedtls_entropy_init(ctx);
79 entropy_init_initialized = 1;
81 Curl_polarsslthreadlock_unlock_function(0);
83 /* end of entropy_init_mutex() */
85 /* start of entropy_func_mutex() */
86 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
89 /* lock 1 = entropy_func_mutex() */
90 Curl_polarsslthreadlock_lock_function(1);
91 ret = mbedtls_entropy_func(data, output, len);
92 Curl_polarsslthreadlock_unlock_function(1);
96 /* end of entropy_func_mutex() */
98 #endif /* THREADING_SUPPORT */
100 /* Define this to enable lots of debugging for mbedTLS */
104 static void mbedtls_debug(void *context, int level, const char *line)
106 struct SessionHandle *data = NULL;
111 data = (struct SessionHandle *)context;
113 infof(data, "%s", line);
119 /* ALPN for http2? */
122 # ifdef MBEDTLS_SSL_ALPN
131 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
133 /* Hashes from SHA-1 and above */
134 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
135 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
136 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
137 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
138 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
139 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
140 0xFFFFFFF, /* Any PK alg */
141 0xFFFFFFF, /* Any curve */
142 1024, /* RSA min key len */
145 /* See https://tls.mbed.org/discussions/generic/
146 howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
148 #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
149 #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
151 #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
152 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
154 static Curl_recv mbedtls_recv;
155 static Curl_send mbedtls_send;
158 mbedtls_connect_step1(struct connectdata *conn,
161 struct SessionHandle *data = conn->data;
162 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
164 bool sni = TRUE; /* default is SNI enabled */
167 struct in6_addr addr;
171 void *old_session = NULL;
172 size_t old_session_size = 0;
176 /* mbedTLS only supports SSLv3 and TLSv1 */
177 if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
178 failf(data, "mbedTLS does not support SSLv2");
179 return CURLE_SSL_CONNECT_ERROR;
181 else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
182 sni = FALSE; /* SSLv3 has no SNI */
184 #ifdef THREADING_SUPPORT
185 entropy_init_mutex(&entropy);
186 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
188 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
189 &entropy, connssl->ssn.id,
190 connssl->ssn.id_len);
192 #ifdef MBEDTLS_ERROR_C
193 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
194 #endif /* MBEDTLS_ERROR_C */
195 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
199 mbedtls_entropy_init(&connssl->entropy);
200 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
202 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
203 &connssl->entropy, connssl->ssn.id,
204 connssl->ssn.id_len);
206 #ifdef MBEDTLS_ERROR_C
207 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
208 #endif /* MBEDTLS_ERROR_C */
209 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
212 #endif /* THREADING_SUPPORT */
214 /* Load the trusted CA */
215 mbedtls_x509_crt_init(&connssl->cacert);
217 if(data->set.str[STRING_SSL_CAFILE]) {
218 ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
219 data->set.str[STRING_SSL_CAFILE]);
222 #ifdef MBEDTLS_ERROR_C
223 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
224 #endif /* MBEDTLS_ERROR_C */
225 failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
226 data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
228 if(data->set.ssl.verifypeer)
229 return CURLE_SSL_CACERT_BADFILE;
233 if(data->set.str[STRING_SSL_CAPATH]) {
234 ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
235 data->set.str[STRING_SSL_CAPATH]);
238 #ifdef MBEDTLS_ERROR_C
239 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
240 #endif /* MBEDTLS_ERROR_C */
241 failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
242 data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
244 if(data->set.ssl.verifypeer)
245 return CURLE_SSL_CACERT_BADFILE;
249 /* Load the client certificate */
250 mbedtls_x509_crt_init(&connssl->clicert);
252 if(data->set.str[STRING_CERT]) {
253 ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
254 data->set.str[STRING_CERT]);
257 #ifdef MBEDTLS_ERROR_C
258 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
259 #endif /* MBEDTLS_ERROR_C */
260 failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
261 data->set.str[STRING_CERT], -ret, errorbuf);
263 return CURLE_SSL_CERTPROBLEM;
267 /* Load the client private key */
268 mbedtls_pk_init(&connssl->pk);
270 if(data->set.str[STRING_KEY]) {
271 ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
272 data->set.str[STRING_KEY_PASSWD]);
273 if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
274 ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
277 #ifdef MBEDTLS_ERROR_C
278 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
279 #endif /* MBEDTLS_ERROR_C */
280 failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
281 data->set.str[STRING_KEY], -ret, errorbuf);
283 return CURLE_SSL_CERTPROBLEM;
288 mbedtls_x509_crl_init(&connssl->crl);
290 if(data->set.str[STRING_SSL_CRLFILE]) {
291 ret = mbedtls_x509_crl_parse_file(&connssl->crl,
292 data->set.str[STRING_SSL_CRLFILE]);
295 #ifdef MBEDTLS_ERROR_C
296 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
297 #endif /* MBEDTLS_ERROR_C */
298 failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
299 data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
301 return CURLE_SSL_CRL_BADFILE;
305 infof(data, "mbedTLS: Connecting to %s:%d\n",
306 conn->host.name, conn->remote_port);
308 mbedtls_ssl_config_init(&connssl->config);
310 mbedtls_ssl_init(&connssl->ssl);
311 if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
312 failf(data, "mbedTLS: ssl_init failed");
313 return CURLE_SSL_CONNECT_ERROR;
315 ret = mbedtls_ssl_config_defaults(&connssl->config,
316 MBEDTLS_SSL_IS_CLIENT,
317 MBEDTLS_SSL_TRANSPORT_STREAM,
318 MBEDTLS_SSL_PRESET_DEFAULT);
320 failf(data, "mbedTLS: ssl_config failed");
321 return CURLE_SSL_CONNECT_ERROR;
324 /* new profile with RSA min key len = 1024 ... */
325 mbedtls_ssl_conf_cert_profile( &connssl->config,
326 &mbedtls_x509_crt_profile_fr);
328 switch(data->set.ssl.version) {
329 case CURL_SSLVERSION_DEFAULT:
330 case CURL_SSLVERSION_TLSv1:
331 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
332 MBEDTLS_SSL_MINOR_VERSION_1);
333 infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
335 case CURL_SSLVERSION_SSLv3:
336 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
337 MBEDTLS_SSL_MINOR_VERSION_0);
338 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
339 MBEDTLS_SSL_MINOR_VERSION_0);
340 infof(data, "mbedTLS: Set SSL version to SSLv3\n");
342 case CURL_SSLVERSION_TLSv1_0:
343 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
344 MBEDTLS_SSL_MINOR_VERSION_1);
345 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
346 MBEDTLS_SSL_MINOR_VERSION_1);
347 infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
349 case CURL_SSLVERSION_TLSv1_1:
350 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
351 MBEDTLS_SSL_MINOR_VERSION_2);
352 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
353 MBEDTLS_SSL_MINOR_VERSION_2);
354 infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
356 case CURL_SSLVERSION_TLSv1_2:
357 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
358 MBEDTLS_SSL_MINOR_VERSION_3);
359 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
360 MBEDTLS_SSL_MINOR_VERSION_3);
361 infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
364 failf(data, "mbedTLS: Unsupported SSL protocol version");
365 return CURLE_SSL_CONNECT_ERROR;
368 mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
370 mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
372 mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
375 NULL /* rev_timeout() */);
377 mbedtls_ssl_conf_ciphersuites(&connssl->config,
378 mbedtls_ssl_list_ciphersuites());
379 if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
380 memcpy(&connssl->ssn, old_session, old_session_size);
381 infof(data, "mbedTLS re-using session\n");
384 mbedtls_ssl_set_session(&connssl->ssl,
387 mbedtls_ssl_conf_ca_chain(&connssl->config,
391 if(data->set.str[STRING_KEY]) {
392 mbedtls_ssl_conf_own_cert(&connssl->config,
393 &connssl->clicert, &connssl->pk);
395 if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
396 /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
397 the name to set in the SNI extension. So even if curl connects to a
398 host specified as an IP address, this function must be used. */
399 failf(data, "couldn't set hostname in mbedTLS");
400 return CURLE_SSL_CONNECT_ERROR;
404 if(data->set.ssl_enable_alpn) {
405 const char **p = &connssl->protocols[0];
407 if(data->set.httpversion >= CURL_HTTP_VERSION_2)
408 *p++ = NGHTTP2_PROTO_VERSION_ID;
410 *p++ = ALPN_HTTP_1_1;
412 /* this function doesn't clone the protocols array, which is why we need
414 if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
415 &connssl->protocols[0])) {
416 failf(data, "Failed setting ALPN protocols");
417 return CURLE_SSL_CONNECT_ERROR;
419 for(p = &connssl->protocols[0]; *p; ++p)
420 infof(data, "ALPN, offering %s\n", *p);
425 mbedtls_ssl_conf_dbg(&connssl->ssl, mbedtls_debug, data);
428 connssl->connecting_state = ssl_connect_2;
434 mbedtls_connect_step2(struct connectdata *conn,
438 struct SessionHandle *data = conn->data;
439 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
440 const mbedtls_x509_crt *peercert;
443 const char* next_protocol;
449 conn->recv[sockindex] = mbedtls_recv;
450 conn->send[sockindex] = mbedtls_send;
452 ret = mbedtls_ssl_handshake(&connssl->ssl);
454 if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
455 connssl->connecting_state = ssl_connect_2_reading;
458 else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
459 connssl->connecting_state = ssl_connect_2_writing;
463 #ifdef MBEDTLS_ERROR_C
464 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
465 #endif /* MBEDTLS_ERROR_C */
466 failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
468 return CURLE_SSL_CONNECT_ERROR;
471 infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
472 mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
475 ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
477 if(ret && data->set.ssl.verifypeer) {
478 if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
479 failf(data, "Cert verify failed: BADCERT_EXPIRED");
481 if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
482 failf(data, "Cert verify failed: BADCERT_REVOKED");
483 return CURLE_SSL_CACERT;
486 if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
487 failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
489 if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
490 failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
492 return CURLE_PEER_FAILED_VERIFICATION;
495 peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
497 if(peercert && data->set.verbose) {
498 const size_t bufsize = 16384;
499 char *buffer = malloc(bufsize);
502 return CURLE_OUT_OF_MEMORY;
504 if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
505 infof(data, "Dumping cert info:\n%s\n", buffer);
507 infof(data, "Unable to dump certificate information.\n");
512 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
516 unsigned char pubkey[PUB_DER_MAX_BYTES];
518 if(!peercert || !peercert->raw.p || !peercert->raw.len) {
519 failf(data, "Failed due to missing peer certificate");
520 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
523 p = calloc(1, sizeof(*p));
526 return CURLE_OUT_OF_MEMORY;
528 mbedtls_x509_crt_init(p);
530 /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
531 needs a non-const key, for now.
532 https://github.com/ARMmbed/mbedtls/issues/396 */
533 if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
534 failf(data, "Failed copying peer certificate");
535 mbedtls_x509_crt_free(p);
537 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
540 size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
543 failf(data, "Failed copying public key from peer certificate");
544 mbedtls_x509_crt_free(p);
546 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
549 /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
550 result = Curl_pin_peer_pubkey(data,
551 data->set.str[STRING_SSL_PINNEDPUBLICKEY],
552 &pubkey[PUB_DER_MAX_BYTES - size], size);
554 mbedtls_x509_crt_free(p);
559 mbedtls_x509_crt_free(p);
564 if(data->set.ssl_enable_alpn) {
565 next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
568 infof(data, "ALPN, server accepted to use %s\n", next_protocol);
570 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
571 NGHTTP2_PROTO_VERSION_ID_LEN) &&
572 !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
573 conn->negnpn = CURL_HTTP_VERSION_2;
577 if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
578 !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
579 conn->negnpn = CURL_HTTP_VERSION_1_1;
583 infof(data, "ALPN, server did not agree to a protocol\n");
588 connssl->connecting_state = ssl_connect_3;
589 infof(data, "SSL connected\n");
595 mbedtls_connect_step3(struct connectdata *conn,
598 CURLcode retcode = CURLE_OK;
599 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
600 struct SessionHandle *data = conn->data;
601 void *old_ssl_sessionid = NULL;
602 mbedtls_ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn;
605 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
607 /* Save the current session data for possible re-use */
608 incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
610 if(old_ssl_sessionid != our_ssl_sessionid) {
611 infof(data, "old SSL session ID is stale, removing\n");
612 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
617 void *new_session = malloc(sizeof(mbedtls_ssl_session));
620 memcpy(new_session, our_ssl_sessionid,
621 sizeof(mbedtls_ssl_session));
623 retcode = Curl_ssl_addsessionid(conn, new_session,
624 sizeof(mbedtls_ssl_session));
627 retcode = CURLE_OUT_OF_MEMORY;
631 failf(data, "failed to store ssl session");
636 connssl->connecting_state = ssl_connect_done;
641 static ssize_t mbedtls_send(struct connectdata *conn,
649 ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
650 (unsigned char *)mem, len);
653 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
654 CURLE_AGAIN : CURLE_SEND_ERROR;
661 void Curl_mbedtls_close_all(struct SessionHandle *data)
666 void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
668 mbedtls_pk_free(&conn->ssl[sockindex].pk);
669 mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
670 mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
671 mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
672 mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
673 mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
674 mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
675 #ifndef THREADING_SUPPORT
676 mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
677 #endif /* THREADING_SUPPORT */
680 static ssize_t mbedtls_recv(struct connectdata *conn,
689 memset(buf, 0, buffersize);
690 ret = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
694 if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
697 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
698 CURLE_AGAIN : CURLE_RECV_ERROR;
707 void Curl_mbedtls_session_free(void *ptr)
712 size_t Curl_mbedtls_version(char *buffer, size_t size)
714 unsigned int version = mbedtls_version_get_number();
715 return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
716 (version>>16)&0xff, (version>>8)&0xff);
720 mbedtls_connect_common(struct connectdata *conn,
726 struct SessionHandle *data = conn->data;
727 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
728 curl_socket_t sockfd = conn->sock[sockindex];
732 /* check if the connection has already been established */
733 if(ssl_connection_complete == connssl->state) {
738 if(ssl_connect_1==connssl->connecting_state) {
739 /* Find out how much more time we're allowed */
740 timeout_ms = Curl_timeleft(data, NULL, TRUE);
743 /* no need to continue if time already is up */
744 failf(data, "SSL connection timeout");
745 return CURLE_OPERATION_TIMEDOUT;
747 retcode = mbedtls_connect_step1(conn, sockindex);
752 while(ssl_connect_2 == connssl->connecting_state ||
753 ssl_connect_2_reading == connssl->connecting_state ||
754 ssl_connect_2_writing == connssl->connecting_state) {
756 /* check allowed time left */
757 timeout_ms = Curl_timeleft(data, NULL, TRUE);
760 /* no need to continue if time already is up */
761 failf(data, "SSL connection timeout");
762 return CURLE_OPERATION_TIMEDOUT;
765 /* if ssl is expecting something, check if it's available. */
766 if(connssl->connecting_state == ssl_connect_2_reading
767 || connssl->connecting_state == ssl_connect_2_writing) {
769 curl_socket_t writefd = ssl_connect_2_writing==
770 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
771 curl_socket_t readfd = ssl_connect_2_reading==
772 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
774 what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
777 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
778 return CURLE_SSL_CONNECT_ERROR;
787 failf(data, "SSL connection timeout");
788 return CURLE_OPERATION_TIMEDOUT;
791 /* socket is readable or writable */
794 /* Run transaction, and return to the caller if it failed or if
795 * this connection is part of a multi handle and this loop would
796 * execute again. This permits the owner of a multi handle to
797 * abort a connection attempt before step2 has completed while
798 * ensuring that a client using select() or epoll() will always
799 * have a valid fdset to wait on.
801 retcode = mbedtls_connect_step2(conn, sockindex);
802 if(retcode || (nonblocking &&
803 (ssl_connect_2 == connssl->connecting_state ||
804 ssl_connect_2_reading == connssl->connecting_state ||
805 ssl_connect_2_writing == connssl->connecting_state)))
808 } /* repeat step2 until all transactions are done. */
810 if(ssl_connect_3==connssl->connecting_state) {
811 retcode = mbedtls_connect_step3(conn, sockindex);
816 if(ssl_connect_done==connssl->connecting_state) {
817 connssl->state = ssl_connection_complete;
818 conn->recv[sockindex] = mbedtls_recv;
819 conn->send[sockindex] = mbedtls_send;
825 /* Reset our connect state machine */
826 connssl->connecting_state = ssl_connect_1;
832 Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
836 return mbedtls_connect_common(conn, sockindex, TRUE, done);
841 Curl_mbedtls_connect(struct connectdata *conn,
847 retcode = mbedtls_connect_common(conn, sockindex, FALSE, &done);
857 * return 0 error initializing SSL
858 * return 1 SSL initialized successfully
860 int mbedtls_init(void)
862 return Curl_polarsslthreadlock_thread_setup();
865 void mbedtls_cleanup(void)
867 (void)Curl_polarsslthreadlock_thread_cleanup();
870 #endif /* USE_MBEDTLS */