in network/MbedTLS/MbedTLSConnection.cpp [100:276]
ResponseCode MbedTLSConnection::ConnectInternal() {
ResponseCode rc = ResponseCode::SUCCESS;
int ret = 0;
const util::String pers = "aws_iot_tls_wrapper";
char port_buf[6];
char vrfy_buf[512];
const char* alpn_protocol_list[] = {"x-amzn-mqtt-ca", nullptr};
mbedtls_net_init(&server_fd_);
mbedtls_ssl_init(&ssl_);
mbedtls_ssl_config_init(&conf_);
mbedtls_ctr_drbg_init(&ctr_drbg_);
mbedtls_x509_crt_init(&cacert_);
mbedtls_x509_crt_init(&clicert_);
mbedtls_pk_init(&pkey_);
if (enable_alpn_) {
#ifdef MBEDTLS_SSL_ALPN
if (0 != mbedtls_ssl_conf_alpn_protocols(&conf_, alpn_protocol_list)) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " SSL INIT Failed - Unable to set ALPN options");
return ResponseCode::NETWORK_SSL_INIT_ERROR;
}
#else
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " SSL INIT Failed - No ALPN support");
return ResponseCode::NETWORK_SSL_INIT_ERROR;
#endif
}
requires_free_ = true;
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "...............................%d", MBEDTLS_SSL_MAX_CONTENT_LEN);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Seeding the random number generator...");
mbedtls_entropy_init(&entropy_);
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_,
(const unsigned char *) (pers.c_str()), pers.length())) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " Connect Failed!!! mbedtls_ctr_drbg_seed returned -0x%x", -ret);
return ResponseCode::NETWORK_SSL_INIT_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Loading the CA root certificate... %s", root_ca_location_.c_str());
ret = mbedtls_x509_crt_parse_file(&cacert_, root_ca_location_.c_str());
if (ret < 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
"Failed!!! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n",
-ret);
return ResponseCode::NETWORK_SSL_ROOT_CRT_PARSE_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "ok (%d skipped)\n", ret);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Loading the client cert. and key...");
ret = mbedtls_x509_crt_parse_file(&clicert_, device_cert_location_.c_str());
if (ret != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
"Failed!!! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n",
-ret);
return ResponseCode::NETWORK_SSL_DEVICE_CRT_PARSE_ERROR;
}
ret = mbedtls_pk_parse_keyfile(&pkey_, device_private_key_location_.c_str(), "");
if (ret != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
"Failed!!! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n",
-ret);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " path : %s ", device_private_key_location_.c_str());
return ResponseCode::NETWORK_SSL_KEY_PARSE_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " ok\n");
snprintf(port_buf, MAX_CHARS_IN_PORT_NUMBER, "%d", endpoint_port_);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Connecting to %s/%s...", endpoint_.c_str(), port_buf);
if ((ret = mbedtls_net_connect(&server_fd_, endpoint_.c_str(), port_buf, MBEDTLS_NET_PROTO_TCP)) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_net_connect returned -0x%x\n\n", -ret);
switch (ret) {
case MBEDTLS_ERR_NET_SOCKET_FAILED:
return ResponseCode::NETWORK_TCP_SETUP_ERROR;
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
return ResponseCode::NETWORK_TCP_UNKNOWN_HOST;
case MBEDTLS_ERR_NET_CONNECT_FAILED:
default:
return ResponseCode::NETWORK_TCP_CONNECT_ERROR;
};
}
ret = mbedtls_net_set_block(&server_fd_);
if (ret != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! net_set_(non)block() returned -0x%x\n\n", -ret);
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "Ok!");
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(&conf_, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG,
"Failed!!! mbedtls_ssl_config_defaults returned -0x%x\n\n",
-ret);
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
}
mbedtls_ssl_conf_verify(&conf_, &MbedTLSConnection::VerifyCertificate, NULL);
if (server_verification_flag_) {
mbedtls_ssl_conf_authmode(&conf_, MBEDTLS_SSL_VERIFY_REQUIRED);
} else {
mbedtls_ssl_conf_authmode(&conf_, MBEDTLS_SSL_VERIFY_OPTIONAL);
}
mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_);
mbedtls_ssl_conf_ca_chain(&conf_, &cacert_, NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&conf_, &clicert_, &pkey_)) !=
0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
}
mbedtls_ssl_conf_read_timeout(&conf_, static_cast<uint32_t>(tls_handshake_timeout_.count()));
if ((ret = mbedtls_ssl_set_hostname(&ssl_, endpoint_.c_str())) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_set_hostname returned %d\n\n", ret);
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "\n\nSSL state connect : %d ", ssl_.state);
mbedtls_ssl_set_bio(&ssl_, &server_fd_, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "Ok!");
if ((ret = mbedtls_ssl_setup(&ssl_, &conf_)) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
return ResponseCode::NETWORK_SSL_UNKNOWN_ERROR;
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "\n\nSSL state connect : %d ", ssl_.state);
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Performing the SSL/TLS handshake...");
while ((ret = mbedtls_ssl_handshake(&ssl_)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "Failed!!! mbedtls_ssl_handshake returned -0x%x\n", -ret);
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " Unable to verify the server's certificate. "
"Either it is invalid,\n"
" or you didn't set ca_file or ca_path "
"to an appropriate value.\n"
" Alternatively, you may want to use "
"auth_mode=optional for testing purposes.\n");
}
return ResponseCode::NETWORK_SSL_TLS_HANDSHAKE_ERROR;
}
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG,
" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
mbedtls_ssl_get_version(&ssl_),
mbedtls_ssl_get_ciphersuite(&ssl_));
if ((ret = mbedtls_ssl_get_record_expansion(&ssl_)) >= 0) {
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " [ Record expansion is %d ]\n", ret);
} else {
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " [ Record expansion is unknown (compression) ]\n");
}
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, "....Verifying peer X.509 certificate...");
if (server_verification_flag_) {
if ((flags_ = mbedtls_ssl_get_verify_result(&ssl_)) != 0) {
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, " failed\n");
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags_);
AWS_LOG_ERROR(MBEDTLS_WRAPPER_LOG_TAG, "%s\n", vrfy_buf);
rc = ResponseCode::NETWORK_SSL_SERVER_VERIFICATION_ERROR;
} else {
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " ok\n");
rc = ResponseCode::SUCCESS;
}
} else {
AWS_LOG_INFO(MBEDTLS_WRAPPER_LOG_TAG, " Server Verification skipped\n");
rc = ResponseCode::SUCCESS;
}
mbedtls_ssl_conf_read_timeout(&conf_, static_cast<uint32_t>(tls_read_timeout_.count()));
is_connected_ = true;
return rc;
}