static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { char buf[1024]; ((void)data); HTTPS_DEBUG_NORMAL("\nVerify requested for (Depth %d):\n", depth); mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); HTTPS_DEBUG_NORMAL("%s", buf); if ((*flags) == 0) { HTTPS_DEBUG_NORMAL(" This certificate has no flags\n"); } else { HTTPS_DEBUG_NORMAL(buf, sizeof(buf), " ! ", *flags); HTTPS_DEBUG_NORMAL("%s\n", buf); } return 0; } #ifdef MBEDTLS_DEBUG_C static void my_debug(void *ctx, int level, const char *file, int line, const char *str) { ((void)level); HTTPS_DEBUG_NORMAL("\r\n%s, at line %d in file %s\n", str, line, file); } #endif typedef struct _rootcert_struct_ { unsigned char* certname; size_t certsize; } ROOTCERT; ROOTCERT rootCertsList[] = { { AffirmTrust_Commercial, sizeof(AffirmTrust_Commercial) }, { AffirmTrust_Networking, sizeof(AffirmTrust_Networking) }, { AffirmTrust_Premium, sizeof(AffirmTrust_Premium) }, // { AffirmTrust_Premium_ECC, sizeof(AffirmTrust_Premium_ECC) }, { Comodo_AAA_Services_root, sizeof(Comodo_AAA_Services_root) }, { COMODO_Certification_Authority, sizeof(COMODO_Certification_Authority) }, // { COMODO_ECC_Certification_Authority, sizeof(COMODO_ECC_Certification_Authority) }, { COMODO_RSA_Certification_Authority, sizeof(COMODO_RSA_Certification_Authority) }, { Cybertrust_Global_Root, sizeof(Cybertrust_Global_Root) }, { DigiCert_Assured_ID_Root_CA, sizeof(DigiCert_Assured_ID_Root_CA) }, { DigiCert_Assured_ID_Root_G2, sizeof(DigiCert_Assured_ID_Root_G2) }, // { DigiCert_Assured_ID_Root_G3, sizeof(DigiCert_Assured_ID_Root_G3) }, { DigiCert_Global_Root_CA, sizeof(DigiCert_Global_Root_CA) }, { DigiCert_Global_Root_G2, sizeof(DigiCert_Global_Root_G2) }, // { DigiCert_Global_Root_G3, sizeof(DigiCert_Global_Root_G3) }, { DigiCert_High_Assurance_EV_Root_CA, sizeof(DigiCert_High_Assurance_EV_Root_CA) }, { DigiCert_Trusted_Root_G4, sizeof(DigiCert_Trusted_Root_G4) }, { Entrust_net_Premium_2048_Secure_Server_CA, sizeof(Entrust_net_Premium_2048_Secure_Server_CA) }, { Entrust_Root_Certification_Authority, sizeof(Entrust_Root_Certification_Authority) }, // { Entrust_Root_Certification_Authority__EC1, sizeof(Entrust_Root_Certification_Authority__EC1) }, { Entrust_Root_Certification_Authority__G2, sizeof(Entrust_Root_Certification_Authority__G2) }, { GeoTrust_Global_CA, sizeof(GeoTrust_Global_CA) }, { GlobalSign_ECC_Root_CA__R4, sizeof(GlobalSign_ECC_Root_CA__R4) }, // { GlobalSign_ECC_Root_CA__R5, sizeof(GlobalSign_ECC_Root_CA__R5) }, { GlobalSign_Root_CA, sizeof(GlobalSign_Root_CA) }, { GlobalSign_Root_CA__R2, sizeof(GlobalSign_Root_CA__R2) }, { GlobalSign_Root_CA__R3, sizeof(GlobalSign_Root_CA__R3) }, { GlobalSign_Root_CA__R6, sizeof(GlobalSign_Root_CA__R6) }, { Go_Daddy_Class_2_CA, sizeof(Go_Daddy_Class_2_CA) }, { Go_Daddy_Root_Certificate_Authority__G2, sizeof(Go_Daddy_Root_Certificate_Authority__G2) }, { GTS_Root_R1, sizeof(GTS_Root_R1) }, { GTS_Root_R2, sizeof(GTS_Root_R2) }, // { GTS_Root_R3, sizeof(GTS_Root_R3) }, // { GTS_Root_R4, sizeof(GTS_Root_R4) }, { Starfield_Class_2_CA, sizeof(Starfield_Class_2_CA) }, { Starfield_Root_Certificate_Authority__G2, sizeof(Starfield_Root_Certificate_Authority__G2) }, // { USERTrust_ECC_Certification_Authority, sizeof(USERTrust_ECC_Certification_Authority) }, { USERTrust_RSA_Certification_Authority, sizeof(USERTrust_RSA_Certification_Authority) }, }; int https_client_init( void ) { int ret = 0; mbedtls_ssl_init(&(tlsDataParams.ssl)); mbedtls_ssl_config_init(&(tlsDataParams.conf)); mbedtls_hmac_drbg_init(&(tlsDataParams.hmac_drbg)); mbedtls_x509_crt_init(&(tlsDataParams.cacert)); #if USE_CLIENT_CERT mbedtls_x509_crt_init(&(tlsDataParams.clicert)); #endif //USE_CLIENT_CERT mbedtls_pk_init(&(tlsDataParams.pkey)); const mbedtls_md_info_t *md_info; const char *pers = "InVue_AM_tls_wrapper"; #if defined(MBEDTLS_DEBUG_C) /* Enable debug output of mbedtls */ mbedtls_ssl_conf_dbg(&(tlsDataParams.conf), my_debug, NULL); mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif HTTPS_DEBUG_NORMAL("\n . Seeding the random number generator..."); mbedtls_entropy_init(&(tlsDataParams.entropy)); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if ((ret = mbedtls_hmac_drbg_seed(&(tlsDataParams.hmac_drbg), md_info, mbedtls_entropy_func, &(tlsDataParams.entropy), (const unsigned char *)pers, strlen(pers))) != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_hmac_drbg_seed returned -%x\n", -ret); return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } HTTPS_DEBUG_NORMAL("\n . Loading the CA root certificate chain..."); for( int index = 0; index < sizeof(rootCertsList)/sizeof(ROOTCERT); ++index ) { if( 0 != (ret = mbedtls_x509_crt_parse(&(tlsDataParams.cacert), rootCertsList[index].certname, rootCertsList[index].certsize)) ) { PRINTF( "%s mbedtls_x509_crt_parse failed on cert #%d at %p\r\n", __FUNCTION__, index, rootCertsList[index].certname ); break; } } if (ret < 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_x509_crt_parse returned -%x while parsing root cert\n\n", -ret); return NETWORK_X509_ROOT_CRT_PARSE_ERROR; } HTTPS_DEBUG_NORMAL(" ok (%d skipped)\n", ret); #if USE_CLIENT_CERT HTTPS_DEBUG_NORMAL(" . Loading the client cert and key..."); ret = mbedtls_x509_crt_parse(&(tlsDataParams.clicert), (const unsigned char *)mbedtls_test_cli_crt, mbedtls_test_cli_crt_len); if (ret != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_x509_crt_parse returned -%x while parsing device cert\n\n", -ret); return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; } ret = mbedtls_pk_parse_key(&(tlsDataParams.pkey), (const unsigned char *)mbedtls_test_cli_key, mbedtls_test_cli_key_len, NULL, 0); if (ret != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_pk_parse_key returned -%x while parsing private key\n\n", -ret); return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; } HTTPS_DEBUG_NORMAL(" ok\n"); #endif //USE_CLIENT_CERT return ret; } int https_client_tls_xchg( CLOUD_OUT_MSG_Q_ITEM* item ) { int ret = 0; char vrfy_buf[512]; bool ServerVerificationFlag = false; char* hostNameLoc = strstr(item->messageHeader, "Host: "); char* hostNameEnd = NULL; #ifdef MBEDTLS_DEBUG_C unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; #endif // find and copy host name from message header to httpsServerName if( NULL == hostNameLoc ) { HTTPS_DEBUG_NORMAL( "\r\n Host name identifier not found\r\n" ); return FAILURE; } else if (NULL == (hostNameLoc = strpbrk(hostNameLoc, " ")) ) { HTTPS_DEBUG_NORMAL( "\r\n Host name space delimiter not found\r\n"); return FAILURE; } else if( NULL == (hostNameEnd = strpbrk(hostNameLoc += 1, "\r\n")) ) { HTTPS_DEBUG_NORMAL( "\r\n Host name end not found\r\n" ); return FAILURE; } memcpy( httpsServerName, hostNameLoc, hostNameEnd - hostNameLoc); httpsServerName[ hostNameEnd - hostNameLoc ] = 0; HTTPS_DEBUG_NORMAL("\nConnecting to %s/%s", httpsServerName, HTTPS_SERVER_PORT); struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(httpsServerName, HTTPS_SERVER_PORT, &hints, &res); if ((ret != 0) || (res == NULL)) { return NETWORK_ERR_NET_UNKNOWN_HOST; } tlsDataParams.fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (tlsDataParams.fd < 0) { return NETWORK_ERR_NET_SOCKET_FAILED; } ret = connect(tlsDataParams.fd, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); if (ret != 0) { close(tlsDataParams.fd); return NETWORK_ERR_NET_CONNECT_FAILED; } HTTPS_DEBUG_NORMAL("\n . 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) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_ssl_config_defaults returned -%x\n\n", -ret); return SSL_CONNECTION_ERROR; } HTTPS_DEBUG_NORMAL("\n . Setting up the SSL/TLS verification..."); mbedtls_ssl_conf_verify(&(tlsDataParams.conf), _iot_tls_verify_cert, NULL); if (ServerVerificationFlag == true) { mbedtls_ssl_conf_authmode(&(tlsDataParams.conf), MBEDTLS_SSL_VERIFY_REQUIRED); HTTPS_DEBUG_NORMAL("verification required\n"); } else { mbedtls_ssl_conf_authmode(&(tlsDataParams.conf), MBEDTLS_SSL_VERIFY_OPTIONAL); HTTPS_DEBUG_NORMAL("verification optional\n"); } HTTPS_DEBUG_NORMAL("\n . Setting up random number generator..."); mbedtls_ssl_conf_rng(&(tlsDataParams.conf), mbedtls_hmac_drbg_random, &(tlsDataParams.hmac_drbg)); HTTPS_DEBUG_NORMAL(" ok\n"); HTTPS_DEBUG_NORMAL("\n . Loading the CA root certificate chain..."); mbedtls_ssl_conf_ca_chain(&(tlsDataParams.conf), &(tlsDataParams.cacert), NULL); HTTPS_DEBUG_NORMAL(" ok\n"); #if USE_CLIENT_CERT if ((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams.conf), &(tlsDataParams.clicert), &(tlsDataParams.pkey))) != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_ssl_conf_own_cert returned -%x\n\n", -ret); return SSL_CONNECTION_ERROR; } #endif //USE_CLIENT_CERT HTTPS_DEBUG_NORMAL("\n mbedtls_ssl_setup..."); if ((ret = mbedtls_ssl_setup(&(tlsDataParams.ssl), &(tlsDataParams.conf))) != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_ssl_setup returned -%x\n\n", -ret); return SSL_CONNECTION_ERROR; } if ((ret = mbedtls_ssl_set_hostname(&(tlsDataParams.ssl), httpsServerName)) != 0) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_ssl_set_hostname returned -%x\n\n", -ret); return SSL_CONNECTION_ERROR; } HTTPS_DEBUG_NORMAL("\n\nSSL state connect : %d ", tlsDataParams.ssl.state); HTTPS_DEBUG_NORMAL("\n mbedtls_ssl_set_bio..."); mbedtls_ssl_set_bio(&(tlsDataParams.ssl), &(tlsDataParams.fd), lwipSend, (mbedtls_ssl_recv_t *)lwipRecv, NULL); HTTPS_DEBUG_NORMAL(" ok\n"); HTTPS_DEBUG_NORMAL("\n\nSSL state connect : %d ", tlsDataParams.ssl.state); HTTPS_DEBUG_NORMAL("\n . 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) { HTTPS_DEBUG_NORMAL(" failed\n ! mbedtls_ssl_handshake returned -%x\n", -ret); if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { HTTPS_DEBUG_NORMAL( "\n Unable to verify the server's certificate. " "\n Alternatively, you may want to use " "\n auth_mode=optional for testing purposes.\n"); } return SSL_CONNECTION_ERROR; } } HTTPS_DEBUG_NORMAL(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams.ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams.ssl))); if ((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams.ssl))) >= 0) { HTTPS_DEBUG_NORMAL(" [ Record expansion is %d ]\n", ret); } else { HTTPS_DEBUG_NORMAL(" [ Record expansion is unknown (compression) ]\n"); } HTTPS_DEBUG_NORMAL("\n . Verifying peer X.509 certificate..."); if (ServerVerificationFlag == true) { if ((tlsDataParams.flags = mbedtls_ssl_get_verify_result(&(tlsDataParams.ssl))) != 0) { HTTPS_DEBUG_NORMAL(" failed\n"); mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams.flags); HTTPS_DEBUG_NORMAL("%s\n", vrfy_buf); ret = SSL_CONNECTION_ERROR; } else { HTTPS_DEBUG_NORMAL(" ok\n"); ret = SUCCESS; } } else { HTTPS_DEBUG_NORMAL(" Server Verification skipped\n"); ret = SUCCESS; } #ifdef MBEDTLS_DEBUG_C if (mbedtls_ssl_get_peer_cert(&(tlsDataParams.ssl)) != NULL) { HTTPS_DEBUG_NORMAL(" . Peer certificate information ...\n"); mbedtls_x509_crt_info((char *)buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams.ssl))); HTTPS_DEBUG_NORMAL("%s\n", buf); } #endif mbedtls_ssl_conf_read_timeout(&(tlsDataParams.conf), IOT_SSL_READ_TIMEOUT); if( (ret = write_request( &item )) > 0 ) { ret = read_request(); HTTPS_DEBUG_VERBOSE( "%s %d read_request ret %d\r\n", __FUNCTION__, __LINE__, ret ); } else { HTTPS_DEBUG_VERBOSE( "%s %d write_request ret %d\r\n", __FUNCTION__, __LINE__, ret ); } https_client_tls_release(); return ret; } /* Release TLS */ void https_client_tls_release() { close(tlsDataParams.fd); #if USE_CLIENT_CERT mbedtls_x509_crt_free(&(tlsDataParams.clicert)); #endif //USE_CLIENT_CERT mbedtls_x509_crt_free(&(tlsDataParams.cacert)); mbedtls_pk_free(&(tlsDataParams.pkey)); mbedtls_ssl_free(&(tlsDataParams.ssl)); mbedtls_ssl_config_free(&(tlsDataParams.conf)); mbedtls_hmac_drbg_free(&(tlsDataParams.hmac_drbg)); mbedtls_entropy_free(&(tlsDataParams.entropy)); }