V.06 11/3

Dependencies:   FT6206 SDFileSystem SPI_TFT_ILI9341 TFT_fonts

Fork of ATT_AWS_IoT_demo by attiot

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers network_mbedtls_wrapper.cpp Source File

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