mbedtls.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
00009  * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00010  *
00011  * This software is licensed as described in the file COPYING, which
00012  * you should have received as part of this distribution. The terms
00013  * are also available at https://curl.haxx.se/docs/copyright.html.
00014  *
00015  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00016  * copies of the Software, and permit persons to whom the Software is
00017  * furnished to do so, under the terms of the COPYING file.
00018  *
00019  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00020  * KIND, either express or implied.
00021  *
00022  ***************************************************************************/
00023 
00024 /*
00025  * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code
00026  * but vtls.c should ever call or use these functions.
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" /* for the connect timeout */
00056 #include "select.h"
00057 #include "polarssl_threadlock.h"
00058 
00059 /* The last 3 #include files should be in this order */
00060 #include "curl_printf.h"
00061 #include "curl_memory.h"
00062 #include "memdebug.h"
00063 
00064 /* apply threading? */
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 /* start of entropy_init_mutex() */
00075 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
00076 {
00077   /* lock 0 = entropy_init_mutex() */
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 /* end of entropy_init_mutex() */
00086 
00087 /* start of entropy_func_mutex() */
00088 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
00089 {
00090   int ret;
00091   /* lock 1 = entropy_func_mutex() */
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 /* end of entropy_func_mutex() */
00099 
00100 #endif /* THREADING_SUPPORT */
00101 
00102 /* Define this to enable lots of debugging for mbedTLS */
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 /* ALPN for http2? */
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  *  profile
00133  */
00134 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
00135 {
00136   /* Hashes from SHA-1 and above */
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, /* Any PK alg    */
00144   0xFFFFFFF, /* Any curve     */
00145   1024,      /* RSA min key len */
00146 };
00147 
00148 /* See https://tls.mbed.org/discussions/generic/
00149    howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
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   /* mbedTLS only supports SSLv3 and TLSv1 */
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 /* MBEDTLS_ERROR_C */
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 /* MBEDTLS_ERROR_C */
00207     failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
00208           -ret, errorbuf);
00209   }
00210 #endif /* THREADING_SUPPORT */
00211 
00212   /* Load the trusted CA */
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 /* MBEDTLS_ERROR_C */
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 /* MBEDTLS_ERROR_C */
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   /* Load the client certificate */
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 /* MBEDTLS_ERROR_C */
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   /* Load the client private key */
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 /* MBEDTLS_ERROR_C */
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   /* Load the CRL */
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 /* MBEDTLS_ERROR_C */
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   /* new profile with RSA min key len = 1024 ... */
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 /*  rev_timeout() */);
00372 
00373   mbedtls_ssl_conf_ciphersuites(&connssl->config,
00374                                 mbedtls_ssl_list_ciphersuites());
00375 
00376   /* Check if there's a cached ID we can/should use here! */
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     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
00403        the name to set in the SNI extension. So even if curl connects to a
00404        host specified as an IP address, this function must be used. */
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     /* this function doesn't clone the protocols array, which is why we need
00419        to keep it around */
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   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
00432   mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
00433   /* - 0 No debug
00434    * - 1 Error
00435    * - 2 State change
00436    * - 3 Informational
00437    * - 4 Verbose
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 /* MBEDTLS_ERROR_C */
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     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
00548        needs a non-const key, for now.
00549        https://github.com/ARMmbed/mbedtls/issues/396 */
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     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
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     /* If there's already a matching session in the cache, delete it */
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 /* THREADING_SUPPORT */
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   /* check if the connection has already been established */
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     /* Find out how much more time we're allowed */
00753     timeout_ms = Curl_timeleft(data, NULL, TRUE);
00754 
00755     if(timeout_ms < 0) {
00756       /* no need to continue if time already is up */
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     /* check allowed time left */
00770     timeout_ms = Curl_timeleft(data, NULL, TRUE);
00771 
00772     if(timeout_ms < 0) {
00773       /* no need to continue if time already is up */
00774       failf(data, "SSL connection timeout");
00775       return CURLE_OPERATION_TIMEDOUT;
00776     }
00777 
00778     /* if ssl is expecting something, check if it's available. */
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         /* fatal error */
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           /* timeout */
00801           failf(data, "SSL connection timeout");
00802           return CURLE_OPERATION_TIMEDOUT;
00803         }
00804       }
00805       /* socket is readable or writable */
00806     }
00807 
00808     /* Run transaction, and return to the caller if it failed or if
00809      * this connection is part of a multi handle and this loop would
00810      * execute again. This permits the owner of a multi handle to
00811      * abort a connection attempt before step2 has completed while
00812      * ensuring that a client using select() or epoll() will always
00813      * have a valid fdset to wait on.
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   } /* repeat step2 until all transactions are done. */
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   /* Reset our connect state machine */
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  * return 0 error initializing SSL
00872  * return 1 SSL initialized successfully
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 /* USE_MBEDTLS */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:05