34 #include <mbedtls/version.h> 35 #if MBEDTLS_VERSION_NUMBER >= 0x02040000 36 #include <mbedtls/net_sockets.h> 38 #include <mbedtls/net.h> 40 #include <mbedtls/ssl.h> 41 #include <mbedtls/certs.h> 42 #include <mbedtls/x509.h> 44 #include <mbedtls/error.h> 45 #include <mbedtls/entropy.h> 46 #include <mbedtls/ctr_drbg.h> 47 #include <mbedtls/sha256.h> 64 struct ssl_backend_data {
65 mbedtls_ctr_drbg_context ctr_drbg;
66 mbedtls_entropy_context entropy;
67 mbedtls_ssl_context ssl;
69 mbedtls_x509_crt cacert;
70 mbedtls_x509_crt clicert;
72 mbedtls_pk_context pk;
77 #define BACKEND connssl->backend 80 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) 81 #define THREADING_SUPPORT 84 #if defined(THREADING_SUPPORT) 85 static mbedtls_entropy_context ts_entropy;
87 static int entropy_init_initialized = 0;
90 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
93 Curl_polarsslthreadlock_lock_function(0);
94 if(entropy_init_initialized == 0) {
95 mbedtls_entropy_init(ctx);
96 entropy_init_initialized = 1;
98 Curl_polarsslthreadlock_unlock_function(0);
103 static int entropy_func_mutex(
void *
data,
unsigned char *
output,
size_t len)
107 Curl_polarsslthreadlock_lock_function(1);
108 ret = mbedtls_entropy_func(data, output, len);
109 Curl_polarsslthreadlock_unlock_function(1);
121 static void mbed_debug(
void *context,
int level,
const char *f_name,
122 int line_nb,
const char *line)
131 infof(data,
"%s", line);
140 # ifdef MBEDTLS_SSL_ALPN 149 static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
152 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
153 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
154 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
155 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
156 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
157 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
166 #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) 167 #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) 169 #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ 170 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) 175 static CURLcode mbedtls_version_from_curl(
int *mbedver,
long version)
179 *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
182 *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
185 *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
194 set_ssl_version_min_max(
struct connectdata *conn,
int sockindex)
198 int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
199 int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
204 switch(ssl_version) {
212 switch(ssl_version_max) {
214 ssl_version_max = ssl_version << 16;
221 result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
223 failf(data,
"unsupported min version passed via CURLOPT_SSLVERSION");
226 result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
228 failf(data,
"unsupported max version passed via CURLOPT_SSLVERSION");
232 mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
234 mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
260 failf(data,
"mbedTLS does not support SSLv2");
264 #ifdef THREADING_SUPPORT 265 entropy_init_mutex(&ts_entropy);
266 mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
268 ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex,
269 &ts_entropy, NULL, 0);
271 #ifdef MBEDTLS_ERROR_C 272 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
274 failf(data,
"Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
278 mbedtls_entropy_init(&BACKEND->entropy);
279 mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
281 ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
282 &BACKEND->entropy, NULL, 0);
284 #ifdef MBEDTLS_ERROR_C 285 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
287 failf(data,
"Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
293 mbedtls_x509_crt_init(&BACKEND->cacert);
296 ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile);
299 #ifdef MBEDTLS_ERROR_C 300 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
302 failf(data,
"Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
303 ssl_cafile, -ret, errorbuf);
311 ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath);
314 #ifdef MBEDTLS_ERROR_C 315 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
317 failf(data,
"Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
318 ssl_capath, -ret, errorbuf);
326 mbedtls_x509_crt_init(&BACKEND->clicert);
329 ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert);
332 #ifdef MBEDTLS_ERROR_C 333 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
335 failf(data,
"Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
336 ssl_cert, -ret, errorbuf);
343 mbedtls_pk_init(&BACKEND->pk);
348 if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
349 ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
352 #ifdef MBEDTLS_ERROR_C 353 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
355 failf(data,
"Error reading private key %s - mbedTLS: (-0x%04X) %s",
363 mbedtls_x509_crl_init(&BACKEND->crl);
366 ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile);
369 #ifdef MBEDTLS_ERROR_C 370 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
372 failf(data,
"Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
373 ssl_crlfile, -ret, errorbuf);
379 infof(data,
"mbedTLS: Connecting to %s:%d\n", hostname, port);
381 mbedtls_ssl_config_init(&BACKEND->config);
383 mbedtls_ssl_init(&BACKEND->ssl);
384 if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
385 failf(data,
"mbedTLS: ssl_init failed");
388 ret = mbedtls_ssl_config_defaults(&BACKEND->config,
389 MBEDTLS_SSL_IS_CLIENT,
390 MBEDTLS_SSL_TRANSPORT_STREAM,
391 MBEDTLS_SSL_PRESET_DEFAULT);
393 failf(data,
"mbedTLS: ssl_config failed");
398 mbedtls_ssl_conf_cert_profile(&BACKEND->config,
399 &mbedtls_x509_crt_profile_fr);
404 mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
405 MBEDTLS_SSL_MINOR_VERSION_1);
406 infof(data,
"mbedTLS: Set min SSL version to TLS 1.0\n");
409 mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
410 MBEDTLS_SSL_MINOR_VERSION_0);
411 mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
412 MBEDTLS_SSL_MINOR_VERSION_0);
413 infof(data,
"mbedTLS: Set SSL version to SSLv3\n");
420 CURLcode result = set_ssl_version_min_max(conn, sockindex);
426 failf(data,
"Unrecognized parameter passed via CURLOPT_SSLVERSION");
430 mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
432 mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
434 mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->
sock[sockindex],
439 mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
440 mbedtls_ssl_list_ciphersuites());
442 #if defined(MBEDTLS_SSL_RENEGOTIATION) 443 mbedtls_ssl_conf_renegotiation(&BACKEND->config,
444 MBEDTLS_SSL_RENEGOTIATION_ENABLED);
447 #if defined(MBEDTLS_SSL_SESSION_TICKETS) 448 mbedtls_ssl_conf_session_tickets(&BACKEND->config,
449 MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
454 void *old_session = NULL;
456 Curl_ssl_sessionid_lock(conn);
457 if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
458 ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session);
460 Curl_ssl_sessionid_unlock(conn);
461 failf(data,
"mbedtls_ssl_set_session returned -0x%x", -ret);
464 infof(data,
"mbedTLS re-using session\n");
466 Curl_ssl_sessionid_unlock(conn);
469 mbedtls_ssl_conf_ca_chain(&BACKEND->config,
474 mbedtls_ssl_conf_own_cert(&BACKEND->config,
475 &BACKEND->clicert, &BACKEND->pk);
477 if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) {
481 failf(data,
"couldn't set hostname in mbedTLS");
487 const char **
p = &BACKEND->protocols[0];
490 *p++ = NGHTTP2_PROTO_VERSION_ID;
496 if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
497 &BACKEND->protocols[0])) {
498 failf(data,
"Failed setting ALPN protocols");
501 for(p = &BACKEND->protocols[0]; *p; ++p)
502 infof(data,
"ALPN, offering %s\n", *p);
508 mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data);
515 mbedtls_debug_set_threshold(4);
523 failf(data,
"error signaled by ssl ctx callback");
540 const mbedtls_x509_crt *peercert;
546 const char *next_protocol;
552 conn->
recv[sockindex] = mbed_recv;
553 conn->
send[sockindex] = mbed_send;
555 ret = mbedtls_ssl_handshake(&BACKEND->ssl);
557 if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
561 else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
566 #ifdef MBEDTLS_ERROR_C 567 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
569 failf(data,
"ssl_handshake returned - mbedTLS: (-0x%04X) %s",
574 infof(data,
"mbedTLS: Handshake complete, cipher is %s\n",
575 mbedtls_ssl_get_ciphersuite(&BACKEND->ssl)
578 ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl);
581 if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
582 failf(data,
"Cert verify failed: BADCERT_EXPIRED");
584 if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
585 failf(data,
"Cert verify failed: BADCERT_REVOKED");
589 if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
590 failf(data,
"Cert verify failed: BADCERT_CN_MISMATCH");
592 if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
593 failf(data,
"Cert verify failed: BADCERT_NOT_TRUSTED");
598 peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl);
601 const size_t bufsize = 16384;
607 if(mbedtls_x509_crt_info(buffer, bufsize,
"* ", peercert) > 0)
608 infof(data,
"Dumping cert info:\n%s\n", buffer);
610 infof(data,
"Unable to dump certificate information.\n");
619 unsigned char pubkey[PUB_DER_MAX_BYTES];
621 if(!peercert || !peercert->raw.p || !peercert->raw.len) {
622 failf(data,
"Failed due to missing peer certificate");
626 p =
calloc(1,
sizeof(*p));
631 mbedtls_x509_crt_init(p);
636 if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
637 failf(data,
"Failed copying peer certificate");
638 mbedtls_x509_crt_free(p);
643 size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
646 failf(data,
"Failed copying public key from peer certificate");
647 mbedtls_x509_crt_free(p);
653 result = Curl_pin_peer_pubkey(data,
655 &pubkey[PUB_DER_MAX_BYTES - size], size);
657 mbedtls_x509_crt_free(p);
662 mbedtls_x509_crt_free(p);
668 next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
671 infof(data,
"ALPN, server accepted to use %s\n", next_protocol);
673 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
674 NGHTTP2_PROTO_VERSION_ID_LEN) &&
675 !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
686 infof(data,
"ALPN, server did not agree to a protocol\n");
692 infof(data,
"SSL connected\n");
709 mbedtls_ssl_session *our_ssl_sessionid;
710 void *old_ssl_sessionid = NULL;
712 our_ssl_sessionid =
malloc(
sizeof(mbedtls_ssl_session));
713 if(!our_ssl_sessionid)
716 mbedtls_ssl_session_init(our_ssl_sessionid);
718 ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
720 free(our_ssl_sessionid);
721 failf(data,
"mbedtls_ssl_get_session returned -0x%x", -ret);
726 Curl_ssl_sessionid_lock(conn);
727 if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
728 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
730 retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
731 Curl_ssl_sessionid_unlock(conn);
733 free(our_ssl_sessionid);
734 failf(data,
"failed to store ssl session");
745 const void *mem,
size_t len,
751 ret = mbedtls_ssl_write(&BACKEND->ssl,
752 (
unsigned char *)mem, len);
755 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
763 static void Curl_mbedtls_close_all(
struct Curl_easy *data)
768 static void Curl_mbedtls_close(
struct connectdata *conn,
int sockindex)
771 mbedtls_pk_free(&BACKEND->pk);
772 mbedtls_x509_crt_free(&BACKEND->clicert);
773 mbedtls_x509_crt_free(&BACKEND->cacert);
774 mbedtls_x509_crl_free(&BACKEND->crl);
775 mbedtls_ssl_config_free(&BACKEND->config);
776 mbedtls_ssl_free(&BACKEND->ssl);
777 mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg);
778 #ifndef THREADING_SUPPORT 779 mbedtls_entropy_free(&BACKEND->entropy);
784 char *
buf,
size_t buffersize,
791 memset(buf, 0, buffersize);
792 ret = mbedtls_ssl_read(&BACKEND->ssl, (
unsigned char *)buf,
796 if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
799 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
809 static void Curl_mbedtls_session_free(
void *
ptr)
811 mbedtls_ssl_session_free(ptr);
815 static size_t Curl_mbedtls_version(
char *buffer,
size_t size)
817 unsigned int version = mbedtls_version_get_number();
818 return snprintf(buffer, size,
"mbedTLS/%d.%d.%d", version>>24,
819 (version>>16)&0xff, (version>>8)&0xff);
823 unsigned char *entropy,
size_t length)
825 #if defined(MBEDTLS_CTR_DRBG_C) 828 mbedtls_entropy_context ctr_entropy;
829 mbedtls_ctr_drbg_context ctr_drbg;
830 mbedtls_entropy_init(&ctr_entropy);
831 mbedtls_ctr_drbg_init(&ctr_drbg);
834 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
835 &ctr_entropy, NULL, 0);
838 #ifdef MBEDTLS_ERROR_C 839 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
841 failf(data,
"Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
845 ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
848 #ifdef MBEDTLS_ERROR_C 849 mbedtls_strerror(ret, errorbuf,
sizeof(errorbuf));
851 failf(data,
"mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
856 mbedtls_ctr_drbg_free(&ctr_drbg);
857 mbedtls_entropy_free(&ctr_entropy);
860 #elif defined(MBEDTLS_HAVEGE_C) 861 mbedtls_havege_state hs;
862 mbedtls_havege_init(&hs);
863 mbedtls_havege_random(&hs, entropy, length);
864 mbedtls_havege_free(&hs);
896 failf(data,
"SSL connection timeout");
899 retcode = mbed_connect_step1(conn, sockindex);
913 failf(data,
"SSL connection timeout");
927 nonblocking ? 0 : timeout_ms);
940 failf(data,
"SSL connection timeout");
954 retcode = mbed_connect_step2(conn, sockindex);
955 if(retcode || (nonblocking &&
964 retcode = mbed_connect_step3(conn, sockindex);
971 conn->
recv[sockindex] = mbed_recv;
972 conn->
send[sockindex] = mbed_send;
985 int sockindex,
bool *done)
987 return mbed_connect_common(conn, sockindex,
TRUE, done);
996 retcode = mbed_connect_common(conn, sockindex,
FALSE, &done);
1009 static int Curl_mbedtls_init(
void)
1011 return Curl_polarsslthreadlock_thread_setup();
1014 static void Curl_mbedtls_cleanup(
void)
1016 (void)Curl_polarsslthreadlock_thread_cleanup();
1019 static bool Curl_mbedtls_data_pending(
const struct connectdata *conn,
1023 return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
1026 static void Curl_mbedtls_sha256sum(
const unsigned char *
input,
1028 unsigned char *sha256sum,
1032 mbedtls_sha256(input, inputlen, sha256sum, 0);
1039 return &BACKEND->ssl;
1042 const struct Curl_ssl Curl_ssl_mbedtls = {
1051 sizeof(
struct ssl_backend_data),
1054 Curl_mbedtls_cleanup,
1055 Curl_mbedtls_version,
1058 Curl_mbedtls_data_pending,
1059 Curl_mbedtls_random,
1061 Curl_mbedtls_connect,
1062 Curl_mbedtls_connect_nonblocking,
1063 Curl_mbedtls_get_internals,
1065 Curl_mbedtls_close_all,
1066 Curl_mbedtls_session_free,
1072 Curl_mbedtls_sha256sum
struct ssl_connect_data ssl[2]
ssize_t( Curl_recv)(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err)
#define SSL_CONN_CONFIG(var)
#define SSL_SET_OPTION(var)
ssl_connect_state connecting_state
UNITTEST_START char * ptr
static const struct Curl_handler *const protocols[]
int Curl_none_shutdown(struct connectdata *conn, int sockindex)
UNITTEST_START int result
struct ssl_config_data ssl
struct proxy_info http_proxy
ssl_connection_state state
int Curl_none_check_cxn(struct connectdata *conn)
UNITTEST_START char * output
#define ALPN_HTTP_1_1_LENGTH
time_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect)
bool Curl_none_false_start(void)
bool Curl_none_cert_status_request(void)
curl_ssl_ctx_callback fsslctx
ssize_t( Curl_send)(struct connectdata *conn, int sockindex, const void *buf, size_t len, CURLcode *err)
static unsigned short port
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, unsigned char *md5sum, size_t md5len)
int Curl_socket_check(curl_socket_t readfd0, curl_socket_t readfd1, curl_socket_t writefd, time_t timeout_ms)
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine)
struct curl_slist * Curl_none_engines_list(struct Curl_easy *data)
#define CURL_HTTP_VERSION_2
CURLcode Curl_none_set_engine_default(struct Curl_easy *data)
#define calloc(nbelem, size)