From 5f0bf944cb489f09d286c804844ce051dc556d0b Mon Sep 17 00:00:00 2001 From: Oscar Michael Abrina Date: Tue, 13 Oct 2020 12:55:26 -0700 Subject: [PATCH] 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> --- .../DemoTasks/MutualAuthMQTTExample.c | 24 +- .../platform/freertos/mbedtls/mbedtls_error.c | 1224 +++++++++-------- .../platform/freertos/mbedtls/mbedtls_error.h | 23 +- .../freertos/mbedtls/mbedtls_freertos_port.c | 2 +- .../retry_utils/retry_utils_freertos.c | 8 +- .../include/freertos_sockets_wrapper.h | 1 + .../freertos/transport/include/tls_freertos.h | 37 +- .../transport/include/tls_freertos_pkcs11.h | 13 +- .../transport/src/freertos_sockets_wrapper.c | 6 +- .../freertos/transport/src/tls_freertos.c | 506 ++++--- .../transport/src/tls_freertos_pkcs11.c | 81 +- .../platform/include/retry_utils.h | 2 +- .../platform/include/transport_interface.h | 138 +- 13 files changed, 1187 insertions(+), 878 deletions(-) diff --git a/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/DemoTasks/MutualAuthMQTTExample.c b/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/DemoTasks/MutualAuthMQTTExample.c index f04a5b190f..1f00b31b9a 100644 --- a/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/DemoTasks/MutualAuthMQTTExample.c +++ b/FreeRTOS-Plus/Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth/DemoTasks/MutualAuthMQTTExample.c @@ -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; diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.c index bf00edce7d..fe3415d07e 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.c @@ -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,676 +202,679 @@ #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 &= 0xFF80; + + /* High level error codes */ + switch( use_ret ) { - use_ret = errnum & 0xFF80; - - /* High level error codes */ - switch( use_ret ) - { - #if defined( MBEDTLS_CIPHER_C ) - case -( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ): - rc = "CIPHER - The selected feature is not available"; - break; - - case -( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ): - rc = "CIPHER - Bad input parameters"; - break; - - case -( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ): - rc = "CIPHER - Failed to allocate memory"; - break; - - case -( MBEDTLS_ERR_CIPHER_INVALID_PADDING ): - rc = "CIPHER - Input data contains invalid padding and is rejected"; - break; - - case -( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ): - rc = "CIPHER - Decryption of block requires a full block"; - break; - - case -( MBEDTLS_ERR_CIPHER_AUTH_FAILED ): - rc = "CIPHER - Authentication failed (for AEAD modes)"; - break; - - case -( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ): - rc = "CIPHER - The context is invalid. For example, because it was freed"; - break; - - case -( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ): - rc = "CIPHER - Cipher hardware accelerator failed"; - break; - #endif /* MBEDTLS_CIPHER_C */ - - #if defined( MBEDTLS_DHM_C ) - case -( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ): - rc = "DHM - Bad input parameters"; - break; - - case -( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED ): - rc = "DHM - Reading of the DHM parameters failed"; - break; - - case -( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ): - rc = "DHM - Making of the DHM parameters failed"; - break; - - case -( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED ): - rc = "DHM - Reading of the public values failed"; - break; - - case -( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ): - rc = "DHM - Making of the public value failed"; - break; - - case -( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED ): - rc = "DHM - Calculation of the DHM secret failed"; - break; - - case -( MBEDTLS_ERR_DHM_INVALID_FORMAT ): - rc = "DHM - The ASN.1 data is not formatted correctly"; - break; - - case -( MBEDTLS_ERR_DHM_ALLOC_FAILED ): - rc = "DHM - Allocation of memory failed"; - break; - - case -( MBEDTLS_ERR_DHM_FILE_IO_ERROR ): - rc = "DHM - Read or write of file failed"; - break; - - case -( MBEDTLS_ERR_DHM_HW_ACCEL_FAILED ): - rc = "DHM - DHM hardware accelerator failed"; - break; - - case -( MBEDTLS_ERR_DHM_SET_GROUP_FAILED ): - rc = "DHM - Setting the modulus and generator failed"; - break; - #endif /* MBEDTLS_DHM_C */ - - #if defined( MBEDTLS_ECP_C ) - case -( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ): - rc = "ECP - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ): - rc = "ECP - The buffer is too small to write to"; - break; - - case -( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ): - rc = "ECP - The requested feature is not available, for example, the requested curve is not supported"; - break; - - case -( MBEDTLS_ERR_ECP_VERIFY_FAILED ): - rc = "ECP - The signature is not valid"; - break; - - case -( MBEDTLS_ERR_ECP_ALLOC_FAILED ): - rc = "ECP - Memory allocation failed"; - break; - - case -( MBEDTLS_ERR_ECP_RANDOM_FAILED ): - rc = "ECP - Generation of random value, such as ephemeral key, failed"; - break; - - case -( MBEDTLS_ERR_ECP_INVALID_KEY ): - rc = "ECP - Invalid private or public key"; - break; - - case -( MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ): - rc = "ECP - The buffer contains a valid signature followed by more data"; - break; - - case -( MBEDTLS_ERR_ECP_HW_ACCEL_FAILED ): - rc = "ECP - The ECP hardware accelerator failed"; - break; - - case -( MBEDTLS_ERR_ECP_IN_PROGRESS ): - rc = "ECP - Operation in progress, call again with the same parameters to continue"; - break; - #endif /* MBEDTLS_ECP_C */ - - #if defined( MBEDTLS_MD_C ) - case -( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ): - rc = "MD - The selected feature is not available"; - break; - - case -( MBEDTLS_ERR_MD_BAD_INPUT_DATA ): - rc = "MD - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_MD_ALLOC_FAILED ): - rc = "MD - Failed to allocate memory"; - break; - - case -( MBEDTLS_ERR_MD_FILE_IO_ERROR ): - rc = "MD - Opening or reading of file failed"; - break; - - case -( MBEDTLS_ERR_MD_HW_ACCEL_FAILED ): - rc = "MD - MD hardware accelerator failed"; - break; - #endif /* MBEDTLS_MD_C */ - - #if defined( MBEDTLS_PEM_PARSE_C ) || defined( MBEDTLS_PEM_WRITE_C ) - case -( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ): - rc = "PEM - No PEM header or footer found"; - break; - - case -( MBEDTLS_ERR_PEM_INVALID_DATA ): - rc = "PEM - PEM string is not as expected"; - break; - - case -( MBEDTLS_ERR_PEM_ALLOC_FAILED ): - rc = "PEM - Failed to allocate memory"; - break; - - case -( MBEDTLS_ERR_PEM_INVALID_ENC_IV ): - rc = "PEM - RSA IV is not in hex-format"; - break; - - case -( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ): - rc = "PEM - Unsupported key encryption algorithm"; - break; - - case -( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ): - rc = "PEM - Private key password can't be empty"; - break; - - case -( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ): - rc = "PEM - Given private key password does not allow for correct decryption"; - break; - - case -( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ): - rc = "PEM - Unavailable feature, e.g. hashing/encryption combination"; - break; - - case -( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ): - rc = "PEM - Bad input parameters to function"; - break; - #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ - - #if defined( MBEDTLS_PK_C ) - case -( MBEDTLS_ERR_PK_ALLOC_FAILED ): - rc = "PK - Memory allocation failed"; - break; - - case -( MBEDTLS_ERR_PK_TYPE_MISMATCH ): - rc = "PK - Type mismatch, eg attempt to encrypt with an ECDSA key"; - break; - - case -( MBEDTLS_ERR_PK_BAD_INPUT_DATA ): - rc = "PK - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_PK_FILE_IO_ERROR ): - rc = "PK - Read/write of file failed"; - break; - - case -( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ): - rc = "PK - Unsupported key version"; - break; - - case -( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ): - rc = "PK - Invalid key tag or value"; - break; - - case -( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ): - rc = "PK - Key algorithm is unsupported (only RSA and EC are supported)"; - break; - - case -( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ): - rc = "PK - Private key password can't be empty"; - break; - - case -( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ): - rc = "PK - Given private key password does not allow for correct decryption"; - break; - - case -( MBEDTLS_ERR_PK_INVALID_PUBKEY ): - rc = "PK - The pubkey tag or value is invalid (only RSA and EC are supported)"; - break; - - case -( MBEDTLS_ERR_PK_INVALID_ALG ): - rc = "PK - The algorithm tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ): - rc = "PK - Elliptic curve is unsupported (only NIST curves are supported)"; - break; - - case -( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ): - rc = "PK - Unavailable feature, e.g. RSA disabled for RSA key"; - break; - - case -( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ): - rc = "PK - The buffer contains a valid signature followed by more data"; - break; - - case -( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ): - rc = "PK - PK hardware accelerator failed"; - break; - #endif /* MBEDTLS_PK_C */ - - #if defined( MBEDTLS_PKCS12_C ) - case -( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ): - rc = "PKCS12 - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ): - rc = "PKCS12 - Feature not available, e.g. unsupported encryption scheme"; - break; - - case -( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT ): - rc = "PKCS12 - PBE ASN.1 data not as expected"; - break; - - case -( MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ): - rc = "PKCS12 - Given private key password does not allow for correct decryption"; - break; - #endif /* MBEDTLS_PKCS12_C */ - - #if defined( MBEDTLS_PKCS5_C ) - case -( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ): - rc = "PKCS5 - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ): - rc = "PKCS5 - Unexpected ASN.1 data"; - break; - - case -( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ): - rc = "PKCS5 - Requested encryption or digest alg not available"; - break; - - case -( MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ): - rc = "PKCS5 - Given private key password does not allow for correct decryption"; - break; - #endif /* MBEDTLS_PKCS5_C */ - - #if defined( MBEDTLS_RSA_C ) - case -( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ): - rc = "RSA - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_RSA_INVALID_PADDING ): - rc = "RSA - Input data contains invalid padding and is rejected"; - break; - - case -( MBEDTLS_ERR_RSA_KEY_GEN_FAILED ): - rc = "RSA - Something failed during generation of a key"; - break; - - case -( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ): - rc = "RSA - Key failed to pass the validity check of the library"; - break; - - case -( MBEDTLS_ERR_RSA_PUBLIC_FAILED ): - rc = "RSA - The public key operation failed"; - break; - - case -( MBEDTLS_ERR_RSA_PRIVATE_FAILED ): - rc = "RSA - The private key operation failed"; - break; - - case -( MBEDTLS_ERR_RSA_VERIFY_FAILED ): - rc = "RSA - The PKCS#1 verification failed"; - break; - - case -( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ): - rc = "RSA - The output buffer for decryption is not large enough"; - break; - - case -( MBEDTLS_ERR_RSA_RNG_FAILED ): - rc = "RSA - The random generator failed to generate non-zeros"; - break; - - case -( MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION ): - rc = "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality"; - break; - - case -( MBEDTLS_ERR_RSA_HW_ACCEL_FAILED ): - rc = "RSA - RSA hardware accelerator failed"; - break; - #endif /* MBEDTLS_RSA_C */ - - #if defined( MBEDTLS_SSL_TLS_C ) - case -( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ): - rc = "SSL - The requested feature is not available"; - break; - - case -( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ): - rc = "SSL - Bad input parameters to function"; - break; - - case -( MBEDTLS_ERR_SSL_INVALID_MAC ): - rc = "SSL - Verification of the message MAC failed"; - break; - - case -( MBEDTLS_ERR_SSL_INVALID_RECORD ): - rc = "SSL - An invalid SSL record was received"; - break; - - case -( MBEDTLS_ERR_SSL_CONN_EOF ): - rc = "SSL - The connection indicated an EOF"; - break; - - case -( MBEDTLS_ERR_SSL_UNKNOWN_CIPHER ): - rc = "SSL - An unknown cipher was received"; - break; - - case -( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ): - rc = "SSL - The server has no ciphersuites in common with the client"; - break; - - case -( MBEDTLS_ERR_SSL_NO_RNG ): - rc = "SSL - No RNG was provided to the SSL module"; - break; - - case -( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ): - rc = "SSL - No client certification received from the client, but required by the authentication mode"; - break; - - case -( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ): - rc = "SSL - Our own certificate(s) is/are too large to send in an SSL message"; - break; + #if defined( MBEDTLS_CIPHER_C ) + case -( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ): + rc = "CIPHER - The selected feature is not available"; + break; + + case -( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ): + rc = "CIPHER - Bad input parameters"; + break; + + case -( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ): + rc = "CIPHER - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_CIPHER_INVALID_PADDING ): + rc = "CIPHER - Input data contains invalid padding and is rejected"; + break; + + case -( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ): + rc = "CIPHER - Decryption of block requires a full block"; + break; + + case -( MBEDTLS_ERR_CIPHER_AUTH_FAILED ): + rc = "CIPHER - Authentication failed (for AEAD modes)"; + break; + + case -( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ): + rc = "CIPHER - The context is invalid. For example, because it was freed"; + break; + + case -( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ): + rc = "CIPHER - Cipher hardware accelerator failed"; + break; + #endif /* MBEDTLS_CIPHER_C */ + + #if defined( MBEDTLS_DHM_C ) + case -( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ): + rc = "DHM - Bad input parameters"; + break; + + case -( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED ): + rc = "DHM - Reading of the DHM parameters failed"; + break; + + case -( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ): + rc = "DHM - Making of the DHM parameters failed"; + break; + + case -( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED ): + rc = "DHM - Reading of the public values failed"; + break; + + case -( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ): + rc = "DHM - Making of the public value failed"; + break; + + case -( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED ): + rc = "DHM - Calculation of the DHM secret failed"; + break; + + case -( MBEDTLS_ERR_DHM_INVALID_FORMAT ): + rc = "DHM - The ASN.1 data is not formatted correctly"; + break; + + case -( MBEDTLS_ERR_DHM_ALLOC_FAILED ): + rc = "DHM - Allocation of memory failed"; + break; + + case -( MBEDTLS_ERR_DHM_FILE_IO_ERROR ): + rc = "DHM - Read or write of file failed"; + break; + + case -( MBEDTLS_ERR_DHM_HW_ACCEL_FAILED ): + rc = "DHM - DHM hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_DHM_SET_GROUP_FAILED ): + rc = "DHM - Setting the modulus and generator failed"; + break; + #endif /* MBEDTLS_DHM_C */ + + #if defined( MBEDTLS_ECP_C ) + case -( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ): + rc = "ECP - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ): + rc = "ECP - The buffer is too small to write to"; + break; + + case -( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ): + rc = "ECP - The requested feature is not available, for example, the requested curve is not supported"; + break; + + case -( MBEDTLS_ERR_ECP_VERIFY_FAILED ): + rc = "ECP - The signature is not valid"; + break; + + case -( MBEDTLS_ERR_ECP_ALLOC_FAILED ): + rc = "ECP - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_ECP_RANDOM_FAILED ): + rc = "ECP - Generation of random value, such as ephemeral key, failed"; + break; + + case -( MBEDTLS_ERR_ECP_INVALID_KEY ): + rc = "ECP - Invalid private or public key"; + break; + + case -( MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ): + rc = "ECP - The buffer contains a valid signature followed by more data"; + break; + + case -( MBEDTLS_ERR_ECP_HW_ACCEL_FAILED ): + rc = "ECP - The ECP hardware accelerator failed"; + break; + + case -( MBEDTLS_ERR_ECP_IN_PROGRESS ): + rc = "ECP - Operation in progress, call again with the same parameters to continue"; + break; + #endif /* MBEDTLS_ECP_C */ + + #if defined( MBEDTLS_MD_C ) + case -( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ): + rc = "MD - The selected feature is not available"; + break; + + case -( MBEDTLS_ERR_MD_BAD_INPUT_DATA ): + rc = "MD - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_MD_ALLOC_FAILED ): + rc = "MD - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_MD_FILE_IO_ERROR ): + rc = "MD - Opening or reading of file failed"; + break; + + case -( MBEDTLS_ERR_MD_HW_ACCEL_FAILED ): + rc = "MD - MD hardware accelerator failed"; + break; + #endif /* MBEDTLS_MD_C */ + + #if defined( MBEDTLS_PEM_PARSE_C ) || defined( MBEDTLS_PEM_WRITE_C ) + case -( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ): + rc = "PEM - No PEM header or footer found"; + break; + + case -( MBEDTLS_ERR_PEM_INVALID_DATA ): + rc = "PEM - PEM string is not as expected"; + break; + + case -( MBEDTLS_ERR_PEM_ALLOC_FAILED ): + rc = "PEM - Failed to allocate memory"; + break; + + case -( MBEDTLS_ERR_PEM_INVALID_ENC_IV ): + rc = "PEM - RSA IV is not in hex-format"; + break; + + case -( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ): + rc = "PEM - Unsupported key encryption algorithm"; + break; + + case -( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ): + rc = "PEM - Private key password can't be empty"; + break; + + case -( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ): + rc = "PEM - Given private key password does not allow for correct decryption"; + break; + + case -( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ): + rc = "PEM - Unavailable feature, e.g. hashing/encryption combination"; + break; + + case -( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ): + rc = "PEM - Bad input parameters to function"; + break; + #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + + #if defined( MBEDTLS_PK_C ) + case -( MBEDTLS_ERR_PK_ALLOC_FAILED ): + rc = "PK - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_PK_TYPE_MISMATCH ): + rc = "PK - Type mismatch, eg attempt to encrypt with an ECDSA key"; + break; + + case -( MBEDTLS_ERR_PK_BAD_INPUT_DATA ): + rc = "PK - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PK_FILE_IO_ERROR ): + rc = "PK - Read/write of file failed"; + break; + + case -( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ): + rc = "PK - Unsupported key version"; + break; + + case -( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ): + rc = "PK - Invalid key tag or value"; + break; + + case -( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ): + rc = "PK - Key algorithm is unsupported (only RSA and EC are supported)"; + break; + + case -( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ): + rc = "PK - Private key password can't be empty"; + break; + + case -( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ): + rc = "PK - Given private key password does not allow for correct decryption"; + break; + + case -( MBEDTLS_ERR_PK_INVALID_PUBKEY ): + rc = "PK - The pubkey tag or value is invalid (only RSA and EC are supported)"; + break; + + case -( MBEDTLS_ERR_PK_INVALID_ALG ): + rc = "PK - The algorithm tag or value is invalid"; + break; + + case -( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ): + rc = "PK - Elliptic curve is unsupported (only NIST curves are supported)"; + break; + + case -( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ): + rc = "PK - Unavailable feature, e.g. RSA disabled for RSA key"; + break; + + case -( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ): + rc = "PK - The buffer contains a valid signature followed by more data"; + break; + + case -( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ): + rc = "PK - PK hardware accelerator failed"; + break; + #endif /* MBEDTLS_PK_C */ + + #if defined( MBEDTLS_PKCS12_C ) + case -( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ): + rc = "PKCS12 - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ): + rc = "PKCS12 - Feature not available, e.g. unsupported encryption scheme"; + break; + + case -( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT ): + rc = "PKCS12 - PBE ASN.1 data not as expected"; + break; + + case -( MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ): + rc = "PKCS12 - Given private key password does not allow for correct decryption"; + break; + #endif /* MBEDTLS_PKCS12_C */ + + #if defined( MBEDTLS_PKCS5_C ) + case -( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ): + rc = "PKCS5 - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ): + rc = "PKCS5 - Unexpected ASN.1 data"; + break; + + case -( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ): + rc = "PKCS5 - Requested encryption or digest alg not available"; + break; + + case -( MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ): + rc = "PKCS5 - Given private key password does not allow for correct decryption"; + break; + #endif /* MBEDTLS_PKCS5_C */ - case -( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ): - rc = "SSL - The own certificate is not set, but needed by the server"; - break; + #if defined( MBEDTLS_RSA_C ) + case -( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ): + rc = "RSA - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_RSA_INVALID_PADDING ): + rc = "RSA - Input data contains invalid padding and is rejected"; + break; + + case -( MBEDTLS_ERR_RSA_KEY_GEN_FAILED ): + rc = "RSA - Something failed during generation of a key"; + break; + + case -( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ): + rc = "RSA - Key failed to pass the validity check of the library"; + break; + + case -( MBEDTLS_ERR_RSA_PUBLIC_FAILED ): + rc = "RSA - The public key operation failed"; + break; + + case -( MBEDTLS_ERR_RSA_PRIVATE_FAILED ): + rc = "RSA - The private key operation failed"; + break; + + case -( MBEDTLS_ERR_RSA_VERIFY_FAILED ): + rc = "RSA - The PKCS#1 verification failed"; + break; + + case -( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ): + rc = "RSA - The output buffer for decryption is not large enough"; + break; + + case -( MBEDTLS_ERR_RSA_RNG_FAILED ): + rc = "RSA - The random generator failed to generate non-zeros"; + break; + + case -( MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION ): + rc = "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality"; + break; + + case -( MBEDTLS_ERR_RSA_HW_ACCEL_FAILED ): + rc = "RSA - RSA hardware accelerator failed"; + break; + #endif /* MBEDTLS_RSA_C */ + + #if defined( MBEDTLS_SSL_TLS_C ) + case -( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ): + rc = "SSL - The requested feature is not available"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ): + rc = "SSL - Bad input parameters to function"; + break; + + case -( MBEDTLS_ERR_SSL_INVALID_MAC ): + rc = "SSL - Verification of the message MAC failed"; + break; + + case -( MBEDTLS_ERR_SSL_INVALID_RECORD ): + rc = "SSL - An invalid SSL record was received"; + break; + + case -( MBEDTLS_ERR_SSL_CONN_EOF ): + rc = "SSL - The connection indicated an EOF"; + break; + + case -( MBEDTLS_ERR_SSL_UNKNOWN_CIPHER ): + rc = "SSL - An unknown cipher was received"; + break; + + case -( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ): + rc = "SSL - The server has no ciphersuites in common with the client"; + break; + + case -( MBEDTLS_ERR_SSL_NO_RNG ): + rc = "SSL - No RNG was provided to the SSL module"; + break; + + case -( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ): + rc = "SSL - No client certification received from the client, but required by the authentication mode"; + break; + + case -( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ): + rc = "SSL - Our own certificate(s) is/are too large to send in an SSL message"; + break; + + case -( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ): + rc = "SSL - The own certificate is not set, but needed by the server"; + break; + + case -( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ): + rc = "SSL - The own private key or pre-shared key is not set, but needed"; + break; + + case -( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ): + rc = "SSL - No CA Chain is set, but required to operate"; + break; + + case -( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ): + rc = "SSL - An unexpected message was received from our peer"; + break; + + case -( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ): + rc = "SSL - A fatal alert message was received from our peer"; + break; + + case -( MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED ): + rc = "SSL - Verification of our peer failed"; + break; + + case -( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ): + rc = "SSL - The peer notified us that the connection is going to be closed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ): + rc = "SSL - Processing of the ClientHello handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ): + rc = "SSL - Processing of the ServerHello handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ): + rc = "SSL - Processing of the Certificate handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ): + rc = "SSL - Processing of the CertificateRequest handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ): + rc = "SSL - Processing of the ServerKeyExchange handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ): + rc = "SSL - Processing of the ServerHelloDone handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ): + rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ): + rc = "SSL - Processing of the CertificateVerify handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ): + rc = "SSL - Processing of the ChangeCipherSpec handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ): + rc = "SSL - Processing of the Finished handshake message failed"; + break; + + case -( MBEDTLS_ERR_SSL_ALLOC_FAILED ): + rc = "SSL - Memory allocation failed"; + break; + + case -( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ): + rc = "SSL - Hardware acceleration function returned with error"; + break; + + case -( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ): + rc = "SSL - Hardware acceleration function skipped / left alone data"; + break; - case -( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ): - rc = "SSL - The own private key or pre-shared key is not set, but needed"; - break; + case -( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ): + rc = "SSL - Processing of the compression / decompression failed"; + break; - case -( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ): - rc = "SSL - No CA Chain is set, but required to operate"; - break; + case -( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ): + rc = "SSL - Handshake protocol not within min/max boundaries"; + break; - case -( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ): - rc = "SSL - An unexpected message was received from our peer"; - break; + case -( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ): + rc = "SSL - Processing of the NewSessionTicket handshake message failed"; + break; - case -( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ): - rc = "SSL - A fatal alert message was received from our peer"; - break; + case -( MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ): + rc = "SSL - Session ticket has expired"; + break; - case -( MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED ): - rc = "SSL - Verification of our peer failed"; - break; + case -( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ): + rc = "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)"; + break; - case -( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ): - rc = "SSL - The peer notified us that the connection is going to be closed"; - break; + case -( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ): + rc = "SSL - Unknown identity received (eg, PSK identity)"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ): - rc = "SSL - Processing of the ClientHello handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_INTERNAL_ERROR ): + rc = "SSL - Internal error (eg, unexpected failure in lower-level module)"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ): - rc = "SSL - Processing of the ServerHello handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ): + rc = "SSL - A counter would wrap (eg, too many messages exchanged)"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ): - rc = "SSL - Processing of the Certificate handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ): + rc = "SSL - Unexpected message at ServerHello in renegotiation"; + break; + + case -( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ): + rc = "SSL - DTLS client must retry for hello verification"; + break; + + case -( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ): + rc = "SSL - A buffer is too small to receive or write a message"; + break; + + case -( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ): + rc = "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)"; + break; + + case -( MBEDTLS_ERR_SSL_WANT_READ ): + rc = "SSL - No data of requested type currently available on underlying transport"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ): - rc = "SSL - Processing of the CertificateRequest handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_WANT_WRITE ): + rc = "SSL - Connection requires a write call"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ): - rc = "SSL - Processing of the ServerKeyExchange handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_TIMEOUT ): + rc = "SSL - The operation timed out"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ): - rc = "SSL - Processing of the ServerHelloDone handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ): + rc = "SSL - The client initiated a reconnect from the same port"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ): - rc = "SSL - Processing of the ClientKeyExchange handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ): + rc = "SSL - Record header looks valid but is not expected"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ): - rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public"; - break; + case -( MBEDTLS_ERR_SSL_NON_FATAL ): + rc = "SSL - The alert message received indicates a non-fatal error"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ): - rc = "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret"; - break; + case -( MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH ): + rc = "SSL - Couldn't set the hash for verifying CertificateVerify"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ): - rc = "SSL - Processing of the CertificateVerify handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ): + rc = "SSL - Internal-only message signaling that further message-processing should be done"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ): - rc = "SSL - Processing of the ChangeCipherSpec handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ): + rc = "SSL - The asynchronous operation is not completed yet"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ): - rc = "SSL - Processing of the Finished handshake message failed"; - break; + case -( MBEDTLS_ERR_SSL_EARLY_MESSAGE ): + rc = "SSL - Internal-only message signaling that a message arrived early"; + break; - case -( MBEDTLS_ERR_SSL_ALLOC_FAILED ): - rc = "SSL - Memory allocation failed"; - break; + case -( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ): + rc = "SSL - A cryptographic operation is in progress. Try again later"; + break; + #endif /* MBEDTLS_SSL_TLS_C */ - case -( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ): - rc = "SSL - Hardware acceleration function returned with error"; - break; + #if defined( MBEDTLS_X509_USE_C ) || defined( MBEDTLS_X509_CREATE_C ) + case -( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ): + rc = "X509 - Unavailable feature, e.g. RSA hashing/encryption combination"; + break; - case -( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ): - rc = "SSL - Hardware acceleration function skipped / left alone data"; - break; + case -( MBEDTLS_ERR_X509_UNKNOWN_OID ): + rc = "X509 - Requested OID is unknown"; + break; - case -( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ): - rc = "SSL - Processing of the compression / decompression failed"; - break; + case -( MBEDTLS_ERR_X509_INVALID_FORMAT ): + rc = "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ): - rc = "SSL - Handshake protocol not within min/max boundaries"; - break; + case -( MBEDTLS_ERR_X509_INVALID_VERSION ): + rc = "X509 - The CRT/CRL/CSR version element is invalid"; + break; - case -( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ): - rc = "SSL - Processing of the NewSessionTicket handshake message failed"; - break; + case -( MBEDTLS_ERR_X509_INVALID_SERIAL ): + rc = "X509 - The serial tag or value is invalid"; + break; - case -( MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ): - rc = "SSL - Session ticket has expired"; - break; + case -( MBEDTLS_ERR_X509_INVALID_ALG ): + rc = "X509 - The algorithm tag or value is invalid"; + break; - case -( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ): - rc = "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)"; - break; + case -( MBEDTLS_ERR_X509_INVALID_NAME ): + rc = "X509 - The name tag or value is invalid"; + break; - case -( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ): - rc = "SSL - Unknown identity received (eg, PSK identity)"; - break; + case -( MBEDTLS_ERR_X509_INVALID_DATE ): + rc = "X509 - The date tag or value is invalid"; + break; - case -( MBEDTLS_ERR_SSL_INTERNAL_ERROR ): - rc = "SSL - Internal error (eg, unexpected failure in lower-level module)"; - break; + case -( MBEDTLS_ERR_X509_INVALID_SIGNATURE ): + rc = "X509 - The signature tag or value invalid"; + break; - case -( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ): - rc = "SSL - A counter would wrap (eg, too many messages exchanged)"; - break; + case -( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ): + rc = "X509 - The extension tag or value is invalid"; + break; - case -( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ): - rc = "SSL - Unexpected message at ServerHello in renegotiation"; - break; + case -( MBEDTLS_ERR_X509_UNKNOWN_VERSION ): + rc = "X509 - CRT/CRL/CSR has an unsupported version number"; + break; - case -( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ): - rc = "SSL - DTLS client must retry for hello verification"; - break; + case -( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ): + rc = "X509 - Signature algorithm (oid) is unsupported"; + break; - case -( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ): - rc = "SSL - A buffer is too small to receive or write a message"; - break; + case -( MBEDTLS_ERR_X509_SIG_MISMATCH ): + rc = "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)"; + break; - case -( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ): - rc = "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)"; - break; + case -( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ): + rc = "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed"; + break; - case -( MBEDTLS_ERR_SSL_WANT_READ ): - rc = "SSL - No data of requested type currently available on underlying transport"; - break; + case -( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ): + rc = "X509 - Format not recognized as DER or PEM"; + break; - case -( MBEDTLS_ERR_SSL_WANT_WRITE ): - rc = "SSL - Connection requires a write call"; - break; + case -( MBEDTLS_ERR_X509_BAD_INPUT_DATA ): + rc = "X509 - Input invalid"; + break; - case -( MBEDTLS_ERR_SSL_TIMEOUT ): - rc = "SSL - The operation timed out"; - break; + case -( MBEDTLS_ERR_X509_ALLOC_FAILED ): + rc = "X509 - Allocation of memory failed"; + break; - case -( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ): - rc = "SSL - The client initiated a reconnect from the same port"; - break; + case -( MBEDTLS_ERR_X509_FILE_IO_ERROR ): + rc = "X509 - Read/write of file failed"; + break; - case -( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ): - rc = "SSL - Record header looks valid but is not expected"; - break; + case -( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ): + rc = "X509 - Destination buffer is too small"; + break; - case -( MBEDTLS_ERR_SSL_NON_FATAL ): - rc = "SSL - The alert message received indicates a non-fatal error"; - break; + case -( MBEDTLS_ERR_X509_FATAL_ERROR ): + 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 */ - case -( MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH ): - rc = "SSL - Couldn't set the hash for verifying CertificateVerify"; - break; - - case -( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ): - rc = "SSL - Internal-only message signaling that further message-processing should be done"; - break; - - case -( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ): - rc = "SSL - The asynchronous operation is not completed yet"; - break; - - case -( MBEDTLS_ERR_SSL_EARLY_MESSAGE ): - rc = "SSL - Internal-only message signaling that a message arrived early"; - break; - - case -( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ): - rc = "SSL - A cryptographic operation is in progress. Try again later"; - break; - #endif /* MBEDTLS_SSL_TLS_C */ - - #if defined( MBEDTLS_X509_USE_C ) || defined( MBEDTLS_X509_CREATE_C ) - case -( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ): - rc = "X509 - Unavailable feature, e.g. RSA hashing/encryption combination"; - break; - - case -( MBEDTLS_ERR_X509_UNKNOWN_OID ): - rc = "X509 - Requested OID is unknown"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_FORMAT ): - rc = "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_VERSION ): - rc = "X509 - The CRT/CRL/CSR version element is invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_SERIAL ): - rc = "X509 - The serial tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_ALG ): - rc = "X509 - The algorithm tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_NAME ): - rc = "X509 - The name tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_DATE ): - rc = "X509 - The date tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_SIGNATURE ): - rc = "X509 - The signature tag or value invalid"; - break; - - case -( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ): - rc = "X509 - The extension tag or value is invalid"; - break; - - case -( MBEDTLS_ERR_X509_UNKNOWN_VERSION ): - rc = "X509 - CRT/CRL/CSR has an unsupported version number"; - break; - - case -( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ): - rc = "X509 - Signature algorithm (oid) is unsupported"; - break; - - case -( MBEDTLS_ERR_X509_SIG_MISMATCH ): - rc = "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)"; - break; - - case -( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ): - rc = "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed"; - break; - - case -( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ): - rc = "X509 - Format not recognized as DER or PEM"; - break; - - case -( MBEDTLS_ERR_X509_BAD_INPUT_DATA ): - rc = "X509 - Input invalid"; - break; - - case -( MBEDTLS_ERR_X509_ALLOC_FAILED ): - rc = "X509 - Allocation of memory failed"; - break; - - case -( MBEDTLS_ERR_X509_FILE_IO_ERROR ): - rc = "X509 - Read/write of file failed"; - break; - - case -( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ): - rc = "X509 - Destination buffer is too small"; - break; - - case -( MBEDTLS_ERR_X509_FATAL_ERROR ): - 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; diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.h index db838074bd..73df1a36d4 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_error.h @@ -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 -#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_ */ diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_freertos_port.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_freertos_port.c index 7516c16506..ae7852b821 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_freertos_port.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/mbedtls/mbedtls_freertos_port.c @@ -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 ); diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/retry_utils/retry_utils_freertos.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/retry_utils/retry_utils_freertos.c index 39c58cfd2f..7063fa2035 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/retry_utils/retry_utils_freertos.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/retry_utils/retry_utils_freertos.c @@ -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++; diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/freertos_sockets_wrapper.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/freertos_sockets_wrapper.h index 445349862a..481662b7c1 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/freertos_sockets_wrapper.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/freertos_sockets_wrapper.h @@ -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 ********/ diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos.h index f6355bea0c..9ae7fb6735 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos.h @@ -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; /** diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos_pkcs11.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos_pkcs11.h index f95e1c712f..6fe88b6be1 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos_pkcs11.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/include/tls_freertos_pkcs11.h @@ -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; /** diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/freertos_sockets_wrapper.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/freertos_sockets_wrapper.c index fc30c9ec7a..f433b3efd5 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/freertos_sockets_wrapper.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/freertos_sockets_wrapper.c @@ -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 diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c index 4e3fece8e8..14cf4165c2 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos.c @@ -77,51 +77,125 @@ static const char * pNoLowLevelMbedTlsCodeStr = ""; /*-----------------------------------------------------------*/ /** - * @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, diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos_pkcs11.c b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos_pkcs11.c index d1d2b260e5..ab24a8db59 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos_pkcs11.c +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/freertos/transport/src/tls_freertos_pkcs11.c @@ -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 diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/include/retry_utils.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/include/retry_utils.h index 57f328403d..734bb8ca04 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/include/retry_utils.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/include/retry_utils.h @@ -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; diff --git a/FreeRTOS-Plus/Source/Application-Protocols/platform/include/transport_interface.h b/FreeRTOS-Plus/Source/Application-Protocols/platform/include/transport_interface.h index 3980221402..6be7b0d8e9 100644 --- a/FreeRTOS-Plus/Source/Application-Protocols/platform/include/transport_interface.h +++ b/FreeRTOS-Plus/Source/Application-Protocols/platform/include/transport_interface.h @@ -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 /** + * @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. + *
+ * + * The functions that must be implemented are:
+ * - [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:

+ * @snippet this define_transportinterface + *
+ * + * @transportsectionimplementation + * + * The following steps give guidance on implementing the transport interface: + * + * -# Implementing @ref NetworkContext_t

+ * @snippet this define_networkcontext + *
+ * @ref NetworkContext_t is the incomplete type struct NetworkContext. + * 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.
+ * In the case of TLS over TCP, struct NetworkContext is typically implemented + * with the TCP socket context and a TLS context.

+ * Example code: + * @code{c} + * struct NetworkContext + * { + * struct MyTCPSocketContext tcpSocketContext; + * struct MyTLSContext tlsContext; + * }; + * @endcode + *
+ * -# Implementing @ref TransportRecv_t

+ * @snippet this define_transportrecv + *
+ * 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. + *

+ * Example code: + * @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 + *
+ * -# Implementing @ref TransportSend_t

+ * @snippet this define_transportsend + *
+ * 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. + *

+ * Example code: + * @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_ */