Annotation of embedaddon/curl/lib/vtls/mbedtls.c, revision 1.1
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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>