Home | History | Annotate | Download | only in vtls
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan (at) gmail.com>
     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 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 #include <polarssl/sha256.h>
     40 
     41 #if POLARSSL_VERSION_NUMBER < 0x01030000
     42 #error too old PolarSSL
     43 #endif
     44 
     45 #include <polarssl/error.h>
     46 #include <polarssl/entropy.h>
     47 #include <polarssl/ctr_drbg.h>
     48 
     49 #include "urldata.h"
     50 #include "sendf.h"
     51 #include "inet_pton.h"
     52 #include "polarssl.h"
     53 #include "vtls.h"
     54 #include "parsedate.h"
     55 #include "connect.h" /* for the connect timeout */
     56 #include "select.h"
     57 #include "rawstr.h"
     58 #include "polarssl_threadlock.h"
     59 #include "curl_printf.h"
     60 #include "curl_memory.h"
     61 /* The last #include file should be: */
     62 #include "memdebug.h"
     63 
     64 /* See https://tls.mbed.org/discussions/generic/
     65    howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
     66 */
     67 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * POLARSSL_MPI_MAX_SIZE)
     68 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * POLARSSL_ECP_MAX_BYTES)
     69 
     70 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
     71                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
     72 
     73 /* apply threading? */
     74 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
     75 #define THREADING_SUPPORT
     76 #endif
     77 
     78 #if defined(THREADING_SUPPORT)
     79 static entropy_context entropy;
     80 
     81 static int  entropy_init_initialized  = 0;
     82 
     83 /* start of entropy_init_mutex() */
     84 static void entropy_init_mutex(entropy_context *ctx)
     85 {
     86   /* lock 0 = entropy_init_mutex() */
     87   Curl_polarsslthreadlock_lock_function(0);
     88   if(entropy_init_initialized == 0) {
     89     entropy_init(ctx);
     90     entropy_init_initialized = 1;
     91   }
     92   Curl_polarsslthreadlock_unlock_function(0);
     93 }
     94 /* end of entropy_init_mutex() */
     95 
     96 /* start of entropy_func_mutex() */
     97 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
     98 {
     99     int ret;
    100     /* lock 1 = entropy_func_mutex() */
    101     Curl_polarsslthreadlock_lock_function(1);
    102     ret = entropy_func(data, output, len);
    103     Curl_polarsslthreadlock_unlock_function(1);
    104 
    105     return ret;
    106 }
    107 /* end of entropy_func_mutex() */
    108 
    109 #endif /* THREADING_SUPPORT */
    110 
    111 /* Define this to enable lots of debugging for PolarSSL */
    112 #undef POLARSSL_DEBUG
    113 
    114 #ifdef POLARSSL_DEBUG
    115 static void polarssl_debug(void *context, int level, const char *line)
    116 {
    117   struct Curl_easy *data = NULL;
    118 
    119   if(!context)
    120     return;
    121 
    122   data = (struct Curl_easy *)context;
    123 
    124   infof(data, "%s", line);
    125   (void) level;
    126 }
    127 #else
    128 #endif
    129 
    130 /* ALPN for http2? */
    131 #ifdef POLARSSL_SSL_ALPN
    132 #  define HAS_ALPN
    133 #endif
    134 
    135 static Curl_recv polarssl_recv;
    136 static Curl_send polarssl_send;
    137 
    138 
    139 static CURLcode
    140 polarssl_connect_step1(struct connectdata *conn,
    141                      int sockindex)
    142 {
    143   struct Curl_easy *data = conn->data;
    144   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
    145 
    146   bool sni = TRUE; /* default is SNI enabled */
    147   int ret = -1;
    148 #ifdef ENABLE_IPV6
    149   struct in6_addr addr;
    150 #else
    151   struct in_addr addr;
    152 #endif
    153   char errorbuf[128];
    154   errorbuf[0]=0;
    155 
    156   /* PolarSSL only supports SSLv3 and TLSv1 */
    157   if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    158     failf(data, "PolarSSL does not support SSLv2");
    159     return CURLE_SSL_CONNECT_ERROR;
    160   }
    161   else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    162     sni = FALSE; /* SSLv3 has no SNI */
    163 
    164 #ifdef THREADING_SUPPORT
    165   entropy_init_mutex(&entropy);
    166 
    167   if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
    168                           NULL, 0)) != 0) {
    169 #ifdef POLARSSL_ERROR_C
    170      error_strerror(ret, errorbuf, sizeof(errorbuf));
    171 #endif /* POLARSSL_ERROR_C */
    172      failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
    173                                                             -ret, errorbuf);
    174   }
    175 #else
    176   entropy_init(&connssl->entropy);
    177 
    178   if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
    179                           NULL, 0)) != 0) {
    180 #ifdef POLARSSL_ERROR_C
    181      error_strerror(ret, errorbuf, sizeof(errorbuf));
    182 #endif /* POLARSSL_ERROR_C */
    183      failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
    184                                                             -ret, errorbuf);
    185   }
    186 #endif /* THREADING_SUPPORT */
    187 
    188   /* Load the trusted CA */
    189   memset(&connssl->cacert, 0, sizeof(x509_crt));
    190 
    191   if(data->set.str[STRING_SSL_CAFILE]) {
    192     ret = x509_crt_parse_file(&connssl->cacert,
    193                               data->set.str[STRING_SSL_CAFILE]);
    194 
    195     if(ret<0) {
    196 #ifdef POLARSSL_ERROR_C
    197       error_strerror(ret, errorbuf, sizeof(errorbuf));
    198 #endif /* POLARSSL_ERROR_C */
    199       failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
    200             data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
    201 
    202       if(data->set.ssl.verifypeer)
    203         return CURLE_SSL_CACERT_BADFILE;
    204     }
    205   }
    206 
    207   if(data->set.str[STRING_SSL_CAPATH]) {
    208     ret = x509_crt_parse_path(&connssl->cacert,
    209                               data->set.str[STRING_SSL_CAPATH]);
    210 
    211     if(ret<0) {
    212 #ifdef POLARSSL_ERROR_C
    213       error_strerror(ret, errorbuf, sizeof(errorbuf));
    214 #endif /* POLARSSL_ERROR_C */
    215       failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
    216             data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
    217 
    218       if(data->set.ssl.verifypeer)
    219         return CURLE_SSL_CACERT_BADFILE;
    220     }
    221   }
    222 
    223   /* Load the client certificate */
    224   memset(&connssl->clicert, 0, sizeof(x509_crt));
    225 
    226   if(data->set.str[STRING_CERT]) {
    227     ret = x509_crt_parse_file(&connssl->clicert,
    228                               data->set.str[STRING_CERT]);
    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 client cert file %s - PolarSSL: (-0x%04X) %s",
    235             data->set.str[STRING_CERT], -ret, errorbuf);
    236 
    237       return CURLE_SSL_CERTPROBLEM;
    238     }
    239   }
    240 
    241   /* Load the client private key */
    242   if(data->set.str[STRING_KEY]) {
    243     pk_context pk;
    244     pk_init(&pk);
    245     ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
    246                            data->set.str[STRING_KEY_PASSWD]);
    247     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
    248       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
    249     if(ret == 0)
    250       rsa_copy(&connssl->rsa, pk_rsa(pk));
    251     else
    252       rsa_free(&connssl->rsa);
    253     pk_free(&pk);
    254 
    255     if(ret) {
    256 #ifdef POLARSSL_ERROR_C
    257       error_strerror(ret, errorbuf, sizeof(errorbuf));
    258 #endif /* POLARSSL_ERROR_C */
    259       failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
    260             data->set.str[STRING_KEY], -ret, errorbuf);
    261 
    262       return CURLE_SSL_CERTPROBLEM;
    263     }
    264   }
    265 
    266   /* Load the CRL */
    267   memset(&connssl->crl, 0, sizeof(x509_crl));
    268 
    269   if(data->set.str[STRING_SSL_CRLFILE]) {
    270     ret = x509_crl_parse_file(&connssl->crl,
    271                               data->set.str[STRING_SSL_CRLFILE]);
    272 
    273     if(ret) {
    274 #ifdef POLARSSL_ERROR_C
    275       error_strerror(ret, errorbuf, sizeof(errorbuf));
    276 #endif /* POLARSSL_ERROR_C */
    277       failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
    278             data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
    279 
    280       return CURLE_SSL_CRL_BADFILE;
    281     }
    282   }
    283 
    284   infof(data, "PolarSSL: Connecting to %s:%d\n",
    285         conn->host.name, conn->remote_port);
    286 
    287   if(ssl_init(&connssl->ssl)) {
    288     failf(data, "PolarSSL: ssl_init failed");
    289     return CURLE_SSL_CONNECT_ERROR;
    290   }
    291 
    292   switch(data->set.ssl.version) {
    293   default:
    294   case CURL_SSLVERSION_DEFAULT:
    295   case CURL_SSLVERSION_TLSv1:
    296     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    297                         SSL_MINOR_VERSION_1);
    298     break;
    299   case CURL_SSLVERSION_SSLv3:
    300     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    301                         SSL_MINOR_VERSION_0);
    302     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    303                         SSL_MINOR_VERSION_0);
    304     infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
    305     break;
    306   case CURL_SSLVERSION_TLSv1_0:
    307     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    308                         SSL_MINOR_VERSION_1);
    309     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    310                         SSL_MINOR_VERSION_1);
    311     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
    312     break;
    313   case CURL_SSLVERSION_TLSv1_1:
    314     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    315                         SSL_MINOR_VERSION_2);
    316     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    317                         SSL_MINOR_VERSION_2);
    318     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
    319     break;
    320   case CURL_SSLVERSION_TLSv1_2:
    321     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    322                         SSL_MINOR_VERSION_3);
    323     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    324                         SSL_MINOR_VERSION_3);
    325     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
    326     break;
    327   }
    328 
    329   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
    330   ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
    331 
    332   ssl_set_rng(&connssl->ssl, ctr_drbg_random,
    333               &connssl->ctr_drbg);
    334   ssl_set_bio(&connssl->ssl,
    335               net_recv, &conn->sock[sockindex],
    336               net_send, &conn->sock[sockindex]);
    337 
    338   ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
    339 
    340   /* Check if there's a cached ID we can/should use here! */
    341   if(conn->ssl_config.sessionid) {
    342     void *old_session = NULL;
    343 
    344     Curl_ssl_sessionid_lock(conn);
    345     if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
    346       ret = ssl_set_session(&connssl->ssl, old_session);
    347       Curl_ssl_sessionid_unlock(conn);
    348       if(ret) {
    349         failf(data, "ssl_set_session returned -0x%x", -ret);
    350         return CURLE_SSL_CONNECT_ERROR;
    351       }
    352       infof(data, "PolarSSL re-using session\n");
    353     }
    354   }
    355 
    356   ssl_set_ca_chain(&connssl->ssl,
    357                    &connssl->cacert,
    358                    &connssl->crl,
    359                    conn->host.name);
    360 
    361   ssl_set_own_cert_rsa(&connssl->ssl,
    362                        &connssl->clicert, &connssl->rsa);
    363 
    364   if(ssl_set_hostname(&connssl->ssl, conn->host.name)) {
    365     /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
    366        to set in the SNI extension. So even if curl connects to a host
    367        specified as an IP address, this function must be used. */
    368     failf(data, "couldn't set hostname in PolarSSL");
    369     return CURLE_SSL_CONNECT_ERROR;
    370   }
    371 
    372 #ifdef HAS_ALPN
    373   if(conn->bits.tls_enable_alpn) {
    374     static const char* protocols[3];
    375     int cur = 0;
    376 
    377 #ifdef USE_NGHTTP2
    378     if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
    379       protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
    380       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
    381     }
    382 #endif
    383 
    384     protocols[cur++] = ALPN_HTTP_1_1;
    385     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
    386 
    387     protocols[cur] = NULL;
    388 
    389     ssl_set_alpn_protocols(&connssl->ssl, protocols);
    390   }
    391 #endif
    392 
    393 #ifdef POLARSSL_DEBUG
    394   ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
    395 #endif
    396 
    397   connssl->connecting_state = ssl_connect_2;
    398 
    399   return CURLE_OK;
    400 }
    401 
    402 static CURLcode
    403 polarssl_connect_step2(struct connectdata *conn,
    404                      int sockindex)
    405 {
    406   int ret;
    407   struct Curl_easy *data = conn->data;
    408   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
    409   char buffer[1024];
    410 
    411   char errorbuf[128];
    412   errorbuf[0] = 0;
    413 
    414   conn->recv[sockindex] = polarssl_recv;
    415   conn->send[sockindex] = polarssl_send;
    416 
    417   ret = ssl_handshake(&connssl->ssl);
    418 
    419   switch(ret) {
    420   case 0:
    421     break;
    422 
    423   case POLARSSL_ERR_NET_WANT_READ:
    424     connssl->connecting_state = ssl_connect_2_reading;
    425     return CURLE_OK;
    426 
    427   case POLARSSL_ERR_NET_WANT_WRITE:
    428     connssl->connecting_state = ssl_connect_2_writing;
    429     return CURLE_OK;
    430 
    431   default:
    432 #ifdef POLARSSL_ERROR_C
    433     error_strerror(ret, errorbuf, sizeof(errorbuf));
    434 #endif /* POLARSSL_ERROR_C */
    435     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
    436           -ret, errorbuf);
    437     return CURLE_SSL_CONNECT_ERROR;
    438   }
    439 
    440   infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
    441         ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
    442 
    443   ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
    444 
    445   if(ret && data->set.ssl.verifypeer) {
    446     if(ret & BADCERT_EXPIRED)
    447       failf(data, "Cert verify failed: BADCERT_EXPIRED");
    448 
    449     if(ret & BADCERT_REVOKED) {
    450       failf(data, "Cert verify failed: BADCERT_REVOKED");
    451       return CURLE_SSL_CACERT;
    452     }
    453 
    454     if(ret & BADCERT_CN_MISMATCH)
    455       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
    456 
    457     if(ret & BADCERT_NOT_TRUSTED)
    458       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
    459 
    460     return CURLE_PEER_FAILED_VERIFICATION;
    461   }
    462 
    463   if(ssl_get_peer_cert(&(connssl->ssl))) {
    464     /* If the session was resumed, there will be no peer certs */
    465     memset(buffer, 0, sizeof(buffer));
    466 
    467     if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
    468                      ssl_get_peer_cert(&(connssl->ssl))) != -1)
    469       infof(data, "Dumping cert info:\n%s\n", buffer);
    470   }
    471 
    472   /* adapted from mbedtls.c */
    473   if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
    474     int size;
    475     CURLcode result;
    476     x509_crt *p;
    477     unsigned char pubkey[PUB_DER_MAX_BYTES];
    478     const x509_crt *peercert;
    479 
    480     peercert = ssl_get_peer_cert(&connssl->ssl);
    481 
    482     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
    483       failf(data, "Failed due to missing peer certificate");
    484       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    485     }
    486 
    487     p = calloc(1, sizeof(*p));
    488 
    489     if(!p)
    490       return CURLE_OUT_OF_MEMORY;
    491 
    492     x509_crt_init(p);
    493 
    494     /* Make a copy of our const peercert because pk_write_pubkey_der
    495        needs a non-const key, for now.
    496        https://github.com/ARMmbed/mbedtls/issues/396 */
    497     if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
    498       failf(data, "Failed copying peer certificate");
    499       x509_crt_free(p);
    500       free(p);
    501       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    502     }
    503 
    504     size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
    505 
    506     if(size <= 0) {
    507       failf(data, "Failed copying public key from peer certificate");
    508       x509_crt_free(p);
    509       free(p);
    510       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    511     }
    512 
    513     /* pk_write_pubkey_der writes data at the end of the buffer. */
    514     result = Curl_pin_peer_pubkey(data,
    515                                   data->set.str[STRING_SSL_PINNEDPUBLICKEY],
    516                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
    517     if(result) {
    518       x509_crt_free(p);
    519       free(p);
    520       return result;
    521     }
    522 
    523     x509_crt_free(p);
    524     free(p);
    525   }
    526 
    527 #ifdef HAS_ALPN
    528   if(conn->bits.tls_enable_alpn) {
    529     const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
    530 
    531     if(next_protocol != NULL) {
    532       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
    533 
    534 #ifdef USE_NGHTTP2
    535       if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
    536                   NGHTTP2_PROTO_VERSION_ID_LEN)) {
    537         conn->negnpn = CURL_HTTP_VERSION_2;
    538       }
    539       else
    540 #endif
    541       if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
    542         conn->negnpn = CURL_HTTP_VERSION_1_1;
    543       }
    544     }
    545     else
    546       infof(data, "ALPN, server did not agree to a protocol\n");
    547   }
    548 #endif
    549 
    550   connssl->connecting_state = ssl_connect_3;
    551   infof(data, "SSL connected\n");
    552 
    553   return CURLE_OK;
    554 }
    555 
    556 static CURLcode
    557 polarssl_connect_step3(struct connectdata *conn,
    558                      int sockindex)
    559 {
    560   CURLcode retcode = CURLE_OK;
    561   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    562   struct Curl_easy *data = conn->data;
    563 
    564   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
    565 
    566   if(conn->ssl_config.sessionid) {
    567     int ret;
    568     ssl_session *our_ssl_sessionid;
    569     void *old_ssl_sessionid = NULL;
    570 
    571     our_ssl_sessionid = malloc(sizeof(ssl_session));
    572     if(!our_ssl_sessionid)
    573       return CURLE_OUT_OF_MEMORY;
    574 
    575     ssl_session_init(our_ssl_sessionid);
    576 
    577     ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
    578     if(ret) {
    579       failf(data, "ssl_get_session returned -0x%x", -ret);
    580       return CURLE_SSL_CONNECT_ERROR;
    581     }
    582 
    583     /* If there's already a matching session in the cache, delete it */
    584     Curl_ssl_sessionid_lock(conn);
    585     if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
    586       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
    587 
    588     retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
    589     Curl_ssl_sessionid_unlock(conn);
    590     if(retcode) {
    591       free(our_ssl_sessionid);
    592       failf(data, "failed to store ssl session");
    593       return retcode;
    594     }
    595   }
    596 
    597   connssl->connecting_state = ssl_connect_done;
    598 
    599   return CURLE_OK;
    600 }
    601 
    602 static ssize_t polarssl_send(struct connectdata *conn,
    603                              int sockindex,
    604                              const void *mem,
    605                              size_t len,
    606                              CURLcode *curlcode)
    607 {
    608   int ret = -1;
    609 
    610   ret = ssl_write(&conn->ssl[sockindex].ssl,
    611                   (unsigned char *)mem, len);
    612 
    613   if(ret < 0) {
    614     *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
    615       CURLE_AGAIN : CURLE_SEND_ERROR;
    616     ret = -1;
    617   }
    618 
    619   return ret;
    620 }
    621 
    622 void Curl_polarssl_close(struct connectdata *conn, int sockindex)
    623 {
    624   rsa_free(&conn->ssl[sockindex].rsa);
    625   x509_crt_free(&conn->ssl[sockindex].clicert);
    626   x509_crt_free(&conn->ssl[sockindex].cacert);
    627   x509_crl_free(&conn->ssl[sockindex].crl);
    628   ssl_free(&conn->ssl[sockindex].ssl);
    629 }
    630 
    631 static ssize_t polarssl_recv(struct connectdata *conn,
    632                              int num,
    633                              char *buf,
    634                              size_t buffersize,
    635                              CURLcode *curlcode)
    636 {
    637   int ret = -1;
    638   ssize_t len = -1;
    639 
    640   memset(buf, 0, buffersize);
    641   ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
    642 
    643   if(ret <= 0) {
    644     if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
    645       return 0;
    646 
    647     *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
    648       CURLE_AGAIN : CURLE_RECV_ERROR;
    649     return -1;
    650   }
    651 
    652   len = ret;
    653 
    654   return len;
    655 }
    656 
    657 void Curl_polarssl_session_free(void *ptr)
    658 {
    659   ssl_session_free(ptr);
    660   free(ptr);
    661 }
    662 
    663 /* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
    664    higher) will be mbed TLS branded.. */
    665 
    666 size_t Curl_polarssl_version(char *buffer, size_t size)
    667 {
    668   unsigned int version = version_get_number();
    669   return snprintf(buffer, size, "%s/%d.%d.%d",
    670                   version >= 0x01030A00?"mbedTLS":"PolarSSL",
    671                   version>>24, (version>>16)&0xff, (version>>8)&0xff);
    672 }
    673 
    674 static CURLcode
    675 polarssl_connect_common(struct connectdata *conn,
    676                         int sockindex,
    677                         bool nonblocking,
    678                         bool *done)
    679 {
    680   CURLcode result;
    681   struct Curl_easy *data = conn->data;
    682   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    683   curl_socket_t sockfd = conn->sock[sockindex];
    684   long timeout_ms;
    685   int what;
    686 
    687   /* check if the connection has already been established */
    688   if(ssl_connection_complete == connssl->state) {
    689     *done = TRUE;
    690     return CURLE_OK;
    691   }
    692 
    693   if(ssl_connect_1 == connssl->connecting_state) {
    694     /* Find out how much more time we're allowed */
    695     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    696 
    697     if(timeout_ms < 0) {
    698       /* no need to continue if time already is up */
    699       failf(data, "SSL connection timeout");
    700       return CURLE_OPERATION_TIMEDOUT;
    701     }
    702 
    703     result = polarssl_connect_step1(conn, sockindex);
    704     if(result)
    705       return result;
    706   }
    707 
    708   while(ssl_connect_2 == connssl->connecting_state ||
    709         ssl_connect_2_reading == connssl->connecting_state ||
    710         ssl_connect_2_writing == connssl->connecting_state) {
    711 
    712     /* check allowed time left */
    713     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    714 
    715     if(timeout_ms < 0) {
    716       /* no need to continue if time already is up */
    717       failf(data, "SSL connection timeout");
    718       return CURLE_OPERATION_TIMEDOUT;
    719     }
    720 
    721     /* if ssl is expecting something, check if it's available. */
    722     if(connssl->connecting_state == ssl_connect_2_reading ||
    723        connssl->connecting_state == ssl_connect_2_writing) {
    724 
    725       curl_socket_t writefd = ssl_connect_2_writing==
    726         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    727       curl_socket_t readfd = ssl_connect_2_reading==
    728         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    729 
    730       what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
    731       if(what < 0) {
    732         /* fatal error */
    733         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
    734         return CURLE_SSL_CONNECT_ERROR;
    735       }
    736       else if(0 == what) {
    737         if(nonblocking) {
    738           *done = FALSE;
    739           return CURLE_OK;
    740         }
    741         else {
    742           /* timeout */
    743           failf(data, "SSL connection timeout");
    744           return CURLE_OPERATION_TIMEDOUT;
    745         }
    746       }
    747       /* socket is readable or writable */
    748     }
    749 
    750     /* Run transaction, and return to the caller if it failed or if
    751      * this connection is part of a multi handle and this loop would
    752      * execute again. This permits the owner of a multi handle to
    753      * abort a connection attempt before step2 has completed while
    754      * ensuring that a client using select() or epoll() will always
    755      * have a valid fdset to wait on.
    756      */
    757     result = polarssl_connect_step2(conn, sockindex);
    758     if(result || (nonblocking &&
    759                   (ssl_connect_2 == connssl->connecting_state ||
    760                    ssl_connect_2_reading == connssl->connecting_state ||
    761                    ssl_connect_2_writing == connssl->connecting_state)))
    762       return result;
    763 
    764   } /* repeat step2 until all transactions are done. */
    765 
    766   if(ssl_connect_3 == connssl->connecting_state) {
    767     result = polarssl_connect_step3(conn, sockindex);
    768     if(result)
    769       return result;
    770   }
    771 
    772   if(ssl_connect_done == connssl->connecting_state) {
    773     connssl->state = ssl_connection_complete;
    774     conn->recv[sockindex] = polarssl_recv;
    775     conn->send[sockindex] = polarssl_send;
    776     *done = TRUE;
    777   }
    778   else
    779     *done = FALSE;
    780 
    781   /* Reset our connect state machine */
    782   connssl->connecting_state = ssl_connect_1;
    783 
    784   return CURLE_OK;
    785 }
    786 
    787 CURLcode
    788 Curl_polarssl_connect_nonblocking(struct connectdata *conn,
    789                                 int sockindex,
    790                                 bool *done)
    791 {
    792   return polarssl_connect_common(conn, sockindex, TRUE, done);
    793 }
    794 
    795 
    796 CURLcode
    797 Curl_polarssl_connect(struct connectdata *conn,
    798                     int sockindex)
    799 {
    800   CURLcode result;
    801   bool done = FALSE;
    802 
    803   result = polarssl_connect_common(conn, sockindex, FALSE, &done);
    804   if(result)
    805     return result;
    806 
    807   DEBUGASSERT(done);
    808 
    809   return CURLE_OK;
    810 }
    811 
    812 /*
    813  * return 0 error initializing SSL
    814  * return 1 SSL initialized successfully
    815  */
    816 int Curl_polarssl_init(void)
    817 {
    818   return Curl_polarsslthreadlock_thread_setup();
    819 }
    820 
    821 void Curl_polarssl_cleanup(void)
    822 {
    823   (void)Curl_polarsslthreadlock_thread_cleanup();
    824 }
    825 
    826 #endif /* USE_POLARSSL */
    827