Demo application for using the AT&T IoT Starter Kit Powered by AWS.
Dependencies: SDFileSystem
Fork of ATT_AWS_IoT_demo 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 #include <stdbool.h> 00017 #include <string.h> 00018 00019 #include "aws_iot_config.h" 00020 #include "aws_iot_error.h" 00021 #include "aws_iot_log.h" 00022 #include "network_interface.h" 00023 #include "mbedtls/config.h" 00024 00025 #include "mbedtls/net.h" 00026 #include "mbedtls/ssl.h" 00027 #include "mbedtls/entropy.h" 00028 #include "mbedtls/ctr_drbg.h" 00029 #include "mbedtls/certs.h" 00030 #include "mbedtls/x509.h" 00031 #include "mbedtls/error.h" 00032 #include "mbedtls/debug.h" 00033 #include "mbedtls/timing.h" 00034 #include "mbedtls/net_sockets.h" 00035 #include "pem.h" 00036 00037 #include "platform.h" 00038 #include "WNCTCPSocketConnection.h" 00039 00040 #ifdef USING_AVNET_SHIELD 00041 // Used for BIO connections 00042 extern WNCTCPSocketConnection* _tcpsocket; 00043 #endif 00044 00045 // SD File System 00046 #include "SDFileSystem.h" 00047 00048 // SD defines 00049 #define CERT_MAX_SIZE 4096 00050 00051 // SD file pointer/buffer 00052 FILE *fp; 00053 char fp_buffer[CERT_MAX_SIZE]; 00054 00055 // From main.cpp 00056 extern char HostAddress[255]; 00057 extern char MqttClientID[32]; 00058 extern char ThingName[32]; 00059 extern char PortString[4]; 00060 00061 /* 00062 * This is a function to do further verification if needed on the cert received 00063 */ 00064 static int myCertVerify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { 00065 char buf[1024]; 00066 ((void) data); 00067 00068 DEBUG("\nVerify requested for (Depth %d):\n", depth); 00069 mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); 00070 DEBUG("%s", buf); 00071 00072 if ((*flags) == 0) { 00073 DEBUG(" This certificate has no flags\n"); 00074 } else { 00075 DEBUG(buf, sizeof(buf), " ! ", *flags); DEBUG("%s\n", buf); 00076 } 00077 00078 return (0); 00079 } 00080 00081 static int ret = 0, i; 00082 static mbedtls_entropy_context entropy; 00083 static mbedtls_ctr_drbg_context ctr_drbg; 00084 static mbedtls_ssl_context ssl; 00085 static mbedtls_ssl_config conf; 00086 static uint32_t flags; 00087 static mbedtls_x509_crt cacert; 00088 static mbedtls_x509_crt clicert; 00089 static mbedtls_pk_context pkey; 00090 static mbedtls_net_context server_fd; 00091 00092 // Used to zero the given buffer 00093 static void mbedtls_zeroize( char *v, size_t n ) { 00094 volatile char *p = v; while( n-- ) *p++ = 0; 00095 } 00096 00097 // Parser sub function 00098 int mqtt_parse_sub(std::string *search_str, char *param, const char *str_to_find) 00099 { 00100 int index_start, index_end; 00101 mbedtls_zeroize(param, strlen(param)); 00102 00103 index_start = search_str->find(str_to_find); 00104 if (index_start < 0) 00105 return -1; 00106 00107 index_end = search_str->find("\n", index_start); 00108 if (index_end < 0) 00109 index_end = search_str->find("\0", index_start); 00110 00111 if (index_end < 0) 00112 return -1; 00113 00114 index_start += strlen(str_to_find); 00115 strcpy(param, search_str->substr(index_start, index_end-index_start-1).c_str()); 00116 00117 return 0; 00118 } 00119 00120 // Read MQTT config info 00121 int mbedtls_mqtt_config_parse_file(ShadowParameters_t *sp, const char *path ) 00122 { 00123 int ret, size; 00124 mbedtls_zeroize(fp_buffer, CERT_MAX_SIZE); 00125 00126 INFO("...Reading MQTT data from SD"); 00127 fp = fopen(path, "r"); 00128 if (fp != NULL) { 00129 size = fread(fp_buffer, sizeof(char), CERT_MAX_SIZE, fp); 00130 DEBUG("...Number of data read: %d, text from file: %s", size, fp_buffer); 00131 fclose(fp); 00132 } 00133 else { 00134 ERROR("Could not open file: %s", path); 00135 return -1; 00136 } 00137 00138 std::string filestr(fp_buffer); 00139 00140 ret = mqtt_parse_sub(&filestr, HostAddress, "AWS_IOT_MQTT_HOST="); 00141 sp->pHost = HostAddress; 00142 INFO("...Host=%s", sp->pHost); 00143 if (ret < 0) { 00144 ERROR("Could not parse AWS_IOT_MQTT_HOST string."); 00145 return ret; 00146 } 00147 00148 ret = mqtt_parse_sub(&filestr, PortString, "AWS_IOT_MQTT_PORT="); 00149 sp->port = atoi(PortString); 00150 INFO("...Port=%d", sp->port); 00151 if (ret < 0) { 00152 ERROR("Could not parse AWS_IOT_MQTT_PORT string."); 00153 return ret; 00154 } 00155 00156 ret = mqtt_parse_sub(&filestr, MqttClientID, "AWS_IOT_MQTT_CLIENT_ID="); 00157 sp->pMqttClientId = MqttClientID; 00158 INFO("...pMqttClientId=%s", sp->pMqttClientId); 00159 if (ret < 0) { 00160 ERROR("Could not parse AWS_IOT_MQTT_CLIENT_ID string."); 00161 return ret; 00162 } 00163 00164 ret = mqtt_parse_sub(&filestr, ThingName, "AWS_IOT_MY_THING_NAME="); 00165 sp->pMyThingName = ThingName; 00166 INFO("...pMyThingName=%s", sp->pMyThingName); 00167 if (ret < 0) { 00168 ERROR("Could not parse AWS_IOT_MY_THING_NAME string."); 00169 return ret; 00170 } 00171 00172 return( ret ); 00173 } 00174 00175 // Override function: Parses CRT from SD 00176 int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) 00177 { 00178 int ret, size; 00179 mbedtls_zeroize(fp_buffer, CERT_MAX_SIZE); 00180 00181 INFO("...Reading CERT data from SD"); 00182 fp = fopen(path, "r"); 00183 if (fp != NULL) { 00184 size = fread(fp_buffer, sizeof(char), CERT_MAX_SIZE, fp); 00185 DEBUG("...Number of data read: %d, text from file: %s", size, fp_buffer); 00186 fclose(fp); 00187 } 00188 else { 00189 ERROR("Could not open file: %s", path); 00190 return -1; 00191 } 00192 00193 DEBUG("...CRT Parse"); 00194 ret = mbedtls_x509_crt_parse( chain, (unsigned char *)fp_buffer, size+2); 00195 00196 return( ret ); 00197 } 00198 00199 // Override function: Parses KEY from SD 00200 int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, 00201 const char *path, const char *pwd ) 00202 { 00203 int ret, size; 00204 mbedtls_zeroize(fp_buffer, CERT_MAX_SIZE); 00205 00206 INFO("...Reading KEY data from SD"); 00207 fp = fopen(path, "r"); 00208 if (fp != NULL) { 00209 size = fread(fp_buffer, sizeof(char), CERT_MAX_SIZE, fp); 00210 DEBUG("...Number of data read: %d, text from file: %s", size, fp_buffer); 00211 fclose(fp); 00212 } 00213 else { 00214 ERROR("Could not open file: %s", path); 00215 return -1; 00216 } 00217 00218 DEBUG("...Key Parse"); 00219 if( pwd == NULL ) { 00220 DEBUG("...Using PWD"); 00221 ret = mbedtls_pk_parse_key( ctx, (unsigned char *)fp_buffer, size+1, NULL, 0 ); 00222 } 00223 else { 00224 DEBUG("...No PWD"); 00225 ret = mbedtls_pk_parse_key( ctx, (unsigned char *)fp_buffer, size+1, (const unsigned char *) pwd, strlen( pwd ) ); 00226 } 00227 00228 return( ret ); 00229 } 00230 00231 00232 /* personalization string for the drbg */ 00233 const char *DRBG_PERS = "mbed TLS helloword client"; 00234 00235 int iot_tls_init(Network *pNetwork) { 00236 IoT_Error_t ret_val = NONE_ERROR; 00237 const char *pers = "aws_iot_tls_wrapper"; 00238 unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; 00239 00240 mbedtls_net_init(&server_fd); 00241 mbedtls_ssl_init(&ssl); 00242 mbedtls_ssl_config_init(&conf); 00243 mbedtls_ctr_drbg_init(&ctr_drbg); 00244 mbedtls_x509_crt_init(&cacert); 00245 mbedtls_x509_crt_init(&clicert); 00246 mbedtls_pk_init(&pkey); 00247 00248 DEBUG("...Seeding the random number generator"); 00249 mbedtls_entropy_init(&entropy); 00250 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) DRBG_PERS, sizeof (DRBG_PERS))) != 0) { 00251 ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); 00252 return ret_val; 00253 } 00254 DEBUG(" ok\n"); 00255 00256 pNetwork->my_socket = 0; 00257 pNetwork->connect = iot_tls_connect; 00258 pNetwork->mqttread = iot_tls_read; 00259 pNetwork->mqttwrite = iot_tls_write; 00260 pNetwork->disconnect = iot_tls_disconnect; 00261 pNetwork->isConnected = iot_tls_is_connected; 00262 pNetwork->destroy = iot_tls_destroy; 00263 00264 return ret_val; 00265 } 00266 00267 int iot_tls_is_connected(Network *pNetwork) { 00268 /* Use this to add implementation which can check for physical layer disconnect */ 00269 return 1; 00270 } 00271 00272 int iot_tls_connect(Network *pNetwork, TLSConnectParams params) { 00273 const char *pers = "aws_iot_tls_wrapper"; 00274 00275 DEBUG("...Loading the CA root certificate"); 00276 #ifdef USING_SD_CARD 00277 ret = mbedtls_x509_crt_parse_file(&cacert, AWS_IOT_ROOT_CA_FILENAME); 00278 #else 00279 ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)AWS_IOT_ROOT_CA, strlen ((const char *)AWS_IOT_ROOT_CA)+1); 00280 #endif 00281 if (ret < 0) { 00282 ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); 00283 return ret; 00284 } 00285 DEBUG(" ok (%d skipped)", ret); 00286 00287 00288 DEBUG("...Loading the client cert"); 00289 #ifdef USING_SD_CARD 00290 ret = mbedtls_x509_crt_parse_file(&clicert, AWS_IOT_CERTIFICATE_FILENAME); 00291 #else 00292 ret = mbedtls_x509_crt_parse(&clicert, (const unsigned char *)AWS_IOT_CERTIFICATE, strlen ((const char *)AWS_IOT_CERTIFICATE)+1); 00293 #endif 00294 if (ret != 0) { 00295 ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); 00296 return ret; 00297 } 00298 DEBUG(" ok"); 00299 00300 DEBUG("...Loading the client key"); 00301 #ifdef USING_SD_CARD 00302 ret = mbedtls_pk_parse_keyfile(&pkey, AWS_IOT_PRIVATE_KEY_FILENAME, ""); 00303 #else 00304 ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *)AWS_IOT_PRIVATE_KEY, strlen ((const char *)AWS_IOT_PRIVATE_KEY)+1, NULL, 0 ); 00305 #endif 00306 if (ret != 0) { 00307 ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret); 00308 return ret; 00309 } 00310 DEBUG(" ok"); 00311 00312 char portBuffer[6]; 00313 sprintf(portBuffer, "%d", params.DestinationPort); 00314 DEBUG("...Connecting to %s/%s", params.pDestinationURL, portBuffer); 00315 if ((ret = mbedtls_net_connect(&server_fd, params.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { 00316 ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); 00317 return ret; 00318 } 00319 00320 00321 ret = mbedtls_net_set_block(&server_fd); 00322 if (ret != 0) { 00323 ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); 00324 return ret; 00325 } 00326 DEBUG(" ok"); 00327 00328 00329 DEBUG("...Setting up the SSL/TLS structure"); 00330 if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, 00331 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 00332 ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); 00333 return ret; 00334 } 00335 00336 00337 mbedtls_ssl_conf_verify(&conf, myCertVerify, NULL); 00338 if (params.ServerVerificationFlag == true) { 00339 mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); 00340 } else { 00341 mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); 00342 } 00343 mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 00344 00345 mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); 00346 if ((ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey)) != 0) { 00347 ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); 00348 return ret; 00349 } 00350 00351 mbedtls_ssl_conf_read_timeout(&conf, params.timeout_ms); 00352 00353 if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { 00354 ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); 00355 return ret; 00356 } 00357 if ((ret = mbedtls_ssl_set_hostname(&ssl, params.pDestinationURL)) != 0) { 00358 ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); 00359 return ret; 00360 } 00361 00362 DEBUG("...Set Socket I/O Functions"); 00363 mbedtls_ssl_set_bio(&ssl, static_cast<void *>(_tcpsocket), mbedtls_net_send, NULL, mbedtls_net_recv_timeout ); 00364 DEBUG(" ok"); 00365 00366 00367 DEBUG("...Performing the SSL/TLS handshake"); 00368 while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 00369 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00370 ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); 00371 if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { 00372 ERROR(" Unable to verify the server's certificate. " 00373 "Either it is invalid,\n" 00374 " or you didn't set ca_file or ca_path " 00375 "to an appropriate value.\n" 00376 " Alternatively, you may want to use " 00377 "auth_mode=optional for testing purposes.\n"); 00378 } 00379 return ret; 00380 } 00381 } 00382 00383 00384 DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&ssl), mbedtls_ssl_get_ciphersuite(&ssl)); 00385 if ((ret = mbedtls_ssl_get_record_expansion(&ssl)) >= 0) { 00386 DEBUG(" [ Record expansion is %d ]\n", ret); 00387 } else { 00388 DEBUG(" [ Record expansion is unknown (compression) ]\n"); 00389 } 00390 00391 00392 DEBUG("...Verifying peer X.509 certificate"); 00393 if (params.ServerVerificationFlag == true) { 00394 if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { 00395 char vrfy_buf[512]; 00396 ERROR(" failed\n"); 00397 mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags); 00398 ERROR("%s\n", vrfy_buf); 00399 } else { 00400 DEBUG(" ok\n"); 00401 ret = NONE_ERROR; 00402 } 00403 } else { 00404 DEBUG(" Server Verification skipped\n"); 00405 ret = NONE_ERROR; 00406 } 00407 00408 00409 DEBUG("...SSL get peer cert"); 00410 if (mbedtls_ssl_get_peer_cert(&ssl) != NULL) { 00411 DEBUG("...Peer certificate information"); 00412 const uint32_t buf_size = 1024; 00413 char *buf = new char[buf_size]; 00414 mbedtls_x509_crt_info(buf, buf_size, " ", mbedtls_ssl_get_peer_cert(&ssl)); 00415 DEBUG("...Server certificate:\r\n%s\r", buf); 00416 } 00417 00418 mbedtls_ssl_conf_read_timeout(&conf, 10); 00419 00420 return ret; 00421 } 00422 00423 int iot_tls_write(Network *pNetwork, unsigned char *pMsg, int len, int timeout_ms) { 00424 00425 int written; 00426 int frags; 00427 00428 for (written = 0, frags = 0; written < len; written += ret, frags++) { 00429 while ((ret = mbedtls_ssl_write(&ssl, pMsg + written, len - written)) <= 0) { 00430 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00431 ERROR(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret); 00432 return ret; 00433 } 00434 } 00435 } 00436 00437 return written; 00438 } 00439 00440 int iot_tls_read(Network *pNetwork, unsigned char *pMsg, int len, int timeout_ms) { 00441 int rxLen = 0; 00442 bool isErrorFlag = false; 00443 bool isCompleteFlag = false; 00444 00445 // TODO check this against base 00446 //mbedtls_ssl_conf_read_timeout(&conf, timeout_ms); 00447 00448 do { 00449 ret = mbedtls_ssl_read(&ssl, pMsg, len); 00450 if (ret > 0) { 00451 rxLen += ret; 00452 } else if (ret != MBEDTLS_ERR_SSL_WANT_READ) { 00453 isErrorFlag = true; 00454 } 00455 if (rxLen >= len) { 00456 isCompleteFlag = true; 00457 } 00458 } while (!isErrorFlag && !isCompleteFlag); 00459 00460 return ret; 00461 } 00462 00463 void iot_tls_disconnect(Network *pNetwork) { 00464 do { 00465 ret = mbedtls_ssl_close_notify(&ssl); 00466 } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); 00467 } 00468 00469 int iot_tls_destroy(Network *pNetwork) { 00470 00471 mbedtls_net_free(&server_fd); 00472 00473 mbedtls_x509_crt_free(&clicert); 00474 mbedtls_x509_crt_free(&cacert); 00475 mbedtls_pk_free(&pkey); 00476 mbedtls_ssl_free(&ssl); 00477 mbedtls_ssl_config_free(&conf); 00478 mbedtls_ctr_drbg_free(&ctr_drbg); 00479 mbedtls_entropy_free(&entropy); 00480 00481 return 0; 00482 } 00483 00484
Generated on Tue Jul 12 2022 22:13:21 by 1.7.2