00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "curl_setup.h"
00031
00032 #ifdef USE_MBEDTLS
00033
00034 #include <mbedtls/version.h>
00035 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
00036 #include <mbedtls/net_sockets.h>
00037 #else
00038 #include <mbedtls/net.h>
00039 #endif
00040 #include <mbedtls/ssl.h>
00041 #include <mbedtls/certs.h>
00042 #include <mbedtls/x509.h>
00043
00044 #include <mbedtls/error.h>
00045 #include <mbedtls/entropy.h>
00046 #include <mbedtls/ctr_drbg.h>
00047 #include <mbedtls/sha256.h>
00048
00049 #include "urldata.h"
00050 #include "sendf.h"
00051 #include "inet_pton.h"
00052 #include "mbedtls.h"
00053 #include "vtls.h"
00054 #include "parsedate.h"
00055 #include "connect.h"
00056 #include "select.h"
00057 #include "polarssl_threadlock.h"
00058
00059
00060 #include "curl_printf.h"
00061 #include "curl_memory.h"
00062 #include "memdebug.h"
00063
00064
00065 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
00066 #define THREADING_SUPPORT
00067 #endif
00068
00069 #if defined(THREADING_SUPPORT)
00070 static mbedtls_entropy_context entropy;
00071
00072 static int entropy_init_initialized = 0;
00073
00074
00075 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
00076 {
00077
00078 Curl_polarsslthreadlock_lock_function(0);
00079 if(entropy_init_initialized == 0) {
00080 mbedtls_entropy_init(ctx);
00081 entropy_init_initialized = 1;
00082 }
00083 Curl_polarsslthreadlock_unlock_function(0);
00084 }
00085
00086
00087
00088 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
00089 {
00090 int ret;
00091
00092 Curl_polarsslthreadlock_lock_function(1);
00093 ret = mbedtls_entropy_func(data, output, len);
00094 Curl_polarsslthreadlock_unlock_function(1);
00095
00096 return ret;
00097 }
00098
00099
00100 #endif
00101
00102
00103 #undef MBEDTLS_DEBUG
00104
00105 #ifdef MBEDTLS_DEBUG
00106 static void mbed_debug(void *context, int level, const char *f_name,
00107 int line_nb, const char *line)
00108 {
00109 struct Curl_easy *data = NULL;
00110
00111 if(!context)
00112 return;
00113
00114 data = (struct Curl_easy *)context;
00115
00116 infof(data, "%s", line);
00117 (void) level;
00118 }
00119 #else
00120 #endif
00121
00122
00123 #ifdef USE_NGHTTP2
00124 # undef HAS_ALPN
00125 # ifdef MBEDTLS_SSL_ALPN
00126 # define HAS_ALPN
00127 # endif
00128 #endif
00129
00130
00131
00132
00133
00134 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
00135 {
00136
00137 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
00138 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
00139 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
00140 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
00141 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
00142 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
00143 0xFFFFFFF,
00144 0xFFFFFFF,
00145 1024,
00146 };
00147
00148
00149
00150
00151 #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
00152 #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
00153
00154 #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
00155 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
00156
00157 static Curl_recv mbed_recv;
00158 static Curl_send mbed_send;
00159
00160 static CURLcode
00161 mbed_connect_step1(struct connectdata *conn,
00162 int sockindex)
00163 {
00164 struct Curl_easy *data = conn->data;
00165 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
00166 const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
00167 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
00168 const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
00169 char * const ssl_cert = SSL_SET_OPTION(cert);
00170 const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
00171 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00172 conn->host.name;
00173 const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
00174 int ret = -1;
00175 char errorbuf[128];
00176 errorbuf[0]=0;
00177
00178
00179 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
00180 failf(data, "mbedTLS does not support SSLv2");
00181 return CURLE_SSL_CONNECT_ERROR;
00182 }
00183
00184 #ifdef THREADING_SUPPORT
00185 entropy_init_mutex(&entropy);
00186 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
00187
00188 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
00189 &entropy, NULL, 0);
00190 if(ret) {
00191 #ifdef MBEDTLS_ERROR_C
00192 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00193 #endif
00194 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
00195 -ret, errorbuf);
00196 }
00197 #else
00198 mbedtls_entropy_init(&connssl->entropy);
00199 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
00200
00201 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
00202 &connssl->entropy, NULL, 0);
00203 if(ret) {
00204 #ifdef MBEDTLS_ERROR_C
00205 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00206 #endif
00207 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
00208 -ret, errorbuf);
00209 }
00210 #endif
00211
00212
00213 mbedtls_x509_crt_init(&connssl->cacert);
00214
00215 if(ssl_cafile) {
00216 ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
00217
00218 if(ret<0) {
00219 #ifdef MBEDTLS_ERROR_C
00220 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00221 #endif
00222 failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
00223 ssl_cafile, -ret, errorbuf);
00224
00225 if(verifypeer)
00226 return CURLE_SSL_CACERT_BADFILE;
00227 }
00228 }
00229
00230 if(ssl_capath) {
00231 ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
00232
00233 if(ret<0) {
00234 #ifdef MBEDTLS_ERROR_C
00235 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00236 #endif
00237 failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
00238 ssl_capath, -ret, errorbuf);
00239
00240 if(verifypeer)
00241 return CURLE_SSL_CACERT_BADFILE;
00242 }
00243 }
00244
00245
00246 mbedtls_x509_crt_init(&connssl->clicert);
00247
00248 if(ssl_cert) {
00249 ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
00250
00251 if(ret) {
00252 #ifdef MBEDTLS_ERROR_C
00253 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00254 #endif
00255 failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
00256 ssl_cert, -ret, errorbuf);
00257
00258 return CURLE_SSL_CERTPROBLEM;
00259 }
00260 }
00261
00262
00263 mbedtls_pk_init(&connssl->pk);
00264
00265 if(SSL_SET_OPTION(key)) {
00266 ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
00267 SSL_SET_OPTION(key_passwd));
00268 if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
00269 ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
00270
00271 if(ret) {
00272 #ifdef MBEDTLS_ERROR_C
00273 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00274 #endif
00275 failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
00276 SSL_SET_OPTION(key), -ret, errorbuf);
00277
00278 return CURLE_SSL_CERTPROBLEM;
00279 }
00280 }
00281
00282
00283 mbedtls_x509_crl_init(&connssl->crl);
00284
00285 if(ssl_crlfile) {
00286 ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
00287
00288 if(ret) {
00289 #ifdef MBEDTLS_ERROR_C
00290 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00291 #endif
00292 failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
00293 ssl_crlfile, -ret, errorbuf);
00294
00295 return CURLE_SSL_CRL_BADFILE;
00296 }
00297 }
00298
00299 infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
00300
00301 mbedtls_ssl_config_init(&connssl->config);
00302
00303 mbedtls_ssl_init(&connssl->ssl);
00304 if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
00305 failf(data, "mbedTLS: ssl_init failed");
00306 return CURLE_SSL_CONNECT_ERROR;
00307 }
00308 ret = mbedtls_ssl_config_defaults(&connssl->config,
00309 MBEDTLS_SSL_IS_CLIENT,
00310 MBEDTLS_SSL_TRANSPORT_STREAM,
00311 MBEDTLS_SSL_PRESET_DEFAULT);
00312 if(ret) {
00313 failf(data, "mbedTLS: ssl_config failed");
00314 return CURLE_SSL_CONNECT_ERROR;
00315 }
00316
00317
00318 mbedtls_ssl_conf_cert_profile(&connssl->config,
00319 &mbedtls_x509_crt_profile_fr);
00320
00321 switch(SSL_CONN_CONFIG(version)) {
00322 case CURL_SSLVERSION_DEFAULT:
00323 case CURL_SSLVERSION_TLSv1:
00324 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00325 MBEDTLS_SSL_MINOR_VERSION_1);
00326 infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
00327 break;
00328 case CURL_SSLVERSION_SSLv3:
00329 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00330 MBEDTLS_SSL_MINOR_VERSION_0);
00331 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00332 MBEDTLS_SSL_MINOR_VERSION_0);
00333 infof(data, "mbedTLS: Set SSL version to SSLv3\n");
00334 break;
00335 case CURL_SSLVERSION_TLSv1_0:
00336 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00337 MBEDTLS_SSL_MINOR_VERSION_1);
00338 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00339 MBEDTLS_SSL_MINOR_VERSION_1);
00340 infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
00341 break;
00342 case CURL_SSLVERSION_TLSv1_1:
00343 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00344 MBEDTLS_SSL_MINOR_VERSION_2);
00345 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00346 MBEDTLS_SSL_MINOR_VERSION_2);
00347 infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
00348 break;
00349 case CURL_SSLVERSION_TLSv1_2:
00350 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00351 MBEDTLS_SSL_MINOR_VERSION_3);
00352 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
00353 MBEDTLS_SSL_MINOR_VERSION_3);
00354 infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
00355 break;
00356 case CURL_SSLVERSION_TLSv1_3:
00357 failf(data, "mbedTLS: TLS 1.3 is not yet supported");
00358 return CURLE_SSL_CONNECT_ERROR;
00359 default:
00360 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00361 return CURLE_SSL_CONNECT_ERROR;
00362 }
00363
00364 mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
00365
00366 mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
00367 &connssl->ctr_drbg);
00368 mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
00369 mbedtls_net_send,
00370 mbedtls_net_recv,
00371 NULL );
00372
00373 mbedtls_ssl_conf_ciphersuites(&connssl->config,
00374 mbedtls_ssl_list_ciphersuites());
00375
00376
00377 if(data->set.general_ssl.sessionid) {
00378 void *old_session = NULL;
00379
00380 Curl_ssl_sessionid_lock(conn);
00381 if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
00382 ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
00383 if(ret) {
00384 Curl_ssl_sessionid_unlock(conn);
00385 failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
00386 return CURLE_SSL_CONNECT_ERROR;
00387 }
00388 infof(data, "mbedTLS re-using session\n");
00389 }
00390 Curl_ssl_sessionid_unlock(conn);
00391 }
00392
00393 mbedtls_ssl_conf_ca_chain(&connssl->config,
00394 &connssl->cacert,
00395 &connssl->crl);
00396
00397 if(SSL_SET_OPTION(key)) {
00398 mbedtls_ssl_conf_own_cert(&connssl->config,
00399 &connssl->clicert, &connssl->pk);
00400 }
00401 if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
00402
00403
00404
00405 failf(data, "couldn't set hostname in mbedTLS");
00406 return CURLE_SSL_CONNECT_ERROR;
00407 }
00408
00409 #ifdef HAS_ALPN
00410 if(conn->bits.tls_enable_alpn) {
00411 const char **p = &connssl->protocols[0];
00412 #ifdef USE_NGHTTP2
00413 if(data->set.httpversion >= CURL_HTTP_VERSION_2)
00414 *p++ = NGHTTP2_PROTO_VERSION_ID;
00415 #endif
00416 *p++ = ALPN_HTTP_1_1;
00417 *p = NULL;
00418
00419
00420 if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
00421 &connssl->protocols[0])) {
00422 failf(data, "Failed setting ALPN protocols");
00423 return CURLE_SSL_CONNECT_ERROR;
00424 }
00425 for(p = &connssl->protocols[0]; *p; ++p)
00426 infof(data, "ALPN, offering %s\n", *p);
00427 }
00428 #endif
00429
00430 #ifdef MBEDTLS_DEBUG
00431
00432 mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
00433
00434
00435
00436
00437
00438
00439 mbedtls_debug_set_threshold(4);
00440 #endif
00441
00442 connssl->connecting_state = ssl_connect_2;
00443
00444 return CURLE_OK;
00445 }
00446
00447 static CURLcode
00448 mbed_connect_step2(struct connectdata *conn,
00449 int sockindex)
00450 {
00451 int ret;
00452 struct Curl_easy *data = conn->data;
00453 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
00454 const mbedtls_x509_crt *peercert;
00455 const char * const pinnedpubkey = SSL_IS_PROXY() ?
00456 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
00457 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
00458
00459 #ifdef HAS_ALPN
00460 const char *next_protocol;
00461 #endif
00462
00463 char errorbuf[128];
00464 errorbuf[0] = 0;
00465
00466 conn->recv[sockindex] = mbed_recv;
00467 conn->send[sockindex] = mbed_send;
00468
00469 ret = mbedtls_ssl_handshake(&connssl->ssl);
00470
00471 if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
00472 connssl->connecting_state = ssl_connect_2_reading;
00473 return CURLE_OK;
00474 }
00475 else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
00476 connssl->connecting_state = ssl_connect_2_writing;
00477 return CURLE_OK;
00478 }
00479 else if(ret) {
00480 #ifdef MBEDTLS_ERROR_C
00481 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
00482 #endif
00483 failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
00484 -ret, errorbuf);
00485 return CURLE_SSL_CONNECT_ERROR;
00486 }
00487
00488 infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
00489 mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
00490 );
00491
00492 ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
00493
00494 if(ret && SSL_CONN_CONFIG(verifypeer)) {
00495 if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
00496 failf(data, "Cert verify failed: BADCERT_EXPIRED");
00497
00498 if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
00499 failf(data, "Cert verify failed: BADCERT_REVOKED");
00500 return CURLE_SSL_CACERT;
00501 }
00502
00503 if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
00504 failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
00505
00506 if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
00507 failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
00508
00509 return CURLE_PEER_FAILED_VERIFICATION;
00510 }
00511
00512 peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
00513
00514 if(peercert && data->set.verbose) {
00515 const size_t bufsize = 16384;
00516 char *buffer = malloc(bufsize);
00517
00518 if(!buffer)
00519 return CURLE_OUT_OF_MEMORY;
00520
00521 if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
00522 infof(data, "Dumping cert info:\n%s\n", buffer);
00523 else
00524 infof(data, "Unable to dump certificate information.\n");
00525
00526 free(buffer);
00527 }
00528
00529 if(pinnedpubkey) {
00530 int size;
00531 CURLcode result;
00532 mbedtls_x509_crt *p;
00533 unsigned char pubkey[PUB_DER_MAX_BYTES];
00534
00535 if(!peercert || !peercert->raw.p || !peercert->raw.len) {
00536 failf(data, "Failed due to missing peer certificate");
00537 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00538 }
00539
00540 p = calloc(1, sizeof(*p));
00541
00542 if(!p)
00543 return CURLE_OUT_OF_MEMORY;
00544
00545 mbedtls_x509_crt_init(p);
00546
00547
00548
00549
00550 if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
00551 failf(data, "Failed copying peer certificate");
00552 mbedtls_x509_crt_free(p);
00553 free(p);
00554 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00555 }
00556
00557 size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
00558
00559 if(size <= 0) {
00560 failf(data, "Failed copying public key from peer certificate");
00561 mbedtls_x509_crt_free(p);
00562 free(p);
00563 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00564 }
00565
00566
00567 result = Curl_pin_peer_pubkey(data,
00568 pinnedpubkey,
00569 &pubkey[PUB_DER_MAX_BYTES - size], size);
00570 if(result) {
00571 mbedtls_x509_crt_free(p);
00572 free(p);
00573 return result;
00574 }
00575
00576 mbedtls_x509_crt_free(p);
00577 free(p);
00578 }
00579
00580 #ifdef HAS_ALPN
00581 if(conn->bits.tls_enable_alpn) {
00582 next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
00583
00584 if(next_protocol) {
00585 infof(data, "ALPN, server accepted to use %s\n", next_protocol);
00586 #ifdef USE_NGHTTP2
00587 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
00588 NGHTTP2_PROTO_VERSION_ID_LEN) &&
00589 !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
00590 conn->negnpn = CURL_HTTP_VERSION_2;
00591 }
00592 else
00593 #endif
00594 if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
00595 !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
00596 conn->negnpn = CURL_HTTP_VERSION_1_1;
00597 }
00598 }
00599 else {
00600 infof(data, "ALPN, server did not agree to a protocol\n");
00601 }
00602 }
00603 #endif
00604
00605 connssl->connecting_state = ssl_connect_3;
00606 infof(data, "SSL connected\n");
00607
00608 return CURLE_OK;
00609 }
00610
00611 static CURLcode
00612 mbed_connect_step3(struct connectdata *conn,
00613 int sockindex)
00614 {
00615 CURLcode retcode = CURLE_OK;
00616 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00617 struct Curl_easy *data = conn->data;
00618
00619 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
00620
00621 if(data->set.general_ssl.sessionid) {
00622 int ret;
00623 mbedtls_ssl_session *our_ssl_sessionid;
00624 void *old_ssl_sessionid = NULL;
00625
00626 our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
00627 if(!our_ssl_sessionid)
00628 return CURLE_OUT_OF_MEMORY;
00629
00630 mbedtls_ssl_session_init(our_ssl_sessionid);
00631
00632 ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
00633 if(ret) {
00634 failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
00635 return CURLE_SSL_CONNECT_ERROR;
00636 }
00637
00638
00639 Curl_ssl_sessionid_lock(conn);
00640 if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
00641 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
00642
00643 retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
00644 Curl_ssl_sessionid_unlock(conn);
00645 if(retcode) {
00646 free(our_ssl_sessionid);
00647 failf(data, "failed to store ssl session");
00648 return retcode;
00649 }
00650 }
00651
00652 connssl->connecting_state = ssl_connect_done;
00653
00654 return CURLE_OK;
00655 }
00656
00657 static ssize_t mbed_send(struct connectdata *conn, int sockindex,
00658 const void *mem, size_t len,
00659 CURLcode *curlcode)
00660 {
00661 int ret = -1;
00662
00663 ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
00664 (unsigned char *)mem, len);
00665
00666 if(ret < 0) {
00667 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
00668 CURLE_AGAIN : CURLE_SEND_ERROR;
00669 ret = -1;
00670 }
00671
00672 return ret;
00673 }
00674
00675 void Curl_mbedtls_close_all(struct Curl_easy *data)
00676 {
00677 (void)data;
00678 }
00679
00680 void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
00681 {
00682 mbedtls_pk_free(&conn->ssl[sockindex].pk);
00683 mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
00684 mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
00685 mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
00686 mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
00687 mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
00688 mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
00689 #ifndef THREADING_SUPPORT
00690 mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
00691 #endif
00692 }
00693
00694 static ssize_t mbed_recv(struct connectdata *conn, int num,
00695 char *buf, size_t buffersize,
00696 CURLcode *curlcode)
00697 {
00698 int ret = -1;
00699 ssize_t len = -1;
00700
00701 memset(buf, 0, buffersize);
00702 ret = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
00703 buffersize);
00704
00705 if(ret <= 0) {
00706 if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
00707 return 0;
00708
00709 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
00710 CURLE_AGAIN : CURLE_RECV_ERROR;
00711 return -1;
00712 }
00713
00714 len = ret;
00715
00716 return len;
00717 }
00718
00719 void Curl_mbedtls_session_free(void *ptr)
00720 {
00721 mbedtls_ssl_session_free(ptr);
00722 free(ptr);
00723 }
00724
00725 size_t Curl_mbedtls_version(char *buffer, size_t size)
00726 {
00727 unsigned int version = mbedtls_version_get_number();
00728 return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
00729 (version>>16)&0xff, (version>>8)&0xff);
00730 }
00731
00732 static CURLcode
00733 mbed_connect_common(struct connectdata *conn,
00734 int sockindex,
00735 bool nonblocking,
00736 bool *done)
00737 {
00738 CURLcode retcode;
00739 struct Curl_easy *data = conn->data;
00740 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00741 curl_socket_t sockfd = conn->sock[sockindex];
00742 long timeout_ms;
00743 int what;
00744
00745
00746 if(ssl_connection_complete == connssl->state) {
00747 *done = TRUE;
00748 return CURLE_OK;
00749 }
00750
00751 if(ssl_connect_1==connssl->connecting_state) {
00752
00753 timeout_ms = Curl_timeleft(data, NULL, TRUE);
00754
00755 if(timeout_ms < 0) {
00756
00757 failf(data, "SSL connection timeout");
00758 return CURLE_OPERATION_TIMEDOUT;
00759 }
00760 retcode = mbed_connect_step1(conn, sockindex);
00761 if(retcode)
00762 return retcode;
00763 }
00764
00765 while(ssl_connect_2 == connssl->connecting_state ||
00766 ssl_connect_2_reading == connssl->connecting_state ||
00767 ssl_connect_2_writing == connssl->connecting_state) {
00768
00769
00770 timeout_ms = Curl_timeleft(data, NULL, TRUE);
00771
00772 if(timeout_ms < 0) {
00773
00774 failf(data, "SSL connection timeout");
00775 return CURLE_OPERATION_TIMEDOUT;
00776 }
00777
00778
00779 if(connssl->connecting_state == ssl_connect_2_reading
00780 || connssl->connecting_state == ssl_connect_2_writing) {
00781
00782 curl_socket_t writefd = ssl_connect_2_writing==
00783 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00784 curl_socket_t readfd = ssl_connect_2_reading==
00785 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00786
00787 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
00788 nonblocking ? 0 : timeout_ms);
00789 if(what < 0) {
00790
00791 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
00792 return CURLE_SSL_CONNECT_ERROR;
00793 }
00794 else if(0 == what) {
00795 if(nonblocking) {
00796 *done = FALSE;
00797 return CURLE_OK;
00798 }
00799 else {
00800
00801 failf(data, "SSL connection timeout");
00802 return CURLE_OPERATION_TIMEDOUT;
00803 }
00804 }
00805
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815 retcode = mbed_connect_step2(conn, sockindex);
00816 if(retcode || (nonblocking &&
00817 (ssl_connect_2 == connssl->connecting_state ||
00818 ssl_connect_2_reading == connssl->connecting_state ||
00819 ssl_connect_2_writing == connssl->connecting_state)))
00820 return retcode;
00821
00822 }
00823
00824 if(ssl_connect_3==connssl->connecting_state) {
00825 retcode = mbed_connect_step3(conn, sockindex);
00826 if(retcode)
00827 return retcode;
00828 }
00829
00830 if(ssl_connect_done==connssl->connecting_state) {
00831 connssl->state = ssl_connection_complete;
00832 conn->recv[sockindex] = mbed_recv;
00833 conn->send[sockindex] = mbed_send;
00834 *done = TRUE;
00835 }
00836 else
00837 *done = FALSE;
00838
00839
00840 connssl->connecting_state = ssl_connect_1;
00841
00842 return CURLE_OK;
00843 }
00844
00845 CURLcode
00846 Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
00847 int sockindex,
00848 bool *done)
00849 {
00850 return mbed_connect_common(conn, sockindex, TRUE, done);
00851 }
00852
00853
00854 CURLcode
00855 Curl_mbedtls_connect(struct connectdata *conn,
00856 int sockindex)
00857 {
00858 CURLcode retcode;
00859 bool done = FALSE;
00860
00861 retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
00862 if(retcode)
00863 return retcode;
00864
00865 DEBUGASSERT(done);
00866
00867 return CURLE_OK;
00868 }
00869
00870
00871
00872
00873
00874 int Curl_mbedtls_init(void)
00875 {
00876 return Curl_polarsslthreadlock_thread_setup();
00877 }
00878
00879 void Curl_mbedtls_cleanup(void)
00880 {
00881 (void)Curl_polarsslthreadlock_thread_cleanup();
00882 }
00883
00884 int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
00885 {
00886 mbedtls_ssl_context *ssl =
00887 (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl;
00888 return ssl->in_msglen != 0;
00889 }
00890
00891 #endif