void _ssl_set_alpn_list(const SSL *ssl) { if (!ssl->ctx->alpn_protos) return; if (mbedtls_ssl_conf_alpn_protocols(&((struct ssl_pm *)(ssl->ssl_pm))->conf, ssl->ctx->alpn_protos)) fprintf(stderr, "mbedtls_ssl_conf_alpn_protocols failed\n"); }
static CURLcode mbed_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif void *old_session = NULL; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, &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_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&connssl->entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, &connssl->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_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* 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(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); if(data->set.ssl.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(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); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* 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(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); return CURLE_SSL_CERTPROBLEM; } } /* 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(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C 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); return CURLE_SSL_CERTPROBLEM; } } /* 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(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); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", conn->host.name, conn->remote_port); mbedtls_ssl_config_init(&connssl->config); mbedtls_ssl_init(&connssl->ssl); if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&connssl->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile(&connssl->config, &mbedtls_x509_crt_profile_fr); switch(data->set.ssl.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); 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; default: failf(data, "mbedTLS: Unsupported SSL protocol version"); return CURLE_SSL_CONNECT_ERROR; } mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random, &connssl->ctr_drbg); mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { ret = mbedtls_ssl_set_session(&connssl->ssl, old_session); if(ret) { failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS re-using session\n"); } mbedtls_ssl_conf_ca_chain(&connssl->config, &connssl->cacert, &connssl->crl); if(data->set.str[STRING_KEY]) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { /* 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. */ failf(data, "couldn't set hostname in mbedTLS"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { const char **p = &connssl->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, &connssl->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &connssl->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG mbedtls_ssl_conf_dbg(&connssl->config, mbedtls_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
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(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT entropy_init_mutex(&ts_entropy); mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, &ts_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_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&BACKEND->entropy); mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, &BACKEND->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_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ mbedtls_x509_crt_init(&BACKEND->cacert); if(ssl_cafile) { ret = mbedtls_x509_crt_parse_file(&BACKEND->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", ssl_cafile, -ret, errorbuf); if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(ssl_capath) { ret = mbedtls_x509_crt_parse_path(&BACKEND->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", ssl_capath, -ret, errorbuf); if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ mbedtls_x509_crt_init(&BACKEND->clicert); if(ssl_cert) { ret = mbedtls_x509_crt_parse_file(&BACKEND->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", ssl_cert, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ mbedtls_pk_init(&BACKEND->pk); if(SSL_SET_OPTION(key)) { ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ mbedtls_x509_crl_init(&BACKEND->crl); if(ssl_crlfile) { ret = mbedtls_x509_crl_parse_file(&BACKEND->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", ssl_crlfile, -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); mbedtls_ssl_config_init(&BACKEND->config); mbedtls_ssl_init(&BACKEND->ssl); if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&BACKEND->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile(&BACKEND->config, &mbedtls_x509_crt_profile_fr); switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Set SSL version to SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { CURLcode result = set_ssl_version_min_max(conn, sockindex); if(result != CURLE_OK) return result; break; } default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, &BACKEND->ctr_drbg); mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&BACKEND->config, mbedtls_ssl_list_ciphersuites()); #if defined(MBEDTLS_SSL_RENEGOTIATION) mbedtls_ssl_conf_renegotiation(&BACKEND->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_session_tickets(&BACKEND->config, MBEDTLS_SSL_SESSION_TICKETS_DISABLED); #endif /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS re-using session\n"); } Curl_ssl_sessionid_unlock(conn); } mbedtls_ssl_conf_ca_chain(&BACKEND->config, &BACKEND->cacert, &BACKEND->crl); if(SSL_SET_OPTION(key)) { mbedtls_ssl_conf_own_cert(&BACKEND->config, &BACKEND->clicert, &BACKEND->pk); } if(mbedtls_ssl_set_hostname(&BACKEND->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. */ failf(data, "couldn't set hostname in mbedTLS"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { const char **p = &BACKEND->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config, &BACKEND->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &BACKEND->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data); /* - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose */ 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, &BACKEND->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; }
static CURLcode mbedtls_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif void *old_session = NULL; size_t old_session_size = 0; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, &entropy, connssl->ssn.id, connssl->ssn.id_len); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&connssl->entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, &connssl->entropy, connssl->ssn.id, connssl->ssn.id_len); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(mbedtls_x509_crt)); if(data->set.str[STRING_SSL_CAFILE]) { ret = mbedtls_x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_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); if(data->set.ssl.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(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); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(mbedtls_x509_crt)); if(data->set.str[STRING_CERT]) { ret = mbedtls_x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_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); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(data->set.str[STRING_KEY]) { mbedtls_pk_init(&connssl->pk); ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C 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); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&connssl->crl, 0, sizeof(mbedtls_x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { ret = mbedtls_x509_crl_parse_file(&connssl->crl, data->set.str[STRING_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); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", conn->host.name, conn->remote_port); mbedtls_ssl_config_init(&connssl->config); mbedtls_ssl_init(&connssl->ssl); if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&connssl->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile( &connssl->config, &mbedtls_x509_crt_profile_fr); switch(data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Forced min. SSL Version to be 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); infof(data, "mbedTLS: Forced min. SSL Version to be 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); infof(data, "mbedTLS: Forced min. SSL Version to be 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); infof(data, "mbedTLS: Forced min. SSL Version to be TLS 1.2\n"); break; } mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random, &connssl->ctr_drbg); mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { memcpy(&connssl->ssn, old_session, old_session_size); infof(data, "mbedTLS re-using session\n"); } mbedtls_ssl_set_session(&connssl->ssl, &connssl->ssn); mbedtls_ssl_conf_ca_chain(&connssl->config, &connssl->cacert, &connssl->crl); if(data->set.str[STRING_KEY]) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && #ifdef ENABLE_IPV6 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && #endif sni && mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { infof(data, "WARNING: failed to configure " "server name indication (SNI) TLS extension\n"); } #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { const char *protocols[3]; const char **p = protocols; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, protocols)) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = protocols; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG mbedtls_ssl_conf_dbg(&connssl->ssl, mbedtls_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostlen, const esp_tls_cfg_t *cfg) { int ret; mbedtls_net_init(&tls->server_fd); tls->server_fd.fd = tls->sockfd; mbedtls_ssl_init(&tls->ssl); mbedtls_ctr_drbg_init(&tls->ctr_drbg); mbedtls_ssl_config_init(&tls->conf); mbedtls_entropy_init(&tls->entropy); if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } /* Hostname set here should match CN in server certificate */ char *use_host = strndup(hostname, hostlen); if (!use_host) { goto exit; } if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); free(use_host); goto exit; } free(use_host); if ((ret = mbedtls_ssl_config_defaults(&tls->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); goto exit; } #ifdef CONFIG_MBEDTLS_SSL_ALPN if (cfg->alpn_protos) { mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); } #endif if (cfg->use_global_ca_store == true) { if (global_cacert == NULL) { ESP_LOGE(TAG, "global_cacert is NULL"); goto exit; } tls->cacert_ptr = global_cacert; mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); } else if (cfg->cacert_pem_buf != NULL) { tls->cacert_ptr = &tls->cacert; mbedtls_x509_crt_init(tls->cacert_ptr); ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cfg->cacert_pem_buf, cfg->cacert_pem_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); } else { mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); } if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { mbedtls_x509_crt_init(&tls->clientcert); mbedtls_pk_init(&tls->clientkey); ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->clientkey_pem_buf, cfg->clientkey_pem_bytes, cfg->clientkey_password, cfg->clientkey_password_len); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); goto exit; } ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); goto exit; } } else if (cfg->clientcert_pem_buf != NULL || cfg->clientkey_pem_buf != NULL) { ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication\n\n"); goto exit; } mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&tls->conf, 4); #endif if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); return 0; exit: mbedtls_cleanup(tls); return -1; }
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { int ret = SUCCESS; TLSDataParams *tlsDataParams = NULL; char portBuffer[6]; char info_buf[256]; if(NULL == pNetwork) { return NULL_VALUE_ERROR; } if(NULL != params) { _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); } tlsDataParams = &(pNetwork->tlsDataParams); mbedtls_net_init(&(tlsDataParams->server_fd)); mbedtls_ssl_init(&(tlsDataParams->ssl)); mbedtls_ssl_config_init(&(tlsDataParams->conf)); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); #endif mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); mbedtls_x509_crt_init(&(tlsDataParams->cacert)); mbedtls_x509_crt_init(&(tlsDataParams->clicert)); mbedtls_pk_init(&(tlsDataParams->pkey)); ESP_LOGD(TAG, "Seeding the random number generator..."); mbedtls_entropy_init(&(tlsDataParams->entropy)); if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), (const unsigned char *) TAG, strlen(TAG))) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } /* Load root CA... Certs/keys can be paths or they can be raw data. These use a very basic heuristic: if the cert starts with '/' then it's a path, if it's longer than this then it's raw cert data (PEM or DER, neither of which can start with a slash. */ if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { ESP_LOGD(TAG, "Loading CA root certificate from file ..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); } else { ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); } if(ret < 0) { ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); return NETWORK_X509_ROOT_CRT_PARSE_ERROR; } ESP_LOGD(TAG, "ok (%d skipped)", ret); /* Load client certificate... */ if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { ESP_LOGD(TAG, "Loading client cert from file..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); } else { ESP_LOGD(TAG, "Loading embedded client certificate..."); ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); } if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; } /* Parse client private key... */ if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { ESP_LOGD(TAG, "Loading client private key from file..."); ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); } else { ESP_LOGD(TAG, "Loading embedded client private key..."); ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, (const unsigned char *)"", 0); } if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; } /* Done parsing certs */ ESP_LOGD(TAG, "ok"); snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); switch(ret) { case MBEDTLS_ERR_NET_SOCKET_FAILED: return NETWORK_ERR_NET_SOCKET_FAILED; case MBEDTLS_ERR_NET_UNKNOWN_HOST: return NETWORK_ERR_NET_UNKNOWN_HOST; case MBEDTLS_ERR_NET_CONNECT_FAILED: default: return NETWORK_ERR_NET_CONNECT_FAILED; }; } ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); if(ret != 0) { ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } ESP_LOGD(TAG, "ok"); ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); } mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); #ifdef CONFIG_MBEDTLS_SSL_ALPN /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ if (pNetwork->tlsConnectParams.DestinationPort == 443) { const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } } #endif if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); return SSL_CONNECTION_ERROR; } ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout); ESP_LOGD(TAG, "ok"); ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ESP_LOGE(TAG, " Unable to verify the server's certificate. "); } return SSL_CONNECTION_ERROR; } } ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); } else { ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); } ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { ESP_LOGE(TAG, "failed"); mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); ESP_LOGE(TAG, "%s", info_buf); ret = SSL_CONNECTION_ERROR; } else { ESP_LOGD(TAG, "ok"); ret = SUCCESS; } } else { ESP_LOGW(TAG, " Server Verification skipped"); ret = SUCCESS; } if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { ESP_LOGD(TAG, "Peer certificate information:"); mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); ESP_LOGD(TAG, "%s", info_buf); } } return (IoT_Error_t) ret; }
/** * @brief Start the SSL client. * @param[in] pssl: mbedtls ssl struct. * @param[in] psocket. The underlying file descriptor. * @param[in] server_addr. server address. * @param[in] custom_config: custome config. * @return The result. 0 is ok. */ static int nghttp2_ssl_start(mbedtls_ssl_context *pssl, mbedtls_net_context *psocket, http2_server_addr_t *server_addr, http2_ssl_custom_conf_t *custom_config) { /* * 0. Init */ int ret = -1; /* alpn */ const char *alpn_list[5]; char a[] = "http/1.1"; char b[] = "h2"; char c[] = "h2-14"; char d[] = "h2-16"; alpn_list[0] = b; alpn_list[1] = c; alpn_list[2] = d; alpn_list[3] = a; alpn_list[4] = NULL; if (0 != (ret = nghttp2_ssl_client_init(pssl, psocket, custom_config))) { NGHTTP2_DBG( " failed ! nghttp2_ssl_client_init returned -0x%04x", -ret ); return ret; } NGHTTP2_DBG(" . Connecting to tcp/%s/%4d...", server_addr->host, server_addr->port); /* * 1. Start the connection */ if (0 != (ret = mbedtls_net_connect(psocket, server_addr->host, "443", MBEDTLS_NET_PROTO_TCP))) { NGHTTP2_DBG(" failed ! net_connect returned -0x%04x", -ret); return ret; } NGHTTP2_DBG( " ok" ); /* * 2. Setup stuff */ NGHTTP2_DBG( " . Setting up the SSL/TLS structure..." ); if ( ( ret = mbedtls_ssl_config_defaults( &(custom_config->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { NGHTTP2_DBG( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); return ret; } NGHTTP2_DBG( " ok" ); /* alpn */ if ((ret = mbedtls_ssl_conf_alpn_protocols(&(custom_config->conf), alpn_list)) != 0) { printf("mbedtls_ssl_conf_alpn_protocols failed ret = %d\r\n", ret); return ret; } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &(custom_config->conf), custom_config->common_settings.authmode ); mbedtls_ssl_conf_ca_chain( &(custom_config->conf), &(custom_config->verify_source.cacertl), custom_config->verify_source.ca_crl ); mbedtls_ssl_conf_rng( &(custom_config->conf), custom_config->common_settings.f_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &(custom_config->conf), custom_config->common_settings.f_debug, NULL ); mbedtls_ssl_conf_cert_profile( &(custom_config->conf), &mbedtls_x509_crt_profile_myclient); mbedtls_ssl_conf_ciphersuites(&(custom_config->conf), (const int *)&nghttp2_ciphersuite); if ( ( ret = mbedtls_ssl_setup( pssl, &(custom_config->conf) ) ) != 0 ) { NGHTTP2_DBG( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); return ret; } /* * set host name, related with SNI */ if ( ( ret = mbedtls_ssl_set_hostname(pssl, server_addr->host) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); return ret; } mbedtls_ssl_set_bio( pssl, psocket, custom_config->common_settings.f_send, custom_config->common_settings.f_recv, mbedtls_net_recv_timeout ); mbedtls_ssl_conf_read_timeout(&(custom_config->conf), 10000); mbedtls_ssl_conf_min_version(&(custom_config->conf), MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); /* * 4. Handshake */ NGHTTP2_DBG(". Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(pssl)) != 0) { if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { NGHTTP2_DBG( " failed ! mbedtls_ssl_handshake returned -0x%04x", -ret); return ret; } } { /* you can check if alpn_str is "h2", if not, should fallback to http/1. */ const char *alpn_str = mbedtls_ssl_get_alpn_protocol(pssl); NGHTTP2_DBG("[ application layer protocol chosen is %s ]", alpn_str ? alpn_str : "(none)"); if (alpn_str == NULL) { ret = NOT_SUPPORT_H2; //you can define an value you know return ret; } } NGHTTP2_DBG( " ok" ); /* * 5. Verify the server certificate */ NGHTTP2_DBG(" Verifying peer X.509 certificate..."); http2_verify_source_t *verify_source = &custom_config->verify_source; if ((NULL != verify_source->f_confirm) && (0 != (ret = verify_source->f_confirm(mbedtls_ssl_get_verify_result(pssl))))) { NGHTTP2_DBG(" failed ! verify result not confirmed."); return ret; } return 0; }