1 /*
2 * FreeRTOS V202212.00
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
24 *
25 */
26
27 /**
28 * @file transport_mbedtls.c
29 * @brief TLS transport interface implementations. This implementation uses
30 * mbedTLS.
31 */
32
33 #include "logging_levels.h"
34
35 #ifndef LIBRARY_LOG_NAME
36 #define LIBRARY_LOG_NAME "MbedtlsTransport"
37 #endif /* LIBRARY_LOG_NAME */
38
39 #ifndef LIBRARY_LOG_LEVEL
40 #define LIBRARY_LOG_LEVEL LOG_INFO
41 #endif /* LIBRARY_LOG_LEVEL*/
42
43 #include "logging_stack.h"
44
45 /* Standard includes. */
46 #include <string.h>
47
48 /* FreeRTOS includes. */
49 #include "FreeRTOS.h"
50
51 /* MBedTLS Includes */
52 #if !defined( MBEDTLS_CONFIG_FILE )
53 #include "mbedtls/mbedtls_config.h"
54 #else
55 #include MBEDTLS_CONFIG_FILE
56 #endif
57
58 #ifdef MBEDTLS_PSA_CRYPTO_C
59 /* MbedTLS PSA Includes */
60 #include "psa/crypto.h"
61 #include "psa/crypto_values.h"
62 #endif /* MBEDTLS_PSA_CRYPTO_C */
63
64 #ifdef MBEDTLS_DEBUG_C
65 #include "mbedtls/debug.h"
66 #endif /* MBEDTLS_DEBUG_C */
67
68 /* MBedTLS Bio TCP sockets wrapper include. */
69 #include "mbedtls_bio_tcp_sockets_wrapper.h"
70
71 /* TLS transport header. */
72 #include "transport_mbedtls.h"
73
74 /*-----------------------------------------------------------*/
75
76 /**
77 * @brief Each compilation unit that consumes the NetworkContext must define it.
78 * It should contain a single pointer as seen below whenever the header file
79 * of this transport implementation is included to your project.
80 *
81 * @note When using multiple transports in the same compilation unit,
82 * define this pointer as void *.
83 */
84 struct NetworkContext
85 {
86 TlsTransportParams_t * pParams;
87 };
88
89 /*-----------------------------------------------------------*/
90
91 /**
92 * @brief Represents string to be logged when mbedTLS returned error
93 * does not contain a high-level code.
94 */
95 static const char * pNoHighLevelMbedTlsCodeStr = "<No-High-Level-Code>";
96
97 /**
98 * @brief Represents string to be logged when mbedTLS returned error
99 * does not contain a low-level code.
100 */
101 static const char * pNoLowLevelMbedTlsCodeStr = "<No-Low-Level-Code>";
102
103 /**
104 * @brief Utility for converting the high-level code in an mbedTLS error to string,
105 * if the code-contains a high-level code; otherwise, using a default string.
106 */
107 #define mbedtlsHighLevelCodeOrDefault( mbedTlsCode ) \
108 ( mbedtls_high_level_strerr( mbedTlsCode ) != NULL ) ? \
109 mbedtls_high_level_strerr( mbedTlsCode ) : pNoHighLevelMbedTlsCodeStr
110
111 /**
112 * @brief Utility for converting the level-level code in an mbedTLS error to string,
113 * if the code-contains a level-level code; otherwise, using a default string.
114 */
115 #define mbedtlsLowLevelCodeOrDefault( mbedTlsCode ) \
116 ( mbedtls_low_level_strerr( mbedTlsCode ) != NULL ) ? \
117 mbedtls_low_level_strerr( mbedTlsCode ) : pNoLowLevelMbedTlsCodeStr
118
119 /*-----------------------------------------------------------*/
120
121 /**
122 * @brief Initialize the mbed TLS structures in a network connection.
123 *
124 * @param[in] pSslContext The SSL context to initialize.
125 */
126 static void sslContextInit( SSLContext_t * pSslContext );
127
128 /**
129 * @brief Free the mbed TLS structures in a network connection.
130 *
131 * @param[in] pSslContext The SSL context to free.
132 */
133 static void sslContextFree( SSLContext_t * pSslContext );
134
135 /**
136 * @brief Add X509 certificate to the trusted list of root certificates.
137 *
138 * OpenSSL does not provide a single function for reading and loading certificates
139 * from files into stores, so the file API must be called. Start with the
140 * root certificate.
141 *
142 * @param[out] pSslContext SSL context to which the trusted server root CA is to be added.
143 * @param[in] pRootCa PEM-encoded string of the trusted server root CA.
144 * @param[in] rootCaSize Size of the trusted server root CA.
145 *
146 * @return 0 on success; otherwise, failure;
147 */
148 static int32_t setRootCa( SSLContext_t * pSslContext,
149 const uint8_t * pRootCa,
150 size_t rootCaSize );
151
152 /**
153 * @brief Set X509 certificate as client certificate for the server to authenticate.
154 *
155 * @param[out] pSslContext SSL context to which the client certificate is to be set.
156 * @param[in] pClientCert PEM-encoded string of the client certificate.
157 * @param[in] clientCertSize Size of the client certificate.
158 *
159 * @return 0 on success; otherwise, failure;
160 */
161 static int32_t setClientCertificate( SSLContext_t * pSslContext,
162 const uint8_t * pClientCert,
163 size_t clientCertSize );
164
165 /**
166 * @brief Set private key for the client's certificate.
167 *
168 * @param[out] pSslContext SSL context to which the private key is to be set.
169 * @param[in] pPrivateKey PEM-encoded string of the client private key.
170 * @param[in] privateKeySize Size of the client private key.
171 *
172 * @return 0 on success; otherwise, failure;
173 */
174 static int32_t setPrivateKey( SSLContext_t * pSslContext,
175 const uint8_t * pPrivateKey,
176 size_t privateKeySize );
177
178 /**
179 * @brief Passes TLS credentials to the OpenSSL library.
180 *
181 * Provides the root CA certificate, client certificate, and private key to the
182 * OpenSSL library. If the client certificate or private key is not NULL, mutual
183 * authentication is used when performing the TLS handshake.
184 *
185 * @param[out] pSslContext SSL context to which the credentials are to be imported.
186 * @param[in] pNetworkCredentials TLS credentials to be imported.
187 *
188 * @return 0 on success; otherwise, failure;
189 */
190 static int32_t setCredentials( SSLContext_t * pSslContext,
191 const NetworkCredentials_t * pNetworkCredentials );
192
193 /**
194 * @brief Set optional configurations for the TLS connection.
195 *
196 * This function is used to set SNI and ALPN protocols.
197 *
198 * @param[in] pSslContext SSL context to which the optional configurations are to be set.
199 * @param[in] pHostName Remote host name, used for server name indication.
200 * @param[in] pNetworkCredentials TLS setup parameters.
201 */
202 static void setOptionalConfigurations( SSLContext_t * pSslContext,
203 const char * pHostName,
204 const NetworkCredentials_t * pNetworkCredentials );
205
206 /**
207 * @brief Setup TLS by initializing contexts and setting configurations.
208 *
209 * @param[in] pNetworkContext Network context.
210 * @param[in] pHostName Remote host name, used for server name indication.
211 * @param[in] pNetworkCredentials TLS setup parameters.
212 *
213 * @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_INSUFFICIENT_MEMORY, #TLS_TRANSPORT_INVALID_CREDENTIALS,
214 * or #TLS_TRANSPORT_INTERNAL_ERROR.
215 */
216 static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
217 const char * pHostName,
218 const NetworkCredentials_t * pNetworkCredentials );
219
220 /**
221 * @brief Perform the TLS handshake on a TCP connection.
222 *
223 * @param[in] pNetworkContext Network context.
224 * @param[in] pNetworkCredentials TLS setup parameters.
225 *
226 * @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_HANDSHAKE_FAILED, or #TLS_TRANSPORT_INTERNAL_ERROR.
227 */
228 static TlsTransportStatus_t tlsHandshake( NetworkContext_t * pNetworkContext,
229 const NetworkCredentials_t * pNetworkCredentials );
230
231 /**
232 * @brief Initialize mbedTLS.
233 *
234 * @param[out] entropyContext mbed TLS entropy context for generation of random numbers.
235 * @param[out] ctrDrbgContext mbed TLS CTR DRBG context for generation of random numbers.
236 *
237 * @return #TLS_TRANSPORT_SUCCESS, or #TLS_TRANSPORT_INTERNAL_ERROR.
238 */
239 static TlsTransportStatus_t initMbedtls( mbedtls_entropy_context * pEntropyContext,
240 mbedtls_ctr_drbg_context * pCtrDrbgContext );
241
242 /*-----------------------------------------------------------*/
243
244 #ifdef MBEDTLS_DEBUG_C
mbedtls_string_printf(void * sslContext,int level,const char * file,int line,const char * str)245 void mbedtls_string_printf( void * sslContext,
246 int level,
247 const char * file,
248 int line,
249 const char * str )
250 {
251 if( ( str != NULL ) && ( file != NULL ) )
252 {
253 LogDebug( ( "%s:%d: [%d] %s", file, line, level, str ) );
254 }
255 }
256 #endif /* MBEDTLS_DEBUG_C */
257
258 /*-----------------------------------------------------------*/
259
sslContextInit(SSLContext_t * pSslContext)260 static void sslContextInit( SSLContext_t * pSslContext )
261 {
262 configASSERT( pSslContext != NULL );
263
264 mbedtls_ssl_config_init( &( pSslContext->config ) );
265 mbedtls_x509_crt_init( &( pSslContext->rootCa ) );
266 mbedtls_pk_init( &( pSslContext->privKey ) );
267 mbedtls_x509_crt_init( &( pSslContext->clientCert ) );
268 mbedtls_ssl_init( &( pSslContext->context ) );
269 #ifdef MBEDTLS_DEBUG_C
270 mbedtls_debug_set_threshold( LIBRARY_LOG_LEVEL + 1U );
271 mbedtls_ssl_conf_dbg( &( pSslContext->config ),
272 mbedtls_string_printf,
273 NULL );
274 #endif /* MBEDTLS_DEBUG_C */
275 }
276 /*-----------------------------------------------------------*/
277
sslContextFree(SSLContext_t * pSslContext)278 static void sslContextFree( SSLContext_t * pSslContext )
279 {
280 configASSERT( pSslContext != NULL );
281
282 mbedtls_ssl_free( &( pSslContext->context ) );
283 mbedtls_x509_crt_free( &( pSslContext->rootCa ) );
284 mbedtls_x509_crt_free( &( pSslContext->clientCert ) );
285 mbedtls_pk_free( &( pSslContext->privKey ) );
286 mbedtls_entropy_free( &( pSslContext->entropyContext ) );
287 mbedtls_ctr_drbg_free( &( pSslContext->ctrDrbgContext ) );
288 mbedtls_ssl_config_free( &( pSslContext->config ) );
289 }
290 /*-----------------------------------------------------------*/
291
setRootCa(SSLContext_t * pSslContext,const uint8_t * pRootCa,size_t rootCaSize)292 static int32_t setRootCa( SSLContext_t * pSslContext,
293 const uint8_t * pRootCa,
294 size_t rootCaSize )
295 {
296 int32_t mbedtlsError = -1;
297
298 configASSERT( pSslContext != NULL );
299 configASSERT( pRootCa != NULL );
300
301 /* Parse the server root CA certificate into the SSL context. */
302 mbedtlsError = mbedtls_x509_crt_parse( &( pSslContext->rootCa ),
303 pRootCa,
304 rootCaSize );
305
306 if( mbedtlsError != 0 )
307 {
308 LogError( ( "Failed to parse server root CA certificate: mbedTLSError= %s : %s.",
309 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
310 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
311 }
312 else
313 {
314 mbedtls_ssl_conf_ca_chain( &( pSslContext->config ),
315 &( pSslContext->rootCa ),
316 NULL );
317 }
318
319 return mbedtlsError;
320 }
321 /*-----------------------------------------------------------*/
322
setClientCertificate(SSLContext_t * pSslContext,const uint8_t * pClientCert,size_t clientCertSize)323 static int32_t setClientCertificate( SSLContext_t * pSslContext,
324 const uint8_t * pClientCert,
325 size_t clientCertSize )
326 {
327 int32_t mbedtlsError = -1;
328
329 configASSERT( pSslContext != NULL );
330 configASSERT( pClientCert != NULL );
331
332 /* Setup the client certificate. */
333 mbedtlsError = mbedtls_x509_crt_parse( &( pSslContext->clientCert ),
334 pClientCert,
335 clientCertSize );
336
337 if( mbedtlsError != 0 )
338 {
339 LogError( ( "Failed to parse the client certificate: mbedTLSError= %s : %s.",
340 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
341 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
342 }
343
344 return mbedtlsError;
345 }
346 /*-----------------------------------------------------------*/
347
setPrivateKey(SSLContext_t * pSslContext,const uint8_t * pPrivateKey,size_t privateKeySize)348 static int32_t setPrivateKey( SSLContext_t * pSslContext,
349 const uint8_t * pPrivateKey,
350 size_t privateKeySize )
351 {
352 int32_t mbedtlsError = -1;
353
354 configASSERT( pSslContext != NULL );
355 configASSERT( pPrivateKey != NULL );
356
357 #if MBEDTLS_VERSION_NUMBER < 0x03000000
358 mbedtlsError = mbedtls_pk_parse_key( &( pSslContext->privKey ),
359 pPrivateKey,
360 privateKeySize,
361 NULL, 0 );
362 #else
363 mbedtlsError = mbedtls_pk_parse_key( &( pSslContext->privKey ),
364 pPrivateKey,
365 privateKeySize,
366 NULL, 0,
367 mbedtls_ctr_drbg_random,
368 &( pSslContext->ctrDrbgContext ) );
369 #endif /* if MBEDTLS_VERSION_NUMBER < 0x03000000 */
370
371 if( mbedtlsError != 0 )
372 {
373 LogError( ( "Failed to parse the client key: mbedTLSError= %s : %s.",
374 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
375 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
376 }
377
378 return mbedtlsError;
379 }
380 /*-----------------------------------------------------------*/
381
setCredentials(SSLContext_t * pSslContext,const NetworkCredentials_t * pNetworkCredentials)382 static int32_t setCredentials( SSLContext_t * pSslContext,
383 const NetworkCredentials_t * pNetworkCredentials )
384 {
385 int32_t mbedtlsError = -1;
386
387 configASSERT( pSslContext != NULL );
388 configASSERT( pNetworkCredentials != NULL );
389
390 /* Set up the certificate security profile, starting from the default value. */
391 pSslContext->certProfile = mbedtls_x509_crt_profile_default;
392
393 /* Set SSL authmode and the RNG context. */
394 mbedtls_ssl_conf_authmode( &( pSslContext->config ),
395 MBEDTLS_SSL_VERIFY_REQUIRED );
396 mbedtls_ssl_conf_rng( &( pSslContext->config ),
397 mbedtls_ctr_drbg_random,
398 &( pSslContext->ctrDrbgContext ) );
399 mbedtls_ssl_conf_cert_profile( &( pSslContext->config ),
400 &( pSslContext->certProfile ) );
401
402 mbedtlsError = setRootCa( pSslContext,
403 pNetworkCredentials->pRootCa,
404 pNetworkCredentials->rootCaSize );
405
406 if( ( pNetworkCredentials->pClientCert != NULL ) &&
407 ( pNetworkCredentials->pPrivateKey != NULL ) )
408 {
409 if( mbedtlsError == 0 )
410 {
411 mbedtlsError = setClientCertificate( pSslContext,
412 pNetworkCredentials->pClientCert,
413 pNetworkCredentials->clientCertSize );
414 }
415
416 if( mbedtlsError == 0 )
417 {
418 mbedtlsError = setPrivateKey( pSslContext,
419 pNetworkCredentials->pPrivateKey,
420 pNetworkCredentials->privateKeySize );
421 }
422
423 if( mbedtlsError == 0 )
424 {
425 mbedtlsError = mbedtls_ssl_conf_own_cert( &( pSslContext->config ),
426 &( pSslContext->clientCert ),
427 &( pSslContext->privKey ) );
428 }
429 }
430
431 return mbedtlsError;
432 }
433 /*-----------------------------------------------------------*/
434
setOptionalConfigurations(SSLContext_t * pSslContext,const char * pHostName,const NetworkCredentials_t * pNetworkCredentials)435 static void setOptionalConfigurations( SSLContext_t * pSslContext,
436 const char * pHostName,
437 const NetworkCredentials_t * pNetworkCredentials )
438 {
439 int32_t mbedtlsError = -1;
440
441 configASSERT( pSslContext != NULL );
442 configASSERT( pHostName != NULL );
443 configASSERT( pNetworkCredentials != NULL );
444
445 if( pNetworkCredentials->pAlpnProtos != NULL )
446 {
447 /* Include an application protocol list in the TLS ClientHello
448 * message. */
449 mbedtlsError = mbedtls_ssl_conf_alpn_protocols( &( pSslContext->config ),
450 pNetworkCredentials->pAlpnProtos );
451
452 if( mbedtlsError != 0 )
453 {
454 LogError( ( "Failed to configure ALPN protocol in mbed TLS: mbedTLSError= %s : %s.",
455 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
456 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
457 }
458 }
459
460 /* Enable SNI if requested. */
461 if( pNetworkCredentials->disableSni == pdFALSE )
462 {
463 mbedtlsError = mbedtls_ssl_set_hostname( &( pSslContext->context ),
464 pHostName );
465 }
466 /* MbedTLS-3.6.3 requires calling the mbedtls_ssl_set_hostname() before calling mbedtls_ssl_handshake(). */
467 else
468 {
469 mbedtlsError = mbedtls_ssl_set_hostname( &( pSslContext->context ),
470 NULL );
471 }
472
473 if( mbedtlsError != 0 )
474 {
475 LogError( ( "Failed to set server name: mbedTLSError= %s : %s.",
476 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
477 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
478 }
479
480 /* Set Maximum Fragment Length if enabled. */
481 #ifdef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
482
483 /* Enable the max fragment extension. 4096 bytes is currently the largest fragment size permitted.
484 * See RFC 8449 https://tools.ietf.org/html/rfc8449 for more information.
485 *
486 * Smaller values can be found in "mbedtls/include/ssl.h".
487 */
488 mbedtlsError = mbedtls_ssl_conf_max_frag_len( &( pSslContext->config ), MBEDTLS_SSL_MAX_FRAG_LEN_4096 );
489
490 if( mbedtlsError != 0 )
491 {
492 LogError( ( "Failed to maximum fragment length extension: mbedTLSError= %s : %s.",
493 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
494 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
495 }
496 #endif /* ifdef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
497 }
498 /*-----------------------------------------------------------*/
499
tlsSetup(NetworkContext_t * pNetworkContext,const char * pHostName,const NetworkCredentials_t * pNetworkCredentials)500 static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetworkContext,
501 const char * pHostName,
502 const NetworkCredentials_t * pNetworkCredentials )
503 {
504 TlsTransportParams_t * pTlsTransportParams = NULL;
505 TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
506 int32_t mbedtlsError = 0;
507
508 configASSERT( pNetworkContext != NULL );
509 configASSERT( pNetworkContext->pParams != NULL );
510 configASSERT( pHostName != NULL );
511 configASSERT( pNetworkCredentials != NULL );
512 configASSERT( pNetworkCredentials->pRootCa != NULL );
513
514 pTlsTransportParams = pNetworkContext->pParams;
515 /* Initialize the mbed TLS context structures. */
516 sslContextInit( &( pTlsTransportParams->sslContext ) );
517
518 mbedtlsError = mbedtls_ssl_config_defaults( &( pTlsTransportParams->sslContext.config ),
519 MBEDTLS_SSL_IS_CLIENT,
520 MBEDTLS_SSL_TRANSPORT_STREAM,
521 MBEDTLS_SSL_PRESET_DEFAULT );
522
523 if( mbedtlsError != 0 )
524 {
525 LogError( ( "Failed to set default SSL configuration: mbedTLSError= %s : %s.",
526 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
527 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
528
529 /* Per mbed TLS docs, mbedtls_ssl_config_defaults only fails on memory allocation. */
530 returnStatus = TLS_TRANSPORT_INSUFFICIENT_MEMORY;
531 }
532
533 if( returnStatus == TLS_TRANSPORT_SUCCESS )
534 {
535 mbedtlsError = setCredentials( &( pTlsTransportParams->sslContext ),
536 pNetworkCredentials );
537
538 if( mbedtlsError != 0 )
539 {
540 returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
541 }
542 else
543 {
544 /* Optionally set SNI and ALPN protocols. */
545 setOptionalConfigurations( &( pTlsTransportParams->sslContext ),
546 pHostName,
547 pNetworkCredentials );
548 }
549 }
550
551 return returnStatus;
552 }
553 /*-----------------------------------------------------------*/
554
tlsHandshake(NetworkContext_t * pNetworkContext,const NetworkCredentials_t * pNetworkCredentials)555 static TlsTransportStatus_t tlsHandshake( NetworkContext_t * pNetworkContext,
556 const NetworkCredentials_t * pNetworkCredentials )
557 {
558 TlsTransportParams_t * pTlsTransportParams = NULL;
559 TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
560 int32_t mbedtlsError = 0;
561
562 configASSERT( pNetworkContext != NULL );
563 configASSERT( pNetworkContext->pParams != NULL );
564 configASSERT( pNetworkCredentials != NULL );
565
566 pTlsTransportParams = pNetworkContext->pParams;
567 /* Initialize the mbed TLS secured connection context. */
568 mbedtlsError = mbedtls_ssl_setup( &( pTlsTransportParams->sslContext.context ),
569 &( pTlsTransportParams->sslContext.config ) );
570
571 if( mbedtlsError != 0 )
572 {
573 LogError( ( "Failed to set up mbed TLS SSL context: mbedTLSError= %s : %s.",
574 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
575 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
576
577 returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
578 }
579 else
580 {
581 /* Set the underlying IO for the TLS connection. */
582
583 /* MISRA Rule 11.2 flags the following line for casting the second
584 * parameter to void *. This rule is suppressed because
585 * #mbedtls_ssl_set_bio requires the second parameter as void *.
586 */
587 /* coverity[misra_c_2012_rule_11_2_violation] */
588
589 /* These two macros MBEDTLS_SSL_SEND and MBEDTLS_SSL_RECV need to be
590 * defined in mbedtls_config.h according to which implementation you use.
591 */
592 mbedtls_ssl_set_bio( &( pTlsTransportParams->sslContext.context ),
593 ( void * ) pTlsTransportParams->tcpSocket,
594 xMbedTLSBioTCPSocketsWrapperSend,
595 xMbedTLSBioTCPSocketsWrapperRecv,
596 NULL );
597 }
598
599 if( returnStatus == TLS_TRANSPORT_SUCCESS )
600 {
601 /* Perform the TLS handshake. */
602 do
603 {
604 mbedtlsError = mbedtls_ssl_handshake( &( pTlsTransportParams->sslContext.context ) );
605 } while( ( mbedtlsError == MBEDTLS_ERR_SSL_WANT_READ ) ||
606 ( mbedtlsError == MBEDTLS_ERR_SSL_WANT_WRITE ) );
607
608 if( mbedtlsError != 0 )
609 {
610 LogError( ( "Failed to perform TLS handshake: mbedTLSError= %s : %s.",
611 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
612 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
613
614 returnStatus = TLS_TRANSPORT_HANDSHAKE_FAILED;
615 }
616 else
617 {
618 LogInfo( ( "(Network connection %p) TLS handshake successful.",
619 pNetworkContext ) );
620 }
621 }
622
623 return returnStatus;
624 }
625 /*-----------------------------------------------------------*/
626
initMbedtls(mbedtls_entropy_context * pEntropyContext,mbedtls_ctr_drbg_context * pCtrDrbgContext)627 static TlsTransportStatus_t initMbedtls( mbedtls_entropy_context * pEntropyContext,
628 mbedtls_ctr_drbg_context * pCtrDrbgContext )
629 {
630 TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
631 int32_t mbedtlsError = 0;
632
633 #if defined( MBEDTLS_THREADING_ALT )
634 /* Set the mutex functions for mbed TLS thread safety. */
635 mbedtls_platform_threading_init();
636 #endif
637
638 /* Initialize contexts for random number generation. */
639 mbedtls_entropy_init( pEntropyContext );
640 mbedtls_ctr_drbg_init( pCtrDrbgContext );
641
642 if( mbedtlsError != 0 )
643 {
644 LogError( ( "Failed to add entropy source: mbedTLSError= %s : %s.",
645 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
646 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
647 returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
648 }
649
650 #ifdef MBEDTLS_PSA_CRYPTO_C
651 if( returnStatus == TLS_TRANSPORT_SUCCESS )
652 {
653 mbedtlsError = psa_crypto_init();
654
655 if( mbedtlsError != PSA_SUCCESS )
656 {
657 LogError( ( "Failed to initialize PSA Crypto implementation: %s", ( int ) mbedtlsError ) );
658 returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
659 }
660 }
661 #endif /* MBEDTLS_PSA_CRYPTO_C */
662
663 if( returnStatus == TLS_TRANSPORT_SUCCESS )
664 {
665 /* Seed the random number generator. */
666 mbedtlsError = mbedtls_ctr_drbg_seed( pCtrDrbgContext,
667 mbedtls_entropy_func,
668 pEntropyContext,
669 NULL,
670 0 );
671
672 if( mbedtlsError != 0 )
673 {
674 LogError( ( "Failed to seed PRNG: mbedTLSError= %s : %s.",
675 mbedtlsHighLevelCodeOrDefault( mbedtlsError ),
676 mbedtlsLowLevelCodeOrDefault( mbedtlsError ) ) );
677 returnStatus = TLS_TRANSPORT_INTERNAL_ERROR;
678 }
679 }
680
681 if( returnStatus == TLS_TRANSPORT_SUCCESS )
682 {
683 LogDebug( ( "Successfully initialized mbedTLS." ) );
684 }
685
686 return returnStatus;
687 }
688 /*-----------------------------------------------------------*/
689
TLS_FreeRTOS_Connect(NetworkContext_t * pNetworkContext,const char * pHostName,uint16_t port,const NetworkCredentials_t * pNetworkCredentials,uint32_t receiveTimeoutMs,uint32_t sendTimeoutMs)690 TlsTransportStatus_t TLS_FreeRTOS_Connect( NetworkContext_t * pNetworkContext,
691 const char * pHostName,
692 uint16_t port,
693 const NetworkCredentials_t * pNetworkCredentials,
694 uint32_t receiveTimeoutMs,
695 uint32_t sendTimeoutMs )
696 {
697 TlsTransportParams_t * pTlsTransportParams = NULL;
698 TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
699 BaseType_t socketStatus = 0;
700 BaseType_t isSocketConnected = pdFALSE, isTlsSetup = pdFALSE;
701
702 if( ( pNetworkContext == NULL ) ||
703 ( pNetworkContext->pParams == NULL ) ||
704 ( pHostName == NULL ) ||
705 ( pNetworkCredentials == NULL ) )
706 {
707 LogError( ( "Invalid input parameter(s): Arguments cannot be NULL. pNetworkContext=%p, "
708 "pHostName=%p, pNetworkCredentials=%p.",
709 pNetworkContext,
710 pHostName,
711 pNetworkCredentials ) );
712 returnStatus = TLS_TRANSPORT_INVALID_PARAMETER;
713 }
714 else if( ( pNetworkCredentials->pRootCa == NULL ) )
715 {
716 LogError( ( "pRootCa cannot be NULL." ) );
717 returnStatus = TLS_TRANSPORT_INVALID_PARAMETER;
718 }
719 else
720 {
721 /* Empty else for MISRA 15.7 compliance. */
722 }
723
724 /* Establish a TCP connection with the server. */
725 if( returnStatus == TLS_TRANSPORT_SUCCESS )
726 {
727 pTlsTransportParams = pNetworkContext->pParams;
728
729 /* Initialize tcpSocket. */
730 pTlsTransportParams->tcpSocket = NULL;
731
732 socketStatus = TCP_Sockets_Connect( &( pTlsTransportParams->tcpSocket ),
733 pHostName,
734 port,
735 receiveTimeoutMs,
736 sendTimeoutMs );
737
738 if( socketStatus != 0 )
739 {
740 LogError( ( "Failed to connect to %s with error %d.",
741 pHostName,
742 socketStatus ) );
743 returnStatus = TLS_TRANSPORT_CONNECT_FAILURE;
744 }
745 }
746
747 /* Initialize mbedtls. */
748 if( returnStatus == TLS_TRANSPORT_SUCCESS )
749 {
750 isSocketConnected = pdTRUE;
751
752 returnStatus = initMbedtls( &( pTlsTransportParams->sslContext.entropyContext ),
753 &( pTlsTransportParams->sslContext.ctrDrbgContext ) );
754 }
755
756 /* Initialize TLS contexts and set credentials. */
757 if( returnStatus == TLS_TRANSPORT_SUCCESS )
758 {
759 returnStatus = tlsSetup( pNetworkContext, pHostName, pNetworkCredentials );
760 }
761
762 /* Perform TLS handshake. */
763 if( returnStatus == TLS_TRANSPORT_SUCCESS )
764 {
765 isTlsSetup = pdTRUE;
766
767 returnStatus = tlsHandshake( pNetworkContext, pNetworkCredentials );
768 }
769
770 /* Clean up on failure. */
771 if( returnStatus != TLS_TRANSPORT_SUCCESS )
772 {
773 /* Free SSL context if it's setup. */
774 if( isTlsSetup == pdTRUE )
775 {
776 sslContextFree( &( pTlsTransportParams->sslContext ) );
777 }
778
779 /* Call Sockets_Disconnect if socket was connected. */
780 if( isSocketConnected == pdTRUE )
781 {
782 TCP_Sockets_Disconnect( pTlsTransportParams->tcpSocket );
783 pTlsTransportParams->tcpSocket = NULL;
784 }
785 }
786 else
787 {
788 LogInfo( ( "(Network connection %p) Connection to %s established.",
789 pNetworkContext,
790 pHostName ) );
791 }
792
793 return returnStatus;
794 }
795 /*-----------------------------------------------------------*/
796
TLS_FreeRTOS_Disconnect(NetworkContext_t * pNetworkContext)797 void TLS_FreeRTOS_Disconnect( NetworkContext_t * pNetworkContext )
798 {
799 TlsTransportParams_t * pTlsTransportParams = NULL;
800 BaseType_t tlsStatus = 0;
801
802 if( ( pNetworkContext != NULL ) && ( pNetworkContext->pParams != NULL ) )
803 {
804 pTlsTransportParams = pNetworkContext->pParams;
805 /* Attempting to terminate TLS connection. */
806 tlsStatus = ( BaseType_t ) mbedtls_ssl_close_notify( &( pTlsTransportParams->sslContext.context ) );
807
808 /* Ignore the WANT_READ and WANT_WRITE return values. */
809 if( ( tlsStatus != ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_READ ) &&
810 ( tlsStatus != ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_WRITE ) )
811 {
812 if( tlsStatus == 0 )
813 {
814 LogInfo( ( "(Network connection %p) TLS close-notify sent.",
815 pNetworkContext ) );
816 }
817 else
818 {
819 LogError( ( "(Network connection %p) Failed to send TLS close-notify: mbedTLSError= %s : %s.",
820 pNetworkContext,
821 mbedtlsHighLevelCodeOrDefault( tlsStatus ),
822 mbedtlsLowLevelCodeOrDefault( tlsStatus ) ) );
823 }
824 }
825 else
826 {
827 /* WANT_READ and WANT_WRITE can be ignored. Logging for debugging purposes. */
828 LogInfo( ( "(Network connection %p) TLS close-notify sent; "
829 "received %s as the TLS status can be ignored for close-notify.",
830 ( tlsStatus == MBEDTLS_ERR_SSL_WANT_READ ) ? "WANT_READ" : "WANT_WRITE",
831 pNetworkContext ) );
832 }
833
834 /* Call socket shutdown function to close connection. */
835 TCP_Sockets_Disconnect( pTlsTransportParams->tcpSocket );
836
837 /* Free mbed TLS contexts. */
838 sslContextFree( &( pTlsTransportParams->sslContext ) );
839 }
840 }
841 /*-----------------------------------------------------------*/
842
TLS_FreeRTOS_recv(NetworkContext_t * pNetworkContext,void * pBuffer,size_t bytesToRecv)843 int32_t TLS_FreeRTOS_recv( NetworkContext_t * pNetworkContext,
844 void * pBuffer,
845 size_t bytesToRecv )
846 {
847 TlsTransportParams_t * pTlsTransportParams = NULL;
848 int32_t tlsStatus = 0;
849
850 if( ( pNetworkContext == NULL ) || ( pNetworkContext->pParams == NULL ) )
851 {
852 LogError( ( "invalid input, pNetworkContext=%p", pNetworkContext ) );
853 tlsStatus = -1;
854 }
855 else if( pBuffer == NULL )
856 {
857 LogError( ( "invalid input, pBuffer == NULL" ) );
858 tlsStatus = -1;
859 }
860 else if( bytesToRecv == 0 )
861 {
862 LogError( ( "invalid input, bytesToRecv == 0" ) );
863 tlsStatus = -1;
864 }
865 else
866 {
867 pTlsTransportParams = pNetworkContext->pParams;
868
869 tlsStatus = ( int32_t ) mbedtls_ssl_read( &( pTlsTransportParams->sslContext.context ),
870 pBuffer,
871 bytesToRecv );
872
873 if( ( tlsStatus == MBEDTLS_ERR_SSL_TIMEOUT ) ||
874 ( tlsStatus == MBEDTLS_ERR_SSL_WANT_READ ) ||
875 ( tlsStatus == MBEDTLS_ERR_SSL_WANT_WRITE ) ||
876 ( tlsStatus == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET ) )
877 {
878 if( tlsStatus == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET )
879 {
880 LogDebug( ( "Received a MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET return code from mbedtls_ssl_read." ) );
881 }
882
883 LogDebug( ( "Failed to read data. However, a read can be retried on this error. "
884 "mbedTLSError= %s : %s.",
885 mbedtlsHighLevelCodeOrDefault( tlsStatus ),
886 mbedtlsLowLevelCodeOrDefault( tlsStatus ) ) );
887
888 /* Mark these set of errors as a timeout. The libraries may retry read
889 * on these errors. */
890 tlsStatus = 0;
891 }
892 else if( tlsStatus < 0 )
893 {
894 LogError( ( "Failed to read data: mbedTLSError= %s : %s.",
895 mbedtlsHighLevelCodeOrDefault( tlsStatus ),
896 mbedtlsLowLevelCodeOrDefault( tlsStatus ) ) );
897 }
898 else
899 {
900 /* Empty else marker. */
901 }
902 }
903
904 return tlsStatus;
905 }
906 /*-----------------------------------------------------------*/
907
TLS_FreeRTOS_send(NetworkContext_t * pNetworkContext,const void * pBuffer,size_t bytesToSend)908 int32_t TLS_FreeRTOS_send( NetworkContext_t * pNetworkContext,
909 const void * pBuffer,
910 size_t bytesToSend )
911 {
912 TlsTransportParams_t * pTlsTransportParams = NULL;
913 int32_t tlsStatus = 0;
914
915 if( ( pNetworkContext == NULL ) || ( pNetworkContext->pParams == NULL ) )
916 {
917 LogError( ( "invalid input, pNetworkContext=%p", pNetworkContext ) );
918 tlsStatus = -1;
919 }
920 else if( pBuffer == NULL )
921 {
922 LogError( ( "invalid input, pBuffer == NULL" ) );
923 tlsStatus = -1;
924 }
925 else if( bytesToSend == 0 )
926 {
927 LogError( ( "invalid input, bytesToSend == 0" ) );
928 tlsStatus = -1;
929 }
930 else
931 {
932 pTlsTransportParams = pNetworkContext->pParams;
933
934 tlsStatus = ( int32_t ) mbedtls_ssl_write( &( pTlsTransportParams->sslContext.context ),
935 pBuffer,
936 bytesToSend );
937
938 if( ( tlsStatus == MBEDTLS_ERR_SSL_TIMEOUT ) ||
939 ( tlsStatus == MBEDTLS_ERR_SSL_WANT_READ ) ||
940 ( tlsStatus == MBEDTLS_ERR_SSL_WANT_WRITE ) ||
941 ( tlsStatus == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET ) )
942 {
943 if( tlsStatus == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET )
944 {
945 LogDebug( ( "Received a MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET return code from mbedtls_ssl_write." ) );
946 }
947
948 LogDebug( ( "Failed to send data. However, send can be retried on this error. "
949 "mbedTLSError= %s : %s.",
950 mbedtlsHighLevelCodeOrDefault( tlsStatus ),
951 mbedtlsLowLevelCodeOrDefault( tlsStatus ) ) );
952
953 /* Mark these set of errors as a timeout. The libraries may retry send
954 * on these errors. */
955 tlsStatus = 0;
956 }
957 else if( tlsStatus < 0 )
958 {
959 LogError( ( "Failed to send data: mbedTLSError= %s : %s.",
960 mbedtlsHighLevelCodeOrDefault( tlsStatus ),
961 mbedtlsLowLevelCodeOrDefault( tlsStatus ) ) );
962 }
963 else
964 {
965 /* Empty else marker. */
966 }
967 }
968
969 return tlsStatus;
970 }
971 /*-----------------------------------------------------------*/
972