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>
pull/343/head^2
Oscar Michael Abrina 4 years ago committed by GitHub
parent 02aafc3a46
commit 5f0bf944cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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,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_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#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 ********/

@ -70,12 +70,14 @@
*/
typedef struct SSLContext
{
mbedtls_ssl_config config; /**< @brief SSL connection configuration. */
mbedtls_ssl_context context; /**< @brief SSL connection context */
mbedtls_x509_crt_profile certProfile; /**< @brief Certificate security profile for this connection. */
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_ssl_config config; /**< @brief SSL connection configuration. */
mbedtls_ssl_context context; /**< @brief SSL connection context */
mbedtls_x509_crt_profile certProfile; /**< @brief Certificate security profile for this connection. */
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

@ -77,51 +77,125 @@ static const char * pNoLowLevelMbedTlsCodeStr = "<No-Low-Level-Code>";
/*-----------------------------------------------------------*/
/**
* @brief mbed TLS entropy context for generation of random numbers.
* @brief Initialize the mbed TLS structures in a network connection.
*
* @param[in] pSslContext The SSL context to initialize.
*/
static mbedtls_entropy_context entropyContext;
static void sslContextInit( SSLContext_t * pSslContext );
/**
* @brief mbed TLS CTR DRBG context for generation of random numbers.
* @brief Free the mbed TLS structures in a network connection.
*
* @param[in] pSslContext The SSL context to free.
*/
static mbedtls_ctr_drbg_context ctrDrgbContext;
static void sslContextFree( SSLContext_t * pSslContext );
/*-----------------------------------------------------------*/
/**
* @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 Initialize the mbed TLS structures in a network connection.
* @brief Set X509 certificate as client certificate for the server to authenticate.
*
* @param[in] pSslContext The SSL context to initialize.
* @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 void sslContextInit( SSLContext_t * pSslContext );
static int32_t setClientCertificate( SSLContext_t * pSslContext,
const uint8_t * pClientCert,
size_t clientCertSize );
/**
* @brief Free the mbed TLS structures in a network connection.
* @brief Set private key for the client's certificate.
*
* @param[in] pSslContext The SSL context to free.
* @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 void sslContextFree( SSLContext_t * pSslContext );
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 up TLS on a TCP connection.
* @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,188 +219,279 @@ 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 TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
const char * pHostName,
const NetworkCredentials_t * pNetworkCredentials )
static int32_t setRootCa( SSLContext_t * pSslContext,
const uint8_t * pRootCa,
size_t rootCaSize )
{
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
int mbedtlsError = 0;
int32_t mbedtlsError = -1;
configASSERT( pNetworkContext != NULL );
configASSERT( pHostName != NULL );
configASSERT( pNetworkCredentials != NULL );
configASSERT( pNetworkCredentials->pRootCa != NULL );
/* Initialize the mbed TLS context structures. */
sslContextInit( &( pNetworkContext->sslContext ) );
configASSERT( pSslContext != NULL );
configASSERT( pRootCa != NULL );
mbedtlsError = mbedtls_ssl_config_defaults( &( pNetworkContext->sslContext.config ),
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT );
/* 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 set default SSL configuration: mbedTLSError= %s : %s.",
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 );
}
/* Per mbed TLS docs, mbedtls_ssl_config_defaults only fails on memory allocation. */
returnStatus = TLS_TRANSPORT_INSUFFICIENT_MEMORY;
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 ) ) );
}
if( returnStatus == TLS_TRANSPORT_SUCCESS )
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 )
{
/* Set up the certificate security profile, starting from the default value. */
pNetworkContext->sslContext.certProfile = mbedtls_x509_crt_profile_default;
LogError( ( "Failed to parse the client key: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
}
/* 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;
}
return mbedtlsError;
}
/*-----------------------------------------------------------*/
/* 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 ) );
static int32_t setCredentials( SSLContext_t * pSslContext,
const NetworkCredentials_t * pNetworkCredentials )
{
int32_t mbedtlsError = -1;
/* Parse the server root CA certificate into the SSL context. */
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkContext->sslContext.rootCa ),
pNetworkCredentials->pRootCa,
pNetworkCredentials->rootCaSize );
configASSERT( pSslContext != NULL );
configASSERT( pNetworkCredentials != NULL );
if( mbedtlsError != 0 )
{
LogError( ( "Failed to parse server root CA certificate: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
/* Set up the certificate security profile, starting from the default value. */
pSslContext->certProfile = mbedtls_x509_crt_profile_default;
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
/* 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 );
}
else
if( mbedtlsError == 0 )
{
mbedtls_ssl_conf_ca_chain( &( pNetworkContext->sslContext.config ),
&( pNetworkContext->sslContext.rootCa ),
NULL );
mbedtlsError = setPrivateKey( pSslContext,
pNetworkCredentials->pPrivateKey,
pNetworkCredentials->privateKeySize );
}
}
if( returnStatus == TLS_TRANSPORT_SUCCESS )
{
if( ( pNetworkCredentials->pPrivateKey != NULL ) && ( pNetworkCredentials->pClientCert != NULL ) )
if( mbedtlsError == 0 )
{
/* Setup the client private key. */
mbedtlsError = mbedtls_pk_parse_key( &( pNetworkContext->sslContext.privKey ),
pNetworkCredentials->pPrivateKey,
pNetworkCredentials->privateKeySize,
0,
0 );
if( mbedtlsError != 0 )
{
LogError( ( "Failed to parse client certificate: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
else
{
/* Setup the client certificate. */
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkContext->sslContext.clientCert ),
pNetworkCredentials->pClientCert,
pNetworkCredentials->clientCertSize );
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 ) );
}
}
mbedtlsError = mbedtls_ssl_conf_own_cert( &( pSslContext->config ),
&( pSslContext->clientCert ),
&( pSslContext->privKey ) );
}
}
if( ( returnStatus == TLS_TRANSPORT_SUCCESS ) && ( pNetworkCredentials->pAlpnProtos != NULL ) )
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( &( pNetworkContext->sslContext.config ),
( const char ** ) &( pNetworkCredentials->pAlpnProtos ) );
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 ) ) );
returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
}
}
if( returnStatus == TLS_TRANSPORT_SUCCESS )
/* Enable SNI if requested. */
if( pNetworkCredentials->disableSni == pdFALSE )
{
/* Initialize the mbed TLS secured connection context. */
mbedtlsError = mbedtls_ssl_setup( &( pNetworkContext->sslContext.context ),
&( pNetworkContext->sslContext.config ) );
mbedtlsError = mbedtls_ssl_set_hostname( &( pSslContext->context ),
pHostName );
if( mbedtlsError != 0 )
{
LogError( ( "Failed to set up mbed TLS SSL context: mbedTLSError= %s : %s.",
LogError( ( "Failed to set server name: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
}
}
}
/*-----------------------------------------------------------*/
returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
const char * pHostName,
const NetworkCredentials_t * pNetworkCredentials )
{
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
int32_t mbedtlsError = 0;
configASSERT( pNetworkContext != NULL );
configASSERT( pHostName != NULL );
configASSERT( pNetworkCredentials != NULL );
configASSERT( pNetworkCredentials->pRootCa != NULL );
/* Initialize the mbed TLS context structures. */
sslContextInit( &( pNetworkContext->sslContext ) );
mbedtlsError = mbedtls_ssl_config_defaults( &( pNetworkContext->sslContext.config ),
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT );
if( mbedtlsError != 0 )
{
LogError( ( "Failed to set default SSL configuration: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
/* Per mbed TLS docs, mbedtls_ssl_config_defaults only fails on memory allocation. */
returnStatus = TLS_TRANSPORT_INSUFFICIENT_MEMORY;
}
if( returnStatus == TLS_TRANSPORT_SUCCESS )
{
mbedtlsError = setCredentials( &( pNetworkContext->sslContext ),
pNetworkCredentials );
if( mbedtlsError != 0 )
{
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
else
{
/* Set the underlying IO for the TLS connection. */
mbedtls_ssl_set_bio( &( pNetworkContext->sslContext.context ),
pNetworkContext->tcpSocket,
mbedtls_platform_send,
mbedtls_platform_recv,
NULL );
/* Optionally set SNI and ALPN protocols. */
setOptionalConfigurations( &( pNetworkContext->sslContext ),
pHostName,
pNetworkCredentials );
}
}
if( returnStatus == TLS_TRANSPORT_SUCCESS )
{
/* Enable SNI if requested. */
if( pNetworkCredentials->disableSni == pdFALSE )
{
mbedtlsError = mbedtls_ssl_set_hostname( &( pNetworkContext->sslContext.context ),
pHostName );
return returnStatus;
}
/*-----------------------------------------------------------*/
if( mbedtlsError != 0 )
{
LogError( ( "Failed to set server name: 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_INTERNAL_ERROR;
}
}
configASSERT( pNetworkContext != NULL );
configASSERT( pNetworkCredentials != NULL );
/* Initialize the mbed TLS secured connection context. */
mbedtlsError = mbedtls_ssl_setup( &( pNetworkContext->sslContext.context ),
&( pNetworkContext->sslContext.config ) );
if( mbedtlsError != 0 )
{
LogError( ( "Failed to set up mbed TLS SSL context: mbedTLSError= %s : %s.",
mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
}
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 ),
( void * ) pNetworkContext->tcpSocket,
mbedtls_platform_send,
mbedtls_platform_recv,
NULL );
}
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 ) );
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,9 +131,9 @@ static TlsTransportStatus_t initMbedtls( void );
*
* @return Zero on success.
*/
static int generateRandomBytes( void * pvCtx,
unsigned char * pucRandom,
size_t xRandomLength );
static int32_t generateRandomBytes( void * pvCtx,
unsigned char * pucRandom,
size_t xRandomLength );
/**
* @brief Helper for reading the specified certificate object, if present,
@ -175,16 +175,16 @@ static CK_RV initializeClientKeys( SSLContext_t * pxCtx );
*
* @return Zero on success.
*/
static int privateKeySigningCallback( void * pvContext,
mbedtls_md_type_t xMdAlg,
const unsigned char * pucHash,
size_t xHashLen,
unsigned char * pucSig,
size_t * pxSigLen,
int ( * piRng )( void *,
unsigned char *,
size_t ),
void * pvRng );
static int32_t privateKeySigningCallback( void * pvContext,
mbedtls_md_type_t xMdAlg,
const unsigned char * pucHash,
size_t xHashLen,
unsigned char * pucSig,
size_t * pxSigLen,
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,9 +319,9 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
}
else
{
mbedtls_ssl_conf_own_cert( &( pNetworkContext->sslContext.config ),
&( pNetworkContext->sslContext.clientCert ),
&( pNetworkContext->sslContext.privKey ) );
( 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,9 +447,9 @@ static TlsTransportStatus_t initMbedtls( void )
/*-----------------------------------------------------------*/
static int generateRandomBytes( void * pvCtx,
unsigned char * pucRandom,
size_t xRandomLength )
static int32_t generateRandomBytes( void * pvCtx,
unsigned char * pucRandom,
size_t xRandomLength )
{
/* Must cast from void pointer to conform to mbed TLS API. */
SSLContext_t * pxCtx = ( SSLContext_t * ) pvCtx;
@ -645,19 +651,19 @@ static CK_RV initializeClientKeys( SSLContext_t * pxCtx )
/*-----------------------------------------------------------*/
static int privateKeySigningCallback( void * pvContext,
mbedtls_md_type_t xMdAlg,
const unsigned char * pucHash,
size_t xHashLen,
unsigned char * pucSig,
size_t * pxSigLen,
int ( * piRng )( void *,
unsigned char *,
size_t ),
void * pvRng )
static int32_t privateKeySigningCallback( void * pvContext,
mbedtls_md_type_t xMdAlg,
const unsigned char * pucHash,
size_t xHashLen,
unsigned char * pucSig,
size_t * pxSigLen,
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>
/**
* @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
*/
/**
* @transportstruct
* @typedef NetworkContext_t
* @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.
* 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_ */

Loading…
Cancel
Save