IBM Watson IoT / Mbed OS IBMIoTF

Dependencies:   MQTT

Dependents:   IBMIoTClientLibrarySamplefinal IBMWIoTPSecureClientSample IBMIoTClientLibrarySample

Committer:
lokeshhk
Date:
Tue May 30 06:24:06 2017 +0000
Revision:
5:ea9f483e0294
mbed-os porting and ssl/tls support

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