/******************************************************************************* * Copyright (c) 2014, 2015 IBM Corp. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Allan Stockdill-Mander - initial API and implementation and/or initial documentation * Ian Craggs - convert to FreeRTOS *******************************************************************************/ #include "MQTTFreertos.h" #include "netdb.h" #ifdef LWIP_IPV6 #undef LWIP_IPV6 #endif #ifdef inet_ntop #undef inet_ntop #endif #ifdef inet_pton #undef inet_pton #endif #define LWIP_IPV6 0 #if LWIP_IPV6 #define inet_ntop(af,src,dst,size) \ (((af) == AF_INET6) ? ip6addr_ntoa_r((src),(dst),(size)) \ : (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL)) #define inet_pton(af,src,dst) \ (((af) == AF_INET6) ? inet6_aton((src),(dst)) \ : (((af) == AF_INET) ? inet_aton((src),(dst)) : 0)) #else /* LWIP_IPV6 */ #define inet_ntop(af,src,dst,size) \ (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL) #define inet_pton(af,src,dst) \ (((af) == AF_INET) ? inet_aton((src),(dst)) : 0) #endif /* LWIP_IPV6 */ int ThreadStart(Thread* thread, void (*fn)(void*), void* arg) { int rc = 0; uint16_t usTaskStackSize = (configMINIMAL_STACK_SIZE * 5); UBaseType_t uxTaskPriority = uxTaskPriorityGet(NULL); /* set the priority as the same as the calling task*/ rc = xTaskCreate(fn, /* The function that implements the task. */ "MQTTTask", /* Just a text name for the task to aid debugging. */ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ arg, /* The task parameter, not used in this case. */ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ &thread->task); /* The task handle is not used. */ return rc; } void MutexInit(Mutex* mutex) { mutex->sem = xSemaphoreCreateMutex(); } int MutexLock(Mutex* mutex) { return xSemaphoreTake(mutex->sem, portMAX_DELAY); } int MutexUnlock(Mutex* mutex) { return xSemaphoreGive(mutex->sem); } void TimerCountdownMS(Timer* timer, unsigned int timeout_ms) { timer->xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */ vTaskSetTimeOutState(&timer->xTimeOut); /* Record the time at which this function was entered. */ } void TimerCountdown(Timer* timer, unsigned int timeout) { TimerCountdownMS(timer, timeout * 1000); } int TimerLeftMS(Timer* timer) { xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait); /* updates xTicksToWait to the number left */ return (timer->xTicksToWait * portTICK_PERIOD_MS); } char TimerIsExpired(Timer* timer) { return xTaskCheckForTimeOut(&timer->xTimeOut, &timer->xTicksToWait) == pdTRUE; } void TimerInit(Timer* timer) { timer->xTicksToWait = 0; memset(&timer->xTimeOut, '\0', sizeof(timer->xTimeOut)); } #if CONFIG_USE_POLARSSL int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms) { TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */ TimeOut_t xTimeOut; int recvLen = 0; int so_error; socklen_t errlen = sizeof(so_error); vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */ do { int rc = 0; #if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0) // timeout format is changed in lwip 1.5.0 struct timeval timeout; timeout.tv_sec = xTicksToWait / 1000; timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000; setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); #else setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait)); #endif #if (MQTT_OVER_SSL) if (n->use_ssl) { rc = ssl_read(n->ssl, buffer + recvLen, len - recvLen); getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error && so_error != EAGAIN) { n->disconnect(n); } } else #endif rc = recv(n->my_socket, buffer + recvLen, len - recvLen, 0); if (rc > 0) recvLen += rc; else if (rc < 0) { getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error != EAGAIN) { n->disconnect(n); } recvLen = rc; break; } } while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE); return recvLen; } int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms) { TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */ TimeOut_t xTimeOut; int sentLen = 0; int so_error; socklen_t errlen = sizeof(so_error); vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */ do { int rc = 0; #if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0) // timeout format is changed in lwip 1.5.0 struct timeval timeout; timeout.tv_sec = xTicksToWait / 1000; timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000; setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)); #else setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &xTicksToWait, sizeof(xTicksToWait)); #endif #if (MQTT_OVER_SSL) if (n->use_ssl) { rc = ssl_write(n->ssl, buffer + sentLen, len - sentLen); getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error && so_error != EAGAIN) { n->disconnect(n); } } else #endif rc = send(n->my_socket, buffer + sentLen, len - sentLen, 0); if (rc > 0) sentLen += rc; else if (rc < 0) { getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &len); if (so_error != EAGAIN) { n->disconnect(n); } sentLen = rc; break; } } while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE); return sentLen; } void FreeRTOS_disconnect(Network* n) { shutdown(n->my_socket, SHUT_RDWR); close(n->my_socket); n->my_socket = -1; #if (MQTT_OVER_SSL) if (n->use_ssl) { ssl_free(n->ssl); free(n->ssl); n->ssl = NULL; } #endif } void NetworkInit(Network* n) { n->my_socket = -1; n->mqttread = FreeRTOS_read; n->mqttwrite = FreeRTOS_write; n->disconnect = FreeRTOS_disconnect; #if (MQTT_OVER_SSL) n->use_ssl = 0; n->ssl = NULL; n->rootCA = NULL; n->clientCA = NULL; n->private_key = NULL; #endif } #if (MQTT_OVER_SSL) static int mqtt_tls_verify( void *data, x509_crt *crt, int depth, int *flags ) { char buf[1024]; mqtt_printf(MQTT_DEBUG, "\nVerify requested for (Depth %d):\n", depth ); x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); mqtt_printf(MQTT_DEBUG, "%s", buf ); if( ( (*flags) & BADCERT_EXPIRED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! server certificate has expired\n" ); if( ( (*flags) & BADCERT_REVOKED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! server certificate has been revoked\n" ); if( ( (*flags) & BADCERT_CN_MISMATCH ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CN mismatch\n" ); if( ( (*flags) & BADCERT_NOT_TRUSTED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! self-signed or not signed by a trusted CA\n" ); if( ( (*flags) & BADCRL_NOT_TRUSTED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CRL not trusted\n" ); if( ( (*flags) & BADCRL_EXPIRED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CRL expired\n" ); if( ( (*flags) & BADCERT_OTHER ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! other (unknown) flag\n" ); if ( ( *flags ) == 0 ) mqtt_printf(MQTT_DEBUG, " This certificate has no flags\n" ); return( 0 ); } static int my_random(void *p_rng, unsigned char *output, size_t output_len) { rtw_get_random_bytes(output, output_len); return 0; } #endif // #if (MQTT_OVER_SSL) int NetworkConnect(Network* n, char* addr, int port) { struct sockaddr_in sAddr; int retVal = -1; struct hostent *hptr; char **pptr; char str[32]; int keepalive_enable = 1; int keep_idle = 30; if(n->my_socket >= 0){ n->disconnect(n); } if ((hptr = gethostbyname(addr)) == 0) { mqtt_printf(MQTT_DEBUG, "gethostbyname failed!"); goto exit; } pptr = hptr->h_addr_list; for(; *pptr!=NULL; pptr++) { inet_ntop(hptr->h_addrtype, (const ip_addr_t *)*pptr, str, sizeof(str)); } inet_ntop(hptr->h_addrtype, (const ip_addr_t *)hptr->h_addr, str, sizeof(str)); sAddr.sin_family = AF_INET; sAddr.sin_port = htons(port); sAddr.sin_addr.s_addr = inet_addr(str); mqtt_printf(MQTT_DEBUG, "addr = %s", str); if ((n->my_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { goto exit; } setsockopt( n->my_socket, SOL_SOCKET, SO_KEEPALIVE, (const char *) &keepalive_enable, sizeof( keepalive_enable ) ); setsockopt( n->my_socket, IPPROTO_TCP, TCP_KEEPIDLE, (const char *) &keep_idle, sizeof( keep_idle ) ); if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0) { close(n->my_socket); mqtt_printf(MQTT_DEBUG, "Connect failed!!"); goto exit; } #if (MQTT_OVER_SSL) x509_crt *root_crt; x509_crt *client_crt; pk_context *client_rsa; root_crt = NULL; client_crt = NULL; client_rsa = NULL; if ( n->use_ssl != 0 ) { memory_set_own(pvPortMalloc, vPortFree); n->ssl = (ssl_context *) malloc( sizeof(ssl_context) ); if ( n->ssl == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc ssl failed!"); goto err; } memset(n->ssl, 0, sizeof(ssl_context)); if ( ssl_init(n->ssl) != 0 ) { mqtt_printf(MQTT_DEBUG, "init ssl failed!"); goto err; } ssl_set_endpoint(n->ssl, SSL_IS_CLIENT); if (n->rootCA != NULL) { root_crt = (x509_crt *) polarssl_malloc( sizeof(x509_crt) ); if ( root_crt == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc root_crt failed!"); goto err; } memset(root_crt, 0, sizeof(x509_crt)); ssl_set_authmode( n->ssl, SSL_VERIFY_REQUIRED ); if (x509_crt_parse( root_crt, n->rootCA, strlen(n->rootCA) ) != 0) { mqtt_printf(MQTT_DEBUG, "parse root_crt failed!"); goto err; } ssl_set_ca_chain( n->ssl, root_crt, NULL, NULL ); ssl_set_verify( n->ssl, mqtt_tls_verify, NULL ); mqtt_printf(MQTT_DEBUG, "root_crt parse done"); } else { ssl_set_authmode(n->ssl, SSL_VERIFY_NONE); } if (n->clientCA != NULL && n->private_key != NULL) { client_crt = (x509_crt *) polarssl_malloc( sizeof(x509_crt) ); if ( client_crt == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc client_crt failed!"); goto err; } memset(client_crt, 0, sizeof(x509_crt)); x509_crt_init(client_crt); client_rsa = (pk_context *) polarssl_malloc( sizeof(pk_context) ); if ( client_rsa == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc client_rsa failed!"); goto err; } memset(client_rsa, 0, sizeof(pk_context)); pk_init(client_rsa); if ( x509_crt_parse(client_crt, n->clientCA, strlen(n->clientCA)) != 0 ) { mqtt_printf(MQTT_DEBUG, "parse client_crt failed!"); goto err; } if ( pk_parse_key(client_rsa, n->private_key, strlen(n->private_key), NULL, 0) != 0 ) { mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!"); goto err; } ssl_set_own_cert(n->ssl, client_crt, client_rsa); mqtt_printf(MQTT_DEBUG, "client_crt parse done"); } ssl_set_rng(n->ssl, my_random, NULL); ssl_set_bio(n->ssl, net_recv, &n->my_socket, net_send, &n->my_socket); retVal = ssl_handshake(n->ssl); if (retVal < 0) { mqtt_printf(MQTT_DEBUG, "ssl handshake failed err:-0x%04X", -retVal); goto err; } else { mqtt_printf(MQTT_DEBUG, "ssl handshake success"); } } if (client_rsa) { pk_free(client_rsa); polarssl_free(client_rsa); } if (client_crt) { x509_crt_free(client_crt); polarssl_free(client_crt); } if (root_crt) { x509_crt_free(root_crt); polarssl_free(root_crt); } goto exit; err: if (client_rsa) { pk_free(client_rsa); polarssl_free(client_rsa); } if (client_crt) { x509_crt_free(client_crt); polarssl_free(client_crt); } if (root_crt) { x509_crt_free(root_crt); polarssl_free(root_crt); } net_close(n->my_socket); ssl_free(n->ssl); free(n->ssl); retVal = -1; #endif // #if (MQTT_OVER_SSL) exit: return retVal; } #elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */ int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms) { TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */ TimeOut_t xTimeOut; int recvLen = 0; int so_error; socklen_t errlen = sizeof(so_error); vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */ do { int rc = 0; #if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0) // timeout format is changed in lwip 1.5.0 struct timeval timeout; timeout.tv_sec = xTicksToWait / 1000; timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000; setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); #else setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, &xTicksToWait, sizeof(xTicksToWait)); #endif #if (MQTT_OVER_SSL) if (n->use_ssl) { rc = mbedtls_ssl_read(n->ssl, buffer + recvLen, len - recvLen); getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error && so_error != EAGAIN) { n->disconnect(n); } } else #endif rc = recv(n->my_socket, buffer + recvLen, len - recvLen, 0); if (rc > 0) recvLen += rc; else if (rc < 0) { getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error != EAGAIN) { n->disconnect(n); } recvLen = rc; break; } } while (recvLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE); return recvLen; } int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms) { TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */ TimeOut_t xTimeOut; int sentLen = 0; int so_error; socklen_t errlen = sizeof(so_error); vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */ do { int rc = 0; #if defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) && (LWIP_SO_SNDRCVTIMEO_NONSTANDARD == 0) // timeout format is changed in lwip 1.5.0 struct timeval timeout; timeout.tv_sec = xTicksToWait / 1000; timeout.tv_usec = ( xTicksToWait % 1000 ) * 1000; setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)); #else setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, &xTicksToWait, sizeof(xTicksToWait)); #endif #if (MQTT_OVER_SSL) if (n->use_ssl) { rc = mbedtls_ssl_write(n->ssl, buffer + sentLen, len - sentLen); getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &errlen); if (so_error && so_error != EAGAIN) { n->disconnect(n); } } else #endif rc = send(n->my_socket, buffer + sentLen, len - sentLen, 0); if (rc > 0) sentLen += rc; else if (rc < 0) { getsockopt(n->my_socket, SOL_SOCKET, SO_ERROR, &so_error, &len); if (so_error != EAGAIN) { n->disconnect(n); } sentLen = rc; break; } } while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE); return sentLen; } void FreeRTOS_disconnect(Network* n) { shutdown(n->my_socket, SHUT_RDWR); close(n->my_socket); n->my_socket = -1; #if (MQTT_OVER_SSL) if (n->use_ssl) { mbedtls_ssl_free(n->ssl); mbedtls_ssl_config_free(n->conf); free(n->ssl); free(n->conf); n->ssl = NULL; n->conf = NULL; } #endif } void NetworkInit(Network* n) { n->my_socket = -1; n->mqttread = FreeRTOS_read; n->mqttwrite = FreeRTOS_write; n->disconnect = FreeRTOS_disconnect; #if (MQTT_OVER_SSL) n->use_ssl = 0; n->ssl = NULL; n->conf = NULL; n->rootCA = NULL; n->clientCA = NULL; n->private_key = NULL; #endif } #if (MQTT_OVER_SSL) static int mqtt_tls_verify( void *data, mbedtls_x509_crt *crt, int depth, int *flags ) { char buf[1024]; mqtt_printf(MQTT_DEBUG, "\nVerify requested for (Depth %d):\n", depth ); mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); mqtt_printf(MQTT_DEBUG, "%s", buf ); if( ( (*flags) & MBEDTLS_X509_BADCERT_EXPIRED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! server certificate has expired\n" ); if( ( (*flags) & MBEDTLS_X509_BADCERT_REVOKED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! server certificate has been revoked\n" ); if( ( (*flags) & MBEDTLS_X509_BADCERT_CN_MISMATCH ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CN mismatch\n" ); if( ( (*flags) & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! self-signed or not signed by a trusted CA\n" ); if( ( (*flags) & MBEDTLS_X509_BADCRL_NOT_TRUSTED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CRL not trusted\n" ); if( ( (*flags) & MBEDTLS_X509_BADCRL_EXPIRED ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! CRL expired\n" ); if( ( (*flags) & MBEDTLS_X509_BADCERT_OTHER ) != 0 ) mqtt_printf(MQTT_DEBUG, " ! other (unknown) flag\n" ); if ( ( *flags ) == 0 ) mqtt_printf(MQTT_DEBUG, " This certificate has no flags\n" ); return( 0 ); } static void* my_calloc(size_t nelements, size_t elementSize) { size_t size; void *ptr = NULL; size = nelements * elementSize; ptr = pvPortMalloc(size); if(ptr) memset(ptr, 0, size); return ptr; } static int my_random(void *p_rng, unsigned char *output, size_t output_len) { rtw_get_random_bytes(output, output_len); return 0; } #endif // #if (MQTT_OVER_SSL) int NetworkConnect(Network* n, char* addr, int port) { struct sockaddr_in sAddr; int retVal = -1; struct hostent *hptr; char **pptr; char str[32]; int keepalive_enable = 1; int keep_idle = 30; if(n->my_socket >= 0){ n->disconnect(n); } if ((hptr = gethostbyname(addr)) == 0) { mqtt_printf(MQTT_DEBUG, "gethostbyname failed!"); goto exit; } pptr = hptr->h_addr_list; for(; *pptr!=NULL; pptr++) { inet_ntop(hptr->h_addrtype, (const ip_addr_t *)*pptr, str, sizeof(str)); } inet_ntop(hptr->h_addrtype, (const ip_addr_t *)hptr->h_addr, str, sizeof(str)); sAddr.sin_family = AF_INET; sAddr.sin_port = htons(port); sAddr.sin_addr.s_addr = inet_addr(str); mqtt_printf(MQTT_DEBUG, "addr = %s", str); if ((n->my_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { goto exit; } setsockopt( n->my_socket, SOL_SOCKET, SO_KEEPALIVE, (const char *) &keepalive_enable, sizeof( keepalive_enable ) ); setsockopt( n->my_socket, IPPROTO_TCP, TCP_KEEPIDLE, (const char *) &keep_idle, sizeof( keep_idle ) ); if ((retVal = connect(n->my_socket, (struct sockaddr*)&sAddr, sizeof(sAddr))) < 0) { close(n->my_socket); mqtt_printf(MQTT_DEBUG, "Connect failed!!"); goto exit; } #if (MQTT_OVER_SSL) mbedtls_x509_crt *root_crt; mbedtls_x509_crt *client_crt; mbedtls_pk_context *client_rsa; root_crt = NULL; client_crt = NULL; client_rsa = NULL; if ( n->use_ssl != 0 ) { mbedtls_platform_set_calloc_free(my_calloc, vPortFree); n->ssl = (mbedtls_ssl_context *) malloc( sizeof(mbedtls_ssl_context) ); n->conf = (mbedtls_ssl_config *) malloc( sizeof(mbedtls_ssl_config) ); if (( n->ssl == NULL )||( n->conf == NULL )) { mqtt_printf(MQTT_DEBUG, "malloc ssl failed!"); goto err; } mbedtls_ssl_init(n->ssl); mbedtls_ssl_config_init(n->conf); if (n->rootCA != NULL) { root_crt = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1); if ( root_crt == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc root_crt failed!"); goto err; } mbedtls_x509_crt_init(root_crt); if (mbedtls_x509_crt_parse( root_crt, n->rootCA, strlen(n->rootCA)+1 ) != 0) { mqtt_printf(MQTT_DEBUG, "parse root_crt failed!"); goto err; } mbedtls_ssl_conf_ca_chain( n->conf, root_crt, NULL); mbedtls_ssl_conf_authmode(n->conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_verify( n->conf, mqtt_tls_verify, NULL ); mqtt_printf(MQTT_DEBUG, "root_crt parse done"); } else { mbedtls_ssl_conf_authmode(n->conf, MBEDTLS_SSL_VERIFY_NONE); } if (n->clientCA != NULL && n->private_key != NULL) { client_crt = (mbedtls_x509_crt *) mbedtls_calloc( sizeof(mbedtls_x509_crt), 1); if ( client_crt == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc client_crt failed!"); goto err; } mbedtls_x509_crt_init(client_crt); client_rsa = (mbedtls_pk_context *) mbedtls_calloc( sizeof(mbedtls_pk_context), 1); if ( client_rsa == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc client_rsa failed!"); goto err; } mbedtls_pk_init(client_rsa); if ( mbedtls_x509_crt_parse(client_crt, n->clientCA, strlen(n->clientCA)+1) != 0 ) { mqtt_printf(MQTT_DEBUG, "parse client_crt failed!"); goto err; } if ( mbedtls_pk_parse_key(client_rsa, n->private_key, strlen(n->private_key)+1, NULL, 0) != 0 ) { mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!"); goto err; } } mbedtls_ssl_conf_own_cert(n->conf, client_crt, client_rsa); mbedtls_ssl_set_bio(n->ssl, &n->my_socket, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_conf_rng(n->conf, my_random, NULL); if((mbedtls_ssl_config_defaults(n->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { mqtt_printf(MQTT_DEBUG, "ssl config defaults failed!"); goto err; } if((mbedtls_ssl_setup(n->ssl, n->conf)) != 0) { mqtt_printf(MQTT_DEBUG,"mbedtls_ssl_setup failed!"); goto err; } retVal = mbedtls_ssl_handshake(n->ssl); if (retVal < 0) { mqtt_printf(MQTT_DEBUG, "ssl handshake failed err:-0x%04X", -retVal); goto err; } else { mqtt_printf(MQTT_DEBUG, "ssl handshake success"); } } if (client_rsa) { mbedtls_pk_free(client_rsa); mbedtls_free(client_rsa); } if (client_crt) { mbedtls_x509_crt_free(client_crt); mbedtls_free(client_crt); } if (root_crt) { mbedtls_x509_crt_free(root_crt); mbedtls_free(root_crt); } goto exit; err: if (client_rsa) { mbedtls_pk_free(client_rsa); mbedtls_free(client_rsa); } if (client_crt) { mbedtls_x509_crt_free(client_crt); mbedtls_free(client_crt); } if (root_crt) { mbedtls_x509_crt_free(root_crt); mbedtls_free(root_crt); } mbedtls_net_free(&n->my_socket); mbedtls_ssl_free(n->ssl); mbedtls_ssl_config_free(n->conf); free(n->ssl); free(n->conf); retVal = -1; #endif // #if (MQTT_OVER_SSL) exit: return retVal; } #endif /* CONFIG_USE_POLARSSL */ #if 0 int NetworkConnectTLS(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify) { SlSockAddrIn_t sAddr; int addrSize; int retVal; unsigned long ipAddress; retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET); if (retVal < 0) { return -1; } sAddr.sin_family = AF_INET; sAddr.sin_port = sl_Htons((unsigned short)port); sAddr.sin_addr.s_addr = sl_Htonl(ipAddress); addrSize = sizeof(SlSockAddrIn_t); n->my_socket = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET); if (n->my_socket < 0) { return -1; } SlSockSecureMethod method; method.secureMethod = sec_method; retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method)); if (retVal < 0) { return retVal; } SlSockSecureMask mask; mask.secureMask = cipher; retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask)); if (retVal < 0) { return retVal; } if (certificates != NULL) { retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t)); if (retVal < 0) { return retVal; } } retVal = sl_Connect(n->my_socket, (SlSockAddr_t *)&sAddr, addrSize); if (retVal < 0) { if (server_verify || retVal != -453) { sl_Close(n->my_socket); return retVal; } } SysTickIntRegister(SysTickIntHandler); SysTickPeriodSet(80000); SysTickEnable(); return retVal; } #endif