blob: 2970edc6bbc68e7f384885c98156f364a511f3c1 [file] [log] [blame]
Qiufang Dai35c31332020-05-13 15:29:06 +08001/*
2 * Amazon FreeRTOS TLS V1.1.1
3 * Copyright (C) 2017 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 * http://aws.amazon.com/freertos
23 * http://www.FreeRTOS.org
24 */
25
26/* FreeRTOS includes. */
27#include "FreeRTOS.h"
28#include "FreeRTOSIPConfig.h"
29#include "aws_tls.h"
30#include "aws_crypto.h"
31#include "aws_pkcs11.h"
32#include "task.h"
33#include "aws_clientcredential.h"
34#include "aws_default_root_certificates.h"
35
36/* mbedTLS includes. */
37#include "mbedtls/platform.h"
38#include "mbedtls/net.h"
39#include "mbedtls/ctr_drbg.h"
40#include "mbedtls/entropy.h"
41#include "mbedtls/sha256.h"
42#include "mbedtls/pk.h"
43#include "mbedtls/debug.h"
44#ifdef MBEDTLS_DEBUG_C
45 #define tlsDEBUG_VERBOSE 4
46#endif
47
48/* C runtime includes. */
49#include <string.h>
50#include <time.h>
51#include <stdio.h>
52
53/**
54 * @brief Internal context structure.
55 *
56 * @param[in] pcDestination Server location, can be a DNS name or IP address.
57 * @param[in] pcServerCertificate Server X.509 certificate in PEM format to trust.
58 * @param[in] ulServerCertificateLength Length in bytes of the server certificate.
59 * @param[in] pxNetworkRecv Callback for receiving data on an open TCP socket.
60 * @param[in] pxNetworkSend Callback for sending data on an open TCP socket.
61 * @param[in] pvCallerContext Opaque pointer provided by caller for above callbacks.
62 * @param[out] mbedSslCtx Connection context for mbedTLS.
63 * @param[out] mbedSslConfig Configuration context for mbedTLS.
64 * @param[out] mbedX509CA Server certificate context for mbedTLS.
65 * @param[out] mbedX509Cli Client certificate context for mbedTLS.
66 * @param[out] mbedPkAltCtx RSA crypto implementation context for mbedTLS.
67 * @param[out] pxP11FunctionList PKCS#11 function list structure.
68 * @param[out] xP11Session PKCS#11 session context.
69 * @param[out] xP11PrivateKey PKCS#11 private key context.
70 * @param[out] ulP11ModulusBytes Number of bytes in the client private key modulus.
71 */
72typedef struct TLSContext
73{
74 const char * pcDestination;
75 const char * pcServerCertificate;
76 uint32_t ulServerCertificateLength;
77 const char ** ppcAlpnProtocols;
78 uint32_t ulAlpnProtocolsCount;
79
80 NetworkRecv_t pxNetworkRecv;
81 NetworkSend_t pxNetworkSend;
82 void * pvCallerContext;
83
84 /* mbedTLS. */
85 mbedtls_ssl_context mbedSslCtx;
86 mbedtls_ssl_config mbedSslConfig;
87 mbedtls_x509_crt mbedX509CA;
88 mbedtls_x509_crt mbedX509Cli;
89 mbedtls_pk_context mbedPkCtx;
90
91 /* PKCS#11. */
92 CK_FUNCTION_LIST_PTR pxP11FunctionList;
93 CK_SESSION_HANDLE xP11Session;
94 CK_OBJECT_HANDLE xP11PrivateKey;
95 CK_ULONG ulP11ModulusBytes;
96} TLSContext_t;
97
98/*
99 * Helper routines.
100 */
101
102/**
103 * @brief Network send callback shim.
104 *
105 * @param[in] pvContext Caller context.
106 * @param[in] pucData Byte buffer to send.
107 * @param[in] xDataLength Length of byte buffer to send.
108 *
109 * @return Number of bytes sent, or a negative value on error.
110 */
111static int prvNetworkSend( void * pvContext,
112 const unsigned char * pucData,
113 size_t xDataLength )
114{
115 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
116
117 return ( int ) pCtx->pxNetworkSend( pCtx->pvCallerContext, pucData, xDataLength );
118}
119
120/**
121 * @brief Network receive callback shim.
122 *
123 * @param[in] pvContext Caller context.
124 * @param[out] pucReceiveBuffer Byte buffer to receive into.
125 * @param[in] xReceiveLength Length of byte buffer for receive.
126 *
127 * @return Number of bytes received, or a negative value on error.
128 */
129static int prvNetworkRecv( void * pvContext,
130 unsigned char * pucReceiveBuffer,
131 size_t xReceiveLength )
132{
133 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
134
135 return ( int ) pCtx->pxNetworkRecv( pCtx->pvCallerContext, pucReceiveBuffer, xReceiveLength );
136}
137
138/**
139 * @brief Callback that wraps PKCS#11 for pseudo-random number generation.
140 *
141 * @param[in] pvCtx Caller context.
142 * @param[in] pucRandom Byte array to fill with random data.
143 * @param[in] xRandomLength Length of byte array.
144 *
145 * @return Zero on success.
146 */
147static int prvGenerateRandomBytes( void * pvCtx,
148 unsigned char * pucRandom,
149 size_t xRandomLength )
150{
151 TLSContext_t * pCtx = ( TLSContext_t * ) pvCtx; /*lint !e9087 !e9079 Allow casting void* to other types. */
152
153 return ( int ) pCtx->pxP11FunctionList->C_GenerateRandom( pCtx->xP11Session, pucRandom, xRandomLength );
154}
155
156/**
157 * @brief Callback that enforces a worst-case expiration check on TLS server
158 * certificates.
159 *
160 * @param[in] pvCtx Caller context.
161 * @param[in] pxCertificate Certificate to check.
162 * @param[in] lPathCount Location of this certificate in the chain.
163 * @param[in] pulFlags Verification status flags.
164 *
165 * @return Zero on success.
166 */
167static int prvCheckCertificate( void * pvCtx,
168 mbedtls_x509_crt * pxCertificate,
169 int lPathCount,
170 uint32_t * pulFlags )
171{
172 int lCompilationYear = 0;
173
174#define tlsCOMPILER_DATE_STRING_MONTH_LENGTH 4
175 char pcCompilationMonth[ tlsCOMPILER_DATE_STRING_MONTH_LENGTH ];
176 int lCompilationMonth = 0;
177 int lCompilationDay = 0;
178 const char pcMonths[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
179
180 /* Unreferenced parameters. */
181 ( void ) ( pvCtx );
182 ( void ) ( lPathCount );
183
184 /* Parse the date string fields. */
185 sscanf( __DATE__,
186 "%3s %d %d",
187 pcCompilationMonth,
188 &lCompilationDay,
189 &lCompilationYear );
190 pcCompilationMonth[ tlsCOMPILER_DATE_STRING_MONTH_LENGTH - 1 ] = '\0';
191
192 /* Check for server expiration. First check the year. */
193 if( pxCertificate->valid_to.year < lCompilationYear )
194 {
195 *pulFlags |= MBEDTLS_X509_BADCERT_EXPIRED;
196 }
197 else if( pxCertificate->valid_to.year == lCompilationYear )
198 {
199 /* Convert the month. */
200 lCompilationMonth =
201 ( ( strstr( pcMonths, pcCompilationMonth ) - pcMonths ) /
202 ( tlsCOMPILER_DATE_STRING_MONTH_LENGTH - 1 ) ) + 1;
203
204 /* Check the month. */
205 if( pxCertificate->valid_to.mon < lCompilationMonth )
206 {
207 *pulFlags |= MBEDTLS_X509_BADCERT_EXPIRED;
208 }
209 else if( pxCertificate->valid_to.mon == lCompilationMonth )
210 {
211 /* Check the day. */
212 if( pxCertificate->valid_to.day < lCompilationDay )
213 {
214 *pulFlags |= MBEDTLS_X509_BADCERT_EXPIRED;
215 }
216 }
217 }
218
219 return 0;
220}
221
222/**
223 * @brief Helper for setting up potentially hardware-based cryptographic context
224 * for the client TLS certificate and private key.
225 *
226 * @param Caller context.
227 *
228 * @return Zero on success.
229 */
230static int prvInitializeClientCredential( TLSContext_t * pCtx )
231{
232 BaseType_t xResult = 0;
233 CK_C_GetFunctionList pxCkGetFunctionList = NULL;
234 CK_SLOT_ID xSlotId = 0;
235 CK_ULONG ulCount = 1;
236 CK_ATTRIBUTE xTemplate = { 0 };
237 CK_OBJECT_CLASS xObjClass = 0;
238 CK_OBJECT_HANDLE xCertObj = 0;
239 CK_BYTE * pucCertificate = NULL;
240
241 /* Initialize the mbed contexts. */
242 mbedtls_x509_crt_init( &pCtx->mbedX509Cli );
243
244 /* Ensure that the PKCS#11 module is initialized. */
245 if( 0 == xResult )
246 {
247 pxCkGetFunctionList = C_GetFunctionList;
248 xResult = ( BaseType_t ) pxCkGetFunctionList( &pCtx->pxP11FunctionList );
249 }
250
251 if( 0 == xResult )
252 {
253 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_Initialize( NULL );
254 }
255
256 /* Get the default private key storage ID. */
257 if( 0 == xResult )
258 {
259 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_GetSlotList( CK_TRUE, &xSlotId, &ulCount );
260 }
261
262 /* Start a private session with the P#11 module. */
263 if( 0 == xResult )
264 {
265 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_OpenSession( xSlotId,
266 CKF_SERIAL_SESSION,
267 NULL,
268 NULL,
269 &pCtx->xP11Session );
270 }
271
272 /* Enumerate the first private key. */
273 if( 0 == xResult )
274 {
275 xTemplate.type = CKA_CLASS;
276 xTemplate.ulValueLen = sizeof( CKA_CLASS );
277 xTemplate.pValue = &xObjClass;
278 xObjClass = CKO_PRIVATE_KEY;
279 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjectsInit( pCtx->xP11Session, &xTemplate, 1 );
280 }
281
282 if( 0 == xResult )
283 {
284 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjects( pCtx->xP11Session, &pCtx->xP11PrivateKey, 1, &ulCount );
285 }
286
287 if( 0 == xResult )
288 {
289 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjectsFinal( pCtx->xP11Session );
290 }
291
292 /* Get the internal key context. */
293 if( 0 == xResult )
294 {
295 xTemplate.type = CKA_VENDOR_DEFINED;
296 xTemplate.ulValueLen = sizeof( pCtx->mbedPkCtx );
297 xTemplate.pValue = &pCtx->mbedPkCtx;
298 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_GetAttributeValue(
299 pCtx->xP11Session, pCtx->xP11PrivateKey, &xTemplate, 1 );
300 }
301
302 /* Get the key size. */
303 if( 0 == xResult )
304 {
305 xTemplate.type = CKA_MODULUS_BITS;
306 xTemplate.ulValueLen = sizeof( pCtx->ulP11ModulusBytes );
307 xTemplate.pValue = &pCtx->ulP11ModulusBytes;
308 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_GetAttributeValue(
309 pCtx->xP11Session, pCtx->xP11PrivateKey, &xTemplate, 1 );
310 }
311
312 if( 0 == xResult )
313 {
314 pCtx->ulP11ModulusBytes /= 8;
315
316 /* Enumerate the first client certificate. */
317 xTemplate.type = CKA_CLASS;
318 xTemplate.ulValueLen = sizeof( CKA_CLASS );
319 xTemplate.pValue = &xObjClass;
320 xObjClass = CKO_CERTIFICATE;
321 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjectsInit( pCtx->xP11Session, &xTemplate, 1 );
322 }
323
324 if( 0 == xResult )
325 {
326 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjects( pCtx->xP11Session, &xCertObj, 1, &ulCount );
327 }
328
329 if( 0 == xResult )
330 {
331 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_FindObjectsFinal( pCtx->xP11Session );
332 }
333
334 if( 0 == xResult )
335 {
336 /* Query the certificate size. */
337 xTemplate.type = CKA_VALUE;
338 xTemplate.ulValueLen = 0;
339 xTemplate.pValue = NULL;
340 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_GetAttributeValue( pCtx->xP11Session, xCertObj, &xTemplate, 1 );
341 }
342
343 if( 0 == xResult )
344 {
345 /* Create a buffer for the certificate. */
346 pucCertificate = ( CK_BYTE_PTR ) pvPortMalloc( xTemplate.ulValueLen ); /*lint !e9079 Allow casting void* to other types. */
347
348 if( NULL == pucCertificate )
349 {
350 xResult = ( BaseType_t ) CKR_HOST_MEMORY;
351 }
352 }
353
354 if( 0 == xResult )
355 {
356 /* Export the certificate. */
357 xTemplate.pValue = pucCertificate;
358 xResult = ( BaseType_t ) pCtx->pxP11FunctionList->C_GetAttributeValue(
359 pCtx->xP11Session, xCertObj, &xTemplate, 1 );
360 }
361
362 /* Decode the client certificate. */
363 if( 0 == xResult )
364 {
365 xResult = mbedtls_x509_crt_parse( &pCtx->mbedX509Cli,
366 ( const unsigned char * ) pucCertificate,
367 xTemplate.ulValueLen );
368 }
369
370 /*
371 * Add a JITR device issuer certificate, if present.
372 */
373 if( ( 0 == xResult ) &&
374 ( NULL != clientcredentialJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM ) )
375 {
376 /* Decode the JITR issuer. The device client certificate will get
377 * inserted as the first certificate in this chain below. */
378 xResult = mbedtls_x509_crt_parse(
379 &pCtx->mbedX509Cli,
380 ( const unsigned char * ) clientcredentialJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM,
381 1 + strlen( clientcredentialJITR_DEVICE_CERTIFICATE_AUTHORITY_PEM ) );
382 }
383
384 /*
385 * Attach the client certificate and private key to the TLS configuration.
386 */
387 if( 0 == xResult )
388 {
389 xResult = mbedtls_ssl_conf_own_cert(
390 &pCtx->mbedSslConfig, &pCtx->mbedX509Cli, &pCtx->mbedPkCtx );
391 }
392
393 if( NULL != pucCertificate )
394 {
395 vPortFree( pucCertificate );
396 }
397
398 return xResult;
399}
400
401/*
402 * Interface routines.
403 */
404
405BaseType_t TLS_Init( void ** ppvContext,
406 TLSParams_t * pxParams )
407{
408 BaseType_t xResult = 0;
409 TLSContext_t * pCtx = NULL;
410
411 /* Allocate an internal context. */
412 pCtx = ( TLSContext_t * ) pvPortMalloc( sizeof( TLSContext_t ) ); /*lint !e9087 !e9079 Allow casting void* to other types. */
413
414 if( NULL != pCtx )
415 {
416 memset( pCtx, 0, sizeof( TLSContext_t ) );
417 *ppvContext = pCtx;
418
419 /* Initialize the context. */
420 pCtx->pcDestination = pxParams->pcDestination;
421 pCtx->pcServerCertificate = pxParams->pcServerCertificate;
422 pCtx->ulServerCertificateLength = pxParams->ulServerCertificateLength;
423 pCtx->ppcAlpnProtocols = pxParams->ppcAlpnProtocols;
424 pCtx->ulAlpnProtocolsCount = pxParams->ulAlpnProtocolsCount;
425 pCtx->pxNetworkRecv = pxParams->pxNetworkRecv;
426 pCtx->pxNetworkSend = pxParams->pxNetworkSend;
427 pCtx->pvCallerContext = pxParams->pvCallerContext;
428 }
429 else
430 {
431 xResult = ( BaseType_t ) CKR_HOST_MEMORY;
432 }
433
434 return xResult;
435}
436
437/*-----------------------------------------------------------*/
438
439#ifdef MBEDTLS_DEBUG_C
440 static void prvTlsDebugPrint( void * ctx,
441 int level,
442 const char * file,
443 int line,
444 const char * str )
445 {
446 /* Unused parameters. */
447 ( void ) ctx;
448 ( void ) file;
449 ( void ) line;
450
451 /* Send the debug string to the portable logger. */
452 vLoggingPrintf( "mbedTLS: |%d| %s", level, str );
453 }
454#endif /* ifdef MBEDTLS_DEBUG_C */
455
456/*-----------------------------------------------------------*/
457
458BaseType_t TLS_Connect( void * pvContext )
459{
460 BaseType_t xResult = 0;
461 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
462
463 /* Ensure that the FreeRTOS heap is used. */
464 CRYPTO_ConfigureHeap();
465
466 /* Initialize mbedTLS structures. */
467 mbedtls_ssl_init( &pCtx->mbedSslCtx );
468 mbedtls_ssl_config_init( &pCtx->mbedSslConfig );
469 mbedtls_x509_crt_init( &pCtx->mbedX509CA );
470
471 /* Decode the root certificate: either the default or the override. */
472 if( NULL != pCtx->pcServerCertificate )
473 {
474 xResult = mbedtls_x509_crt_parse( &pCtx->mbedX509CA,
475 ( const unsigned char * ) pCtx->pcServerCertificate,
476 pCtx->ulServerCertificateLength );
477 }
478 else
479 {
480 xResult = mbedtls_x509_crt_parse( &pCtx->mbedX509CA,
481 ( const unsigned char * ) tlsVERISIGN_ROOT_CERTIFICATE_PEM,
482 tlsVERISIGN_ROOT_CERTIFICATE_LENGTH );
483
484 if( 0 == xResult )
485 {
486 xResult = mbedtls_x509_crt_parse( &pCtx->mbedX509CA,
487 ( const unsigned char * ) tlsATS1_ROOT_CERTIFICATE_PEM,
488 tlsATS1_ROOT_CERTIFICATE_LENGTH );
489 }
490 }
491
492 /* Start with protocol defaults. */
493 if( 0 == xResult )
494 {
495 xResult = mbedtls_ssl_config_defaults( &pCtx->mbedSslConfig,
496 MBEDTLS_SSL_IS_CLIENT,
497 MBEDTLS_SSL_TRANSPORT_STREAM,
498 MBEDTLS_SSL_PRESET_DEFAULT );
499 }
500
501 if( 0 == xResult )
502 {
503 /* Use a callback for additional server certificate validation. */
504 mbedtls_ssl_conf_verify( &pCtx->mbedSslConfig,
505 &prvCheckCertificate,
506 pCtx );
507
508 /* Server certificate validation is mandatory. */
509 mbedtls_ssl_conf_authmode( &pCtx->mbedSslConfig, MBEDTLS_SSL_VERIFY_REQUIRED );
510
511 /* Set the RNG callback. */
512 mbedtls_ssl_conf_rng( &pCtx->mbedSslConfig, &prvGenerateRandomBytes, pCtx ); /*lint !e546 Nothing wrong here. */
513
514 /* Set issuer certificate. */
515 mbedtls_ssl_conf_ca_chain( &pCtx->mbedSslConfig, &pCtx->mbedX509CA, NULL );
516
517 /* Setup the client credential. */
518 xResult = prvInitializeClientCredential( pCtx );
519 }
520
521 if( ( 0 == xResult ) && ( NULL != pCtx->ppcAlpnProtocols ) )
522 {
523 /* Include an application protocol list in the TLS ClientHello
524 * message. */
525 xResult = mbedtls_ssl_conf_alpn_protocols(
526 &pCtx->mbedSslConfig,
527 pCtx->ppcAlpnProtocols );
528 }
529
530 #ifdef MBEDTLS_DEBUG_C
531
532 /* If mbedTLS is being compiled with debug support, assume that the
533 * runtime configuration should use verbose output. */
534 mbedtls_ssl_conf_dbg( &pCtx->mbedSslConfig, prvTlsDebugPrint, NULL );
535 mbedtls_debug_set_threshold( tlsDEBUG_VERBOSE );
536 #endif
537
538 if( 0 == xResult )
539 {
540 /* Set the resulting protocol configuration. */
541 xResult = mbedtls_ssl_setup( &pCtx->mbedSslCtx, &pCtx->mbedSslConfig );
542 }
543
544 /* Set the hostname, if requested. */
545 if( ( 0 == xResult ) && ( NULL != pCtx->pcDestination ) )
546 {
547 xResult = mbedtls_ssl_set_hostname( &pCtx->mbedSslCtx, pCtx->pcDestination );
548 }
549
550 /* Set the socket callbacks. */
551 if( 0 == xResult )
552 {
553 mbedtls_ssl_set_bio( &pCtx->mbedSslCtx,
554 pCtx,
555 prvNetworkSend,
556 prvNetworkRecv,
557 NULL );
558
559 /* Negotiate. */
560 while( 0 != ( xResult = mbedtls_ssl_handshake( &pCtx->mbedSslCtx ) ) )
561 {
562 if( ( MBEDTLS_ERR_SSL_WANT_READ != xResult ) &&
563 ( MBEDTLS_ERR_SSL_WANT_WRITE != xResult ) )
564 {
565 break;
566 }
567 }
568 }
569
570 /* Free up allocated memory. */
571 mbedtls_x509_crt_free( &pCtx->mbedX509CA );
572 mbedtls_x509_crt_free( &pCtx->mbedX509Cli );
573
574 return xResult;
575}
576
577/*-----------------------------------------------------------*/
578
579BaseType_t TLS_Recv( void * pvContext,
580 unsigned char * pucReadBuffer,
581 size_t xReadLength )
582{
583 BaseType_t xResult = 0;
584 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
585 size_t xRead = 0;
586
587 if( NULL != pCtx )
588 {
589 while( xRead < xReadLength )
590 {
591 xResult = mbedtls_ssl_read( &pCtx->mbedSslCtx,
592 pucReadBuffer + xRead,
593 xReadLength - xRead );
594
595 if( 0 < xResult )
596 {
597 /* Got data, so update the tally and keep looping. */
598 xRead += ( size_t ) xResult;
599 }
600 else
601 {
602 if( ( 0 == xResult ) || ( MBEDTLS_ERR_SSL_WANT_READ != xResult ) )
603 {
604 /* No data and no error or call read again, if indicated, otherwise return error. */
605 break;
606 }
607 }
608 }
609 }
610
611 if( 0 <= xResult )
612 {
613 xResult = ( BaseType_t ) xRead;
614 }
615
616 return xResult;
617}
618
619/*-----------------------------------------------------------*/
620
621BaseType_t TLS_Send( void * pvContext,
622 const unsigned char * pucMsg,
623 size_t xMsgLength )
624{
625 BaseType_t xResult = 0;
626 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
627 size_t xWritten = 0;
628
629 if( NULL != pCtx )
630 {
631 while( xWritten < xMsgLength )
632 {
633 xResult = mbedtls_ssl_write( &pCtx->mbedSslCtx,
634 pucMsg + xWritten,
635 xMsgLength - xWritten );
636
637 if( 0 < xResult )
638 {
639 /* Sent data, so update the tally and keep looping. */
640 xWritten += ( size_t ) xResult;
641 }
642 else
643 {
644 if( ( 0 == xResult ) || ( MBEDTLS_ERR_SSL_WANT_WRITE != xResult ) )
645 {
646 /* No data and no error or call read again, if indicated, otherwise return error. */
647 break;
648 }
649 }
650 }
651 }
652
653 if( 0 <= xResult )
654 {
655 xResult = ( BaseType_t ) xWritten;
656 }
657
658 return xResult;
659}
660
661/*-----------------------------------------------------------*/
662
663void TLS_Cleanup( void * pvContext )
664{
665 TLSContext_t * pCtx = ( TLSContext_t * ) pvContext; /*lint !e9087 !e9079 Allow casting void* to other types. */
666
667 if( NULL != pCtx )
668 {
669 /* Cleanup mbedTLS. */
670 mbedtls_ssl_close_notify( &pCtx->mbedSslCtx ); /*lint !e534 The error is already taken care of inside mbedtls_ssl_close_notify*/
671 mbedtls_ssl_free( &pCtx->mbedSslCtx );
672 mbedtls_ssl_config_free( &pCtx->mbedSslConfig );
673
674 /* Cleanup PKCS#11. */
675 if( ( NULL != pCtx->pxP11FunctionList ) &&
676 ( NULL != pCtx->pxP11FunctionList->C_CloseSession ) )
677 {
678 pCtx->pxP11FunctionList->C_CloseSession( pCtx->xP11Session ); /*lint !e534 This function always return CKR_OK. */
679 pCtx->pxP11FunctionList->C_Finalize( NULL ); /*lint !e534 This function always return CKR_OK. */
680 }
681
682 /* Free memory. */
683 vPortFree( pCtx );
684 }
685}