Return to mbedtls.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / vtls |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> ! 9: * Copyright (C) 2012 - 2020, 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 "mbedtls_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: /* apply threading? */ ! 79: #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) ! 80: #define THREADING_SUPPORT ! 81: #endif ! 82: ! 83: #if defined(THREADING_SUPPORT) ! 84: static mbedtls_entropy_context ts_entropy; ! 85: ! 86: static int entropy_init_initialized = 0; ! 87: ! 88: /* start of entropy_init_mutex() */ ! 89: static void entropy_init_mutex(mbedtls_entropy_context *ctx) ! 90: { ! 91: /* lock 0 = entropy_init_mutex() */ ! 92: Curl_mbedtlsthreadlock_lock_function(0); ! 93: if(entropy_init_initialized == 0) { ! 94: mbedtls_entropy_init(ctx); ! 95: entropy_init_initialized = 1; ! 96: } ! 97: Curl_mbedtlsthreadlock_unlock_function(0); ! 98: } ! 99: /* end of entropy_init_mutex() */ ! 100: ! 101: /* start of entropy_func_mutex() */ ! 102: static int entropy_func_mutex(void *data, unsigned char *output, size_t len) ! 103: { ! 104: int ret; ! 105: /* lock 1 = entropy_func_mutex() */ ! 106: Curl_mbedtlsthreadlock_lock_function(1); ! 107: ret = mbedtls_entropy_func(data, output, len); ! 108: Curl_mbedtlsthreadlock_unlock_function(1); ! 109: ! 110: return ret; ! 111: } ! 112: /* end of entropy_func_mutex() */ ! 113: ! 114: #endif /* THREADING_SUPPORT */ ! 115: ! 116: /* Define this to enable lots of debugging for mbedTLS */ ! 117: #undef MBEDTLS_DEBUG ! 118: ! 119: #ifdef MBEDTLS_DEBUG ! 120: static void mbed_debug(void *context, int level, const char *f_name, ! 121: int line_nb, const char *line) ! 122: { ! 123: struct Curl_easy *data = NULL; ! 124: ! 125: if(!context) ! 126: return; ! 127: ! 128: data = (struct Curl_easy *)context; ! 129: ! 130: infof(data, "%s", line); ! 131: (void) level; ! 132: } ! 133: #else ! 134: #endif ! 135: ! 136: /* ALPN for http2? */ ! 137: #ifdef USE_NGHTTP2 ! 138: # undef HAS_ALPN ! 139: # ifdef MBEDTLS_SSL_ALPN ! 140: # define HAS_ALPN ! 141: # endif ! 142: #endif ! 143: ! 144: ! 145: /* ! 146: * profile ! 147: */ ! 148: static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = ! 149: { ! 150: /* Hashes from SHA-1 and above */ ! 151: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | ! 152: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | ! 153: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | ! 154: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | ! 155: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | ! 156: MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), ! 157: 0xFFFFFFF, /* Any PK alg */ ! 158: 0xFFFFFFF, /* Any curve */ ! 159: 1024, /* RSA min key len */ ! 160: }; ! 161: ! 162: /* See https://tls.mbed.org/discussions/generic/ ! 163: howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der ! 164: */ ! 165: #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) ! 166: #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) ! 167: ! 168: #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ ! 169: RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) ! 170: ! 171: static Curl_recv mbed_recv; ! 172: static Curl_send mbed_send; ! 173: ! 174: static CURLcode mbedtls_version_from_curl(int *mbedver, long version) ! 175: { ! 176: switch(version) { ! 177: case CURL_SSLVERSION_TLSv1_0: ! 178: *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; ! 179: return CURLE_OK; ! 180: case CURL_SSLVERSION_TLSv1_1: ! 181: *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; ! 182: return CURLE_OK; ! 183: case CURL_SSLVERSION_TLSv1_2: ! 184: *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; ! 185: return CURLE_OK; ! 186: case CURL_SSLVERSION_TLSv1_3: ! 187: break; ! 188: } ! 189: return CURLE_SSL_CONNECT_ERROR; ! 190: } ! 191: ! 192: static CURLcode ! 193: set_ssl_version_min_max(struct connectdata *conn, int sockindex) ! 194: { ! 195: struct Curl_easy *data = conn->data; ! 196: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 197: struct ssl_backend_data *backend = connssl->backend; ! 198: int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; ! 199: int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; ! 200: long ssl_version = SSL_CONN_CONFIG(version); ! 201: long ssl_version_max = SSL_CONN_CONFIG(version_max); ! 202: CURLcode result = CURLE_OK; ! 203: ! 204: switch(ssl_version) { ! 205: case CURL_SSLVERSION_DEFAULT: ! 206: case CURL_SSLVERSION_TLSv1: ! 207: ssl_version = CURL_SSLVERSION_TLSv1_0; ! 208: break; ! 209: } ! 210: ! 211: switch(ssl_version_max) { ! 212: case CURL_SSLVERSION_MAX_NONE: ! 213: case CURL_SSLVERSION_MAX_DEFAULT: ! 214: ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; ! 215: break; ! 216: } ! 217: ! 218: result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); ! 219: if(result) { ! 220: failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); ! 221: return result; ! 222: } ! 223: result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); ! 224: if(result) { ! 225: failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); ! 226: return result; ! 227: } ! 228: ! 229: mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, ! 230: mbedtls_ver_min); ! 231: mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, ! 232: mbedtls_ver_max); ! 233: ! 234: return result; ! 235: } ! 236: ! 237: static CURLcode ! 238: mbed_connect_step1(struct connectdata *conn, ! 239: int sockindex) ! 240: { ! 241: struct Curl_easy *data = conn->data; ! 242: struct ssl_connect_data* connssl = &conn->ssl[sockindex]; ! 243: struct ssl_backend_data *backend = connssl->backend; ! 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: struct ssl_backend_data *backend = connssl->backend; ! 540: const mbedtls_x509_crt *peercert; ! 541: const char * const pinnedpubkey = SSL_IS_PROXY() ? ! 542: data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : ! 543: data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; ! 544: ! 545: conn->recv[sockindex] = mbed_recv; ! 546: conn->send[sockindex] = mbed_send; ! 547: ! 548: ret = mbedtls_ssl_handshake(&backend->ssl); ! 549: ! 550: if(ret == MBEDTLS_ERR_SSL_WANT_READ) { ! 551: connssl->connecting_state = ssl_connect_2_reading; ! 552: return CURLE_OK; ! 553: } ! 554: else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { ! 555: connssl->connecting_state = ssl_connect_2_writing; ! 556: return CURLE_OK; ! 557: } ! 558: else if(ret) { ! 559: char errorbuf[128]; ! 560: errorbuf[0] = 0; ! 561: #ifdef MBEDTLS_ERROR_C ! 562: mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); ! 563: #endif /* MBEDTLS_ERROR_C */ ! 564: failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", ! 565: -ret, errorbuf); ! 566: return CURLE_SSL_CONNECT_ERROR; ! 567: } ! 568: ! 569: infof(data, "mbedTLS: Handshake complete, cipher is %s\n", ! 570: mbedtls_ssl_get_ciphersuite(&backend->ssl) ! 571: ); ! 572: ! 573: ret = mbedtls_ssl_get_verify_result(&backend->ssl); ! 574: ! 575: if(!SSL_CONN_CONFIG(verifyhost)) ! 576: /* Ignore hostname errors if verifyhost is disabled */ ! 577: ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; ! 578: ! 579: if(ret && SSL_CONN_CONFIG(verifypeer)) { ! 580: if(ret & MBEDTLS_X509_BADCERT_EXPIRED) ! 581: failf(data, "Cert verify failed: BADCERT_EXPIRED"); ! 582: ! 583: else if(ret & MBEDTLS_X509_BADCERT_REVOKED) ! 584: failf(data, "Cert verify failed: BADCERT_REVOKED"); ! 585: ! 586: else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) ! 587: failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); ! 588: ! 589: else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) ! 590: failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); ! 591: ! 592: else if(ret & MBEDTLS_X509_BADCERT_FUTURE) ! 593: failf(data, "Cert verify failed: BADCERT_FUTURE"); ! 594: ! 595: return CURLE_PEER_FAILED_VERIFICATION; ! 596: } ! 597: ! 598: peercert = mbedtls_ssl_get_peer_cert(&backend->ssl); ! 599: ! 600: if(peercert && data->set.verbose) { ! 601: const size_t bufsize = 16384; ! 602: char *buffer = malloc(bufsize); ! 603: ! 604: if(!buffer) ! 605: return CURLE_OUT_OF_MEMORY; ! 606: ! 607: if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) ! 608: infof(data, "Dumping cert info:\n%s\n", buffer); ! 609: else ! 610: infof(data, "Unable to dump certificate information.\n"); ! 611: ! 612: free(buffer); ! 613: } ! 614: ! 615: if(pinnedpubkey) { ! 616: int size; ! 617: CURLcode result; ! 618: mbedtls_x509_crt *p; ! 619: unsigned char pubkey[PUB_DER_MAX_BYTES]; ! 620: ! 621: if(!peercert || !peercert->raw.p || !peercert->raw.len) { ! 622: failf(data, "Failed due to missing peer certificate"); ! 623: return CURLE_SSL_PINNEDPUBKEYNOTMATCH; ! 624: } ! 625: ! 626: p = calloc(1, sizeof(*p)); ! 627: ! 628: if(!p) ! 629: return CURLE_OUT_OF_MEMORY; ! 630: ! 631: mbedtls_x509_crt_init(p); ! 632: ! 633: /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der ! 634: needs a non-const key, for now. ! 635: https://github.com/ARMmbed/mbedtls/issues/396 */ ! 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); ! 639: free(p); ! 640: return CURLE_SSL_PINNEDPUBKEYNOTMATCH; ! 641: } ! 642: ! 643: size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); ! 644: ! 645: if(size <= 0) { ! 646: failf(data, "Failed copying public key from peer certificate"); ! 647: mbedtls_x509_crt_free(p); ! 648: free(p); ! 649: return CURLE_SSL_PINNEDPUBKEYNOTMATCH; ! 650: } ! 651: ! 652: /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ ! 653: result = Curl_pin_peer_pubkey(data, ! 654: pinnedpubkey, ! 655: &pubkey[PUB_DER_MAX_BYTES - size], size); ! 656: if(result) { ! 657: mbedtls_x509_crt_free(p); ! 658: free(p); ! 659: return result; ! 660: } ! 661: ! 662: mbedtls_x509_crt_free(p); ! 663: free(p); ! 664: } ! 665: ! 666: #ifdef HAS_ALPN ! 667: if(conn->bits.tls_enable_alpn) { ! 668: const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl); ! 669: ! 670: if(next_protocol) { ! 671: infof(data, "ALPN, server accepted to use %s\n", next_protocol); ! 672: #ifdef USE_NGHTTP2 ! 673: if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, ! 674: NGHTTP2_PROTO_VERSION_ID_LEN) && ! 675: !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { ! 676: conn->negnpn = CURL_HTTP_VERSION_2; ! 677: } ! 678: else ! 679: #endif ! 680: if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && ! 681: !next_protocol[ALPN_HTTP_1_1_LENGTH]) { ! 682: conn->negnpn = CURL_HTTP_VERSION_1_1; ! 683: } ! 684: } ! 685: else { ! 686: infof(data, "ALPN, server did not agree to a protocol\n"); ! 687: } ! 688: Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? ! 689: BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); ! 690: } ! 691: #endif ! 692: ! 693: connssl->connecting_state = ssl_connect_3; ! 694: infof(data, "SSL connected\n"); ! 695: ! 696: return CURLE_OK; ! 697: } ! 698: ! 699: static CURLcode ! 700: mbed_connect_step3(struct connectdata *conn, ! 701: int sockindex) ! 702: { ! 703: CURLcode retcode = CURLE_OK; ! 704: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 705: struct ssl_backend_data *backend = connssl->backend; ! 706: struct Curl_easy *data = conn->data; ! 707: ! 708: DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); ! 709: ! 710: if(SSL_SET_OPTION(primary.sessionid)) { ! 711: int ret; ! 712: mbedtls_ssl_session *our_ssl_sessionid; ! 713: void *old_ssl_sessionid = NULL; ! 714: ! 715: our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); ! 716: if(!our_ssl_sessionid) ! 717: return CURLE_OUT_OF_MEMORY; ! 718: ! 719: mbedtls_ssl_session_init(our_ssl_sessionid); ! 720: ! 721: ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid); ! 722: if(ret) { ! 723: if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) ! 724: mbedtls_ssl_session_free(our_ssl_sessionid); ! 725: free(our_ssl_sessionid); ! 726: failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); ! 727: return CURLE_SSL_CONNECT_ERROR; ! 728: } ! 729: ! 730: /* If there's already a matching session in the cache, delete it */ ! 731: Curl_ssl_sessionid_lock(conn); ! 732: if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) ! 733: Curl_ssl_delsessionid(conn, old_ssl_sessionid); ! 734: ! 735: retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); ! 736: Curl_ssl_sessionid_unlock(conn); ! 737: if(retcode) { ! 738: mbedtls_ssl_session_free(our_ssl_sessionid); ! 739: free(our_ssl_sessionid); ! 740: failf(data, "failed to store ssl session"); ! 741: return retcode; ! 742: } ! 743: } ! 744: ! 745: connssl->connecting_state = ssl_connect_done; ! 746: ! 747: return CURLE_OK; ! 748: } ! 749: ! 750: static ssize_t mbed_send(struct connectdata *conn, int sockindex, ! 751: const void *mem, size_t len, ! 752: CURLcode *curlcode) ! 753: { ! 754: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 755: struct ssl_backend_data *backend = connssl->backend; ! 756: int ret = -1; ! 757: ! 758: ret = mbedtls_ssl_write(&backend->ssl, ! 759: (unsigned char *)mem, len); ! 760: ! 761: if(ret < 0) { ! 762: *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? ! 763: CURLE_AGAIN : CURLE_SEND_ERROR; ! 764: ret = -1; ! 765: } ! 766: ! 767: return ret; ! 768: } ! 769: ! 770: static void Curl_mbedtls_close_all(struct Curl_easy *data) ! 771: { ! 772: (void)data; ! 773: } ! 774: ! 775: static void Curl_mbedtls_close(struct connectdata *conn, int sockindex) ! 776: { ! 777: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 778: struct ssl_backend_data *backend = connssl->backend; ! 779: mbedtls_pk_free(&backend->pk); ! 780: mbedtls_x509_crt_free(&backend->clicert); ! 781: mbedtls_x509_crt_free(&backend->cacert); ! 782: mbedtls_x509_crl_free(&backend->crl); ! 783: mbedtls_ssl_config_free(&backend->config); ! 784: mbedtls_ssl_free(&backend->ssl); ! 785: mbedtls_ctr_drbg_free(&backend->ctr_drbg); ! 786: #ifndef THREADING_SUPPORT ! 787: mbedtls_entropy_free(&backend->entropy); ! 788: #endif /* THREADING_SUPPORT */ ! 789: } ! 790: ! 791: static ssize_t mbed_recv(struct connectdata *conn, int num, ! 792: char *buf, size_t buffersize, ! 793: CURLcode *curlcode) ! 794: { ! 795: struct ssl_connect_data *connssl = &conn->ssl[num]; ! 796: struct ssl_backend_data *backend = connssl->backend; ! 797: int ret = -1; ! 798: ssize_t len = -1; ! 799: ! 800: memset(buf, 0, buffersize); ! 801: ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, ! 802: buffersize); ! 803: ! 804: if(ret <= 0) { ! 805: if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ! 806: return 0; ! 807: ! 808: *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? ! 809: CURLE_AGAIN : CURLE_RECV_ERROR; ! 810: return -1; ! 811: } ! 812: ! 813: len = ret; ! 814: ! 815: return len; ! 816: } ! 817: ! 818: static void Curl_mbedtls_session_free(void *ptr) ! 819: { ! 820: mbedtls_ssl_session_free(ptr); ! 821: free(ptr); ! 822: } ! 823: ! 824: static size_t Curl_mbedtls_version(char *buffer, size_t size) ! 825: { ! 826: #ifdef MBEDTLS_VERSION_C ! 827: /* if mbedtls_version_get_number() is available it is better */ ! 828: unsigned int version = mbedtls_version_get_number(); ! 829: return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, ! 830: (version>>16)&0xff, (version>>8)&0xff); ! 831: #else ! 832: return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); ! 833: #endif ! 834: } ! 835: ! 836: static CURLcode Curl_mbedtls_random(struct Curl_easy *data, ! 837: unsigned char *entropy, size_t length) ! 838: { ! 839: #if defined(MBEDTLS_CTR_DRBG_C) ! 840: int ret = -1; ! 841: char errorbuf[128]; ! 842: mbedtls_entropy_context ctr_entropy; ! 843: mbedtls_ctr_drbg_context ctr_drbg; ! 844: mbedtls_entropy_init(&ctr_entropy); ! 845: mbedtls_ctr_drbg_init(&ctr_drbg); ! 846: errorbuf[0] = 0; ! 847: ! 848: ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, ! 849: &ctr_entropy, NULL, 0); ! 850: ! 851: if(ret) { ! 852: #ifdef MBEDTLS_ERROR_C ! 853: mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); ! 854: #endif /* MBEDTLS_ERROR_C */ ! 855: failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n", ! 856: -ret, errorbuf); ! 857: } ! 858: else { ! 859: ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); ! 860: ! 861: if(ret) { ! 862: #ifdef MBEDTLS_ERROR_C ! 863: mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); ! 864: #endif /* MBEDTLS_ERROR_C */ ! 865: failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", ! 866: -ret, errorbuf); ! 867: } ! 868: } ! 869: ! 870: mbedtls_ctr_drbg_free(&ctr_drbg); ! 871: mbedtls_entropy_free(&ctr_entropy); ! 872: ! 873: return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; ! 874: #elif defined(MBEDTLS_HAVEGE_C) ! 875: mbedtls_havege_state hs; ! 876: mbedtls_havege_init(&hs); ! 877: mbedtls_havege_random(&hs, entropy, length); ! 878: mbedtls_havege_free(&hs); ! 879: return CURLE_OK; ! 880: #else ! 881: return CURLE_NOT_BUILT_IN; ! 882: #endif ! 883: } ! 884: ! 885: static CURLcode ! 886: mbed_connect_common(struct connectdata *conn, ! 887: int sockindex, ! 888: bool nonblocking, ! 889: bool *done) ! 890: { ! 891: CURLcode retcode; ! 892: struct Curl_easy *data = conn->data; ! 893: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 894: curl_socket_t sockfd = conn->sock[sockindex]; ! 895: timediff_t timeout_ms; ! 896: int what; ! 897: ! 898: /* check if the connection has already been established */ ! 899: if(ssl_connection_complete == connssl->state) { ! 900: *done = TRUE; ! 901: return CURLE_OK; ! 902: } ! 903: ! 904: if(ssl_connect_1 == connssl->connecting_state) { ! 905: /* Find out how much more time we're allowed */ ! 906: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 907: ! 908: if(timeout_ms < 0) { ! 909: /* no need to continue if time already is up */ ! 910: failf(data, "SSL connection timeout"); ! 911: return CURLE_OPERATION_TIMEDOUT; ! 912: } ! 913: retcode = mbed_connect_step1(conn, sockindex); ! 914: if(retcode) ! 915: return retcode; ! 916: } ! 917: ! 918: while(ssl_connect_2 == connssl->connecting_state || ! 919: ssl_connect_2_reading == connssl->connecting_state || ! 920: ssl_connect_2_writing == connssl->connecting_state) { ! 921: ! 922: /* check allowed time left */ ! 923: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 924: ! 925: if(timeout_ms < 0) { ! 926: /* no need to continue if time already is up */ ! 927: failf(data, "SSL connection timeout"); ! 928: return CURLE_OPERATION_TIMEDOUT; ! 929: } ! 930: ! 931: /* if ssl is expecting something, check if it's available. */ ! 932: if(connssl->connecting_state == ssl_connect_2_reading ! 933: || connssl->connecting_state == ssl_connect_2_writing) { ! 934: ! 935: curl_socket_t writefd = ssl_connect_2_writing == ! 936: connssl->connecting_state?sockfd:CURL_SOCKET_BAD; ! 937: curl_socket_t readfd = ssl_connect_2_reading == ! 938: connssl->connecting_state?sockfd:CURL_SOCKET_BAD; ! 939: ! 940: what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, ! 941: nonblocking ? 0 : (time_t)timeout_ms); ! 942: if(what < 0) { ! 943: /* fatal error */ ! 944: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); ! 945: return CURLE_SSL_CONNECT_ERROR; ! 946: } ! 947: else if(0 == what) { ! 948: if(nonblocking) { ! 949: *done = FALSE; ! 950: return CURLE_OK; ! 951: } ! 952: else { ! 953: /* timeout */ ! 954: failf(data, "SSL connection timeout"); ! 955: return CURLE_OPERATION_TIMEDOUT; ! 956: } ! 957: } ! 958: /* socket is readable or writable */ ! 959: } ! 960: ! 961: /* Run transaction, and return to the caller if it failed or if ! 962: * this connection is part of a multi handle and this loop would ! 963: * execute again. This permits the owner of a multi handle to ! 964: * abort a connection attempt before step2 has completed while ! 965: * ensuring that a client using select() or epoll() will always ! 966: * have a valid fdset to wait on. ! 967: */ ! 968: retcode = mbed_connect_step2(conn, sockindex); ! 969: if(retcode || (nonblocking && ! 970: (ssl_connect_2 == connssl->connecting_state || ! 971: ssl_connect_2_reading == connssl->connecting_state || ! 972: ssl_connect_2_writing == connssl->connecting_state))) ! 973: return retcode; ! 974: ! 975: } /* repeat step2 until all transactions are done. */ ! 976: ! 977: if(ssl_connect_3 == connssl->connecting_state) { ! 978: retcode = mbed_connect_step3(conn, sockindex); ! 979: if(retcode) ! 980: return retcode; ! 981: } ! 982: ! 983: if(ssl_connect_done == connssl->connecting_state) { ! 984: connssl->state = ssl_connection_complete; ! 985: conn->recv[sockindex] = mbed_recv; ! 986: conn->send[sockindex] = mbed_send; ! 987: *done = TRUE; ! 988: } ! 989: else ! 990: *done = FALSE; ! 991: ! 992: /* Reset our connect state machine */ ! 993: connssl->connecting_state = ssl_connect_1; ! 994: ! 995: return CURLE_OK; ! 996: } ! 997: ! 998: static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn, ! 999: int sockindex, bool *done) ! 1000: { ! 1001: return mbed_connect_common(conn, sockindex, TRUE, done); ! 1002: } ! 1003: ! 1004: ! 1005: static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex) ! 1006: { ! 1007: CURLcode retcode; ! 1008: bool done = FALSE; ! 1009: ! 1010: retcode = mbed_connect_common(conn, sockindex, FALSE, &done); ! 1011: if(retcode) ! 1012: return retcode; ! 1013: ! 1014: DEBUGASSERT(done); ! 1015: ! 1016: return CURLE_OK; ! 1017: } ! 1018: ! 1019: /* ! 1020: * return 0 error initializing SSL ! 1021: * return 1 SSL initialized successfully ! 1022: */ ! 1023: static int Curl_mbedtls_init(void) ! 1024: { ! 1025: return Curl_mbedtlsthreadlock_thread_setup(); ! 1026: } ! 1027: ! 1028: static void Curl_mbedtls_cleanup(void) ! 1029: { ! 1030: (void)Curl_mbedtlsthreadlock_thread_cleanup(); ! 1031: } ! 1032: ! 1033: static bool Curl_mbedtls_data_pending(const struct connectdata *conn, ! 1034: int sockindex) ! 1035: { ! 1036: const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 1037: struct ssl_backend_data *backend = connssl->backend; ! 1038: return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0; ! 1039: } ! 1040: ! 1041: static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, ! 1042: size_t inputlen, ! 1043: unsigned char *sha256sum, ! 1044: size_t sha256len UNUSED_PARAM) ! 1045: { ! 1046: (void)sha256len; ! 1047: #if MBEDTLS_VERSION_NUMBER < 0x02070000 ! 1048: mbedtls_sha256(input, inputlen, sha256sum, 0); ! 1049: #else ! 1050: /* returns 0 on success, otherwise failure */ ! 1051: if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) ! 1052: return CURLE_BAD_FUNCTION_ARGUMENT; ! 1053: #endif ! 1054: return CURLE_OK; ! 1055: } ! 1056: ! 1057: static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl, ! 1058: CURLINFO info UNUSED_PARAM) ! 1059: { ! 1060: struct ssl_backend_data *backend = connssl->backend; ! 1061: (void)info; ! 1062: return &backend->ssl; ! 1063: } ! 1064: ! 1065: const struct Curl_ssl Curl_ssl_mbedtls = { ! 1066: { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ ! 1067: ! 1068: SSLSUPP_CA_PATH | ! 1069: SSLSUPP_PINNEDPUBKEY | ! 1070: SSLSUPP_SSL_CTX, ! 1071: ! 1072: sizeof(struct ssl_backend_data), ! 1073: ! 1074: Curl_mbedtls_init, /* init */ ! 1075: Curl_mbedtls_cleanup, /* cleanup */ ! 1076: Curl_mbedtls_version, /* version */ ! 1077: Curl_none_check_cxn, /* check_cxn */ ! 1078: Curl_none_shutdown, /* shutdown */ ! 1079: Curl_mbedtls_data_pending, /* data_pending */ ! 1080: Curl_mbedtls_random, /* random */ ! 1081: Curl_none_cert_status_request, /* cert_status_request */ ! 1082: Curl_mbedtls_connect, /* connect */ ! 1083: Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */ ! 1084: Curl_mbedtls_get_internals, /* get_internals */ ! 1085: Curl_mbedtls_close, /* close_one */ ! 1086: Curl_mbedtls_close_all, /* close_all */ ! 1087: Curl_mbedtls_session_free, /* session_free */ ! 1088: Curl_none_set_engine, /* set_engine */ ! 1089: Curl_none_set_engine_default, /* set_engine_default */ ! 1090: Curl_none_engines_list, /* engines_list */ ! 1091: Curl_none_false_start, /* false_start */ ! 1092: Curl_none_md5sum, /* md5sum */ ! 1093: Curl_mbedtls_sha256sum /* sha256sum */ ! 1094: }; ! 1095: ! 1096: #endif /* USE_MBEDTLS */