Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of AWS-test by
network_mbedtls_wrapper.cpp
00001 /* 00002 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"). 00005 * You may not use this file except in compliance with the License. 00006 * A copy of the License is located at 00007 * 00008 * http://aws.amazon.com/apache2.0 00009 * 00010 * or in the "license" file accompanying this file. This file is distributed 00011 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 00012 * express or implied. See the License for the specific language governing 00013 * permissions and limitations under the License. 00014 */ 00015 00016 #ifdef __cplusplus 00017 extern "C" { 00018 #endif 00019 00020 #include <stdbool.h> 00021 #include <string.h> 00022 #include <timer_platform.h> 00023 #include <network_interface.h> 00024 00025 #include "aws_iot_error.h" 00026 #include "aws_iot_log.h" 00027 #include "network_interface.h" 00028 #include "network_platform.h" 00029 00030 #include "aws_iot_config.h" 00031 00032 /* This is the value used for ssl read timeout */ 00033 #define IOT_SSL_READ_TIMEOUT 10 00034 00035 /* 00036 * This is a function to do further verification if needed on the cert received 00037 */ 00038 00039 static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { 00040 char buf[1024]; 00041 ((void) data); 00042 00043 IOT_DEBUG("\nVerify requested for (Depth %d):\n", depth); 00044 mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); 00045 IOT_DEBUG("%s", buf); 00046 00047 if((*flags) == 0) { 00048 IOT_DEBUG(" This certificate has no flags\n"); 00049 } else { 00050 IOT_DEBUG(buf, sizeof(buf), " ! ", *flags); 00051 IOT_DEBUG("%s\n", buf); 00052 } 00053 00054 return 0; 00055 } 00056 00057 void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, 00058 char *pDevicePrivateKeyLocation, char *pDestinationURL, 00059 uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { 00060 pNetwork->tlsConnectParams.DestinationPort = destinationPort; 00061 pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL; 00062 pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation; 00063 pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation; 00064 pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation; 00065 pNetwork->tlsConnectParams.timeout_ms = timeout_ms; 00066 pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag; 00067 } 00068 00069 IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation, 00070 char *pDevicePrivateKeyLocation, char *pDestinationURL, 00071 uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) { 00072 _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation, 00073 pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag); 00074 00075 pNetwork->connect = iot_tls_connect; 00076 pNetwork->read = iot_tls_read; 00077 pNetwork->write = iot_tls_write; 00078 pNetwork->disconnect = iot_tls_disconnect; 00079 pNetwork->isConnected = iot_tls_is_connected; 00080 pNetwork->destroy = iot_tls_destroy; 00081 00082 pNetwork->tlsDataParams.flags = 0; 00083 00084 return IOT_SUCCESS; 00085 } 00086 00087 IoT_Error_t iot_tls_is_connected(Network *pNetwork) { 00088 /* Use this to add implementation which can check for physical layer disconnect */ 00089 return NETWORK_PHYSICAL_LAYER_CONNECTED; 00090 } 00091 00092 IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { 00093 int ret = 0; 00094 const char *pers = "aws_iot_tls_wrapper"; 00095 TLSDataParams *tlsDataParams = NULL; 00096 char portBuffer[6]; 00097 char vrfy_buf[512]; 00098 #ifdef IOT_DEBUG 00099 unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; 00100 #endif 00101 00102 if(NULL == pNetwork) { 00103 return NULL_VALUE_ERROR; 00104 } 00105 00106 if(NULL != params) { 00107 _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, 00108 params->pDevicePrivateKeyLocation, params->pDestinationURL, 00109 params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); 00110 } 00111 00112 tlsDataParams = &(pNetwork->tlsDataParams); 00113 00114 mbedtls_net_init(&(tlsDataParams->server_fd)); 00115 mbedtls_ssl_init(&(tlsDataParams->ssl)); 00116 mbedtls_ssl_config_init(&(tlsDataParams->conf)); 00117 mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); 00118 mbedtls_x509_crt_init(&(tlsDataParams->cacert)); 00119 mbedtls_x509_crt_init(&(tlsDataParams->clicert)); 00120 mbedtls_pk_init(&(tlsDataParams->pkey)); 00121 00122 IOT_DEBUG("\n . Seeding the random number generator..."); 00123 mbedtls_entropy_init(&(tlsDataParams->entropy)); 00124 if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), 00125 (const unsigned char *) pers, strlen(pers))) != 0) { 00126 IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); 00127 return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 00128 } 00129 00130 IOT_DEBUG(" . Loading the CA root certificate ..."); 00131 ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)AWS_IOT_ROOT_CA, strlen(AWS_IOT_ROOT_CA)); 00132 if(ret < 0) { 00133 IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret); 00134 return NETWORK_X509_ROOT_CRT_PARSE_ERROR; 00135 } 00136 IOT_DEBUG(" ok (%d skipped)\n", ret); 00137 00138 IOT_DEBUG(" . Loading the client cert. and key..."); 00139 ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), (const unsigned char *)AWS_IOT_CERTIFICATE, strlen(AWS_IOT_CERTIFICATE)); 00140 if(ret != 0) { 00141 IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret); 00142 return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; 00143 } 00144 00145 ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), (const unsigned char *)AWS_IOT_PRIVATE_KEY, strlen(AWS_IOT_PRIVATE_KEY), (const unsigned char *)(PASSWORD),strlen(PASSWORD)); 00146 if(ret != 0) { 00147 IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret); 00148 IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation); 00149 return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; 00150 } 00151 IOT_DEBUG(" ok\n"); 00152 snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); 00153 IOT_DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); 00154 if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, 00155 portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { 00156 IOT_ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); 00157 switch(ret) { 00158 case MBEDTLS_ERR_NET_SOCKET_FAILED: 00159 return NETWORK_ERR_NET_SOCKET_FAILED; 00160 case MBEDTLS_ERR_NET_UNKNOWN_HOST: 00161 return NETWORK_ERR_NET_UNKNOWN_HOST; 00162 case MBEDTLS_ERR_NET_CONNECT_FAILED: 00163 default: 00164 return NETWORK_ERR_NET_CONNECT_FAILED; 00165 }; 00166 } 00167 00168 ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); 00169 if(ret != 0) { 00170 IOT_ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); 00171 return SSL_CONNECTION_ERROR; 00172 } IOT_DEBUG(" ok\n"); 00173 00174 IOT_DEBUG(" . Setting up the SSL/TLS structure..."); 00175 if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, 00176 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 00177 IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); 00178 return SSL_CONNECTION_ERROR; 00179 } 00180 00181 mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); 00182 if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { 00183 mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); 00184 } else { 00185 mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); 00186 } 00187 mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); 00188 00189 mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); 00190 if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != 00191 0) { 00192 IOT_ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); 00193 return SSL_CONNECTION_ERROR; 00194 } 00195 00196 mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); 00197 00198 if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { 00199 IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); 00200 return SSL_CONNECTION_ERROR; 00201 } 00202 if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { 00203 IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); 00204 return SSL_CONNECTION_ERROR; 00205 } 00206 IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); 00207 mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, 00208 mbedtls_net_recv_timeout); 00209 IOT_DEBUG(" ok\n"); 00210 00211 IOT_DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); 00212 IOT_DEBUG(" . Performing the SSL/TLS handshake..."); 00213 while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { 00214 if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00215 IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); 00216 if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { 00217 IOT_ERROR(" Unable to verify the server's certificate. " 00218 "Either it is invalid,\n" 00219 " or you didn't set ca_file or ca_path " 00220 "to an appropriate value.\n" 00221 " Alternatively, you may want to use " 00222 "auth_mode=optional for testing purposes.\n"); 00223 } 00224 return SSL_CONNECTION_ERROR; 00225 } 00226 } 00227 00228 IOT_DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), 00229 mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); 00230 if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { 00231 IOT_DEBUG(" [ Record expansion is %d ]\n", ret); 00232 } else { 00233 IOT_DEBUG(" [ Record expansion is unknown (compression) ]\n"); 00234 } 00235 00236 IOT_DEBUG(" . Verifying peer X.509 certificate..."); 00237 00238 if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { 00239 if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { 00240 IOT_ERROR(" failed\n"); 00241 mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags); 00242 IOT_ERROR("%s\n", vrfy_buf); 00243 ret = SSL_CONNECTION_ERROR; 00244 } else { 00245 IOT_DEBUG(" ok\n"); 00246 ret = IOT_SUCCESS; 00247 } 00248 } else { 00249 IOT_DEBUG(" Server Verification skipped\n"); 00250 ret = IOT_SUCCESS; 00251 } 00252 00253 #ifdef IOT_DEBUG 00254 if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { 00255 IOT_DEBUG(" . Peer certificate information ...\n"); 00256 mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); 00257 IOT_DEBUG("%s\n", buf); 00258 } 00259 #endif 00260 00261 mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT); 00262 00263 return (IoT_Error_t) ret; 00264 } 00265 00266 IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, TimerAWS *timer, size_t *written_len) { 00267 size_t written_so_far; 00268 bool isErrorFlag = false; 00269 int frags, ret; 00270 TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); 00271 00272 for(written_so_far = 0, frags = 0; 00273 written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) { 00274 while(!has_timer_expired(timer) && 00275 (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) { 00276 if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00277 IOT_ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret); 00278 /* All other negative return values indicate connection needs to be reset. 00279 * Will be caught in ping request so ignored here */ 00280 isErrorFlag = true; 00281 break; 00282 } 00283 } 00284 if(isErrorFlag) { 00285 break; 00286 } 00287 } 00288 00289 *written_len = written_so_far; 00290 00291 if(isErrorFlag) { 00292 return NETWORK_SSL_WRITE_ERROR; 00293 } else if(has_timer_expired(timer) && written_so_far != len) { 00294 return NETWORK_SSL_WRITE_TIMEOUT_ERROR; 00295 } 00296 00297 return IOT_SUCCESS; 00298 } 00299 00300 IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, TimerAWS *timer, size_t *read_len) { 00301 mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); 00302 size_t rxLen = 0; 00303 int ret; 00304 00305 while (len > 0) { 00306 // This read will timeout after IOT_SSL_READ_TIMEOUT if there's no data to be read 00307 ret = mbedtls_ssl_read(ssl, pMsg, len); 00308 if (ret > 0) { 00309 rxLen += ret; 00310 pMsg += ret; 00311 len -= ret; 00312 } else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) { 00313 return NETWORK_SSL_READ_ERROR; 00314 } 00315 00316 // Evaluate timeout after the read to make sure read is done at least once 00317 if (has_timer_expired(timer)) { 00318 break; 00319 } 00320 } 00321 00322 if (len == 0) { 00323 *read_len = rxLen; 00324 return IOT_SUCCESS; 00325 } 00326 00327 if (rxLen == 0) { 00328 return NETWORK_SSL_NOTHING_TO_READ; 00329 } else { 00330 return NETWORK_SSL_READ_TIMEOUT_ERROR; 00331 } 00332 } 00333 00334 IoT_Error_t iot_tls_disconnect(Network *pNetwork) { 00335 mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl); 00336 int ret = 0; 00337 do { 00338 ret = mbedtls_ssl_close_notify(ssl); 00339 } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); 00340 00341 /* All other negative return values indicate connection needs to be reset. 00342 * No further action required since this is disconnect call */ 00343 00344 return IOT_SUCCESS; 00345 } 00346 00347 IoT_Error_t iot_tls_destroy(Network *pNetwork) { 00348 TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); 00349 00350 mbedtls_net_free(&(tlsDataParams->server_fd)); 00351 00352 mbedtls_x509_crt_free(&(tlsDataParams->clicert)); 00353 mbedtls_x509_crt_free(&(tlsDataParams->cacert)); 00354 mbedtls_pk_free(&(tlsDataParams->pkey)); 00355 mbedtls_ssl_free(&(tlsDataParams->ssl)); 00356 mbedtls_ssl_config_free(&(tlsDataParams->conf)); 00357 mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg)); 00358 mbedtls_entropy_free(&(tlsDataParams->entropy)); 00359 00360 return IOT_SUCCESS; 00361 } 00362 00363 #ifdef __cplusplus 00364 } 00365 #endif
Generated on Tue Jul 12 2022 11:16:38 by
1.7.2
