Fork of Hello MQTT, using mbed TLS for secure mqtt transport
Fork of HelloMQTT by
MQTTSNetwork.h
00001 #ifndef _MQTTSNETWORK_H_ 00002 #define _MQTTSNETWORK_H_ 00003 00004 #include "NetworkInterface.h" 00005 #include "TCPSocket.h" 00006 #include "mbedtls/platform.h" 00007 #include "mbedtls/ssl.h" 00008 #include "mbedtls/entropy.h" 00009 #include "mbedtls/ctr_drbg.h" 00010 #include "mbedtls/error.h" 00011 00012 #if DEBUG_LEVEL > 0 00013 #include "mbedtls/debug.h" 00014 #endif 00015 00016 class MQTTSNetwork { 00017 public: 00018 00019 MQTTSNetwork() 00020 : tcpsocket(NULL) 00021 ,ssl_ca_pem(NULL) 00022 ,keepalive(1) 00023 { 00024 DRBG_PERS = "mbed TLS MQTT client"; 00025 00026 mbedtls_entropy_init(&_entropy); 00027 mbedtls_ctr_drbg_init(&_ctr_drbg); 00028 mbedtls_x509_crt_init(&_cacert); 00029 mbedtls_ssl_init(&_ssl); 00030 mbedtls_ssl_config_init(&_ssl_conf); 00031 memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) ); 00032 } 00033 00034 ~MQTTSNetwork() 00035 { 00036 00037 mbedtls_entropy_free(&_entropy); 00038 mbedtls_ctr_drbg_free(&_ctr_drbg); 00039 mbedtls_x509_crt_free(&_cacert); 00040 mbedtls_ssl_free(&_ssl); 00041 mbedtls_ssl_config_free(&_ssl_conf); 00042 00043 if (tcpsocket) 00044 delete tcpsocket; 00045 00046 } 00047 00048 00049 00050 int setupTLS(NetworkInterface * net, const char * pem) 00051 { 00052 int ret; 00053 00054 network = net; 00055 ssl_ca_pem = pem; 00056 00057 printf("Initializing TLS ...\r\n"); 00058 printf("mbedtls_ctr_drdbg_seed ...\r\n"); 00059 if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy, 00060 (const unsigned char *) DRBG_PERS, 00061 sizeof (DRBG_PERS))) != 0) { 00062 print_mbedtls_error("mbedtls_crt_drbg_init", ret); 00063 _error = ret; 00064 return -1; 00065 } 00066 printf("mbedtls_x509_crt_parse ...\r\n"); 00067 if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *) ssl_ca_pem, 00068 strlen(ssl_ca_pem) + 1)) != 0) { 00069 print_mbedtls_error("mbedtls_x509_crt_parse", ret); 00070 _error = ret; 00071 return -1; 00072 } 00073 00074 printf("mbedtls_ssl_config_defaults ...\r\n"); 00075 if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf, 00076 MBEDTLS_SSL_IS_CLIENT, 00077 MBEDTLS_SSL_TRANSPORT_STREAM, 00078 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 00079 print_mbedtls_error("mbedtls_ssl_config_defaults", ret); 00080 _error = ret; 00081 return -1; 00082 } 00083 00084 printf("mbedtls_ssl_config_ca_chain ...\r\n"); 00085 mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL); 00086 printf("mbedtls_ssl_conf_rng ...\r\n"); 00087 mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); 00088 00089 /* It is possible to disable authentication by passing 00090 * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode() 00091 */ 00092 printf("mbedtls_ssl_conf_authmode ...\r\n"); 00093 mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); 00094 00095 #if DEBUG_LEVEL > 0 00096 mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL); 00097 mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL); 00098 mbedtls_debug_set_threshold(DEBUG_LEVEL); 00099 #endif 00100 00101 printf("mbedtls_ssl_setup ...\r\n"); 00102 if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) { 00103 print_mbedtls_error("mbedtls_ssl_setup", ret); 00104 _error = ret; 00105 return -1; 00106 } 00107 00108 00109 return ret; 00110 } 00111 00112 int read(unsigned char* buffer, int len, int timeout) 00113 { 00114 int ret; 00115 printf("MQTTS client read ...\r\n"); 00116 00117 printf("read set timeout ... %d\r\n", timeout); 00118 tcpsocket->set_timeout(timeout); 00119 00120 ret = mbedtls_ssl_read(&_ssl, buffer, len); 00121 printf("mbedtls_ssl_read returned %d\r\n", ret); 00122 if (ret < 0) { 00123 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) 00124 print_mbedtls_error("mbedtls_ssl_read", ret); 00125 else 00126 printf("Timed out? ...\r\n"); 00127 00128 _error = ret; 00129 printf("MQTTS client read returns with error!!!...\r\n"); 00130 return ret; 00131 } 00132 printf("MQTS client read successfully!! ...\r\n"); 00133 return ret ; 00134 } 00135 00136 int write(unsigned char* buffer, int len, int timeout) 00137 { 00138 int ret; 00139 00140 printf("MQTTS client write ...\r\n"); 00141 tcpsocket->set_timeout(timeout); 00142 00143 ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) buffer, len); 00144 if (ret < 0) { 00145 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00146 print_mbedtls_error("mbedtls_ssl_write", ret); 00147 //onError(tcpsocket, -1 ); 00148 } 00149 else { 00150 _error = ret; 00151 } 00152 return ret; 00153 } 00154 00155 return ret; 00156 } 00157 00158 int connect(const char* host, int port) 00159 { 00160 // Do the TLS handshake here ... 00161 /* Initialize the flags */ 00162 /* 00163 * Initialize TLS-related stuf. 00164 */ 00165 int ret; 00166 00167 // Save the hostname and port on first connect 00168 // Create the socket 00169 if (tcpsocket == NULL) 00170 { 00171 printf("Creating TCP socket ...\r\n"); 00172 tcpsocket = new TCPSocket(network); 00173 } 00174 00175 if (tcpsocket == NULL) 00176 ret = -1; 00177 00178 00179 printf("mbedtls_ssl_set_hostname ...\r\n"); 00180 mbedtls_ssl_set_hostname(&_ssl, host); 00181 printf("mbedtls_ssl_set_bio ...\r\n"); 00182 mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(tcpsocket), 00183 ssl_send, ssl_recv, NULL ); 00184 00185 printf("Connecting to %s:%d\r\n", host, port); 00186 ret = tcpsocket->connect(host, port); 00187 if (ret != NSAPI_ERROR_OK) { 00188 if (_debug) mbedtls_printf("Failed to connect\r\n"); 00189 onError(tcpsocket, -1); 00190 return -1; 00191 } 00192 00193 /* Start the handshake, the rest will be done in onReceive() */ 00194 printf("Starting the TLS handshake...\r\n"); 00195 ret = mbedtls_ssl_handshake(&_ssl); 00196 if (ret < 0) { 00197 if (ret != MBEDTLS_ERR_SSL_WANT_READ && 00198 ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 00199 print_mbedtls_error("mbedtls_ssl_handshake", ret); 00200 onError(tcpsocket, -1); 00201 } 00202 else { 00203 _error = ret; 00204 } 00205 return -1; 00206 } 00207 00208 /* Handshake done, time to print info */ 00209 printf("TLS connection to %s:%d established\r\n", 00210 host, port); 00211 00212 const uint32_t buf_size = 1024; 00213 char *buf = new char[buf_size]; 00214 mbedtls_x509_crt_info(buf, buf_size, "\r ", 00215 mbedtls_ssl_get_peer_cert(&_ssl)); 00216 printf("Server certificate:\r\n%s\r", buf); 00217 00218 uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); 00219 if( flags != 0 ) 00220 { 00221 mbedtls_x509_crt_verify_info(buf, buf_size, "\r ! ", flags); 00222 printf("Certificate verification failed:\r\n%s\r\r\n", buf); 00223 return -1; 00224 } 00225 00226 printf("Certificate verification passed\r\n\r\n"); 00227 00228 // TODO: Save the session here for reconnect. 00229 if( ( ret = mbedtls_ssl_get_session( &_ssl, &saved_session ) ) != 0 ) 00230 { 00231 printf( "mbedtls_ssl_get_session returned -0x%x\n\n", -ret ); 00232 return -1; 00233 } 00234 printf("Session saved for reconnect ...\r\n"); 00235 00236 // Set socket to non-blocking mode ... 00237 00238 return 0; 00239 } 00240 00241 void disconnect() 00242 { 00243 if (tcpsocket) 00244 { 00245 tcpsocket->close(); 00246 delete tcpsocket; 00247 tcpsocket = NULL; 00248 } 00249 } 00250 00251 protected: 00252 /** 00253 * Helper for pretty-printing mbed TLS error codes 00254 */ 00255 static void print_mbedtls_error(const char *name, int err) { 00256 char buf[128]; 00257 mbedtls_strerror(err, buf, sizeof (buf)); 00258 mbedtls_printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf); 00259 } 00260 00261 #if DEBUG_LEVEL > 0 00262 /** 00263 * Debug callback for mbed TLS 00264 * Just prints on the USB serial port 00265 */ 00266 static void my_debug(void *ctx, int level, const char *file, int line, 00267 const char *str) 00268 { 00269 const char *p, *basename; 00270 (void) ctx; 00271 00272 /* Extract basename from file */ 00273 for(p = basename = file; *p != '\0'; p++) { 00274 if(*p == '/' || *p == '\\') { 00275 basename = p + 1; 00276 } 00277 } 00278 00279 if (_debug) { 00280 mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); 00281 } 00282 } 00283 00284 /** 00285 * Certificate verification callback for mbed TLS 00286 * Here we only use it to display information on each cert in the chain 00287 */ 00288 static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) 00289 { 00290 const uint32_t buf_size = 1024; 00291 char *buf = new char[buf_size]; 00292 (void) data; 00293 00294 if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); 00295 mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); 00296 if (_debug) mbedtls_printf("%s", buf); 00297 00298 if (*flags == 0) 00299 if (_debug) mbedtls_printf("No verification issue for this certificate\n"); 00300 else 00301 { 00302 mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); 00303 if (_debug) mbedtls_printf("%s\n", buf); 00304 } 00305 00306 delete[] buf; 00307 return 0; 00308 } 00309 #endif 00310 00311 /** 00312 * Receive callback for mbed TLS 00313 */ 00314 static int ssl_recv(void *ctx, unsigned char *buf, size_t len) { 00315 int recv = -1; 00316 TCPSocket *socket = static_cast<TCPSocket *>(ctx); 00317 recv = socket->recv(buf, len); 00318 00319 if (NSAPI_ERROR_WOULD_BLOCK == recv) { 00320 return MBEDTLS_ERR_SSL_WANT_READ; 00321 } 00322 else if (recv < 0) { 00323 return -1; 00324 } 00325 else { 00326 return recv; 00327 } 00328 } 00329 00330 /** 00331 * Send callback for mbed TLS 00332 */ 00333 static int ssl_send(void *ctx, const unsigned char *buf, size_t len) { 00334 int sent = -1; 00335 TCPSocket *socket = static_cast<TCPSocket *>(ctx); 00336 sent = socket->send(buf, len); 00337 00338 if(NSAPI_ERROR_WOULD_BLOCK == sent) { 00339 return MBEDTLS_ERR_SSL_WANT_WRITE; 00340 } 00341 else if (sent < 0){ 00342 return -1; 00343 } 00344 else { 00345 return sent; 00346 } 00347 } 00348 00349 void onError(TCPSocket *s, int error) { 00350 s->close(); 00351 _error = error; 00352 } 00353 00354 private: 00355 NetworkInterface * network; 00356 TCPSocket* tcpsocket; 00357 const char * ssl_ca_pem; 00358 bool _debug; 00359 nsapi_error_t _error; 00360 const char *DRBG_PERS; 00361 int keepalive; 00362 mbedtls_entropy_context _entropy; 00363 mbedtls_ctr_drbg_context _ctr_drbg; 00364 mbedtls_x509_crt _cacert; 00365 mbedtls_ssl_context _ssl; 00366 mbedtls_ssl_config _ssl_conf; 00367 mbedtls_ssl_session saved_session; 00368 00369 }; 00370 00371 #endif // _MQTTNETWORK_H_
Generated on Fri Jul 15 2022 22:45:13 by
1.7.2
