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 mbedTLS-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 /* The last 3 #include files should be in this order */
57 #include "curl_printf.h"
58 #include "curl_memory.h"
61 /* apply threading? */
62 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
63 #define THREADING_SUPPORT
66 #if defined(THREADING_SUPPORT)
67 static mbedtls_entropy_context entropy
;
69 static int entropy_init_initialized
= 0;
71 /* start of entropy_init_mutex() */
72 static void entropy_init_mutex(mbedtls_entropy_context
*ctx
)
74 /* lock 0 = entropy_init_mutex() */
75 Curl_polarsslthreadlock_lock_function(0);
76 if(entropy_init_initialized
== 0) {
77 mbedtls_entropy_init(ctx
);
78 entropy_init_initialized
= 1;
80 Curl_polarsslthreadlock_unlock_function(0);
82 /* end of entropy_init_mutex() */
84 /* start of entropy_func_mutex() */
85 static int entropy_func_mutex(void *data
, unsigned char *output
, size_t len
)
88 /* lock 1 = entropy_func_mutex() */
89 Curl_polarsslthreadlock_lock_function(1);
90 ret
= mbedtls_entropy_func(data
, output
, len
);
91 Curl_polarsslthreadlock_unlock_function(1);
95 /* end of entropy_func_mutex() */
97 #endif /* THREADING_SUPPORT */
99 /* Define this to enable lots of debugging for mbedTLS */
103 static void mbed_debug(void *context
, int level
, const char *f_name
,
104 int line_nb
, 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 mbed_recv
;
155 static Curl_send mbed_send
;
158 mbed_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
;
175 /* mbedTLS only supports SSLv3 and TLSv1 */
176 if(data
->set
.ssl
.version
== CURL_SSLVERSION_SSLv2
) {
177 failf(data
, "mbedTLS does not support SSLv2");
178 return CURLE_SSL_CONNECT_ERROR
;
180 else if(data
->set
.ssl
.version
== CURL_SSLVERSION_SSLv3
)
181 sni
= FALSE
; /* SSLv3 has no SNI */
183 #ifdef THREADING_SUPPORT
184 entropy_init_mutex(&entropy
);
185 mbedtls_ctr_drbg_init(&connssl
->ctr_drbg
);
187 ret
= mbedtls_ctr_drbg_seed(&connssl
->ctr_drbg
, entropy_func_mutex
,
190 #ifdef MBEDTLS_ERROR_C
191 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
192 #endif /* MBEDTLS_ERROR_C */
193 failf(data
, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
197 mbedtls_entropy_init(&connssl
->entropy
);
198 mbedtls_ctr_drbg_init(&connssl
->ctr_drbg
);
200 ret
= mbedtls_ctr_drbg_seed(&connssl
->ctr_drbg
, mbedtls_entropy_func
,
201 &connssl
->entropy
, NULL
, 0);
203 #ifdef MBEDTLS_ERROR_C
204 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
205 #endif /* MBEDTLS_ERROR_C */
206 failf(data
, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
209 #endif /* THREADING_SUPPORT */
211 /* Load the trusted CA */
212 mbedtls_x509_crt_init(&connssl
->cacert
);
214 if(data
->set
.str
[STRING_SSL_CAFILE
]) {
215 ret
= mbedtls_x509_crt_parse_file(&connssl
->cacert
,
216 data
->set
.str
[STRING_SSL_CAFILE
]);
219 #ifdef MBEDTLS_ERROR_C
220 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
221 #endif /* MBEDTLS_ERROR_C */
222 failf(data
, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
223 data
->set
.str
[STRING_SSL_CAFILE
], -ret
, errorbuf
);
225 if(data
->set
.ssl
.verifypeer
)
226 return CURLE_SSL_CACERT_BADFILE
;
230 if(data
->set
.str
[STRING_SSL_CAPATH
]) {
231 ret
= mbedtls_x509_crt_parse_path(&connssl
->cacert
,
232 data
->set
.str
[STRING_SSL_CAPATH
]);
235 #ifdef MBEDTLS_ERROR_C
236 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
237 #endif /* MBEDTLS_ERROR_C */
238 failf(data
, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
239 data
->set
.str
[STRING_SSL_CAPATH
], -ret
, errorbuf
);
241 if(data
->set
.ssl
.verifypeer
)
242 return CURLE_SSL_CACERT_BADFILE
;
246 /* Load the client certificate */
247 mbedtls_x509_crt_init(&connssl
->clicert
);
249 if(data
->set
.str
[STRING_CERT
]) {
250 ret
= mbedtls_x509_crt_parse_file(&connssl
->clicert
,
251 data
->set
.str
[STRING_CERT
]);
254 #ifdef MBEDTLS_ERROR_C
255 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
256 #endif /* MBEDTLS_ERROR_C */
257 failf(data
, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
258 data
->set
.str
[STRING_CERT
], -ret
, errorbuf
);
260 return CURLE_SSL_CERTPROBLEM
;
264 /* Load the client private key */
265 mbedtls_pk_init(&connssl
->pk
);
267 if(data
->set
.str
[STRING_KEY
]) {
268 ret
= mbedtls_pk_parse_keyfile(&connssl
->pk
, data
->set
.str
[STRING_KEY
],
269 data
->set
.str
[STRING_KEY_PASSWD
]);
270 if(ret
== 0 && !mbedtls_pk_can_do(&connssl
->pk
, MBEDTLS_PK_RSA
))
271 ret
= MBEDTLS_ERR_PK_TYPE_MISMATCH
;
274 #ifdef MBEDTLS_ERROR_C
275 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
276 #endif /* MBEDTLS_ERROR_C */
277 failf(data
, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
278 data
->set
.str
[STRING_KEY
], -ret
, errorbuf
);
280 return CURLE_SSL_CERTPROBLEM
;
285 mbedtls_x509_crl_init(&connssl
->crl
);
287 if(data
->set
.str
[STRING_SSL_CRLFILE
]) {
288 ret
= mbedtls_x509_crl_parse_file(&connssl
->crl
,
289 data
->set
.str
[STRING_SSL_CRLFILE
]);
292 #ifdef MBEDTLS_ERROR_C
293 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
294 #endif /* MBEDTLS_ERROR_C */
295 failf(data
, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
296 data
->set
.str
[STRING_SSL_CRLFILE
], -ret
, errorbuf
);
298 return CURLE_SSL_CRL_BADFILE
;
302 infof(data
, "mbedTLS: Connecting to %s:%d\n",
303 conn
->host
.name
, conn
->remote_port
);
305 mbedtls_ssl_config_init(&connssl
->config
);
307 mbedtls_ssl_init(&connssl
->ssl
);
308 if(mbedtls_ssl_setup(&connssl
->ssl
, &connssl
->config
)) {
309 failf(data
, "mbedTLS: ssl_init failed");
310 return CURLE_SSL_CONNECT_ERROR
;
312 ret
= mbedtls_ssl_config_defaults(&connssl
->config
,
313 MBEDTLS_SSL_IS_CLIENT
,
314 MBEDTLS_SSL_TRANSPORT_STREAM
,
315 MBEDTLS_SSL_PRESET_DEFAULT
);
317 failf(data
, "mbedTLS: ssl_config failed");
318 return CURLE_SSL_CONNECT_ERROR
;
321 /* new profile with RSA min key len = 1024 ... */
322 mbedtls_ssl_conf_cert_profile(&connssl
->config
,
323 &mbedtls_x509_crt_profile_fr
);
325 switch(data
->set
.ssl
.version
) {
326 case CURL_SSLVERSION_DEFAULT
:
327 case CURL_SSLVERSION_TLSv1
:
328 mbedtls_ssl_conf_min_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
329 MBEDTLS_SSL_MINOR_VERSION_1
);
330 infof(data
, "mbedTLS: Set min SSL version to TLS 1.0\n");
332 case CURL_SSLVERSION_SSLv3
:
333 mbedtls_ssl_conf_min_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
334 MBEDTLS_SSL_MINOR_VERSION_0
);
335 mbedtls_ssl_conf_max_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
336 MBEDTLS_SSL_MINOR_VERSION_0
);
337 infof(data
, "mbedTLS: Set SSL version to SSLv3\n");
339 case CURL_SSLVERSION_TLSv1_0
:
340 mbedtls_ssl_conf_min_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
341 MBEDTLS_SSL_MINOR_VERSION_1
);
342 mbedtls_ssl_conf_max_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
343 MBEDTLS_SSL_MINOR_VERSION_1
);
344 infof(data
, "mbedTLS: Set SSL version to TLS 1.0\n");
346 case CURL_SSLVERSION_TLSv1_1
:
347 mbedtls_ssl_conf_min_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
348 MBEDTLS_SSL_MINOR_VERSION_2
);
349 mbedtls_ssl_conf_max_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
350 MBEDTLS_SSL_MINOR_VERSION_2
);
351 infof(data
, "mbedTLS: Set SSL version to TLS 1.1\n");
353 case CURL_SSLVERSION_TLSv1_2
:
354 mbedtls_ssl_conf_min_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
355 MBEDTLS_SSL_MINOR_VERSION_3
);
356 mbedtls_ssl_conf_max_version(&connssl
->config
, MBEDTLS_SSL_MAJOR_VERSION_3
,
357 MBEDTLS_SSL_MINOR_VERSION_3
);
358 infof(data
, "mbedTLS: Set SSL version to TLS 1.2\n");
361 failf(data
, "mbedTLS: Unsupported SSL protocol version");
362 return CURLE_SSL_CONNECT_ERROR
;
365 mbedtls_ssl_conf_authmode(&connssl
->config
, MBEDTLS_SSL_VERIFY_OPTIONAL
);
367 mbedtls_ssl_conf_rng(&connssl
->config
, mbedtls_ctr_drbg_random
,
369 mbedtls_ssl_set_bio(&connssl
->ssl
, &conn
->sock
[sockindex
],
372 NULL
/* rev_timeout() */);
374 mbedtls_ssl_conf_ciphersuites(&connssl
->config
,
375 mbedtls_ssl_list_ciphersuites());
376 if(!Curl_ssl_getsessionid(conn
, &old_session
, NULL
)) {
377 ret
= mbedtls_ssl_set_session(&connssl
->ssl
, old_session
);
379 failf(data
, "mbedtls_ssl_set_session returned -0x%x", -ret
);
380 return CURLE_SSL_CONNECT_ERROR
;
382 infof(data
, "mbedTLS re-using session\n");
385 mbedtls_ssl_conf_ca_chain(&connssl
->config
,
389 if(data
->set
.str
[STRING_KEY
]) {
390 mbedtls_ssl_conf_own_cert(&connssl
->config
,
391 &connssl
->clicert
, &connssl
->pk
);
393 if(mbedtls_ssl_set_hostname(&connssl
->ssl
, conn
->host
.name
)) {
394 /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
395 the name to set in the SNI extension. So even if curl connects to a
396 host specified as an IP address, this function must be used. */
397 failf(data
, "couldn't set hostname in mbedTLS");
398 return CURLE_SSL_CONNECT_ERROR
;
402 if(conn
->bits
.tls_enable_alpn
) {
403 const char **p
= &connssl
->protocols
[0];
405 if(data
->set
.httpversion
>= CURL_HTTP_VERSION_2
)
406 *p
++ = NGHTTP2_PROTO_VERSION_ID
;
408 *p
++ = ALPN_HTTP_1_1
;
410 /* this function doesn't clone the protocols array, which is why we need
412 if(mbedtls_ssl_conf_alpn_protocols(&connssl
->config
,
413 &connssl
->protocols
[0])) {
414 failf(data
, "Failed setting ALPN protocols");
415 return CURLE_SSL_CONNECT_ERROR
;
417 for(p
= &connssl
->protocols
[0]; *p
; ++p
)
418 infof(data
, "ALPN, offering %s\n", *p
);
423 mbedtls_ssl_conf_dbg(&connssl
->config
, mbedtls_debug
, data
);
426 connssl
->connecting_state
= ssl_connect_2
;
432 mbed_connect_step2(struct connectdata
*conn
,
436 struct SessionHandle
*data
= conn
->data
;
437 struct ssl_connect_data
* connssl
= &conn
->ssl
[sockindex
];
438 const mbedtls_x509_crt
*peercert
;
441 const char* next_protocol
;
447 conn
->recv
[sockindex
] = mbed_recv
;
448 conn
->send
[sockindex
] = mbed_send
;
450 ret
= mbedtls_ssl_handshake(&connssl
->ssl
);
452 if(ret
== MBEDTLS_ERR_SSL_WANT_READ
) {
453 connssl
->connecting_state
= ssl_connect_2_reading
;
456 else if(ret
== MBEDTLS_ERR_SSL_WANT_WRITE
) {
457 connssl
->connecting_state
= ssl_connect_2_writing
;
461 #ifdef MBEDTLS_ERROR_C
462 mbedtls_strerror(ret
, errorbuf
, sizeof(errorbuf
));
463 #endif /* MBEDTLS_ERROR_C */
464 failf(data
, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
466 return CURLE_SSL_CONNECT_ERROR
;
469 infof(data
, "mbedTLS: Handshake complete, cipher is %s\n",
470 mbedtls_ssl_get_ciphersuite(&conn
->ssl
[sockindex
].ssl
)
473 ret
= mbedtls_ssl_get_verify_result(&conn
->ssl
[sockindex
].ssl
);
475 if(ret
&& data
->set
.ssl
.verifypeer
) {
476 if(ret
& MBEDTLS_X509_BADCERT_EXPIRED
)
477 failf(data
, "Cert verify failed: BADCERT_EXPIRED");
479 if(ret
& MBEDTLS_X509_BADCERT_REVOKED
) {
480 failf(data
, "Cert verify failed: BADCERT_REVOKED");
481 return CURLE_SSL_CACERT
;
484 if(ret
& MBEDTLS_X509_BADCERT_CN_MISMATCH
)
485 failf(data
, "Cert verify failed: BADCERT_CN_MISMATCH");
487 if(ret
& MBEDTLS_X509_BADCERT_NOT_TRUSTED
)
488 failf(data
, "Cert verify failed: BADCERT_NOT_TRUSTED");
490 return CURLE_PEER_FAILED_VERIFICATION
;
493 peercert
= mbedtls_ssl_get_peer_cert(&connssl
->ssl
);
495 if(peercert
&& data
->set
.verbose
) {
496 const size_t bufsize
= 16384;
497 char *buffer
= malloc(bufsize
);
500 return CURLE_OUT_OF_MEMORY
;
502 if(mbedtls_x509_crt_info(buffer
, bufsize
, "* ", peercert
) > 0)
503 infof(data
, "Dumping cert info:\n%s\n", buffer
);
505 infof(data
, "Unable to dump certificate information.\n");
510 if(data
->set
.str
[STRING_SSL_PINNEDPUBLICKEY
]) {
514 unsigned char pubkey
[PUB_DER_MAX_BYTES
];
516 if(!peercert
|| !peercert
->raw
.p
|| !peercert
->raw
.len
) {
517 failf(data
, "Failed due to missing peer certificate");
518 return CURLE_SSL_PINNEDPUBKEYNOTMATCH
;
521 p
= calloc(1, sizeof(*p
));
524 return CURLE_OUT_OF_MEMORY
;
526 mbedtls_x509_crt_init(p
);
528 /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
529 needs a non-const key, for now.
530 https://github.com/ARMmbed/mbedtls/issues/396 */
531 if(mbedtls_x509_crt_parse_der(p
, peercert
->raw
.p
, peercert
->raw
.len
)) {
532 failf(data
, "Failed copying peer certificate");
533 mbedtls_x509_crt_free(p
);
535 return CURLE_SSL_PINNEDPUBKEYNOTMATCH
;
538 size
= mbedtls_pk_write_pubkey_der(&p
->pk
, pubkey
, PUB_DER_MAX_BYTES
);
541 failf(data
, "Failed copying public key from peer certificate");
542 mbedtls_x509_crt_free(p
);
544 return CURLE_SSL_PINNEDPUBKEYNOTMATCH
;
547 /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
548 result
= Curl_pin_peer_pubkey(data
,
549 data
->set
.str
[STRING_SSL_PINNEDPUBLICKEY
],
550 &pubkey
[PUB_DER_MAX_BYTES
- size
], size
);
552 mbedtls_x509_crt_free(p
);
557 mbedtls_x509_crt_free(p
);
562 if(conn
->bits
.tls_enable_alpn
) {
563 next_protocol
= mbedtls_ssl_get_alpn_protocol(&connssl
->ssl
);
566 infof(data
, "ALPN, server accepted to use %s\n", next_protocol
);
568 if(!strncmp(next_protocol
, NGHTTP2_PROTO_VERSION_ID
,
569 NGHTTP2_PROTO_VERSION_ID_LEN
) &&
570 !next_protocol
[NGHTTP2_PROTO_VERSION_ID_LEN
]) {
571 conn
->negnpn
= CURL_HTTP_VERSION_2
;
575 if(!strncmp(next_protocol
, ALPN_HTTP_1_1
, ALPN_HTTP_1_1_LENGTH
) &&
576 !next_protocol
[ALPN_HTTP_1_1_LENGTH
]) {
577 conn
->negnpn
= CURL_HTTP_VERSION_1_1
;
581 infof(data
, "ALPN, server did not agree to a protocol\n");
586 connssl
->connecting_state
= ssl_connect_3
;
587 infof(data
, "SSL connected\n");
593 mbed_connect_step3(struct connectdata
*conn
,
596 CURLcode retcode
= CURLE_OK
;
597 struct ssl_connect_data
*connssl
= &conn
->ssl
[sockindex
];
598 struct SessionHandle
*data
= conn
->data
;
599 void *old_ssl_sessionid
= NULL
;
600 mbedtls_ssl_session
*our_ssl_sessionid
;
603 DEBUGASSERT(ssl_connect_3
== connssl
->connecting_state
);
605 our_ssl_sessionid
= malloc(sizeof(mbedtls_ssl_session
));
606 if(!our_ssl_sessionid
)
607 return CURLE_OUT_OF_MEMORY
;
609 mbedtls_ssl_session_init(our_ssl_sessionid
);
611 ret
= mbedtls_ssl_get_session(&connssl
->ssl
, our_ssl_sessionid
);
613 failf(data
, "mbedtls_ssl_get_session returned -0x%x", -ret
);
614 return CURLE_SSL_CONNECT_ERROR
;
617 /* If there's already a matching session in the cache, delete it */
618 if(!Curl_ssl_getsessionid(conn
, &old_ssl_sessionid
, NULL
))
619 Curl_ssl_delsessionid(conn
, old_ssl_sessionid
);
621 retcode
= Curl_ssl_addsessionid(conn
, our_ssl_sessionid
, 0);
623 free(our_ssl_sessionid
);
624 failf(data
, "failed to store ssl session");
628 connssl
->connecting_state
= ssl_connect_done
;
633 static ssize_t
mbed_send(struct connectdata
*conn
, int sockindex
,
634 const void *mem
, size_t len
,
639 ret
= mbedtls_ssl_write(&conn
->ssl
[sockindex
].ssl
,
640 (unsigned char *)mem
, len
);
643 *curlcode
= (ret
== MBEDTLS_ERR_SSL_WANT_WRITE
) ?
644 CURLE_AGAIN
: CURLE_SEND_ERROR
;
651 void Curl_mbedtls_close_all(struct SessionHandle
*data
)
656 void Curl_mbedtls_close(struct connectdata
*conn
, int sockindex
)
658 mbedtls_pk_free(&conn
->ssl
[sockindex
].pk
);
659 mbedtls_x509_crt_free(&conn
->ssl
[sockindex
].clicert
);
660 mbedtls_x509_crt_free(&conn
->ssl
[sockindex
].cacert
);
661 mbedtls_x509_crl_free(&conn
->ssl
[sockindex
].crl
);
662 mbedtls_ssl_config_free(&conn
->ssl
[sockindex
].config
);
663 mbedtls_ssl_free(&conn
->ssl
[sockindex
].ssl
);
664 mbedtls_ctr_drbg_free(&conn
->ssl
[sockindex
].ctr_drbg
);
665 #ifndef THREADING_SUPPORT
666 mbedtls_entropy_free(&conn
->ssl
[sockindex
].entropy
);
667 #endif /* THREADING_SUPPORT */
670 static ssize_t
mbed_recv(struct connectdata
*conn
, int num
,
671 char *buf
, size_t buffersize
,
677 memset(buf
, 0, buffersize
);
678 ret
= mbedtls_ssl_read(&conn
->ssl
[num
].ssl
, (unsigned char *)buf
,
682 if(ret
== MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY
)
685 *curlcode
= (ret
== MBEDTLS_ERR_SSL_WANT_READ
) ?
686 CURLE_AGAIN
: CURLE_RECV_ERROR
;
695 void Curl_mbedtls_session_free(void *ptr
)
697 mbedtls_ssl_session_free(ptr
);
701 size_t Curl_mbedtls_version(char *buffer
, size_t size
)
703 unsigned int version
= mbedtls_version_get_number();
704 return snprintf(buffer
, size
, "mbedTLS/%d.%d.%d", version
>>24,
705 (version
>>16)&0xff, (version
>>8)&0xff);
709 mbed_connect_common(struct connectdata
*conn
,
715 struct SessionHandle
*data
= conn
->data
;
716 struct ssl_connect_data
*connssl
= &conn
->ssl
[sockindex
];
717 curl_socket_t sockfd
= conn
->sock
[sockindex
];
721 /* check if the connection has already been established */
722 if(ssl_connection_complete
== connssl
->state
) {
727 if(ssl_connect_1
==connssl
->connecting_state
) {
728 /* Find out how much more time we're allowed */
729 timeout_ms
= Curl_timeleft(data
, NULL
, TRUE
);
732 /* no need to continue if time already is up */
733 failf(data
, "SSL connection timeout");
734 return CURLE_OPERATION_TIMEDOUT
;
736 retcode
= mbed_connect_step1(conn
, sockindex
);
741 while(ssl_connect_2
== connssl
->connecting_state
||
742 ssl_connect_2_reading
== connssl
->connecting_state
||
743 ssl_connect_2_writing
== connssl
->connecting_state
) {
745 /* check allowed time left */
746 timeout_ms
= Curl_timeleft(data
, NULL
, TRUE
);
749 /* no need to continue if time already is up */
750 failf(data
, "SSL connection timeout");
751 return CURLE_OPERATION_TIMEDOUT
;
754 /* if ssl is expecting something, check if it's available. */
755 if(connssl
->connecting_state
== ssl_connect_2_reading
756 || connssl
->connecting_state
== ssl_connect_2_writing
) {
758 curl_socket_t writefd
= ssl_connect_2_writing
==
759 connssl
->connecting_state
?sockfd
:CURL_SOCKET_BAD
;
760 curl_socket_t readfd
= ssl_connect_2_reading
==
761 connssl
->connecting_state
?sockfd
:CURL_SOCKET_BAD
;
763 what
= Curl_socket_ready(readfd
, writefd
, nonblocking
? 0 : timeout_ms
);
766 failf(data
, "select/poll on SSL socket, errno: %d", SOCKERRNO
);
767 return CURLE_SSL_CONNECT_ERROR
;
776 failf(data
, "SSL connection timeout");
777 return CURLE_OPERATION_TIMEDOUT
;
780 /* socket is readable or writable */
783 /* Run transaction, and return to the caller if it failed or if
784 * this connection is part of a multi handle and this loop would
785 * execute again. This permits the owner of a multi handle to
786 * abort a connection attempt before step2 has completed while
787 * ensuring that a client using select() or epoll() will always
788 * have a valid fdset to wait on.
790 retcode
= mbed_connect_step2(conn
, sockindex
);
791 if(retcode
|| (nonblocking
&&
792 (ssl_connect_2
== connssl
->connecting_state
||
793 ssl_connect_2_reading
== connssl
->connecting_state
||
794 ssl_connect_2_writing
== connssl
->connecting_state
)))
797 } /* repeat step2 until all transactions are done. */
799 if(ssl_connect_3
==connssl
->connecting_state
) {
800 retcode
= mbed_connect_step3(conn
, sockindex
);
805 if(ssl_connect_done
==connssl
->connecting_state
) {
806 connssl
->state
= ssl_connection_complete
;
807 conn
->recv
[sockindex
] = mbed_recv
;
808 conn
->send
[sockindex
] = mbed_send
;
814 /* Reset our connect state machine */
815 connssl
->connecting_state
= ssl_connect_1
;
821 Curl_mbedtls_connect_nonblocking(struct connectdata
*conn
,
825 return mbed_connect_common(conn
, sockindex
, TRUE
, done
);
830 Curl_mbedtls_connect(struct connectdata
*conn
,
836 retcode
= mbed_connect_common(conn
, sockindex
, FALSE
, &done
);
846 * return 0 error initializing SSL
847 * return 1 SSL initialized successfully
849 int Curl_mbedtls_init(void)
851 return Curl_polarsslthreadlock_thread_setup();
854 void Curl_mbedtls_cleanup(void)
856 (void)Curl_polarsslthreadlock_thread_cleanup();
859 int Curl_mbedtls_data_pending(const struct connectdata
*conn
, int sockindex
)
861 mbedtls_ssl_context
*ssl
=
862 (mbedtls_ssl_context
*)&conn
->ssl
[sockindex
].ssl
;
863 return ssl
->in_msglen
!= 0;
866 #endif /* USE_MBEDTLS */