1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> 9 * Copyright (C) 2012 - 2014, 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 http://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 PolarSSL-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_POLARSSL 33 34#include <polarssl/net.h> 35#include <polarssl/ssl.h> 36#include <polarssl/certs.h> 37#include <polarssl/x509.h> 38#include <polarssl/version.h> 39 40#if POLARSSL_VERSION_NUMBER < 0x01030000 41#error too old PolarSSL 42#endif 43 44#include <polarssl/error.h> 45#include <polarssl/entropy.h> 46#include <polarssl/ctr_drbg.h> 47 48#include "urldata.h" 49#include "sendf.h" 50#include "inet_pton.h" 51#include "polarssl.h" 52#include "vtls.h" 53#include "parsedate.h" 54#include "connect.h" /* for the connect timeout */ 55#include "select.h" 56#include "rawstr.h" 57#include "polarssl_threadlock.h" 58 59#define _MPRINTF_REPLACE /* use our functions only */ 60#include <curl/mprintf.h> 61#include "curl_memory.h" 62/* The last #include file should be: */ 63#include "memdebug.h" 64 65/* apply threading? */ 66#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) 67#define THREADING_SUPPORT 68#endif 69 70#if defined(THREADING_SUPPORT) 71static entropy_context entropy; 72 73static int entropy_init_initialized = 0; 74 75/* start of entropy_init_mutex() */ 76static void entropy_init_mutex(entropy_context *ctx) 77{ 78 /* lock 0 = entropy_init_mutex() */ 79 polarsslthreadlock_lock_function(0); 80 if(entropy_init_initialized == 0) { 81 entropy_init(ctx); 82 entropy_init_initialized = 1; 83 } 84 polarsslthreadlock_unlock_function(0); 85} 86/* end of entropy_init_mutex() */ 87 88/* start of entropy_func_mutex() */ 89static int entropy_func_mutex(void *data, unsigned char *output, size_t len) 90{ 91 int ret; 92 /* lock 1 = entropy_func_mutex() */ 93 polarsslthreadlock_lock_function(1); 94 ret = entropy_func(data, output, len); 95 polarsslthreadlock_unlock_function(1); 96 97 return ret; 98} 99/* end of entropy_func_mutex() */ 100 101#endif /* THREADING_SUPPORT */ 102 103/* Define this to enable lots of debugging for PolarSSL */ 104#undef POLARSSL_DEBUG 105 106#ifdef POLARSSL_DEBUG 107static void polarssl_debug(void *context, int level, const char *line) 108{ 109 struct SessionHandle *data = NULL; 110 111 if(!context) 112 return; 113 114 data = (struct SessionHandle *)context; 115 116 infof(data, "%s", line); 117 (void) level; 118} 119#else 120#endif 121 122static Curl_recv polarssl_recv; 123static Curl_send polarssl_send; 124 125 126static CURLcode 127polarssl_connect_step1(struct connectdata *conn, 128 int sockindex) 129{ 130 struct SessionHandle *data = conn->data; 131 struct ssl_connect_data* connssl = &conn->ssl[sockindex]; 132 133 bool sni = TRUE; /* default is SNI enabled */ 134 int ret = -1; 135#ifdef ENABLE_IPV6 136 struct in6_addr addr; 137#else 138 struct in_addr addr; 139#endif 140 void *old_session = NULL; 141 size_t old_session_size = 0; 142 143 char errorbuf[128]; 144 memset(errorbuf, 0, sizeof(errorbuf)); 145 146 147 /* PolarSSL only supports SSLv3 and TLSv1 */ 148 if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { 149 failf(data, "PolarSSL does not support SSLv2"); 150 return CURLE_SSL_CONNECT_ERROR; 151 } 152 else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) 153 sni = FALSE; /* SSLv3 has no SNI */ 154 155#ifdef THREADING_SUPPORT 156 entropy_init_mutex(&entropy); 157 158 if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, 159 connssl->ssn.id, connssl->ssn.length)) != 0) { 160#ifdef POLARSSL_ERROR_C 161 error_strerror(ret, errorbuf, sizeof(errorbuf)); 162#endif /* POLARSSL_ERROR_C */ 163 failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", 164 -ret, errorbuf); 165 } 166#else 167 entropy_init(&connssl->entropy); 168 169 if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, 170 connssl->ssn.id, connssl->ssn.length)) != 0) { 171#ifdef POLARSSL_ERROR_C 172 error_strerror(ret, errorbuf, sizeof(errorbuf)); 173#endif /* POLARSSL_ERROR_C */ 174 failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", 175 -ret, errorbuf); 176 } 177#endif /* THREADING_SUPPORT */ 178 179 /* Load the trusted CA */ 180 memset(&connssl->cacert, 0, sizeof(x509_crt)); 181 182 if(data->set.str[STRING_SSL_CAFILE]) { 183 ret = x509_crt_parse_file(&connssl->cacert, 184 data->set.str[STRING_SSL_CAFILE]); 185 186 if(ret<0) { 187#ifdef POLARSSL_ERROR_C 188 error_strerror(ret, errorbuf, sizeof(errorbuf)); 189#endif /* POLARSSL_ERROR_C */ 190 failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", 191 data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); 192 193 if(data->set.ssl.verifypeer) 194 return CURLE_SSL_CACERT_BADFILE; 195 } 196 } 197 198 /* Load the client certificate */ 199 memset(&connssl->clicert, 0, sizeof(x509_crt)); 200 201 if(data->set.str[STRING_CERT]) { 202 ret = x509_crt_parse_file(&connssl->clicert, 203 data->set.str[STRING_CERT]); 204 205 if(ret) { 206#ifdef POLARSSL_ERROR_C 207 error_strerror(ret, errorbuf, sizeof(errorbuf)); 208#endif /* POLARSSL_ERROR_C */ 209 failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", 210 data->set.str[STRING_CERT], -ret, errorbuf); 211 212 return CURLE_SSL_CERTPROBLEM; 213 } 214 } 215 216 /* Load the client private key */ 217 if(data->set.str[STRING_KEY]) { 218 pk_context pk; 219 pk_init(&pk); 220 ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], 221 data->set.str[STRING_KEY_PASSWD]); 222 if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) 223 ret = POLARSSL_ERR_PK_TYPE_MISMATCH; 224 if(ret == 0) 225 rsa_copy(&connssl->rsa, pk_rsa(pk)); 226 else 227 rsa_free(&connssl->rsa); 228 pk_free(&pk); 229 230 if(ret) { 231#ifdef POLARSSL_ERROR_C 232 error_strerror(ret, errorbuf, sizeof(errorbuf)); 233#endif /* POLARSSL_ERROR_C */ 234 failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", 235 data->set.str[STRING_KEY], -ret, errorbuf); 236 237 return CURLE_SSL_CERTPROBLEM; 238 } 239 } 240 241 /* Load the CRL */ 242 memset(&connssl->crl, 0, sizeof(x509_crl)); 243 244 if(data->set.str[STRING_SSL_CRLFILE]) { 245 ret = x509_crl_parse_file(&connssl->crl, 246 data->set.str[STRING_SSL_CRLFILE]); 247 248 if(ret) { 249#ifdef POLARSSL_ERROR_C 250 error_strerror(ret, errorbuf, sizeof(errorbuf)); 251#endif /* POLARSSL_ERROR_C */ 252 failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", 253 data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); 254 255 return CURLE_SSL_CRL_BADFILE; 256 } 257 } 258 259 infof(data, "PolarSSL: Connecting to %s:%d\n", 260 conn->host.name, conn->remote_port); 261 262 if(ssl_init(&connssl->ssl)) { 263 failf(data, "PolarSSL: ssl_init failed"); 264 return CURLE_SSL_CONNECT_ERROR; 265 } 266 267 ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); 268 ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); 269 270 ssl_set_rng(&connssl->ssl, ctr_drbg_random, 271 &connssl->ctr_drbg); 272 ssl_set_bio(&connssl->ssl, 273 net_recv, &conn->sock[sockindex], 274 net_send, &conn->sock[sockindex]); 275 276 ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); 277 if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { 278 memcpy(&connssl->ssn, old_session, old_session_size); 279 infof(data, "PolarSSL re-using session\n"); 280 } 281 282 ssl_set_session(&connssl->ssl, 283 &connssl->ssn); 284 285 ssl_set_ca_chain(&connssl->ssl, 286 &connssl->cacert, 287 &connssl->crl, 288 conn->host.name); 289 290 ssl_set_own_cert_rsa(&connssl->ssl, 291 &connssl->clicert, &connssl->rsa); 292 293 if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && 294#ifdef ENABLE_IPV6 295 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && 296#endif 297 sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) { 298 infof(data, "WARNING: failed to configure " 299 "server name indication (SNI) TLS extension\n"); 300 } 301 302#ifdef POLARSSL_DEBUG 303 ssl_set_dbg(&connssl->ssl, polarssl_debug, data); 304#endif 305 306 connssl->connecting_state = ssl_connect_2; 307 308 return CURLE_OK; 309} 310 311static CURLcode 312polarssl_connect_step2(struct connectdata *conn, 313 int sockindex) 314{ 315 int ret; 316 struct SessionHandle *data = conn->data; 317 struct ssl_connect_data* connssl = &conn->ssl[sockindex]; 318 char buffer[1024]; 319 320 char errorbuf[128]; 321 memset(errorbuf, 0, sizeof(errorbuf)); 322 323 conn->recv[sockindex] = polarssl_recv; 324 conn->send[sockindex] = polarssl_send; 325 326 for(;;) { 327 if(!(ret = ssl_handshake(&connssl->ssl))) 328 break; 329 else if(ret != POLARSSL_ERR_NET_WANT_READ && 330 ret != POLARSSL_ERR_NET_WANT_WRITE) { 331#ifdef POLARSSL_ERROR_C 332 error_strerror(ret, errorbuf, sizeof(errorbuf)); 333#endif /* POLARSSL_ERROR_C */ 334 failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", 335 -ret, errorbuf); 336 337 return CURLE_SSL_CONNECT_ERROR; 338 } 339 else { 340 if(ret == POLARSSL_ERR_NET_WANT_READ) { 341 connssl->connecting_state = ssl_connect_2_reading; 342 return CURLE_OK; 343 } 344 if(ret == POLARSSL_ERR_NET_WANT_WRITE) { 345 connssl->connecting_state = ssl_connect_2_writing; 346 return CURLE_OK; 347 } 348 failf(data, "SSL_connect failed with error %d.", ret); 349 return CURLE_SSL_CONNECT_ERROR; 350 351 } 352 } 353 354 infof(data, "PolarSSL: Handshake complete, cipher is %s\n", 355 ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) 356 ); 357 358 ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); 359 360 if(ret && data->set.ssl.verifypeer) { 361 if(ret & BADCERT_EXPIRED) 362 failf(data, "Cert verify failed: BADCERT_EXPIRED"); 363 364 if(ret & BADCERT_REVOKED) { 365 failf(data, "Cert verify failed: BADCERT_REVOKED"); 366 return CURLE_SSL_CACERT; 367 } 368 369 if(ret & BADCERT_CN_MISMATCH) 370 failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); 371 372 if(ret & BADCERT_NOT_TRUSTED) 373 failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); 374 375 return CURLE_PEER_FAILED_VERIFICATION; 376 } 377 378 if(ssl_get_peer_cert(&(connssl->ssl))) { 379 /* If the session was resumed, there will be no peer certs */ 380 memset(buffer, 0, sizeof(buffer)); 381 382 if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", 383 ssl_get_peer_cert(&(connssl->ssl))) != -1) 384 infof(data, "Dumping cert info:\n%s\n", buffer); 385 } 386 387 connssl->connecting_state = ssl_connect_3; 388 infof(data, "SSL connected\n"); 389 390 return CURLE_OK; 391} 392 393static CURLcode 394polarssl_connect_step3(struct connectdata *conn, 395 int sockindex) 396{ 397 CURLcode retcode = CURLE_OK; 398 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 399 struct SessionHandle *data = conn->data; 400 void *old_ssl_sessionid = NULL; 401 ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn ; 402 int incache; 403 404 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 405 406 /* Save the current session data for possible re-use */ 407 incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); 408 if(incache) { 409 if(old_ssl_sessionid != our_ssl_sessionid) { 410 infof(data, "old SSL session ID is stale, removing\n"); 411 Curl_ssl_delsessionid(conn, old_ssl_sessionid); 412 incache = FALSE; 413 } 414 } 415 if(!incache) { 416 void *new_session = malloc(sizeof(ssl_session)); 417 418 if(new_session) { 419 memcpy(new_session, our_ssl_sessionid, 420 sizeof(ssl_session)); 421 422 retcode = Curl_ssl_addsessionid(conn, new_session, 423 sizeof(ssl_session)); 424 } 425 else { 426 retcode = CURLE_OUT_OF_MEMORY; 427 } 428 429 if(retcode) { 430 failf(data, "failed to store ssl session"); 431 return retcode; 432 } 433 } 434 435 connssl->connecting_state = ssl_connect_done; 436 437 return CURLE_OK; 438} 439 440static ssize_t polarssl_send(struct connectdata *conn, 441 int sockindex, 442 const void *mem, 443 size_t len, 444 CURLcode *curlcode) 445{ 446 int ret = -1; 447 448 ret = ssl_write(&conn->ssl[sockindex].ssl, 449 (unsigned char *)mem, len); 450 451 if(ret < 0) { 452 *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ? 453 CURLE_AGAIN : CURLE_SEND_ERROR; 454 ret = -1; 455 } 456 457 return ret; 458} 459 460void Curl_polarssl_close_all(struct SessionHandle *data) 461{ 462 (void)data; 463} 464 465void Curl_polarssl_close(struct connectdata *conn, int sockindex) 466{ 467 rsa_free(&conn->ssl[sockindex].rsa); 468 x509_crt_free(&conn->ssl[sockindex].clicert); 469 x509_crt_free(&conn->ssl[sockindex].cacert); 470 x509_crl_free(&conn->ssl[sockindex].crl); 471 ssl_free(&conn->ssl[sockindex].ssl); 472} 473 474static ssize_t polarssl_recv(struct connectdata *conn, 475 int num, 476 char *buf, 477 size_t buffersize, 478 CURLcode *curlcode) 479{ 480 int ret = -1; 481 ssize_t len = -1; 482 483 memset(buf, 0, buffersize); 484 ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize); 485 486 if(ret <= 0) { 487 if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) 488 return 0; 489 490 *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ? 491 CURLE_AGAIN : CURLE_RECV_ERROR; 492 return -1; 493 } 494 495 len = ret; 496 497 return len; 498} 499 500void Curl_polarssl_session_free(void *ptr) 501{ 502 free(ptr); 503} 504 505size_t Curl_polarssl_version(char *buffer, size_t size) 506{ 507 unsigned int version = version_get_number(); 508 return snprintf(buffer, size, "PolarSSL/%d.%d.%d", version>>24, 509 (version>>16)&0xff, (version>>8)&0xff); 510} 511 512static CURLcode 513polarssl_connect_common(struct connectdata *conn, 514 int sockindex, 515 bool nonblocking, 516 bool *done) 517{ 518 CURLcode retcode; 519 struct SessionHandle *data = conn->data; 520 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 521 curl_socket_t sockfd = conn->sock[sockindex]; 522 long timeout_ms; 523 int what; 524 525 /* check if the connection has already been established */ 526 if(ssl_connection_complete == connssl->state) { 527 *done = TRUE; 528 return CURLE_OK; 529 } 530 531 if(ssl_connect_1==connssl->connecting_state) { 532 /* Find out how much more time we're allowed */ 533 timeout_ms = Curl_timeleft(data, NULL, TRUE); 534 535 if(timeout_ms < 0) { 536 /* no need to continue if time already is up */ 537 failf(data, "SSL connection timeout"); 538 return CURLE_OPERATION_TIMEDOUT; 539 } 540 retcode = polarssl_connect_step1(conn, sockindex); 541 if(retcode) 542 return retcode; 543 } 544 545 while(ssl_connect_2 == connssl->connecting_state || 546 ssl_connect_2_reading == connssl->connecting_state || 547 ssl_connect_2_writing == connssl->connecting_state) { 548 549 /* check allowed time left */ 550 timeout_ms = Curl_timeleft(data, NULL, TRUE); 551 552 if(timeout_ms < 0) { 553 /* no need to continue if time already is up */ 554 failf(data, "SSL connection timeout"); 555 return CURLE_OPERATION_TIMEDOUT; 556 } 557 558 /* if ssl is expecting something, check if it's available. */ 559 if(connssl->connecting_state == ssl_connect_2_reading 560 || connssl->connecting_state == ssl_connect_2_writing) { 561 562 curl_socket_t writefd = ssl_connect_2_writing== 563 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 564 curl_socket_t readfd = ssl_connect_2_reading== 565 connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 566 567 what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms); 568 if(what < 0) { 569 /* fatal error */ 570 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 571 return CURLE_SSL_CONNECT_ERROR; 572 } 573 else if(0 == what) { 574 if(nonblocking) { 575 *done = FALSE; 576 return CURLE_OK; 577 } 578 else { 579 /* timeout */ 580 failf(data, "SSL connection timeout"); 581 return CURLE_OPERATION_TIMEDOUT; 582 } 583 } 584 /* socket is readable or writable */ 585 } 586 587 /* Run transaction, and return to the caller if it failed or if 588 * this connection is part of a multi handle and this loop would 589 * execute again. This permits the owner of a multi handle to 590 * abort a connection attempt before step2 has completed while 591 * ensuring that a client using select() or epoll() will always 592 * have a valid fdset to wait on. 593 */ 594 retcode = polarssl_connect_step2(conn, sockindex); 595 if(retcode || (nonblocking && 596 (ssl_connect_2 == connssl->connecting_state || 597 ssl_connect_2_reading == connssl->connecting_state || 598 ssl_connect_2_writing == connssl->connecting_state))) 599 return retcode; 600 601 } /* repeat step2 until all transactions are done. */ 602 603 if(ssl_connect_3==connssl->connecting_state) { 604 retcode = polarssl_connect_step3(conn, sockindex); 605 if(retcode) 606 return retcode; 607 } 608 609 if(ssl_connect_done==connssl->connecting_state) { 610 connssl->state = ssl_connection_complete; 611 conn->recv[sockindex] = polarssl_recv; 612 conn->send[sockindex] = polarssl_send; 613 *done = TRUE; 614 } 615 else 616 *done = FALSE; 617 618 /* Reset our connect state machine */ 619 connssl->connecting_state = ssl_connect_1; 620 621 return CURLE_OK; 622} 623 624CURLcode 625Curl_polarssl_connect_nonblocking(struct connectdata *conn, 626 int sockindex, 627 bool *done) 628{ 629 return polarssl_connect_common(conn, sockindex, TRUE, done); 630} 631 632 633CURLcode 634Curl_polarssl_connect(struct connectdata *conn, 635 int sockindex) 636{ 637 CURLcode retcode; 638 bool done = FALSE; 639 640 retcode = polarssl_connect_common(conn, sockindex, FALSE, &done); 641 if(retcode) 642 return retcode; 643 644 DEBUGASSERT(done); 645 646 return CURLE_OK; 647} 648 649/* 650 * return 0 error initializing SSL 651 * return 1 SSL initialized successfully 652 */ 653int polarssl_init(void) 654{ 655 return polarsslthreadlock_thread_setup(); 656} 657 658void polarssl_cleanup(void) 659{ 660 (void)polarsslthreadlock_thread_cleanup(); 661} 662 663#endif /* USE_POLARSSL */ 664