Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
