mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-19 14:54:28 +08:00
Fix MISRA warnings for platform code used by MQTT demos (#337)
In addition to fixing MISRA warnings, code is updated to have complexity <= 8. Also, this adds changes from PR #313, which allows the support of simultaneous connections in the mbedTLS transport wrapper. Co-authored-by: Muneeb Ahmed <54290492+muneebahmed10@users.noreply.github.com>
This commit is contained in:

committed by
GitHub

parent
02aafc3a46
commit
5f0bf944cb
@ -190,22 +190,12 @@
|
||||
*/
|
||||
#define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca"
|
||||
|
||||
/**
|
||||
* @brief Length of ALPN protocol name.
|
||||
*/
|
||||
#define AWS_IOT_MQTT_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_MQTT_ALPN ) - 1 ) )
|
||||
|
||||
/**
|
||||
* @brief This is the ALPN (Application-Layer Protocol Negotiation) string
|
||||
* required by AWS IoT for password-based authentication using TCP port 443.
|
||||
*/
|
||||
#define AWS_IOT_CUSTOM_AUTH_ALPN "\x04mqtt"
|
||||
|
||||
/**
|
||||
* @brief Length of password ALPN.
|
||||
*/
|
||||
#define AWS_IOT_CUSTOM_AUTH_ALPN_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_CUSTOM_AUTH_ALPN ) - 1 ) )
|
||||
|
||||
/**
|
||||
* Provide default values for undefined configuration settings.
|
||||
*/
|
||||
@ -567,6 +557,11 @@ static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredent
|
||||
RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess;
|
||||
RetryUtilsParams_t xReconnectParams;
|
||||
|
||||
/* ALPN protocols must be a NULL-terminated list of strings. Therefore,
|
||||
* the first entry will contain the actual ALPN protocol string while the
|
||||
* second entry must remain NULL. */
|
||||
char * pcAlpnProtocols[] = { NULL, NULL };
|
||||
|
||||
/* Set the credentials for establishing a TLS connection. */
|
||||
pxNetworkCredentials->pRootCa = ( const unsigned char * ) democonfigROOT_CA_PEM;
|
||||
pxNetworkCredentials->rootCaSize = sizeof( democonfigROOT_CA_PEM );
|
||||
@ -580,11 +575,12 @@ static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkCredent
|
||||
pxNetworkCredentials->disableSni = pdFALSE;
|
||||
/* The ALPN string changes depending on whether username/password authentication is used. */
|
||||
#ifdef democonfigCLIENT_USERNAME
|
||||
pxNetworkCredentials->pAlpnProtos = AWS_IOT_CUSTOM_AUTH_ALPN;
|
||||
pcAlpnProtocols[ 0 ] = AWS_IOT_CUSTOM_AUTH_ALPN;
|
||||
#else
|
||||
pxNetworkCredentials->pAlpnProtos = AWS_IOT_MQTT_ALPN;
|
||||
pcAlpnProtocols[ 0 ] = AWS_IOT_MQTT_ALPN;
|
||||
#endif
|
||||
#else
|
||||
pxNetworkCredentials->pAlpnProtos = pcAlpnProtocols;
|
||||
#else /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */
|
||||
|
||||
/* When using a local Mosquitto server setup, SNI needs to be disabled for
|
||||
* an MQTT broker that only has an IP address but no hostname. However,
|
||||
@ -686,7 +682,7 @@ static void prvCreateMQTTConnectionWithBroker( MQTTContext_t * pxMQTTContext,
|
||||
/* Password for authentication is not used. */
|
||||
xConnectInfo.pPassword = NULL;
|
||||
xConnectInfo.passwordLength = 0U;
|
||||
#endif /* ifdef democonfigCLIENT_USERNAME */
|
||||
#endif
|
||||
#else /* ifdef democonfigUSE_AWS_IOT_CORE_BROKER */
|
||||
#ifdef democonfigCLIENT_USERNAME
|
||||
xConnectInfo.pUserName = democonfigCLIENT_USERNAME;
|
||||
|
@ -18,9 +18,6 @@
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -205,19 +202,21 @@
|
||||
#endif
|
||||
|
||||
|
||||
const char * mbedtls_strerror_highlevel( int errnum )
|
||||
const char * mbedtls_strerror_highlevel( int32_t errnum )
|
||||
{
|
||||
const char * rc = NULL;
|
||||
int use_ret;
|
||||
uint32_t use_ret = 0;
|
||||
|
||||
if( errnum < 0 )
|
||||
{
|
||||
errnum = -errnum;
|
||||
use_ret = ( uint32_t ) -errnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_ret = ( uint32_t ) errnum;
|
||||
}
|
||||
|
||||
if( errnum & 0xFF80 )
|
||||
{
|
||||
use_ret = errnum & 0xFF80;
|
||||
use_ret &= 0xFF80;
|
||||
|
||||
/* High level error codes */
|
||||
switch( use_ret )
|
||||
@ -851,30 +850,31 @@ const char * mbedtls_strerror_highlevel( int errnum )
|
||||
rc = "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed";
|
||||
break;
|
||||
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
|
||||
/* END generated code */
|
||||
}
|
||||
|
||||
default:
|
||||
rc = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char * mbedtls_strerror_lowlevel( int errnum )
|
||||
const char * mbedtls_strerror_lowlevel( int32_t errnum )
|
||||
{
|
||||
const char * rc = NULL;
|
||||
int use_ret;
|
||||
uint32_t use_ret = 0;
|
||||
|
||||
if( errnum < 0 )
|
||||
{
|
||||
errnum = -errnum;
|
||||
use_ret = ( uint32_t ) -errnum;
|
||||
}
|
||||
|
||||
use_ret = errnum & ~0xFF80;
|
||||
|
||||
if( use_ret == 0 )
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
use_ret = ( uint32_t ) errnum;
|
||||
}
|
||||
|
||||
use_ret &= 0xFF80;
|
||||
|
||||
/* Low level error codes */
|
||||
/* */
|
||||
switch( use_ret )
|
||||
@ -1330,6 +1330,10 @@ const char * mbedtls_strerror_lowlevel( int errnum )
|
||||
rc = "XTEA - XTEA hardware accelerator failed";
|
||||
break;
|
||||
#endif /* MBEDTLS_XTEA_C */
|
||||
|
||||
default:
|
||||
rc = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -18,7 +18,6 @@
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -26,10 +25,14 @@
|
||||
* @brief Stringification utilities for high-level and low-level codes of mbed TLS.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_ERROR_H_
|
||||
#define MBEDTLS_ERROR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Translate an mbed TLS high level code into its string representation.
|
||||
@ -40,7 +43,7 @@
|
||||
*
|
||||
* @warning The string returned by this function must never be modified.
|
||||
*/
|
||||
const char * mbedtls_strerror_highlevel( int errnum );
|
||||
const char * mbedtls_strerror_highlevel( int32_t errnum );
|
||||
|
||||
/**
|
||||
* @brief Translate an mbed TLS low level code into its string representation,
|
||||
@ -51,8 +54,10 @@ const char * mbedtls_strerror_highlevel( int errnum );
|
||||
*
|
||||
* @warning The string returned by this function must never be modified.
|
||||
*/
|
||||
const char * mbedtls_strerror_lowlevel( int errnum );
|
||||
const char * mbedtls_strerror_lowlevel( int32_t errnum );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef MBEDTLS_ERROR_H_ */
|
||||
|
@ -54,7 +54,7 @@ void * mbedtls_platform_calloc( size_t nmemb,
|
||||
if( totalSize > 0 )
|
||||
{
|
||||
/* Overflow check. */
|
||||
if( totalSize / size == nmemb )
|
||||
if( ( totalSize / size ) == nmemb )
|
||||
{
|
||||
pBuffer = pvPortMalloc( totalSize );
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "retry_utils.h"
|
||||
|
||||
#define _MILLISECONDS_PER_SECOND ( 1000U ) /**< @brief Milliseconds per second. */
|
||||
#define MILLISECONDS_PER_SECOND ( 1000U ) /**< @brief Milliseconds per second. */
|
||||
|
||||
extern UBaseType_t uxRand( void );
|
||||
|
||||
@ -42,17 +42,17 @@ extern UBaseType_t uxRand( void );
|
||||
RetryUtilsStatus_t RetryUtils_BackoffAndSleep( RetryUtilsParams_t * pRetryParams )
|
||||
{
|
||||
RetryUtilsStatus_t status = RetryUtilsRetriesExhausted;
|
||||
int32_t backOffDelayMs = 0;
|
||||
uint32_t backOffDelayMs = 0;
|
||||
|
||||
/* If pRetryParams->maxRetryAttempts is set to 0, try forever. */
|
||||
if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) ||
|
||||
( 0 == pRetryParams->maxRetryAttempts ) )
|
||||
( 0U == pRetryParams->maxRetryAttempts ) )
|
||||
{
|
||||
/* Choose a random value for back-off time between 0 and the max jitter value. */
|
||||
backOffDelayMs = uxRand() % pRetryParams->nextJitterMax;
|
||||
|
||||
/* Wait for backoff time to expire for the next retry. */
|
||||
vTaskDelay( pdMS_TO_TICKS( backOffDelayMs * _MILLISECONDS_PER_SECOND ) );
|
||||
vTaskDelay( pdMS_TO_TICKS( backOffDelayMs * MILLISECONDS_PER_SECOND ) );
|
||||
|
||||
/* Increment backoff counts. */
|
||||
pRetryParams->attemptsDone++;
|
||||
|
@ -30,6 +30,7 @@
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_DNS.h"
|
||||
|
||||
/**************************************************/
|
||||
/******* DO NOT CHANGE the following order ********/
|
||||
|
@ -76,6 +76,8 @@ typedef struct SSLContext
|
||||
mbedtls_x509_crt rootCa; /**< @brief Root CA certificate context. */
|
||||
mbedtls_x509_crt clientCert; /**< @brief Client certificate context. */
|
||||
mbedtls_pk_context privKey; /**< @brief Client private key context. */
|
||||
mbedtls_entropy_context entropyContext; /**< @brief Entropy context for random number generation. */
|
||||
mbedtls_ctr_drbg_context ctrDrgbContext; /**< @brief CTR DRBG context for random number generation. */
|
||||
} SSLContext_t;
|
||||
|
||||
/**
|
||||
@ -94,31 +96,26 @@ struct NetworkContext
|
||||
typedef struct NetworkCredentials
|
||||
{
|
||||
/**
|
||||
* @brief Set this to a non-NULL value to use ALPN.
|
||||
*
|
||||
* This string must be NULL-terminated.
|
||||
* @brief To use ALPN, set this to a NULL-terminated list of supported
|
||||
* protocols in decreasing order of preference.
|
||||
*
|
||||
* See [this link]
|
||||
* (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/)
|
||||
* for more information.
|
||||
*/
|
||||
const char * pAlpnProtos;
|
||||
const char ** pAlpnProtos;
|
||||
|
||||
/**
|
||||
* @brief Disable server name indication (SNI) for a TLS session.
|
||||
*/
|
||||
BaseType_t disableSni;
|
||||
|
||||
const unsigned char * pRootCa; /**< @brief String representing a trusted server root certificate. */
|
||||
size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials.pRootCa. */
|
||||
const unsigned char * pClientCert; /**< @brief String representing the client certificate. */
|
||||
size_t clientCertSize; /**< @brief Size associated with #IotNetworkCredentials.pClientCert. */
|
||||
const unsigned char * pPrivateKey; /**< @brief String representing the client certificate's private key. */
|
||||
size_t privateKeySize; /**< @brief Size associated with #IotNetworkCredentials.pPrivateKey. */
|
||||
const unsigned char * pUserName; /**< @brief String representing the username for MQTT. */
|
||||
size_t userNameSize; /**< @brief Size associated with #IotNetworkCredentials.pUserName. */
|
||||
const unsigned char * pPassword; /**< @brief String representing the password for MQTT. */
|
||||
size_t passwordSize; /**< @brief Size associated with #IotNetworkCredentials.pPassword. */
|
||||
const uint8_t * pRootCa; /**< @brief String representing a trusted server root certificate. */
|
||||
size_t rootCaSize; /**< @brief Size associated with #NetworkCredentials.pRootCa. */
|
||||
const uint8_t * pClientCert; /**< @brief String representing the client certificate. */
|
||||
size_t clientCertSize; /**< @brief Size associated with #NetworkCredentials.pClientCert. */
|
||||
const uint8_t * pPrivateKey; /**< @brief String representing the client certificate's private key. */
|
||||
size_t privateKeySize; /**< @brief Size associated with #NetworkCredentials.pPrivateKey. */
|
||||
} NetworkCredentials_t;
|
||||
|
||||
/**
|
||||
|
@ -109,15 +109,14 @@ struct NetworkContext
|
||||
typedef struct NetworkCredentials
|
||||
{
|
||||
/**
|
||||
* @brief Set this to a non-NULL value to use ALPN.
|
||||
*
|
||||
* This string must be NULL-terminated.
|
||||
* @brief To use ALPN, set this to a NULL-terminated list of supported
|
||||
* protocols in decreasing order of preference.
|
||||
*
|
||||
* See [this link]
|
||||
* (https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/)
|
||||
* for more information.
|
||||
*/
|
||||
const char * pAlpnProtos;
|
||||
const char ** pAlpnProtos;
|
||||
|
||||
/**
|
||||
* @brief Disable server name indication (SNI) for a TLS session.
|
||||
@ -125,11 +124,11 @@ typedef struct NetworkCredentials
|
||||
BaseType_t disableSni;
|
||||
|
||||
const unsigned char * pRootCa; /**< @brief String representing a trusted server root certificate. */
|
||||
size_t rootCaSize; /**< @brief Size associated with #IotNetworkCredentials.pRootCa. */
|
||||
size_t rootCaSize; /**< @brief Size associated with #NetworkCredentials.pRootCa. */
|
||||
const unsigned char * pUserName; /**< @brief String representing the username for MQTT. */
|
||||
size_t userNameSize; /**< @brief Size associated with #IotNetworkCredentials.pUserName. */
|
||||
size_t userNameSize; /**< @brief Size associated with #NetworkCredentials.pUserName. */
|
||||
const unsigned char * pPassword; /**< @brief String representing the password for MQTT. */
|
||||
size_t passwordSize; /**< @brief Size associated with #IotNetworkCredentials.pPassword. */
|
||||
size_t passwordSize; /**< @brief Size associated with #NetworkCredentials.pPassword. */
|
||||
} NetworkCredentials_t;
|
||||
|
||||
/**
|
||||
|
@ -70,11 +70,11 @@ BaseType_t Sockets_Connect( Socket_t * pTcpSocket,
|
||||
/* Connection parameters. */
|
||||
serverAddress.sin_family = FREERTOS_AF_INET;
|
||||
serverAddress.sin_port = FreeRTOS_htons( port );
|
||||
serverAddress.sin_addr = FreeRTOS_gethostbyname( pHostName );
|
||||
serverAddress.sin_addr = ( uint32_t ) FreeRTOS_gethostbyname( pHostName );
|
||||
serverAddress.sin_len = ( uint8_t ) sizeof( serverAddress );
|
||||
|
||||
/* Check for errors from DNS lookup. */
|
||||
if( serverAddress.sin_addr == 0 )
|
||||
if( serverAddress.sin_addr == 0U )
|
||||
{
|
||||
LogError( ( "Failed to connect to server: DNS resolution failed: Hostname=%s.",
|
||||
pHostName ) );
|
||||
@ -124,7 +124,7 @@ BaseType_t Sockets_Connect( Socket_t * pTcpSocket,
|
||||
{
|
||||
if( tcpSocket != FREERTOS_INVALID_SOCKET )
|
||||
{
|
||||
FreeRTOS_closesocket( tcpSocket );
|
||||
( void ) FreeRTOS_closesocket( tcpSocket );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -76,18 +76,6 @@ static const char * pNoLowLevelMbedTlsCodeStr = "<No-Low-Level-Code>";
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief mbed TLS entropy context for generation of random numbers.
|
||||
*/
|
||||
static mbedtls_entropy_context entropyContext;
|
||||
|
||||
/**
|
||||
* @brief mbed TLS CTR DRBG context for generation of random numbers.
|
||||
*/
|
||||
static mbedtls_ctr_drbg_context ctrDrgbContext;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the mbed TLS structures in a network connection.
|
||||
*
|
||||
@ -103,25 +91,111 @@ static void sslContextInit( SSLContext_t * pSslContext );
|
||||
static void sslContextFree( SSLContext_t * pSslContext );
|
||||
|
||||
/**
|
||||
* @brief Set up TLS on a TCP connection.
|
||||
* @brief Add X509 certificate to the trusted list of root certificates.
|
||||
*
|
||||
* OpenSSL does not provide a single function for reading and loading certificates
|
||||
* from files into stores, so the file API must be called. Start with the
|
||||
* root certificate.
|
||||
*
|
||||
* @param[out] pSslContext SSL context to which the trusted server root CA is to be added.
|
||||
* @param[in] pRootCa PEM-encoded string of the trusted server root CA.
|
||||
* @param[in] rootCaSize Size of the trusted server root CA.
|
||||
*
|
||||
* @return 0 on success; otherwise, failure;
|
||||
*/
|
||||
static int32_t setRootCa( SSLContext_t * pSslContext,
|
||||
const uint8_t * pRootCa,
|
||||
size_t rootCaSize );
|
||||
|
||||
/**
|
||||
* @brief Set X509 certificate as client certificate for the server to authenticate.
|
||||
*
|
||||
* @param[out] pSslContext SSL context to which the client certificate is to be set.
|
||||
* @param[in] pClientCert PEM-encoded string of the client certificate.
|
||||
* @param[in] clientCertSize Size of the client certificate.
|
||||
*
|
||||
* @return 0 on success; otherwise, failure;
|
||||
*/
|
||||
static int32_t setClientCertificate( SSLContext_t * pSslContext,
|
||||
const uint8_t * pClientCert,
|
||||
size_t clientCertSize );
|
||||
|
||||
/**
|
||||
* @brief Set private key for the client's certificate.
|
||||
*
|
||||
* @param[out] pSslContext SSL context to which the private key is to be set.
|
||||
* @param[in] pPrivateKey PEM-encoded string of the client private key.
|
||||
* @param[in] privateKeySize Size of the client private key.
|
||||
*
|
||||
* @return 0 on success; otherwise, failure;
|
||||
*/
|
||||
static int32_t setPrivateKey( SSLContext_t * pSslContext,
|
||||
const uint8_t * pPrivateKey,
|
||||
size_t privateKeySize );
|
||||
|
||||
/**
|
||||
* @brief Passes TLS credentials to the OpenSSL library.
|
||||
*
|
||||
* Provides the root CA certificate, client certificate, and private key to the
|
||||
* OpenSSL library. If the client certificate or private key is not NULL, mutual
|
||||
* authentication is used when performing the TLS handshake.
|
||||
*
|
||||
* @param[out] pSslContext SSL context to which the credentials are to be imported.
|
||||
* @param[in] pNetworkCredentials TLS credentials to be imported.
|
||||
*
|
||||
* @return 0 on success; otherwise, failure;
|
||||
*/
|
||||
static int32_t setCredentials( SSLContext_t * pSslContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials );
|
||||
|
||||
/**
|
||||
* @brief Set optional configurations for the TLS connection.
|
||||
*
|
||||
* This function is used to set SNI and ALPN protocols.
|
||||
*
|
||||
* @param[in] pSslContext SSL context to which the optional configurations are to be set.
|
||||
* @param[in] pHostName Remote host name, used for server name indication.
|
||||
* @param[in] pNetworkCredentials TLS setup parameters.
|
||||
*/
|
||||
static void setOptionalConfigurations( SSLContext_t * pSslContext,
|
||||
const char * pHostName,
|
||||
const NetworkCredentials_t * pNetworkCredentials );
|
||||
|
||||
/**
|
||||
* @brief Setup TLS by initializing contexts and setting configurations.
|
||||
*
|
||||
* @param[in] pNetworkContext Network context.
|
||||
* @param[in] pHostName Remote host name, used for server name indication.
|
||||
* @param[in] pNetworkCredentials TLS setup parameters.
|
||||
*
|
||||
* @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_INSUFFICIENT_MEMORY, #TLS_TRANSPORT_INVALID_CREDENTIALS,
|
||||
* #TLS_TRANSPORT_HANDSHAKE_FAILED, or #TLS_TRANSPORT_INTERNAL_ERROR.
|
||||
* or #TLS_TRANSPORT_INTERNAL_ERROR.
|
||||
*/
|
||||
static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
const char * pHostName,
|
||||
const NetworkCredentials_t * pNetworkCredentials );
|
||||
|
||||
/**
|
||||
* @brief Perform the TLS handshake on a TCP connection.
|
||||
*
|
||||
* @param[in] pNetworkContext Network context.
|
||||
* @param[in] pNetworkCredentials TLS setup parameters.
|
||||
*
|
||||
* @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_HANDSHAKE_FAILED, or #TLS_TRANSPORT_INTERNAL_ERROR.
|
||||
*/
|
||||
static TlsTransportStatus_t tlsHandshake( NetworkContext_t * pNetworkContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials );
|
||||
|
||||
/**
|
||||
* @brief Initialize mbedTLS.
|
||||
*
|
||||
* @param[out] entropyContext mbed TLS entropy context for generation of random numbers.
|
||||
* @param[out] ctrDrgbContext mbed TLS CTR DRBG context for generation of random numbers.
|
||||
*
|
||||
* @return #TLS_TRANSPORT_SUCCESS, or #TLS_TRANSPORT_INTERNAL_ERROR.
|
||||
*/
|
||||
static TlsTransportStatus_t initMbedtls( void );
|
||||
static TlsTransportStatus_t initMbedtls( mbedtls_entropy_context * pEntropyContext,
|
||||
mbedtls_ctr_drbg_context * pCtrDrgbContext );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@ -145,9 +219,190 @@ static void sslContextFree( SSLContext_t * pSslContext )
|
||||
mbedtls_x509_crt_free( &( pSslContext->rootCa ) );
|
||||
mbedtls_x509_crt_free( &( pSslContext->clientCert ) );
|
||||
mbedtls_pk_free( &( pSslContext->privKey ) );
|
||||
mbedtls_entropy_free( &( pSslContext->entropyContext ) );
|
||||
mbedtls_ctr_drbg_free( &( pSslContext->ctrDrgbContext ) );
|
||||
mbedtls_ssl_config_free( &( pSslContext->config ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t setRootCa( SSLContext_t * pSslContext,
|
||||
const uint8_t * pRootCa,
|
||||
size_t rootCaSize )
|
||||
{
|
||||
int32_t mbedtlsError = -1;
|
||||
|
||||
configASSERT( pSslContext != NULL );
|
||||
configASSERT( pRootCa != NULL );
|
||||
|
||||
/* Parse the server root CA certificate into the SSL context. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pSslContext->rootCa ),
|
||||
pRootCa,
|
||||
rootCaSize );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse server root CA certificate: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_ssl_conf_ca_chain( &( pSslContext->config ),
|
||||
&( pSslContext->rootCa ),
|
||||
NULL );
|
||||
}
|
||||
|
||||
return mbedtlsError;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t setClientCertificate( SSLContext_t * pSslContext,
|
||||
const uint8_t * pClientCert,
|
||||
size_t clientCertSize )
|
||||
{
|
||||
int32_t mbedtlsError = -1;
|
||||
|
||||
configASSERT( pSslContext != NULL );
|
||||
configASSERT( pClientCert != NULL );
|
||||
|
||||
/* Setup the client certificate. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pSslContext->clientCert ),
|
||||
pClientCert,
|
||||
clientCertSize );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse the client certificate: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
}
|
||||
|
||||
return mbedtlsError;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t setPrivateKey( SSLContext_t * pSslContext,
|
||||
const uint8_t * pPrivateKeyPath,
|
||||
size_t privateKeySize )
|
||||
{
|
||||
int32_t mbedtlsError = -1;
|
||||
|
||||
configASSERT( pSslContext != NULL );
|
||||
configASSERT( pPrivateKeyPath != NULL );
|
||||
|
||||
/* Setup the client private key. */
|
||||
mbedtlsError = mbedtls_pk_parse_key( &( pSslContext->privKey ),
|
||||
pPrivateKeyPath,
|
||||
privateKeySize,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse the client key: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
}
|
||||
|
||||
return mbedtlsError;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t setCredentials( SSLContext_t * pSslContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials )
|
||||
{
|
||||
int32_t mbedtlsError = -1;
|
||||
|
||||
configASSERT( pSslContext != NULL );
|
||||
configASSERT( pNetworkCredentials != NULL );
|
||||
|
||||
/* Set up the certificate security profile, starting from the default value. */
|
||||
pSslContext->certProfile = mbedtls_x509_crt_profile_default;
|
||||
|
||||
/* Set SSL authmode and the RNG context. */
|
||||
mbedtls_ssl_conf_authmode( &( pSslContext->config ),
|
||||
MBEDTLS_SSL_VERIFY_REQUIRED );
|
||||
mbedtls_ssl_conf_rng( &( pSslContext->config ),
|
||||
mbedtls_ctr_drbg_random,
|
||||
&( pSslContext->ctrDrgbContext ) );
|
||||
mbedtls_ssl_conf_cert_profile( &( pSslContext->config ),
|
||||
&( pSslContext->certProfile ) );
|
||||
|
||||
if( pNetworkCredentials->pRootCa != NULL )
|
||||
{
|
||||
mbedtlsError = setRootCa( pSslContext,
|
||||
pNetworkCredentials->pRootCa,
|
||||
pNetworkCredentials->rootCaSize );
|
||||
}
|
||||
|
||||
if( ( pNetworkCredentials->pClientCert != NULL ) &&
|
||||
( pNetworkCredentials->pPrivateKey != NULL ) )
|
||||
{
|
||||
if( mbedtlsError == 0 )
|
||||
{
|
||||
mbedtlsError = setClientCertificate( pSslContext,
|
||||
pNetworkCredentials->pClientCert,
|
||||
pNetworkCredentials->clientCertSize );
|
||||
}
|
||||
|
||||
if( mbedtlsError == 0 )
|
||||
{
|
||||
mbedtlsError = setPrivateKey( pSslContext,
|
||||
pNetworkCredentials->pPrivateKey,
|
||||
pNetworkCredentials->privateKeySize );
|
||||
}
|
||||
|
||||
if( mbedtlsError == 0 )
|
||||
{
|
||||
mbedtlsError = mbedtls_ssl_conf_own_cert( &( pSslContext->config ),
|
||||
&( pSslContext->clientCert ),
|
||||
&( pSslContext->privKey ) );
|
||||
}
|
||||
}
|
||||
|
||||
return mbedtlsError;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void setOptionalConfigurations( SSLContext_t * pSslContext,
|
||||
const char * pHostName,
|
||||
const NetworkCredentials_t * pNetworkCredentials )
|
||||
{
|
||||
int32_t mbedtlsError = -1;
|
||||
|
||||
configASSERT( pSslContext != NULL );
|
||||
configASSERT( pHostName != NULL );
|
||||
configASSERT( pNetworkCredentials != NULL );
|
||||
|
||||
if( pNetworkCredentials->pAlpnProtos != NULL )
|
||||
{
|
||||
/* Include an application protocol list in the TLS ClientHello
|
||||
* message. */
|
||||
mbedtlsError = mbedtls_ssl_conf_alpn_protocols( &( pSslContext->config ),
|
||||
pNetworkCredentials->pAlpnProtos );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to configure ALPN protocol in mbed TLS: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable SNI if requested. */
|
||||
if( pNetworkCredentials->disableSni == pdFALSE )
|
||||
{
|
||||
mbedtlsError = mbedtls_ssl_set_hostname( &( pSslContext->context ),
|
||||
pHostName );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to set server name: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
@ -155,7 +410,7 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials )
|
||||
{
|
||||
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
|
||||
int mbedtlsError = 0;
|
||||
int32_t mbedtlsError = 0;
|
||||
|
||||
configASSERT( pNetworkContext != NULL );
|
||||
configASSERT( pHostName != NULL );
|
||||
@ -182,111 +437,35 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
/* Set up the certificate security profile, starting from the default value. */
|
||||
pNetworkContext->sslContext.certProfile = mbedtls_x509_crt_profile_default;
|
||||
|
||||
/* test.mosquitto.org only provides a 1024-bit RSA certificate, which is
|
||||
* not acceptable by the default mbed TLS certificate security profile.
|
||||
* For the purposes of this demo, allow the use of 1024-bit RSA certificates.
|
||||
* This block should be removed otherwise. */
|
||||
if( strncmp( pHostName, "test.mosquitto.org", strlen( pHostName ) ) == 0 )
|
||||
{
|
||||
pNetworkContext->sslContext.certProfile.rsa_min_bitlen = 1024;
|
||||
}
|
||||
|
||||
/* Set SSL authmode and the RNG context. */
|
||||
mbedtls_ssl_conf_authmode( &( pNetworkContext->sslContext.config ),
|
||||
MBEDTLS_SSL_VERIFY_REQUIRED );
|
||||
mbedtls_ssl_conf_rng( &( pNetworkContext->sslContext.config ),
|
||||
mbedtls_ctr_drbg_random,
|
||||
&ctrDrgbContext );
|
||||
mbedtls_ssl_conf_cert_profile( &( pNetworkContext->sslContext.config ),
|
||||
&( pNetworkContext->sslContext.certProfile ) );
|
||||
|
||||
/* Parse the server root CA certificate into the SSL context. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkContext->sslContext.rootCa ),
|
||||
pNetworkCredentials->pRootCa,
|
||||
pNetworkCredentials->rootCaSize );
|
||||
mbedtlsError = setCredentials( &( pNetworkContext->sslContext ),
|
||||
pNetworkCredentials );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse server root CA certificate: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
|
||||
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_ssl_conf_ca_chain( &( pNetworkContext->sslContext.config ),
|
||||
&( pNetworkContext->sslContext.rootCa ),
|
||||
NULL );
|
||||
/* Optionally set SNI and ALPN protocols. */
|
||||
setOptionalConfigurations( &( pNetworkContext->sslContext ),
|
||||
pHostName,
|
||||
pNetworkCredentials );
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
if( ( pNetworkCredentials->pPrivateKey != NULL ) && ( pNetworkCredentials->pClientCert != NULL ) )
|
||||
{
|
||||
/* Setup the client private key. */
|
||||
mbedtlsError = mbedtls_pk_parse_key( &( pNetworkContext->sslContext.privKey ),
|
||||
pNetworkCredentials->pPrivateKey,
|
||||
pNetworkCredentials->privateKeySize,
|
||||
0,
|
||||
0 );
|
||||
return returnStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse client certificate: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
static TlsTransportStatus_t tlsHandshake( NetworkContext_t * pNetworkContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials )
|
||||
{
|
||||
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
|
||||
int32_t mbedtlsError = 0;
|
||||
|
||||
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Setup the client certificate. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkContext->sslContext.clientCert ),
|
||||
pNetworkCredentials->pClientCert,
|
||||
pNetworkCredentials->clientCertSize );
|
||||
configASSERT( pNetworkContext != NULL );
|
||||
configASSERT( pNetworkCredentials != NULL );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to parse the client private key: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
|
||||
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_ssl_conf_own_cert( &( pNetworkContext->sslContext.config ),
|
||||
&( pNetworkContext->sslContext.clientCert ),
|
||||
&( pNetworkContext->sslContext.privKey ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( returnStatus == TLS_TRANSPORT_SUCCESS ) && ( pNetworkCredentials->pAlpnProtos != NULL ) )
|
||||
{
|
||||
/* Include an application protocol list in the TLS ClientHello
|
||||
* message. */
|
||||
mbedtlsError = mbedtls_ssl_conf_alpn_protocols( &( pNetworkContext->sslContext.config ),
|
||||
( const char ** ) &( pNetworkCredentials->pAlpnProtos ) );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to configure ALPN protocol in mbed TLS: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
|
||||
returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
/* Initialize the mbed TLS secured connection context. */
|
||||
mbedtlsError = mbedtls_ssl_setup( &( pNetworkContext->sslContext.context ),
|
||||
&( pNetworkContext->sslContext.config ) );
|
||||
@ -302,32 +481,18 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
else
|
||||
{
|
||||
/* Set the underlying IO for the TLS connection. */
|
||||
|
||||
/* MISRA Rule 11.2 flags the following line for casting the second
|
||||
* parameter to void *. This rule is suppressed because
|
||||
* #mbedtls_ssl_set_bio requires the second parameter as void *.
|
||||
*/
|
||||
/* coverity[misra_c_2012_rule_11_2_violation] */
|
||||
mbedtls_ssl_set_bio( &( pNetworkContext->sslContext.context ),
|
||||
pNetworkContext->tcpSocket,
|
||||
( void * ) pNetworkContext->tcpSocket,
|
||||
mbedtls_platform_send,
|
||||
mbedtls_platform_recv,
|
||||
NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
/* Enable SNI if requested. */
|
||||
if( pNetworkCredentials->disableSni == pdFALSE )
|
||||
{
|
||||
mbedtlsError = mbedtls_ssl_set_hostname( &( pNetworkContext->sslContext.context ),
|
||||
pHostName );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
LogError( ( "Failed to set server name: mbedTLSError= %s : %s.",
|
||||
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
|
||||
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
|
||||
|
||||
returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
@ -346,27 +511,22 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
|
||||
returnStatus = TLS_TRANSPORT_HANDSHAKE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus != TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
sslContextFree( &( pNetworkContext->sslContext ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "(Network connection %p) TLS handshake successful.",
|
||||
pNetworkContext ) );
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static TlsTransportStatus_t initMbedtls( void )
|
||||
static TlsTransportStatus_t initMbedtls( mbedtls_entropy_context * pEntropyContext,
|
||||
mbedtls_ctr_drbg_context * pCtrDrgbContext )
|
||||
{
|
||||
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
|
||||
int mbedtlsError = 0;
|
||||
int32_t mbedtlsError = 0;
|
||||
|
||||
/* Set the mutex functions for mbed TLS thread safety. */
|
||||
mbedtls_threading_set_alt( mbedtls_platform_mutex_init,
|
||||
@ -375,11 +535,11 @@ static TlsTransportStatus_t initMbedtls( void )
|
||||
mbedtls_platform_mutex_unlock );
|
||||
|
||||
/* Initialize contexts for random number generation. */
|
||||
mbedtls_entropy_init( &entropyContext );
|
||||
mbedtls_ctr_drbg_init( &ctrDrgbContext );
|
||||
mbedtls_entropy_init( pEntropyContext );
|
||||
mbedtls_ctr_drbg_init( pCtrDrgbContext );
|
||||
|
||||
/* Add a strong entropy source. At least one is required. */
|
||||
mbedtlsError = mbedtls_entropy_add_source( &entropyContext,
|
||||
mbedtlsError = mbedtls_entropy_add_source( pEntropyContext,
|
||||
mbedtls_platform_entropy_poll,
|
||||
NULL,
|
||||
32,
|
||||
@ -396,9 +556,9 @@ static TlsTransportStatus_t initMbedtls( void )
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
/* Seed the random number generator. */
|
||||
mbedtlsError = mbedtls_ctr_drbg_seed( &ctrDrgbContext,
|
||||
mbedtlsError = mbedtls_ctr_drbg_seed( pCtrDrgbContext,
|
||||
mbedtls_entropy_func,
|
||||
&entropyContext,
|
||||
pEntropyContext,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
@ -418,7 +578,6 @@ static TlsTransportStatus_t initMbedtls( void )
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
@ -447,6 +606,10 @@ TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
LogError( ( "pRootCa cannot be NULL." ) );
|
||||
returnStatus = TLS_TRANSPORT_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Empty else for MISRA 15.7 compliance. */
|
||||
}
|
||||
|
||||
/* Establish a TCP connection with the server. */
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
@ -469,21 +632,31 @@ TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
/* Initialize mbedtls. */
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
returnStatus = initMbedtls();
|
||||
returnStatus = initMbedtls( &( pNetworkContext->sslContext.entropyContext ),
|
||||
&( pNetworkContext->sslContext.ctrDrgbContext ) );
|
||||
}
|
||||
|
||||
/* Perform TLS handshake. */
|
||||
/* Initialize TLS contexts and set credentials. */
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
returnStatus = tlsSetup( pNetworkContext, pHostName, pNetworkCredentials );
|
||||
}
|
||||
|
||||
/* Perform TLS handshake. */
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
returnStatus = tlsHandshake( pNetworkContext, pNetworkCredentials );
|
||||
}
|
||||
|
||||
/* Clean up on failure. */
|
||||
if( returnStatus != TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
if( pNetworkContext->tcpSocket != FREERTOS_INVALID_SOCKET )
|
||||
sslContextFree( &( pNetworkContext->sslContext ) );
|
||||
|
||||
if( ( pNetworkContext != NULL ) &&
|
||||
( pNetworkContext->tcpSocket != FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
FreeRTOS_closesocket( pNetworkContext->tcpSocket );
|
||||
( void ) FreeRTOS_closesocket( pNetworkContext->tcpSocket );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -495,7 +668,6 @@ TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext )
|
||||
@ -537,14 +709,9 @@ void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext )
|
||||
/* Free mbed TLS contexts. */
|
||||
sslContextFree( &( pNetworkContext->sslContext ) );
|
||||
|
||||
/* Free the contexts for random number generation. */
|
||||
mbedtls_ctr_drbg_free( &ctrDrgbContext );
|
||||
mbedtls_entropy_free( &entropyContext );
|
||||
|
||||
/* Clear the mutex functions for mbed TLS thread safety. */
|
||||
mbedtls_threading_free_alt();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext,
|
||||
@ -583,7 +750,6 @@ int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext,
|
||||
|
||||
return tlsStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext,
|
||||
|
@ -131,7 +131,7 @@ static TlsTransportStatus_t initMbedtls( void );
|
||||
*
|
||||
* @return Zero on success.
|
||||
*/
|
||||
static int generateRandomBytes( void * pvCtx,
|
||||
static int32_t generateRandomBytes( void * pvCtx,
|
||||
unsigned char * pucRandom,
|
||||
size_t xRandomLength );
|
||||
|
||||
@ -175,13 +175,13 @@ static CK_RV initializeClientKeys( SSLContext_t * pxCtx );
|
||||
*
|
||||
* @return Zero on success.
|
||||
*/
|
||||
static int privateKeySigningCallback( void * pvContext,
|
||||
static int32_t privateKeySigningCallback( void * pvContext,
|
||||
mbedtls_md_type_t xMdAlg,
|
||||
const unsigned char * pucHash,
|
||||
size_t xHashLen,
|
||||
unsigned char * pucSig,
|
||||
size_t * pxSigLen,
|
||||
int ( * piRng )( void *,
|
||||
int32_t ( * piRng )( void *,
|
||||
unsigned char *,
|
||||
size_t ),
|
||||
void * pvRng );
|
||||
@ -222,7 +222,7 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
const NetworkCredentials_t * pNetworkCredentials )
|
||||
{
|
||||
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
|
||||
int mbedtlsError = 0;
|
||||
int32_t mbedtlsError = 0;
|
||||
CK_RV xResult = CKR_OK;
|
||||
|
||||
configASSERT( pNetworkContext != NULL );
|
||||
@ -319,7 +319,7 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_ssl_conf_own_cert( &( pNetworkContext->sslContext.config ),
|
||||
( void ) mbedtls_ssl_conf_own_cert( &( pNetworkContext->sslContext.config ),
|
||||
&( pNetworkContext->sslContext.clientCert ),
|
||||
&( pNetworkContext->sslContext.privKey ) );
|
||||
}
|
||||
@ -331,7 +331,7 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
/* Include an application protocol list in the TLS ClientHello
|
||||
* message. */
|
||||
mbedtlsError = mbedtls_ssl_conf_alpn_protocols( &( pNetworkContext->sslContext.config ),
|
||||
( const char ** ) &( pNetworkCredentials->pAlpnProtos ) );
|
||||
pNetworkCredentials->pAlpnProtos );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
@ -360,8 +360,14 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
|
||||
else
|
||||
{
|
||||
/* Set the underlying IO for the TLS connection. */
|
||||
|
||||
/* MISRA Rule 11.2 flags the following line for casting the second
|
||||
* parameter to void *. This rule is suppressed because
|
||||
* #mbedtls_ssl_set_bio requires the second parameter as void *.
|
||||
*/
|
||||
/* coverity[misra_c_2012_rule_11_2_violation] */
|
||||
mbedtls_ssl_set_bio( &( pNetworkContext->sslContext.context ),
|
||||
pNetworkContext->tcpSocket,
|
||||
( void * ) pNetworkContext->tcpSocket,
|
||||
mbedtls_platform_send,
|
||||
mbedtls_platform_recv,
|
||||
NULL );
|
||||
@ -441,7 +447,7 @@ static TlsTransportStatus_t initMbedtls( void )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int generateRandomBytes( void * pvCtx,
|
||||
static int32_t generateRandomBytes( void * pvCtx,
|
||||
unsigned char * pucRandom,
|
||||
size_t xRandomLength )
|
||||
{
|
||||
@ -645,19 +651,19 @@ static CK_RV initializeClientKeys( SSLContext_t * pxCtx )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int privateKeySigningCallback( void * pvContext,
|
||||
static int32_t privateKeySigningCallback( void * pvContext,
|
||||
mbedtls_md_type_t xMdAlg,
|
||||
const unsigned char * pucHash,
|
||||
size_t xHashLen,
|
||||
unsigned char * pucSig,
|
||||
size_t * pxSigLen,
|
||||
int ( * piRng )( void *,
|
||||
int32_t ( * piRng )( void *,
|
||||
unsigned char *,
|
||||
size_t ),
|
||||
void * pvRng )
|
||||
{
|
||||
CK_RV xResult = CKR_OK;
|
||||
int lFinalResult = 0;
|
||||
int32_t lFinalResult = 0;
|
||||
SSLContext_t * pxTLSContext = ( SSLContext_t * ) pvContext;
|
||||
CK_MECHANISM xMech = { 0 };
|
||||
CK_BYTE xToBeSigned[ 256 ];
|
||||
@ -766,6 +772,10 @@ TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
LogError( ( "pRootCa cannot be NULL." ) );
|
||||
returnStatus = TLS_TRANSPORT_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Empty else for MISRA 15.7 compliance. */
|
||||
}
|
||||
|
||||
/* Establish a TCP connection with the server. */
|
||||
if( returnStatus == TLS_TRANSPORT_SUCCESS )
|
||||
@ -800,9 +810,10 @@ TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
|
||||
/* Clean up on failure. */
|
||||
if( returnStatus != TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
if( pNetworkContext->tcpSocket != FREERTOS_INVALID_SOCKET )
|
||||
if( ( pNetworkContext != NULL ) &&
|
||||
( pNetworkContext->tcpSocket != FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
FreeRTOS_closesocket( pNetworkContext->tcpSocket );
|
||||
( void ) FreeRTOS_closesocket( pNetworkContext->tcpSocket );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -128,7 +128,7 @@
|
||||
*
|
||||
* // If pRetryParams->maxRetryAttempts is set to 0, try forever.
|
||||
* if( ( pRetryParams->attemptsDone < pRetryParams->maxRetryAttempts ) ||
|
||||
* ( 0 == pRetryParams->maxRetryAttempts ) )
|
||||
* ( 0U == pRetryParams->maxRetryAttempts ) )
|
||||
* {
|
||||
* // Choose a random value for back-off time between 0 and the max jitter value.
|
||||
* backOffDelay = rand() % pRetryParams->nextJitterMax;
|
||||
|
@ -19,6 +19,11 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file transport_interface.h
|
||||
* @brief Transport interface definitions to send and receive data over the
|
||||
* network.
|
||||
*/
|
||||
#ifndef TRANSPORT_INTERFACE_H_
|
||||
#define TRANSPORT_INTERFACE_H_
|
||||
|
||||
@ -26,14 +31,131 @@
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @brief The NetworkContext is an incomplete type. An implementation of this
|
||||
* interface must define NetworkContext as per the requirements. This context
|
||||
* is passed into the network interface functions.
|
||||
* @transportpage
|
||||
* @brief The transport interface definition.
|
||||
*
|
||||
* @transportsectionoverview
|
||||
*
|
||||
* The transport interface is a set of APIs that must be implemented using an
|
||||
* external transport layer protocol. The transport interface is defined in
|
||||
* @ref transport_interface.h. This interface allows protocols like MQTT and
|
||||
* HTTP to send and receive data over the transport layer. This
|
||||
* interface does not handle connection and disconnection to the server of
|
||||
* interest. The connection, disconnection, and other transport settings, like
|
||||
* timeout and TLS setup, must be handled in the user application.
|
||||
* <br>
|
||||
*
|
||||
* The functions that must be implemented are:<br>
|
||||
* - [Transport Receive](@ref TransportRecv_t)
|
||||
* - [Transport Send](@ref TransportSend_t)
|
||||
*
|
||||
* Each of the functions above take in an opaque context @ref NetworkContext_t.
|
||||
* The functions above and the context are also grouped together in the
|
||||
* @ref TransportInterface_t structure:<br><br>
|
||||
* @snippet this define_transportinterface
|
||||
* <br>
|
||||
*
|
||||
* @transportsectionimplementation
|
||||
*
|
||||
* The following steps give guidance on implementing the transport interface:
|
||||
*
|
||||
* -# Implementing @ref NetworkContext_t<br><br>
|
||||
* @snippet this define_networkcontext
|
||||
* <br>
|
||||
* @ref NetworkContext_t is the incomplete type <b>struct NetworkContext</b>.
|
||||
* The implemented struct NetworkContext must contain all of the information
|
||||
* that is needed to receive and send data with the @ref TransportRecv_t
|
||||
* and the @ref TransportSend_t implementations.<br>
|
||||
* In the case of TLS over TCP, struct NetworkContext is typically implemented
|
||||
* with the TCP socket context and a TLS context.<br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* struct NetworkContext
|
||||
* {
|
||||
* struct MyTCPSocketContext tcpSocketContext;
|
||||
* struct MyTLSContext tlsContext;
|
||||
* };
|
||||
* @endcode
|
||||
* <br>
|
||||
* -# Implementing @ref TransportRecv_t<br><br>
|
||||
* @snippet this define_transportrecv
|
||||
* <br>
|
||||
* This function is expected to populate a buffer, with bytes received from the
|
||||
* transport, and return the number of bytes placed in the buffer.
|
||||
* In the case of TLS over TCP, @ref TransportRecv_t is typically implemented by
|
||||
* calling the TLS layer function to receive data. In case of plaintext TCP
|
||||
* without TLS, it is typically implemented by calling the TCP layer receive
|
||||
* function. @ref TransportRecv_t may be invoked multiple times by the protocol
|
||||
* library, if fewer bytes than were requested to receive are returned.
|
||||
* <br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* int32_t myNetworkRecvImplementation( const NetworkContext_t * pNetworkContext,
|
||||
* void * pBuffer,
|
||||
* size_t bytesToRecv )
|
||||
* {
|
||||
* int32_t bytesReceived = 0;
|
||||
* bytesReceived = TLSRecv( pNetworkContext->tlsContext,
|
||||
* pBuffer,
|
||||
* bytesToRecv,
|
||||
* MY_SOCKET_TIMEOUT );
|
||||
* if( bytesReceived < 0 )
|
||||
* {
|
||||
* // Handle socket error.
|
||||
* }
|
||||
* // Handle other cases.
|
||||
*
|
||||
* return bytesReceived;
|
||||
* }
|
||||
* @endcode
|
||||
* <br>
|
||||
* -# Implementing @ref TransportSend_t<br><br>
|
||||
* @snippet this define_transportsend
|
||||
* <br>
|
||||
* This function is expected to send the bytes, in the given buffer over the
|
||||
* transport, and return the number of bytes sent.
|
||||
* In the case of TLS over TCP, @ref TransportSend_t is typically implemented by
|
||||
* calling the TLS layer function to send data. In case of plaintext TCP
|
||||
* without TLS, it is typically implemented by calling the TCP layer send
|
||||
* function. @ref TransportSend_t may be invoked multiple times by the protocol
|
||||
* library, if fewer bytes than were requested to send are returned.
|
||||
* <br><br>
|
||||
* <b>Example code:</b>
|
||||
* @code{c}
|
||||
* int32_t myNetworkSendImplementation( const NetworkContext_t * pNetworkContext,
|
||||
* const void * pBuffer,
|
||||
* size_t bytesToSend )
|
||||
* {
|
||||
* int32_t bytesSent = 0;
|
||||
* bytesSent = TLSSend( pNetworkContext->tlsContext,
|
||||
* pBuffer,
|
||||
* bytesToSend,
|
||||
* MY_SOCKET_TIMEOUT );
|
||||
* if( bytesSent < 0 )
|
||||
* {
|
||||
* // Handle socket error.
|
||||
* }
|
||||
* // Handle other cases.
|
||||
*
|
||||
* return bytesSent;
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
struct NetworkContext;
|
||||
typedef struct NetworkContext NetworkContext_t;
|
||||
|
||||
/**
|
||||
* @transportstruct
|
||||
* @typedef NetworkContext_t
|
||||
* @brief The NetworkContext is an incomplete type. An implementation of this
|
||||
* interface must define struct NetworkContext for the system requirements.
|
||||
* This context is passed into the network interface functions.
|
||||
*/
|
||||
/* @[define_networkcontext] */
|
||||
struct NetworkContext;
|
||||
typedef struct NetworkContext NetworkContext_t;
|
||||
/* @[define_networkcontext] */
|
||||
|
||||
/**
|
||||
* @transportcallback
|
||||
* @brief Transport interface for receiving data on the network.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
@ -42,11 +164,14 @@ typedef struct NetworkContext NetworkContext_t;
|
||||
*
|
||||
* @return The number of bytes received or a negative error code.
|
||||
*/
|
||||
typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
|
||||
/* @[define_transportrecv] */
|
||||
typedef int32_t ( * TransportRecv_t )( const NetworkContext_t * pNetworkContext,
|
||||
void * pBuffer,
|
||||
size_t bytesToRecv );
|
||||
/* @[define_transportrecv] */
|
||||
|
||||
/**
|
||||
* @transportcallback
|
||||
* @brief Transport interface for sending data over the network.
|
||||
*
|
||||
* @param[in] pNetworkContext Implementation-defined network context.
|
||||
@ -55,18 +180,23 @@ typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
|
||||
*
|
||||
* @return The number of bytes sent or a negative error code.
|
||||
*/
|
||||
typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
|
||||
/* @[define_transportsend] */
|
||||
typedef int32_t ( * TransportSend_t )( const NetworkContext_t * pNetworkContext,
|
||||
const void * pBuffer,
|
||||
size_t bytesToSend );
|
||||
/* @[define_transportsend] */
|
||||
|
||||
/**
|
||||
* @transportstruct
|
||||
* @brief The transport layer interface.
|
||||
*/
|
||||
/* @[define_transportinterface] */
|
||||
typedef struct TransportInterface
|
||||
{
|
||||
TransportRecv_t recv; /**< Transport receive interface. */
|
||||
TransportSend_t send; /**< Transport send interface. */
|
||||
NetworkContext_t * pNetworkContext; /**< Implementation-defined network context. */
|
||||
} TransportInterface_t;
|
||||
/* @[define_transportinterface] */
|
||||
|
||||
#endif /* ifndef TRANSPORT_INTERFACE_H_ */
|
||||
|
Reference in New Issue
Block a user