Luis Amell / IBMIoTF-2

Dependencies:   MQTT

Committer:
lamell
Date:
Fri Dec 27 14:06:13 2019 -0400
Revision:
22:d9576c025cd7
Parent:
18:ce12e2072cbb
Child:
23:1523bdaba8c8
2019-12-27 14:06
Changed Serial to RawSerial, so serial comms can be used with interrupts in the main.cpp file.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lokeshhk 5:ea9f483e0294 1 /*******************************************************************************
lokeshhk 5:ea9f483e0294 2 * Copyright (c) 2017 IBM Corp.
lokeshhk 5:ea9f483e0294 3 *
lokeshhk 5:ea9f483e0294 4 * All rights reserved. This program and the accompanying materials
lokeshhk 5:ea9f483e0294 5 * are made available under the terms of the Eclipse Public License v1.0
lokeshhk 5:ea9f483e0294 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
lokeshhk 5:ea9f483e0294 7 *
lokeshhk 5:ea9f483e0294 8 * The Eclipse Public License is available at
lokeshhk 5:ea9f483e0294 9 * http://www.eclipse.org/legal/epl-v10.html
lokeshhk 5:ea9f483e0294 10 * and the Eclipse Distribution License is available at
lokeshhk 5:ea9f483e0294 11 * http://www.eclipse.org/org/documents/edl-v10.php.
lokeshhk 5:ea9f483e0294 12 *
lokeshhk 5:ea9f483e0294 13 * Contributors:
lokeshhk 5:ea9f483e0294 14 * Lokesh K Haralakatta Initial implementation to support mbed OS 5
lokeshhk 5:ea9f483e0294 15 * Lokesh K Haralakatta Added SSL/TLS Support
lokeshhk 5:ea9f483e0294 16 *******************************************************************************/
lokeshhk 5:ea9f483e0294 17 #ifndef MQTTNetwork_H
lokeshhk 5:ea9f483e0294 18 #define MQTTNetwork_H
lokeshhk 5:ea9f483e0294 19
lamell 18:ce12e2072cbb 20 //mbed
lamell 18:ce12e2072cbb 21 #include "mbed.h"
lamell 18:ce12e2072cbb 22
lokeshhk 5:ea9f483e0294 23 // Network related header files
lokeshhk 5:ea9f483e0294 24 #include "NetworkInterface.h"
lokeshhk 5:ea9f483e0294 25 #include "EthernetInterface.h"
lokeshhk 5:ea9f483e0294 26
lokeshhk 5:ea9f483e0294 27 // mbedTLS related header files
lokeshhk 5:ea9f483e0294 28 #include "mbedtls/platform.h"
lokeshhk 5:ea9f483e0294 29 #include "mbedtls/ssl.h"
lokeshhk 5:ea9f483e0294 30 #include "mbedtls/entropy.h"
lokeshhk 5:ea9f483e0294 31 #include "mbedtls/ctr_drbg.h"
lokeshhk 5:ea9f483e0294 32 #include "mbedtls/error.h"
lokeshhk 5:ea9f483e0294 33 #include "mbedtls/debug.h"
lokeshhk 5:ea9f483e0294 34
lokeshhk 5:ea9f483e0294 35 //Include certificates header
lokeshhk 5:ea9f483e0294 36 #include "Certificates.h"
lokeshhk 5:ea9f483e0294 37
lamell 22:d9576c025cd7 38 extern RawSerial pc;
lamell 18:ce12e2072cbb 39
lokeshhk 5:ea9f483e0294 40 namespace IoTF {
lokeshhk 5:ea9f483e0294 41
lokeshhk 5:ea9f483e0294 42 //Class to represent Network layer
lokeshhk 5:ea9f483e0294 43 class MQTTNetwork {
lokeshhk 5:ea9f483e0294 44 private:
lamell 18:ce12e2072cbb 45
lokeshhk 5:ea9f483e0294 46 //Pointer member to represent socket
lamell 18:ce12e2072cbb 47 TCPSocket socket;
lokeshhk 5:ea9f483e0294 48
lokeshhk 5:ea9f483e0294 49 //Variable to stored server port
lokeshhk 5:ea9f483e0294 50 int serverPort;
lokeshhk 5:ea9f483e0294 51
lokeshhk 5:ea9f483e0294 52 //Poniter mebers for mbedTLS structures
lokeshhk 5:ea9f483e0294 53 mbedtls_entropy_context* _entropy;
lokeshhk 5:ea9f483e0294 54 mbedtls_ctr_drbg_context* _ctr_drbg;
lokeshhk 5:ea9f483e0294 55 mbedtls_x509_crt* _cacert;
lokeshhk 5:ea9f483e0294 56 mbedtls_ssl_context* _ssl;
lokeshhk 5:ea9f483e0294 57 mbedtls_ssl_config* _ssl_conf;
lokeshhk 5:ea9f483e0294 58 public:
lamell 18:ce12e2072cbb 59 //Pointer member for ethernet interface
lamell 18:ce12e2072cbb 60 NetworkInterface *network;
lamell 18:ce12e2072cbb 61
lamell 18:ce12e2072cbb 62 //Default constructor to initialize network, mbedTLS structures
lokeshhk 5:ea9f483e0294 63 MQTTNetwork(): serverPort(1883){
lokeshhk 5:ea9f483e0294 64 //Instantiate new ethernet interface
lokeshhk 5:ea9f483e0294 65 network = new EthernetInterface();
lokeshhk 5:ea9f483e0294 66 //Connect to ethernet interface
lokeshhk 5:ea9f483e0294 67 network->connect();
lokeshhk 5:ea9f483e0294 68 //Create socket with created ethernet interface
lamell 18:ce12e2072cbb 69 //socket = new TCPSocket(network);
lamell 18:ce12e2072cbb 70 //TCPSocket* socket;
lokeshhk 5:ea9f483e0294 71
lokeshhk 5:ea9f483e0294 72 //Instantiate mbedTLS structures
lokeshhk 5:ea9f483e0294 73 _entropy = new mbedtls_entropy_context();
lokeshhk 5:ea9f483e0294 74 _ctr_drbg = new mbedtls_ctr_drbg_context();
lokeshhk 5:ea9f483e0294 75 _cacert = new mbedtls_x509_crt();
lokeshhk 5:ea9f483e0294 76 _ssl = new mbedtls_ssl_context();
lokeshhk 5:ea9f483e0294 77 _ssl_conf = new mbedtls_ssl_config();
lokeshhk 5:ea9f483e0294 78
lokeshhk 5:ea9f483e0294 79 //Initialize mbedTLS structures
lokeshhk 5:ea9f483e0294 80 mbedtls_entropy_init(_entropy);
lokeshhk 5:ea9f483e0294 81 mbedtls_ctr_drbg_init(_ctr_drbg);
lokeshhk 5:ea9f483e0294 82 mbedtls_x509_crt_init(_cacert);
lokeshhk 5:ea9f483e0294 83 mbedtls_ssl_init(_ssl);
lokeshhk 5:ea9f483e0294 84 mbedtls_ssl_config_init(_ssl_conf);
lokeshhk 5:ea9f483e0294 85 }
lokeshhk 5:ea9f483e0294 86
lamell 18:ce12e2072cbb 87 // //Getter method to return underlying EthernetInterface
lamell 18:ce12e2072cbb 88 // NetworkInterface* getEth()
lamell 18:ce12e2072cbb 89 // {
lamell 18:ce12e2072cbb 90 // return network;
lamell 18:ce12e2072cbb 91 // }
lokeshhk 5:ea9f483e0294 92
lokeshhk 5:ea9f483e0294 93 //Destructor to release the resources
lokeshhk 5:ea9f483e0294 94 ~MQTTNetwork() {
lokeshhk 5:ea9f483e0294 95 //Release mbedTLS resources
lokeshhk 5:ea9f483e0294 96 mbedtls_entropy_free(_entropy);
lokeshhk 5:ea9f483e0294 97 mbedtls_ctr_drbg_free(_ctr_drbg);
lokeshhk 5:ea9f483e0294 98 mbedtls_x509_crt_free(_cacert);
lokeshhk 5:ea9f483e0294 99 mbedtls_ssl_free(_ssl);
lokeshhk 5:ea9f483e0294 100 mbedtls_ssl_config_free(_ssl_conf);
lokeshhk 5:ea9f483e0294 101
lokeshhk 5:ea9f483e0294 102 //Free the allocated memory for socket and network pointers
lamell 18:ce12e2072cbb 103 //delete socket;
lokeshhk 5:ea9f483e0294 104 delete network;
lokeshhk 5:ea9f483e0294 105
lokeshhk 5:ea9f483e0294 106 //Free the allocated memory for mbedTLS structures
lokeshhk 5:ea9f483e0294 107 delete _entropy;
lokeshhk 5:ea9f483e0294 108 delete _ctr_drbg;
lokeshhk 5:ea9f483e0294 109 delete _cacert;
lokeshhk 5:ea9f483e0294 110 delete _ssl;
lokeshhk 5:ea9f483e0294 111 delete _ssl_conf;
lokeshhk 5:ea9f483e0294 112 }
lokeshhk 5:ea9f483e0294 113
lokeshhk 5:ea9f483e0294 114 //Connect method to establish TCP socket connection
lokeshhk 5:ea9f483e0294 115 //If port=1883, opens unsecured socket connection
lokeshhk 5:ea9f483e0294 116 //If port is other than 1883, opens secured socket connection
lokeshhk 5:ea9f483e0294 117 int connect(const char*host, int port){
lokeshhk 5:ea9f483e0294 118 int rc = -1;
lokeshhk 5:ea9f483e0294 119
lamell 18:ce12e2072cbb 120 socket.open(network);
lokeshhk 5:ea9f483e0294 121 serverPort = port;
lokeshhk 5:ea9f483e0294 122 if(port == 1883)
lokeshhk 5:ea9f483e0294 123 //Establish unsecured socket connection
lamell 18:ce12e2072cbb 124
lamell 18:ce12e2072cbb 125 rc = socket.connect(host, port);
lokeshhk 5:ea9f483e0294 126 else{
lokeshhk 5:ea9f483e0294 127 //Establish secure socket connection using SSL/TLS
lokeshhk 5:ea9f483e0294 128 //Perform mbedTLS initialization
lokeshhk 5:ea9f483e0294 129 if((rc = initializeTLS(host)) == 0){
lamell 18:ce12e2072cbb 130 //if((rc = socket->connect(host, port))==0){
lamell 18:ce12e2072cbb 131 if((rc = socket.connect(host, port))==0){
lamell 18:ce12e2072cbb 132 pc.printf("Socket connection to %s:%d successful...\r\n",host,port);
lokeshhk 5:ea9f483e0294 133 //Perform SSL handshake
lokeshhk 5:ea9f483e0294 134 if ((rc = mbedtls_ssl_handshake(_ssl)) < 0) {
lokeshhk 5:ea9f483e0294 135 if (rc != MBEDTLS_ERR_SSL_WANT_READ &&
lokeshhk 5:ea9f483e0294 136 rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
lamell 18:ce12e2072cbb 137 pc.printf("mbedtls_ssl_handshake failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 138 }
lokeshhk 5:ea9f483e0294 139 goto exit;
lokeshhk 5:ea9f483e0294 140 }
lokeshhk 5:ea9f483e0294 141 }
lokeshhk 5:ea9f483e0294 142 }
lokeshhk 5:ea9f483e0294 143 }
lokeshhk 5:ea9f483e0294 144
lokeshhk 5:ea9f483e0294 145 exit:
lokeshhk 5:ea9f483e0294 146 return rc;
lokeshhk 5:ea9f483e0294 147 }
lokeshhk 5:ea9f483e0294 148
lokeshhk 5:ea9f483e0294 149 //Method to initialize mbedTLS structures
lokeshhk 5:ea9f483e0294 150 int initializeTLS(const char* hostName){
lokeshhk 5:ea9f483e0294 151 int rc = 0;
lokeshhk 5:ea9f483e0294 152
lokeshhk 5:ea9f483e0294 153 //Initialize entropy seeding
lokeshhk 5:ea9f483e0294 154 if ((rc = mbedtls_ctr_drbg_seed(_ctr_drbg, mbedtls_entropy_func, _entropy,
lokeshhk 5:ea9f483e0294 155 (const unsigned char *) tlsClientName,
lokeshhk 5:ea9f483e0294 156 sizeof (tlsClientName))) != 0) {
lamell 18:ce12e2072cbb 157 pc.printf("mbedtls_crt_drbg_init failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 158 goto exit;
lokeshhk 5:ea9f483e0294 159 }
lokeshhk 5:ea9f483e0294 160
lokeshhk 5:ea9f483e0294 161 //Parse certificates into mbedTLS structure
lokeshhk 5:ea9f483e0294 162 if ((rc = mbedtls_x509_crt_parse(_cacert, (const unsigned char *) serverCert,
lokeshhk 5:ea9f483e0294 163 sizeof(serverCert))) != 0) {
lamell 18:ce12e2072cbb 164 pc.printf("mbedtls_x509_crt_parse for serverCert failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 165 goto exit;
lokeshhk 5:ea9f483e0294 166 }
lokeshhk 5:ea9f483e0294 167
lokeshhk 5:ea9f483e0294 168 //Set ssl config details
lokeshhk 5:ea9f483e0294 169 if ((rc = mbedtls_ssl_config_defaults(_ssl_conf,
lokeshhk 5:ea9f483e0294 170 MBEDTLS_SSL_IS_CLIENT,
lokeshhk 5:ea9f483e0294 171 MBEDTLS_SSL_TRANSPORT_STREAM,
lokeshhk 5:ea9f483e0294 172 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
lamell 18:ce12e2072cbb 173 pc.printf("mbedtls_ssl_config_defaults failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 174 goto exit;
lokeshhk 5:ea9f483e0294 175 }
lokeshhk 5:ea9f483e0294 176
lokeshhk 5:ea9f483e0294 177 //Add parsed server certificate to ssl config
lokeshhk 5:ea9f483e0294 178 mbedtls_ssl_conf_ca_chain(_ssl_conf, _cacert, NULL);
lokeshhk 5:ea9f483e0294 179
lokeshhk 5:ea9f483e0294 180 mbedtls_ssl_conf_rng(_ssl_conf, mbedtls_ctr_drbg_random, _ctr_drbg);
lokeshhk 5:ea9f483e0294 181
lokeshhk 5:ea9f483e0294 182 //Set Server Certificate authorization mode
lokeshhk 5:ea9f483e0294 183 mbedtls_ssl_conf_authmode(_ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
lokeshhk 5:ea9f483e0294 184
lokeshhk 5:ea9f483e0294 185 //Perform mbedTLS ssl setup
lokeshhk 5:ea9f483e0294 186 if ((rc = mbedtls_ssl_setup(_ssl, _ssl_conf)) != 0) {
lamell 18:ce12e2072cbb 187 pc.printf("mbedtls_ssl_setup failed - 0x%x\r\n", -rc);
lokeshhk 5:ea9f483e0294 188 goto exit;
lokeshhk 5:ea9f483e0294 189 }
lokeshhk 5:ea9f483e0294 190
lokeshhk 5:ea9f483e0294 191 //Set hostname to establish SSL connection
lokeshhk 5:ea9f483e0294 192 mbedtls_ssl_set_hostname(_ssl, hostName);
lokeshhk 5:ea9f483e0294 193
lokeshhk 5:ea9f483e0294 194 //Set buffer I/O methods for SSL connection
lamell 18:ce12e2072cbb 195 mbedtls_ssl_set_bio(_ssl, static_cast<void *>(&socket),
lokeshhk 5:ea9f483e0294 196 tlsWrite, tlsRead, NULL );
lokeshhk 5:ea9f483e0294 197
lokeshhk 5:ea9f483e0294 198 exit:
lokeshhk 5:ea9f483e0294 199 return rc;
lokeshhk 5:ea9f483e0294 200 }
lokeshhk 5:ea9f483e0294 201
lokeshhk 5:ea9f483e0294 202 //Method to read from SSL socket
lokeshhk 5:ea9f483e0294 203 static int tlsRead(void *ctx,unsigned char* buffer, size_t len) {
lokeshhk 5:ea9f483e0294 204 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
lokeshhk 5:ea9f483e0294 205 int rc = socket->recv(buffer, len);
lokeshhk 5:ea9f483e0294 206 return rc;
lokeshhk 5:ea9f483e0294 207 }
lokeshhk 5:ea9f483e0294 208
lokeshhk 5:ea9f483e0294 209 //Method to write to SSL socket
lokeshhk 5:ea9f483e0294 210 static int tlsWrite(void *ctx,const unsigned char* buffer, size_t len) {
lokeshhk 5:ea9f483e0294 211 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
lokeshhk 5:ea9f483e0294 212 int rc = socket->send(buffer, len);
lokeshhk 5:ea9f483e0294 213 return rc;
lokeshhk 5:ea9f483e0294 214 }
lokeshhk 5:ea9f483e0294 215
lokeshhk 5:ea9f483e0294 216 //Method to read MQTT Packets
lokeshhk 5:ea9f483e0294 217 int read(unsigned char* buffer, int len, int timeout) {
lokeshhk 5:ea9f483e0294 218 int rc = 0;
lokeshhk 5:ea9f483e0294 219
lokeshhk 5:ea9f483e0294 220 if(serverPort == 1883)
lamell 18:ce12e2072cbb 221 rc = socket.recv(buffer,len);
lokeshhk 5:ea9f483e0294 222 else
lokeshhk 5:ea9f483e0294 223 rc = mbedtls_ssl_read(_ssl, (unsigned char *) buffer, len);
lokeshhk 5:ea9f483e0294 224
lokeshhk 5:ea9f483e0294 225 return rc;
lokeshhk 5:ea9f483e0294 226 }
lokeshhk 5:ea9f483e0294 227
lokeshhk 5:ea9f483e0294 228 //Method to send MQTT Packets
lokeshhk 5:ea9f483e0294 229 int write(unsigned char* buffer, int len, int timeout) {
lokeshhk 5:ea9f483e0294 230 int rc = 0;
lokeshhk 5:ea9f483e0294 231
lokeshhk 5:ea9f483e0294 232 if(serverPort == 1883)
lamell 18:ce12e2072cbb 233 rc = socket.send(buffer,len);
lokeshhk 5:ea9f483e0294 234 else
lokeshhk 5:ea9f483e0294 235 rc = mbedtls_ssl_write(_ssl, (const unsigned char *) buffer, len);
lokeshhk 5:ea9f483e0294 236
lokeshhk 5:ea9f483e0294 237 return rc;
lokeshhk 5:ea9f483e0294 238 }
lokeshhk 5:ea9f483e0294 239
lokeshhk 5:ea9f483e0294 240 //Method to close socket connection
lokeshhk 5:ea9f483e0294 241 void disconnect(){
lamell 18:ce12e2072cbb 242 socket.close();
lokeshhk 5:ea9f483e0294 243 }
lokeshhk 5:ea9f483e0294 244
lokeshhk 5:ea9f483e0294 245 };
lokeshhk 5:ea9f483e0294 246 }
lokeshhk 5:ea9f483e0294 247 #endif