summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls/mbedtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/mbedtls.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c250
1 files changed, 188 insertions, 62 deletions
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 24249dd..3ffa957 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,11 +31,15 @@
#ifdef USE_MBEDTLS
+#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER >= 0x02040000
#include <mbedtls/net_sockets.h>
+#else
+#include <mbedtls/net.h>
+#endif
#include <mbedtls/ssl.h>
#include <mbedtls/certs.h>
#include <mbedtls/x509.h>
-#include <mbedtls/version.h>
#include <mbedtls/error.h>
#include <mbedtls/entropy.h>
@@ -153,19 +157,91 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
static Curl_recv mbed_recv;
static Curl_send mbed_send;
+static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
+{
+ switch(version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_1:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_2:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+static CURLcode
+set_ssl_version_min_max(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
+ int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+ long ssl_version = SSL_CONN_CONFIG(version);
+ long ssl_version_max = SSL_CONN_CONFIG(version_max);
+ CURLcode result = CURLE_OK;
+
+ switch(ssl_version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ ssl_version = CURL_SSLVERSION_TLSv1_0;
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ switch(ssl_version_max) {
+ case CURL_SSLVERSION_MAX_NONE:
+ ssl_version_max = ssl_version << 16;
+ break;
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
+ }
+
+ result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
+ if(result) {
+ failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+ result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
+ if(result) {
+ failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
+ return result;
+ }
+
+ mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_min);
+ mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+ mbedtls_ver_max);
+
+ return result;
+}
+
static CURLcode
mbed_connect_step1(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-
+ const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ char * const ssl_cert = SSL_SET_OPTION(cert);
+ const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+ const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
int ret = -1;
char errorbuf[128];
errorbuf[0]=0;
/* mbedTLS only supports SSLv3 and TLSv1 */
- if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
failf(data, "mbedTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -201,34 +277,32 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the trusted CA */
mbedtls_x509_crt_init(&connssl->cacert);
- if(data->set.str[STRING_SSL_CAFILE]) {
- ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
- data->set.str[STRING_SSL_CAFILE]);
+ if(ssl_cafile) {
+ ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+ ssl_cafile, -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
}
- if(data->set.str[STRING_SSL_CAPATH]) {
- ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
- data->set.str[STRING_SSL_CAPATH]);
+ if(ssl_capath) {
+ ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
if(ret<0) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+ ssl_capath, -ret, errorbuf);
- if(data->set.ssl.verifypeer)
+ if(verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
}
@@ -236,16 +310,15 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the client certificate */
mbedtls_x509_crt_init(&connssl->clicert);
- if(data->set.str[STRING_CERT]) {
- ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
- data->set.str[STRING_CERT]);
+ if(ssl_cert) {
+ ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_CERT], -ret, errorbuf);
+ ssl_cert, -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
@@ -254,9 +327,9 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the client private key */
mbedtls_pk_init(&connssl->pk);
- if(data->set.str[STRING_KEY]) {
- ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
- data->set.str[STRING_KEY_PASSWD]);
+ if(SSL_SET_OPTION(key)) {
+ ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd));
if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
@@ -265,7 +338,7 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_KEY], -ret, errorbuf);
+ SSL_SET_OPTION(key), -ret, errorbuf);
return CURLE_SSL_CERTPROBLEM;
}
@@ -274,23 +347,21 @@ mbed_connect_step1(struct connectdata *conn,
/* Load the CRL */
mbedtls_x509_crl_init(&connssl->crl);
- if(data->set.str[STRING_SSL_CRLFILE]) {
- ret = mbedtls_x509_crl_parse_file(&connssl->crl,
- data->set.str[STRING_SSL_CRLFILE]);
+ if(ssl_crlfile) {
+ ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
- data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+ ssl_crlfile, -ret, errorbuf);
return CURLE_SSL_CRL_BADFILE;
}
}
- infof(data, "mbedTLS: Connecting to %s:%d\n",
- conn->host.name, conn->remote_port);
+ infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
mbedtls_ssl_config_init(&connssl->config);
@@ -312,7 +383,7 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_conf_cert_profile(&connssl->config,
&mbedtls_x509_crt_profile_fr);
- switch(data->set.ssl.version) {
+ switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
@@ -327,28 +398,17 @@ mbed_connect_step1(struct connectdata *conn,
infof(data, "mbedTLS: Set SSL version to SSLv3\n");
break;
case CURL_SSLVERSION_TLSv1_0:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_1);
- infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
- break;
case CURL_SSLVERSION_TLSv1_1:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_2);
- infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
- break;
case CURL_SSLVERSION_TLSv1_2:
- mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
- MBEDTLS_SSL_MINOR_VERSION_3);
- infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
- break;
+ case CURL_SSLVERSION_TLSv1_3:
+ {
+ CURLcode result = set_ssl_version_min_max(conn, sockindex);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
default:
- failf(data, "mbedTLS: Unsupported SSL protocol version");
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -364,12 +424,17 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_conf_ciphersuites(&connssl->config,
mbedtls_ssl_list_ciphersuites());
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+ mbedtls_ssl_conf_session_tickets(&connssl->config,
+ MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
+#endif
+
/* Check if there's a cached ID we can/should use here! */
- if(conn->ssl_config.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+ if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
if(ret) {
Curl_ssl_sessionid_unlock(conn);
@@ -385,11 +450,11 @@ mbed_connect_step1(struct connectdata *conn,
&connssl->cacert,
&connssl->crl);
- if(data->set.str[STRING_KEY]) {
+ if(SSL_SET_OPTION(key)) {
mbedtls_ssl_conf_own_cert(&connssl->config,
&connssl->clicert, &connssl->pk);
}
- if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+ if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -430,6 +495,16 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_debug_set_threshold(4);
#endif
+ /* give application a chance to interfere with mbedTLS set up. */
+ if(data->set.ssl.fsslctx) {
+ ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+ data->set.ssl.fsslctxp);
+ if(ret) {
+ failf(data, "error signaled by ssl ctx callback");
+ return ret;
+ }
+ }
+
connssl->connecting_state = ssl_connect_2;
return CURLE_OK;
@@ -443,9 +518,12 @@ mbed_connect_step2(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex];
const mbedtls_x509_crt *peercert;
+ const char * const pinnedpubkey = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
#ifdef HAS_ALPN
- const char* next_protocol;
+ const char *next_protocol;
#endif
char errorbuf[128];
@@ -479,7 +557,7 @@ mbed_connect_step2(struct connectdata *conn,
ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
- if(ret && data->set.ssl.verifypeer) {
+ if(ret && SSL_CONN_CONFIG(verifypeer)) {
if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
failf(data, "Cert verify failed: BADCERT_EXPIRED");
@@ -514,7 +592,7 @@ mbed_connect_step2(struct connectdata *conn,
free(buffer);
}
- if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ if(pinnedpubkey) {
int size;
CURLcode result;
mbedtls_x509_crt *p;
@@ -553,7 +631,7 @@ mbed_connect_step2(struct connectdata *conn,
/* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
result = Curl_pin_peer_pubkey(data,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ pinnedpubkey,
&pubkey[PUB_DER_MAX_BYTES - size], size);
if(result) {
mbedtls_x509_crt_free(p);
@@ -606,7 +684,7 @@ mbed_connect_step3(struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- if(conn->ssl_config.sessionid) {
+ if(SSL_SET_OPTION(primary.sessionid)) {
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
@@ -619,16 +697,17 @@ mbed_connect_step3(struct connectdata *conn,
ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
if(ret) {
+ free(our_ssl_sessionid);
failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
/* If there's already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+ if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+ retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
Curl_ssl_sessionid_unlock(conn);
if(retcode) {
free(our_ssl_sessionid);
@@ -717,6 +796,55 @@ size_t Curl_mbedtls_version(char *buffer, size_t size)
(version>>16)&0xff, (version>>8)&0xff);
}
+CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
+ size_t length)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+ int ret = -1;
+ char errorbuf[128];
+ mbedtls_entropy_context ctr_entropy;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_entropy_init(&ctr_entropy);
+ mbedtls_ctr_drbg_init(&ctr_drbg);
+ errorbuf[0]=0;
+
+ ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
+ &ctr_entropy, NULL, 0);
+
+ if(ret) {
+#ifdef MBEDTLS_ERROR_C
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* MBEDTLS_ERROR_C */
+ failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+ else {
+ ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
+
+ if(ret) {
+#ifdef MBEDTLS_ERROR_C
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+#endif /* MBEDTLS_ERROR_C */
+ failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
+ -ret, errorbuf);
+ }
+ }
+
+ mbedtls_ctr_drbg_free(&ctr_drbg);
+ mbedtls_entropy_free(&ctr_entropy);
+
+ return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
+#elif defined(MBEDTLS_HAVEGE_C)
+ mbedtls_havege_state hs;
+ mbedtls_havege_init(&hs);
+ mbedtls_havege_random(&hs, entropy, length);
+ mbedtls_havege_free(&hs);
+ return CURLE_OK;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
+}
+
static CURLcode
mbed_connect_common(struct connectdata *conn,
int sockindex,
@@ -871,9 +999,7 @@ void Curl_mbedtls_cleanup(void)
int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
{
- mbedtls_ssl_context *ssl =
- (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl;
- return ssl->in_msglen != 0;
+ return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
}
#endif /* USE_MBEDTLS */