leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_TLS.c Source File

pal_plat_TLS.c

00001 /*******************************************************************************
00002  * Copyright 2016, 2017 ARM Ltd.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *******************************************************************************/
00016 #include "pal.h"
00017 #include "pal_plat_TLS.h"
00018 #include "mbedtls/ssl.h"
00019 #include "mbedtls/entropy.h"
00020 #include "mbedtls/ctr_drbg.h"
00021 #include "mbedtls/ssl_internal.h"
00022 
00023 
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #define TRACE_GROUP "PAL"
00028 
00029 #define SSL_LIB_SUCCESS 0
00030 
00031 #if PAL_USE_SECURE_TIME
00032 #include "platform_time.h"
00033 PAL_PRIVATE mbedtls_time_t g_timeFromHS = 0;
00034 PAL_PRIVATE palMutexID_t g_palTLSTimeMutex = NULLPTR;
00035 #ifdef MBEDTLS_PLATFORM_TIME_ALT
00036 PAL_PRIVATE mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer);
00037 #endif
00038 #endif //PAL_USE_SECURE_TIME
00039 
00040 #if defined(MBEDTLS_DEBUG_C)
00041 //! Add forward declaration for the function from mbedTLS
00042 void mbedtls_debug_set_threshold( int threshold );
00043 #endif
00044 
00045 
00046 typedef mbedtls_ssl_context platTlsContext;
00047 typedef mbedtls_ssl_config platTlsConfiguraionContext;
00048 
00049 PAL_PRIVATE mbedtls_entropy_context *g_entropy = NULL;
00050 PAL_PRIVATE bool g_entropyInitiated = false;
00051 
00052 typedef struct palTimingDelayContext
00053 {
00054     uint64_t                              start_ticks;
00055     uint32_t                              int_ms;
00056     uint32_t                              fin_ms;
00057 } palTimingDelayContext_t;
00058 
00059 
00060 //! the full structures will be defined later in the implemetation.
00061 typedef struct palTLS {
00062     platTlsContext tlsCtx;
00063     bool tlsInit;
00064     char* psk; //NULL terminated
00065     char* identity; //NULL terminated
00066     bool wantReadOrWrite;
00067 }palTLS_t;
00068 
00069 
00070 //! the full structures will be defined later in the implemetation.
00071 typedef struct palTLSConf {
00072     platTlsConfiguraionContext*  confCtx;
00073     palTLSSocketHandle_t palIOCtx; // which will be used as bio context for mbedTLS
00074     palTLS_t* tlsContext; // to help us to get the index of the containing palTLS_t in the array. will be updated in the init
00075                           // maybe we need to make this an array, since index can be shared for more than one TLS context
00076     mbedtls_ctr_drbg_context ctrDrbg;
00077     palTimingDelayContext_t timerCtx;
00078 #if (PAL_ENABLE_X509 == 1)
00079     mbedtls_x509_crt owncert;
00080     mbedtls_x509_crt cacert;
00081 #endif
00082     mbedtls_pk_context pkey;
00083     bool hasKeys;
00084     bool hasChain;
00085     int cipherSuites[PAL_MAX_ALLOWED_CIPHER_SUITES + 1];  // The +1 is for the Zero Termination required by mbedTLS
00086 }palTLSConf_t;
00087 
00088 
00089 
00090 
00091 
00092 
00093 PAL_PRIVATE palStatus_t translateTLSErrToPALError(int32_t error)
00094 {
00095     palStatus_t status;
00096     switch(error)
00097     {
00098         case SSL_LIB_SUCCESS:
00099             status = PAL_ERR_END_OF_FILE ;
00100             break;
00101         case MBEDTLS_ERR_SSL_WANT_READ:
00102             status = PAL_ERR_TLS_WANT_READ;
00103             break;
00104         case MBEDTLS_ERR_SSL_WANT_WRITE:
00105             status = PAL_ERR_TLS_WANT_WRITE;
00106             break;
00107         case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
00108             status = PAL_ERR_TLS_HELLO_VERIFY_REQUIRED;
00109             break;
00110         case MBEDTLS_ERR_SSL_TIMEOUT:
00111             status = PAL_ERR_TIMEOUT_EXPIRED ;
00112             break;
00113         case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
00114             status = PAL_ERR_TLS_BAD_INPUT_DATA;
00115             break;
00116         case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
00117             status = PAL_ERR_TLS_CLIENT_RECONNECT;
00118             break;
00119         case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
00120             status = PAL_ERR_TLS_PEER_CLOSE_NOTIFY;
00121             break;
00122 #if (PAL_ENABLE_X509 == 1)
00123         case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
00124             status = PAL_ERR_X509_CERT_VERIFY_FAILED;
00125             break;
00126 #endif
00127         case MBEDTLS_ERR_X509_ALLOC_FAILED:
00128         case MBEDTLS_ERR_SSL_ALLOC_FAILED:
00129         case MBEDTLS_ERR_PK_ALLOC_FAILED:
00130         case MBEDTLS_ERR_MD_ALLOC_FAILED:
00131         case MBEDTLS_ERR_ECP_ALLOC_FAILED:
00132         case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
00133         case MBEDTLS_ERR_MPI_ALLOC_FAILED:
00134             status = PAL_ERR_NO_MEMORY ;
00135             break;
00136 
00137         default:
00138             // Caller prints out error
00139             status = PAL_ERR_GENERIC_FAILURE ;
00140     }
00141     return status;
00142 
00143 }
00144 
00145 
00146 PAL_PRIVATE palStatus_t translateTLSHandShakeErrToPALError(palTLS_t* tlsCtx, int32_t error)
00147 {
00148     palStatus_t status;
00149     switch(error)
00150     {
00151         case SSL_LIB_SUCCESS:
00152             status = PAL_SUCCESS;
00153             tlsCtx->wantReadOrWrite = false;
00154             break;
00155         case MBEDTLS_ERR_SSL_WANT_READ:
00156             status = PAL_ERR_TLS_WANT_READ;
00157             tlsCtx->wantReadOrWrite = true;
00158             break;
00159         case MBEDTLS_ERR_SSL_WANT_WRITE:
00160             status = PAL_ERR_TLS_WANT_WRITE;
00161             tlsCtx->wantReadOrWrite = true;
00162             break;
00163         case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
00164             status = PAL_ERR_TLS_HELLO_VERIFY_REQUIRED;
00165             break;
00166         case MBEDTLS_ERR_SSL_TIMEOUT:
00167             status = PAL_ERR_TIMEOUT_EXPIRED ;
00168             break;
00169         case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
00170             status = PAL_ERR_TLS_PEER_CLOSE_NOTIFY;
00171             break;
00172         case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
00173             status = PAL_ERR_TLS_CLIENT_RECONNECT;
00174             break;
00175 #if (PAL_ENABLE_X509 == 1)
00176         case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
00177             status = PAL_ERR_X509_CERT_VERIFY_FAILED;
00178             break;
00179 #endif
00180         case MBEDTLS_ERR_X509_ALLOC_FAILED:
00181         case MBEDTLS_ERR_SSL_ALLOC_FAILED:
00182         case MBEDTLS_ERR_PK_ALLOC_FAILED:
00183         case MBEDTLS_ERR_MD_ALLOC_FAILED:
00184         case MBEDTLS_ERR_ECP_ALLOC_FAILED:
00185         case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
00186         case MBEDTLS_ERR_MPI_ALLOC_FAILED:
00187             status = PAL_ERR_NO_MEMORY ;
00188             break;
00189 
00190         default:
00191             PAL_LOG_ERR("SSL handshake return code 0x%" PRIx32 ".", error);
00192             status = PAL_ERR_GENERIC_FAILURE ;
00193 
00194     }
00195     return status;
00196 }
00197 
00198 //! Forward declaration
00199 PAL_PRIVATE int palBIORecv_timeout(palTLSSocketHandle_t socket, unsigned char *buf, size_t len, uint32_t timeout);
00200 PAL_PRIVATE int palBIORecv(palTLSSocketHandle_t socket, unsigned char *buf, size_t len);
00201 PAL_PRIVATE int palBIOSend(palTLSSocketHandle_t socket, const unsigned char *buf, size_t len);
00202 PAL_PRIVATE void palDebug(void *ctx, int debugLevel, const char *fileName, int line, const char *message);
00203 int pal_plat_entropySourceTLS( void *data, unsigned char *output, size_t len, size_t *olen );
00204 PAL_PRIVATE int palTimingGetDelay( void *data );
00205 PAL_PRIVATE void palTimingSetDelay( void *data, uint32_t intMs, uint32_t finMs );
00206 
00207 palStatus_t pal_plat_initTLSLibrary(void)
00208 {
00209     palStatus_t status = PAL_SUCCESS;
00210 
00211     g_entropy = (mbedtls_entropy_context*)malloc(sizeof(mbedtls_entropy_context));
00212     if (NULL == g_entropy)
00213     {
00214         status = PAL_ERR_NO_MEMORY ;
00215         goto finish;
00216     }
00217     else
00218     {
00219         mbedtls_entropy_init(g_entropy);
00220         g_entropyInitiated = false;
00221     }
00222 
00223 #if PAL_USE_SECURE_TIME
00224     #ifdef MBEDTLS_PLATFORM_TIME_ALT
00225         // this scope is here to keep warnings away from gotos which skip over variable initialization
00226         {
00227             int32_t platStatus = SSL_LIB_SUCCESS;
00228             platStatus = mbedtls_platform_set_time(pal_mbedtlsTimeCB);
00229             if (SSL_LIB_SUCCESS != platStatus)
00230             {
00231                 status = PAL_ERR_FAILED_SET_TIME_CB;
00232                 goto finish;
00233             }
00234         }
00235     #endif //MBEDTLS_PLATFORM_TIME_ALT
00236         status = pal_osMutexCreate(&g_palTLSTimeMutex);
00237         if(PAL_SUCCESS != status)
00238         {
00239             PAL_LOG_ERR("Failed to Create TLS time Mutex error: %" PRId32 ".", status);
00240         }
00241 #endif //PAL_USE_SECURE_TIME
00242 finish:
00243     return status;
00244 }
00245 
00246 
00247 palStatus_t pal_plat_cleanupTLS(void)
00248 {
00249     palStatus_t status = PAL_SUCCESS;
00250     if(g_entropy != NULL)
00251     {
00252         mbedtls_entropy_free(g_entropy);
00253     }
00254     g_entropyInitiated = false;
00255     free(g_entropy);
00256     g_entropy = NULL;
00257 
00258 #if PAL_USE_SECURE_TIME
00259     //! Try to catch the Mutex in order to prevent situation of deleteing under use mutex
00260     status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
00261     if (PAL_SUCCESS != status)
00262     {
00263         PAL_LOG_ERR("Failed to get TLS time Mutex error: %" PRId32 ".", status);
00264     }
00265 
00266     status = pal_osMutexRelease(g_palTLSTimeMutex);
00267     if (PAL_SUCCESS != status)
00268     {
00269         PAL_LOG_ERR("Failed to release TLS time Mutex error: %" PRId32 ".", status);
00270     }
00271 
00272     status = pal_osMutexDelete(&g_palTLSTimeMutex);
00273     if(PAL_SUCCESS != status)
00274     {
00275         PAL_LOG_ERR("Failed to Delete TLS time Mutex");
00276     }
00277 #endif //PAL_USE_SECURE_TIME
00278     return status;
00279 }
00280 
00281 
00282 palStatus_t pal_plat_addEntropySource(palEntropySource_f entropyCallback)
00283 {
00284     palStatus_t status = PAL_SUCCESS;
00285     int32_t platStatus = SSL_LIB_SUCCESS;
00286 
00287     if (NULL == entropyCallback)
00288     {
00289         return PAL_ERR_INVALID_ARGUMENT ;
00290     }
00291 
00292     if (!g_entropyInitiated)
00293     {
00294         platStatus = mbedtls_entropy_add_source(g_entropy, entropyCallback, NULL, PAL_INITIAL_RANDOM_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG );
00295         if (SSL_LIB_SUCCESS != platStatus)
00296         {
00297             status = PAL_ERR_TLS_CONFIG_INIT;
00298         }
00299         else
00300         {
00301             g_entropyInitiated = true;
00302         }
00303 
00304     }
00305 
00306     return status;
00307 }
00308 
00309 
00310 palStatus_t pal_plat_initTLSConf(palTLSConfHandle_t* palConfCtx, palTLSTransportMode_t transportVersion, palDTLSSide_t methodType)
00311 {
00312     palStatus_t status = PAL_SUCCESS;
00313     palTLSConf_t* localConfigCtx = NULL;
00314     int32_t platStatus = SSL_LIB_SUCCESS;
00315     int32_t endpoint = 0;
00316     int32_t transport = 0;
00317 
00318     if (NULLPTR == palConfCtx)
00319     {
00320         return PAL_ERR_INVALID_ARGUMENT ;
00321     }
00322 
00323     localConfigCtx = (palTLSConf_t*)malloc(sizeof(palTLSConf_t));
00324     if (NULL == localConfigCtx)
00325     {
00326         status = PAL_ERR_NO_MEMORY ;
00327         goto finish;
00328     }
00329 
00330     localConfigCtx->confCtx = (platTlsConfiguraionContext*)malloc(sizeof(platTlsConfiguraionContext));
00331     if (NULL == localConfigCtx->confCtx)
00332     {
00333         status = PAL_ERR_NO_MEMORY ;
00334         goto finish;
00335     }
00336     localConfigCtx->tlsContext = NULL;
00337     localConfigCtx->hasKeys = false;
00338     localConfigCtx->hasChain = false;
00339     memset(localConfigCtx->cipherSuites, 0,(sizeof(int)* (PAL_MAX_ALLOWED_CIPHER_SUITES+1)) );
00340     mbedtls_ssl_config_init(localConfigCtx->confCtx);
00341 
00342 #if (PAL_ENABLE_X509 == 1)
00343     mbedtls_x509_crt_init(&localConfigCtx->owncert);
00344     mbedtls_x509_crt_init(&localConfigCtx->cacert);
00345 #endif
00346 
00347     if (PAL_TLS_IS_CLIENT == methodType)
00348     {
00349         endpoint = MBEDTLS_SSL_IS_CLIENT;
00350     }
00351     else
00352     {
00353         endpoint = MBEDTLS_SSL_IS_SERVER;
00354     }
00355 
00356     if (PAL_TLS_MODE == transportVersion)
00357     {
00358         transport = MBEDTLS_SSL_TRANSPORT_STREAM;
00359     }
00360     else
00361     {
00362         transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
00363     }
00364     platStatus = mbedtls_ssl_config_defaults(localConfigCtx->confCtx, endpoint, transport, MBEDTLS_SSL_PRESET_DEFAULT);
00365     if (SSL_LIB_SUCCESS != platStatus)
00366     {
00367         PAL_LOG_ERR("TLS Init conf status %" PRId32 ".", platStatus);
00368         status = PAL_ERR_TLS_CONFIG_INIT;
00369         goto finish;
00370     }
00371 
00372     mbedtls_ctr_drbg_init(&localConfigCtx->ctrDrbg);
00373     status = pal_plat_addEntropySource(pal_plat_entropySourceTLS);
00374     if (PAL_SUCCESS != status)
00375     {
00376         goto finish;
00377     }
00378 
00379     platStatus = mbedtls_ctr_drbg_seed(&localConfigCtx->ctrDrbg, mbedtls_entropy_func, g_entropy, NULL, 0); //Custom data can be defined in
00380                                                                                           //pal_TLS.h header and to be defined by
00381                                                                                           //Service code. But we need to check if other platform support this
00382                                                                                           //input!
00383     if (SSL_LIB_SUCCESS != platStatus)
00384     {
00385         status = PAL_ERR_TLS_CONFIG_INIT;
00386         goto finish;
00387     }
00388 
00389     mbedtls_ssl_conf_rng(localConfigCtx->confCtx, mbedtls_ctr_drbg_random, &localConfigCtx->ctrDrbg);
00390     *palConfCtx = (uintptr_t)localConfigCtx;
00391 
00392 finish:
00393     if (PAL_SUCCESS != status && NULL != localConfigCtx)
00394     {
00395         if (NULL != localConfigCtx->confCtx)
00396         {
00397             free(localConfigCtx->confCtx);
00398         }
00399         free(localConfigCtx);
00400         *palConfCtx = NULLPTR;
00401     }
00402     return status;
00403 }
00404 
00405 
00406 palStatus_t pal_plat_tlsConfigurationFree(palTLSConfHandle_t* palTLSConf)
00407 {
00408     palStatus_t status = PAL_SUCCESS;
00409     palTLSConf_t* localConfigCtx = NULL;
00410 
00411     if (NULLPTR == palTLSConf || NULLPTR == *palTLSConf)
00412     {
00413         return PAL_ERR_INVALID_ARGUMENT ;
00414     }
00415 
00416     localConfigCtx = (palTLSConf_t*)*palTLSConf;
00417 
00418     if (true == localConfigCtx->hasKeys)
00419     {
00420         mbedtls_pk_free(&localConfigCtx->pkey);
00421 #if (PAL_ENABLE_X509 == 1)
00422         mbedtls_x509_crt_free(&localConfigCtx->owncert);
00423     }
00424 
00425     if (true == localConfigCtx->hasChain)
00426     {
00427         mbedtls_x509_crt_free(&localConfigCtx->cacert);
00428 #endif
00429     }
00430 
00431     mbedtls_ssl_config_free(localConfigCtx->confCtx);
00432     mbedtls_ctr_drbg_free(&localConfigCtx->ctrDrbg);
00433 
00434     free(localConfigCtx->confCtx);
00435 
00436     memset(localConfigCtx, 0, sizeof(palTLSConf_t));
00437     free(localConfigCtx);
00438     *palTLSConf = NULLPTR;
00439     return status;
00440 }
00441 
00442 
00443 palStatus_t pal_plat_initTLS(palTLSConfHandle_t palTLSConf, palTLSHandle_t* palTLSHandle)
00444 {
00445     palStatus_t status = PAL_SUCCESS;
00446     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00447 
00448     palTLS_t* localTLSHandle = (palTLS_t*)malloc( sizeof(palTLS_t));
00449     if (NULL == localTLSHandle)
00450     {
00451         status = PAL_ERR_TLS_RESOURCE;
00452         goto finish;
00453     }
00454 
00455     memset(localTLSHandle, 0 , sizeof(palTLS_t));
00456     mbedtls_ssl_init(&localTLSHandle->tlsCtx);
00457     localConfigCtx->tlsContext = localTLSHandle;
00458     localTLSHandle->tlsInit = true;
00459     mbedtls_ssl_set_timer_cb(&localTLSHandle->tlsCtx, &localConfigCtx->timerCtx, palTimingSetDelay, palTimingGetDelay);
00460     *palTLSHandle = (palTLSHandle_t)localTLSHandle;
00461 
00462 finish:
00463     return status;
00464 }
00465 
00466 
00467 palStatus_t pal_plat_freeTLS(palTLSHandle_t* palTLSHandle)
00468 {
00469     palStatus_t status = PAL_SUCCESS;
00470     palTLS_t* localTLSCtx = NULL;
00471 
00472     localTLSCtx = (palTLS_t*)*palTLSHandle;
00473     if (false == localTLSCtx->tlsInit)
00474     {
00475         status = PAL_ERR_TLS_CONTEXT_NOT_INITIALIZED;
00476         goto finish;
00477     }
00478 
00479 
00480     mbedtls_ssl_free(&localTLSCtx->tlsCtx);
00481     free(localTLSCtx);
00482     *palTLSHandle = NULLPTR;
00483 
00484 finish:
00485     return status;
00486 }
00487 
00488 
00489 palStatus_t pal_plat_setAuthenticationMode(palTLSConfHandle_t sslConf, palTLSAuthMode_t authMode)
00490 {
00491     palStatus_t status = PAL_SUCCESS;
00492     int32_t platAuthMode;
00493     palTLSConf_t* localConfigCtx = (palTLSConf_t*)sslConf;
00494 
00495     switch(authMode)
00496     {
00497         case PAL_TLS_VERIFY_NONE:
00498             platAuthMode = MBEDTLS_SSL_VERIFY_NONE;
00499             break;
00500         case PAL_TLS_VERIFY_OPTIONAL:
00501             platAuthMode = MBEDTLS_SSL_VERIFY_OPTIONAL;
00502             break;
00503         case PAL_TLS_VERIFY_REQUIRED:
00504             platAuthMode = MBEDTLS_SSL_VERIFY_REQUIRED;
00505             break;
00506         default:
00507             status = PAL_ERR_INVALID_ARGUMENT ;
00508             goto finish;
00509     };
00510     mbedtls_ssl_conf_authmode(localConfigCtx->confCtx, platAuthMode );
00511 
00512 finish:
00513     return status;
00514 }
00515 
00516 palStatus_t pal_plat_setCipherSuites(palTLSConfHandle_t sslConf, palTLSSuites_t palSuite)
00517 {
00518     palStatus_t status = PAL_SUCCESS;
00519     palTLSConf_t* localConfigCtx = (palTLSConf_t*)sslConf;
00520 
00521     switch(palSuite)
00522     {
00523         case PAL_TLS_PSK_WITH_AES_128_CCM_8:
00524             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8;
00525             break;
00526         case PAL_TLS_PSK_WITH_AES_256_CCM_8:
00527             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8;
00528             break;
00529         case PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
00530             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
00531             break;
00532         case PAL_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
00533             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
00534             break;
00535         case PAL_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
00536             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
00537             break;
00538 #ifdef MBEDTLS_ARIA_C
00539         case PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:
00540             localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256;
00541             break;
00542 #endif
00543         default:
00544             localConfigCtx->cipherSuites[0] = 0;
00545             status = PAL_ERR_TLS_INVALID_CIPHER;
00546             goto finish;
00547     }
00548 
00549     mbedtls_ssl_conf_ciphersuites(localConfigCtx->confCtx, localConfigCtx->cipherSuites);
00550 finish:
00551     return status;
00552 }
00553 
00554 palStatus_t pal_plat_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult)
00555 {
00556     palStatus_t status = PAL_SUCCESS;
00557     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00558     int32_t platStatus = SSL_LIB_SUCCESS;
00559     *verifyResult = 0;
00560 
00561     platStatus = mbedtls_ssl_get_verify_result(&localTLSCtx->tlsCtx);
00562     if (SSL_LIB_SUCCESS != platStatus)
00563     {
00564         status = PAL_ERR_X509_CERT_VERIFY_FAILED;
00565 #if (PAL_ENABLE_X509 == 1)
00566         //! please DO NOT change errors order
00567         if (MBEDTLS_X509_BADCERT_NOT_TRUSTED & platStatus)
00568         {
00569             *verifyResult |= PAL_ERR_X509_BADCERT_NOT_TRUSTED;
00570             status = PAL_ERR_X509_BADCERT_NOT_TRUSTED;
00571         }
00572         if (MBEDTLS_X509_BADCERT_BAD_KEY & platStatus)
00573         {
00574             *verifyResult |= PAL_ERR_X509_BADCERT_BAD_KEY;
00575             status = PAL_ERR_X509_BADCERT_BAD_KEY;
00576         }
00577         if (MBEDTLS_X509_BADCERT_BAD_PK & platStatus)
00578         {
00579             *verifyResult |= PAL_ERR_X509_BADCERT_BAD_PK;
00580             status = PAL_ERR_X509_BADCERT_BAD_PK;
00581         }
00582         if (MBEDTLS_X509_BADCERT_BAD_MD & platStatus)
00583         {
00584             *verifyResult |= PAL_ERR_X509_BADCERT_BAD_MD;
00585             status = PAL_ERR_X509_BADCERT_BAD_MD;
00586         }
00587         if (MBEDTLS_X509_BADCERT_FUTURE & platStatus)
00588         {
00589             *verifyResult |= PAL_ERR_X509_BADCERT_FUTURE;
00590             status = PAL_ERR_X509_BADCERT_FUTURE;
00591         }
00592         if (MBEDTLS_X509_BADCERT_EXPIRED & platStatus)
00593         {
00594             *verifyResult |= PAL_ERR_X509_BADCERT_EXPIRED;
00595             status = PAL_ERR_X509_BADCERT_EXPIRED;
00596         }
00597 #endif
00598     }
00599     return status;
00600 }
00601 
00602 palStatus_t pal_plat_sslRead(palTLSHandle_t palTLSHandle, void *buffer, uint32_t len, uint32_t* actualLen)
00603 {
00604     palStatus_t status = PAL_SUCCESS;
00605     int32_t platStatus = SSL_LIB_SUCCESS;
00606     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00607 
00608     platStatus = mbedtls_ssl_read(&localTLSCtx->tlsCtx, (unsigned char*)buffer, len);
00609     if (platStatus > SSL_LIB_SUCCESS)
00610     {
00611         *actualLen = platStatus;
00612     }
00613     else
00614     {
00615         status = translateTLSErrToPALError(platStatus);
00616         if (MBEDTLS_ERR_SSL_WANT_READ != platStatus)
00617         {
00618             PAL_LOG_ERR("SSL Read return code %" PRId32 ".", platStatus);
00619         }
00620         else
00621         {
00622             PAL_LOG_DBG("SSL Read return code %" PRId32 ".", platStatus);
00623         }
00624     }
00625 
00626     return status;
00627 }
00628 
00629 
00630 palStatus_t pal_plat_sslWrite(palTLSHandle_t palTLSHandle, const void *buffer, uint32_t len, uint32_t *bytesWritten)
00631 {
00632     palStatus_t status = PAL_SUCCESS;
00633     int32_t platStatus = SSL_LIB_SUCCESS;
00634     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00635 
00636     platStatus = mbedtls_ssl_write(&localTLSCtx->tlsCtx, (unsigned char*)buffer, len);
00637     if (platStatus > SSL_LIB_SUCCESS)
00638     {
00639         *bytesWritten = platStatus;
00640     }
00641     else
00642     {
00643         status = translateTLSErrToPALError(platStatus);
00644         if (MBEDTLS_ERR_SSL_WANT_WRITE != platStatus)
00645         {
00646             PAL_LOG_ERR("SSL Write platform return code %" PRId32 ".", platStatus);
00647         }
00648         else
00649         {
00650             PAL_LOG_DBG("SSL Write platform return code %" PRId32 ".", platStatus);
00651         }
00652     }
00653 
00654     return status;
00655 }
00656 
00657 
00658 palStatus_t pal_plat_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t timeoutInMilliSec)
00659 {
00660     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00661     uint32_t minTimeout = PAL_DTLS_PEER_MIN_TIMEOUT;
00662     uint32_t maxTimeout = timeoutInMilliSec >> 1; //! faster dividing by 2
00663     //! Since mbedTLS algorithm for UDP handshake algorithm is as follow:
00664     //! wait 'minTimeout' ..=> 'minTimeout = 2*minTimeout' while 'minTimeout < maxTimeout'
00665     //! if 'minTimeout >= maxTimeout' them wait 'maxTimeout'.
00666     //! The whole waiting time is the sum of the different intervals waited.
00667     //! Therefore we need divide the 'timeoutInMilliSec' by 2 to give a close approximation of the desired 'timeoutInMilliSec'
00668     //! 1 + 2 + ... + 'timeoutInMilliSec/2' ~= 'timeoutInMilliSec'
00669 
00670     if (maxTimeout < PAL_DTLS_PEER_MIN_TIMEOUT)
00671     {
00672         minTimeout = (timeoutInMilliSec+1) >> 1; //to prevent 'minTimeout == 0'
00673         maxTimeout = timeoutInMilliSec;
00674     }
00675 
00676     mbedtls_ssl_conf_handshake_timeout(localConfigCtx->confCtx, minTimeout, maxTimeout);
00677 
00678     return PAL_SUCCESS;
00679 }
00680 
00681 
00682 palStatus_t pal_plat_sslSetup(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf)
00683 {
00684     palStatus_t status = PAL_SUCCESS;
00685     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00686     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00687     int32_t platStatus = SSL_LIB_SUCCESS;
00688 
00689     if (!localTLSCtx->wantReadOrWrite)
00690     {
00691         platStatus = mbedtls_ssl_setup(&localTLSCtx->tlsCtx, localConfigCtx->confCtx);
00692         if (SSL_LIB_SUCCESS != platStatus)
00693         {
00694             PAL_LOG_ERR("SSL setup return code %" PRId32 ".", platStatus);
00695             if (MBEDTLS_ERR_SSL_ALLOC_FAILED == platStatus)
00696             {
00697                 status = PAL_ERR_NO_MEMORY ;
00698                 goto finish;
00699             }
00700             status = PAL_ERR_GENERIC_FAILURE ;
00701             goto finish;
00702         }
00703 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && (PAL_MAX_FRAG_LEN > 0)
00704         platStatus = mbedtls_ssl_conf_max_frag_len(localConfigCtx->confCtx, PAL_MAX_FRAG_LEN);
00705         if (SSL_LIB_SUCCESS != platStatus)
00706         {
00707             PAL_LOG_ERR("SSL fragment setup error code %" PRId32 ".", platStatus);
00708             if (MBEDTLS_ERR_SSL_BAD_INPUT_DATA == platStatus)
00709             {
00710                 status = PAL_ERR_TLS_BAD_INPUT_DATA;
00711                 goto finish;
00712             }
00713             status = PAL_ERR_TLS_INIT;
00714             goto finish;
00715         }
00716 #endif // #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
00717         localConfigCtx->tlsContext = localTLSCtx;
00718     }
00719 finish:
00720     return status;
00721 }
00722 
00723 palStatus_t pal_plat_handShake(palTLSHandle_t palTLSHandle, uint64_t* serverTime)
00724 {
00725     palStatus_t status = PAL_SUCCESS;
00726     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00727     int32_t platStatus = SSL_LIB_SUCCESS;
00728 
00729     while( (MBEDTLS_SSL_HANDSHAKE_OVER != localTLSCtx->tlsCtx.state) && (PAL_SUCCESS == status) )
00730     {
00731         platStatus = mbedtls_ssl_handshake_step( &localTLSCtx->tlsCtx );
00732 
00733         /* Extract the first 4 bytes of the ServerHello random */
00734         if( MBEDTLS_SSL_SERVER_HELLO_DONE == localTLSCtx->tlsCtx.state )
00735         {
00736             *serverTime = (uint64_t)
00737                 ( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 0] << 24 ) |
00738                 ( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 1] << 16 ) |
00739                 ( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 2] << 8  ) |
00740                 ( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 3] << 0  );
00741         }
00742         if (SSL_LIB_SUCCESS != platStatus)
00743         {
00744             status = translateTLSHandShakeErrToPALError(localTLSCtx, platStatus);
00745         }
00746     }
00747     return status;
00748 }
00749 
00750 #if PAL_USE_SECURE_TIME
00751 palStatus_t pal_plat_renegotiate(palTLSHandle_t palTLSHandle, uint64_t serverTime)
00752 {
00753     palStatus_t status = PAL_SUCCESS;
00754     palStatus_t mutexStatus = PAL_SUCCESS;
00755     palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
00756     int32_t platStatus = SSL_LIB_SUCCESS;
00757 
00758     status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
00759     if (PAL_SUCCESS != status)
00760     {
00761         PAL_LOG_ERR("Failed to get TLS time Mutex error: %" PRId32 ".", status);
00762         goto finish;
00763     }
00764 
00765 
00766     if (0 == g_timeFromHS)
00767     {
00768         g_timeFromHS = (mbedtls_time_t)serverTime;
00769     }
00770     else
00771     { //! need to change the code for multi-threading mode (Erez)
00772         status = PAL_ERR_TLS_MULTIPLE_HANDSHAKE;
00773         goto finish;
00774     }
00775 
00776     platStatus = mbedtls_ssl_renegotiate(&localTLSCtx->tlsCtx);
00777     status = translateTLSHandShakeErrToPALError(localTLSCtx, platStatus);
00778 
00779 finish:
00780     g_timeFromHS = 0;
00781 
00782     mutexStatus = pal_osMutexRelease(g_palTLSTimeMutex);
00783     if (PAL_SUCCESS != mutexStatus)
00784     {
00785         PAL_LOG_ERR("Failed to get TLS time Mutex error: %" PRId32 ".", mutexStatus);
00786     }
00787     if (PAL_SUCCESS == status)
00788     {
00789         status = mutexStatus;
00790     }
00791 
00792     return status;
00793 }
00794 #endif //PAL_USE_SECURE_TIME
00795 
00796 
00797 #if (PAL_ENABLE_X509 == 1)
00798 palStatus_t pal_plat_setOwnCertAndPrivateKey(palTLSConfHandle_t palTLSConf, palX509_t* ownCert, palPrivateKey_t* privateKey)
00799 {
00800     palStatus_t status = PAL_SUCCESS;
00801     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00802     int32_t platStatus = SSL_LIB_SUCCESS;
00803 
00804     mbedtls_pk_init(&localConfigCtx->pkey);
00805 
00806 
00807     platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->owncert, (const unsigned char *)ownCert->buffer, ownCert->size);
00808     if (SSL_LIB_SUCCESS != platStatus)
00809     {
00810         status = PAL_ERR_TLS_FAILED_TO_PARSE_CERT;
00811         goto finish;
00812     }
00813 
00814     platStatus = mbedtls_pk_parse_key(&localConfigCtx->pkey, (const unsigned char *)privateKey->buffer, privateKey->size, NULL, 0 );
00815     if (SSL_LIB_SUCCESS != platStatus)
00816     {
00817         status = PAL_ERR_TLS_FAILED_TO_PARSE_KEY;
00818         goto finish;
00819     }
00820 
00821     platStatus = mbedtls_ssl_conf_own_cert(localConfigCtx->confCtx, &localConfigCtx->owncert, &localConfigCtx->pkey);
00822     if (SSL_LIB_SUCCESS != platStatus)
00823     {
00824         status = PAL_ERR_TLS_FAILED_TO_SET_CERT;
00825     }
00826 
00827     localConfigCtx->hasKeys = true;
00828 
00829 finish:
00830     PAL_LOG_DBG("TLS set and parse status %" PRIu32 ".", platStatus);
00831     return status;
00832 }
00833 
00834 palStatus_t pal_plat_setOwnPrivateKey(palTLSConfHandle_t palTLSConf, palPrivateKey_t* privateKey)
00835 {
00836     palStatus_t status = PAL_SUCCESS;
00837     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00838     int32_t platStatus = SSL_LIB_SUCCESS;
00839 
00840     mbedtls_pk_init(&localConfigCtx->pkey);
00841 
00842     platStatus = mbedtls_pk_parse_key(&localConfigCtx->pkey, (const unsigned char *)privateKey->buffer, privateKey->size, NULL, 0 );
00843     if (SSL_LIB_SUCCESS != platStatus)
00844     {
00845         status = PAL_ERR_TLS_FAILED_TO_PARSE_KEY;
00846         goto finish;
00847     }
00848 
00849 
00850     localConfigCtx->hasKeys = true;
00851 
00852 finish:
00853     PAL_LOG_DBG("Privatekey set and parse status %" PRIu32 ".", platStatus);
00854     return status;
00855 }
00856 
00857 palStatus_t pal_plat_setOwnCertChain(palTLSConfHandle_t palTLSConf, palX509_t* ownCert)
00858 {
00859     palStatus_t status = PAL_SUCCESS;
00860     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00861     int32_t platStatus = SSL_LIB_SUCCESS;
00862 
00863     platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->owncert, (const unsigned char *)ownCert->buffer, ownCert->size);
00864     if (SSL_LIB_SUCCESS != platStatus)
00865     {
00866         status = PAL_ERR_TLS_FAILED_TO_PARSE_CERT;
00867         goto finish;
00868     }
00869 
00870     platStatus = mbedtls_ssl_conf_own_cert(localConfigCtx->confCtx, &localConfigCtx->owncert, &localConfigCtx->pkey);
00871     if (SSL_LIB_SUCCESS != platStatus)
00872     {
00873         status = PAL_ERR_TLS_FAILED_TO_SET_CERT;
00874     }
00875 
00876     localConfigCtx->hasKeys = true;
00877 
00878 finish:
00879     PAL_LOG_DBG("Own cert chain set and parse status %" PRIu32 ".", platStatus);
00880     return status;
00881 }
00882 
00883 
00884 palStatus_t pal_plat_setCAChain(palTLSConfHandle_t palTLSConf, palX509_t* caChain, palX509CRL_t* caCRL)
00885 {
00886     palStatus_t status = PAL_SUCCESS;
00887     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00888     int32_t platStatus = SSL_LIB_SUCCESS;
00889 
00890     platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->cacert, (const unsigned char *)caChain->buffer, caChain->size);
00891     if (SSL_LIB_SUCCESS != platStatus)
00892     {
00893         PAL_LOG_ERR("TLS CA chain status %" PRId32 ".", platStatus);
00894         status = PAL_ERR_GENERIC_FAILURE ;
00895         goto finish;
00896     }
00897     mbedtls_ssl_conf_ca_chain(localConfigCtx->confCtx, &localConfigCtx->cacert, NULL );
00898 
00899     localConfigCtx->hasChain = true;
00900 finish:
00901     return status;
00902 }
00903 #endif
00904 
00905 #if (PAL_ENABLE_PSK == 1)
00906 palStatus_t pal_plat_setPSK(palTLSConfHandle_t palTLSConf, const unsigned char *identity, uint32_t maxIdentityLenInBytes, const unsigned char *psk, uint32_t maxPskLenInBytes)
00907 {
00908     palStatus_t status = PAL_SUCCESS;
00909     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00910     int32_t platStatus = SSL_LIB_SUCCESS;
00911 
00912     platStatus = mbedtls_ssl_conf_psk(localConfigCtx->confCtx, psk, maxPskLenInBytes, identity, maxIdentityLenInBytes);
00913     if (SSL_LIB_SUCCESS != platStatus)
00914     {
00915         if (MBEDTLS_ERR_SSL_ALLOC_FAILED == platStatus)
00916         {
00917             status = PAL_ERR_TLS_INIT;
00918             goto finish;
00919         }
00920         PAL_LOG_ERR("TLS set psk status %" PRId32 ".", platStatus);
00921         status = PAL_ERR_GENERIC_FAILURE ;
00922     }
00923 finish:
00924     return status;
00925 }
00926 
00927 #endif
00928 palStatus_t pal_plat_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* socket)
00929 {
00930     palStatus_t status = PAL_SUCCESS;
00931 
00932     status = pal_plat_sslSetIOCallBacks(palTLSConf, socket, palBIOSend, palBIORecv);
00933     return status;
00934 }
00935 
00936 palStatus_t pal_plat_sslSetIOCallBacks(palTLSConfHandle_t palTLSConf, palTLSSocket_t* palIOCtx, palBIOSend_f palBIOSend, palBIORecv_f palBIORecv)
00937 {
00938     palStatus_t status = PAL_SUCCESS;
00939     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00940     bool isNonBlocking = false;
00941 
00942     localConfigCtx->palIOCtx = palIOCtx;
00943 
00944     status = pal_isNonBlocking(palIOCtx->socket, &isNonBlocking);
00945     if (PAL_SUCCESS != status)
00946     {
00947         return status;
00948     }
00949 
00950     if (isNonBlocking)
00951     {
00952         mbedtls_ssl_set_bio(&localConfigCtx->tlsContext->tlsCtx, palIOCtx, palBIOSend, palBIORecv, NULL);
00953     }
00954     else
00955     {
00956         mbedtls_ssl_set_bio(&localConfigCtx->tlsContext->tlsCtx, palIOCtx, palBIOSend, NULL, palBIORecv_timeout);
00957     }
00958 
00959     return PAL_SUCCESS;
00960 }
00961 
00962 
00963 
00964 palStatus_t pal_plat_sslSetDebugging(palTLSConfHandle_t palTLSConf, uint8_t turnOn)
00965 {
00966     palStatus_t status = PAL_SUCCESS;
00967     palLogFunc_f func = NULL;
00968 #if defined(MBEDTLS_DEBUG_C)
00969     mbedtls_debug_set_threshold(PAL_TLS_DEBUG_THRESHOLD);
00970 #endif
00971 
00972     if (turnOn)
00973     {
00974         func = palDebug;
00975     }
00976     status = pal_plat_SetLoggingCb(palTLSConf, func, NULL);
00977     return  status;
00978 }
00979 
00980 palStatus_t pal_plat_SetLoggingCb(palTLSConfHandle_t palTLSConf, palLogFunc_f palLogFunction, void *logContext)
00981 {
00982     palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
00983 
00984     mbedtls_ssl_conf_dbg(localConfigCtx->confCtx, palLogFunction, logContext);
00985     return PAL_SUCCESS;
00986 }
00987 
00988 PAL_PRIVATE uint64_t palTimingGetTimer(uint64_t *start_ticks, int reset)
00989 {
00990     uint64_t delta_ms;
00991     uint64_t ticks = pal_osKernelSysTick();
00992 
00993     if (reset)
00994     {
00995         *start_ticks = ticks;
00996         delta_ms = 0;
00997     }
00998     else
00999     {
01000         delta_ms = pal_osKernelSysMilliSecTick(ticks - *start_ticks);
01001     }
01002 
01003     return delta_ms;
01004 }
01005 
01006 
01007 /*
01008  * Set delays to watch
01009  */
01010 PAL_PRIVATE void palTimingSetDelay( void *data, uint32_t intMs, uint32_t finMs )
01011 {
01012 
01013     palTimingDelayContext_t *ctx = data;
01014 
01015     ctx->int_ms = intMs;
01016     ctx->fin_ms = finMs;
01017 
01018     if( finMs != 0 )
01019     {
01020         (void) palTimingGetTimer( &ctx->start_ticks, 1 );
01021     }
01022 }
01023 
01024 /*
01025  * Get number of delays expired
01026  */
01027 PAL_PRIVATE int palTimingGetDelay( void *data )
01028 {
01029     int result = 0;
01030     palTimingDelayContext_t *ctx = data;
01031     uint64_t elapsed_ms;
01032 
01033     if( ctx->fin_ms == 0 )
01034     {
01035         result = -1;
01036         goto finish;
01037     }
01038 
01039     elapsed_ms = palTimingGetTimer( &ctx->start_ticks, 0 );
01040 
01041     if( elapsed_ms >= ctx->fin_ms )
01042     {
01043         result = 2;
01044         goto finish;
01045     }
01046 
01047     if( elapsed_ms >= ctx->int_ms )
01048     {
01049         result = 1;
01050         goto finish;
01051     }
01052 
01053 finish:
01054     return result;
01055 }
01056 
01057 
01058 int pal_plat_entropySourceTLS( void *data, unsigned char *output, size_t len, size_t *olen )
01059 {
01060     palStatus_t status = PAL_SUCCESS;
01061     (void)data;
01062 
01063     status = pal_osRandomBuffer((uint8_t*) output, len);
01064     if (PAL_SUCCESS == status)
01065     {
01066         if (NULL != olen)
01067         {
01068             *olen = len;
01069         }
01070         return 0;
01071     }
01072     else
01073     {
01074         return -1;
01075     }
01076 }
01077 
01078 PAL_PRIVATE int palBIOSend(palTLSSocketHandle_t socket, const unsigned char *buf, size_t len)
01079 {
01080     palStatus_t status = PAL_SUCCESS;
01081     size_t sentDataSize = 0;
01082     palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
01083 
01084     if (NULLPTR == socket)
01085     {
01086         status = -1;
01087         goto finish;
01088     }
01089 
01090     if (PAL_TLS_MODE == localSocket->transportationMode)
01091     {
01092         status = pal_send(localSocket->socket, buf, len, &sentDataSize);
01093     }
01094     else if (PAL_DTLS_MODE == localSocket->transportationMode)
01095     {
01096         #if defined(PAL_UDP_MTU_SIZE)
01097         if(len > PAL_UDP_MTU_SIZE) {
01098             len = PAL_UDP_MTU_SIZE;
01099         }
01100         #endif
01101         status = pal_sendTo(localSocket->socket, buf, len, localSocket->socketAddress, localSocket->addressLength, &sentDataSize);
01102     }
01103     else
01104     {
01105         PAL_LOG_ERR("TLS BIO send error");
01106         status = PAL_ERR_GENERIC_FAILURE ;
01107     }
01108     if (PAL_SUCCESS == status || PAL_ERR_NO_MEMORY  == status || PAL_ERR_SOCKET_WOULD_BLOCK  == status)
01109     {
01110         if (PAL_ERR_NO_MEMORY  == status)
01111         {
01112             PAL_LOG_DBG("Network module returned out of memory error, retrying..."); //Network module can return NO_MEMORY error since it was not able to allocate
01113                                                                                       //memory at this point of time. In this case we translate the error to WANT_WRITE
01114                                                                                       //in order to let the Network module retry to allocate the memory.
01115                                                                                       //In case of real out of memory the handshake timeout will break the handshake process.
01116         }
01117 
01118         if (0 != sentDataSize)
01119         {
01120             status = sentDataSize;
01121         }
01122         else
01123         {
01124             status = MBEDTLS_ERR_SSL_WANT_WRITE;
01125         }
01126     }
01127 finish:
01128     return status;
01129 }
01130 
01131 PAL_PRIVATE int palBIORecv(palTLSSocketHandle_t socket, unsigned char *buf, size_t len)
01132 {
01133     palStatus_t status = PAL_SUCCESS;
01134     size_t recievedDataSize = 0;
01135     palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
01136 
01137     if (NULLPTR == socket)
01138     {
01139         status = -1;
01140         goto finish;
01141     }
01142 
01143     if (PAL_TLS_MODE == localSocket->transportationMode)
01144     {
01145         status = pal_recv(localSocket->socket, buf, len, &recievedDataSize);
01146         if (PAL_SUCCESS == status)
01147         {
01148             status = recievedDataSize;
01149         }
01150         else if (PAL_ERR_SOCKET_WOULD_BLOCK  == status)
01151         {
01152             status = MBEDTLS_ERR_SSL_WANT_READ;
01153         }
01154     }
01155     else if (PAL_DTLS_MODE == localSocket->transportationMode)
01156     {
01157         #if defined(PAL_UDP_MTU_SIZE)
01158         if(len > PAL_UDP_MTU_SIZE) {
01159             len = PAL_UDP_MTU_SIZE;
01160         }
01161         #endif
01162         status = pal_receiveFrom(localSocket->socket, buf, len, localSocket->socketAddress, &localSocket->addressLength, &recievedDataSize);
01163         if (PAL_SUCCESS == status)
01164         {
01165             if (0 != recievedDataSize)
01166             {
01167                 status = recievedDataSize;
01168             }
01169             else
01170             {
01171                 status = MBEDTLS_ERR_SSL_WANT_READ;
01172             }
01173         }
01174         else if (PAL_ERR_SOCKET_WOULD_BLOCK  == status)
01175         {
01176             status = MBEDTLS_ERR_SSL_WANT_READ;
01177         }
01178     }
01179     else
01180     {
01181         PAL_LOG_ERR("TLS BIO recv error");
01182         status = PAL_ERR_GENERIC_FAILURE ;
01183     }
01184 
01185 finish:
01186     return status;
01187 }
01188 
01189 PAL_PRIVATE int palBIORecv_timeout(palTLSSocketHandle_t socket, unsigned char *buf, size_t len, uint32_t timeout)
01190 {
01191     palStatus_t status = PAL_SUCCESS;
01192     size_t recievedDataSize = 0;
01193     uint32_t localTimeOut = timeout;
01194     palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
01195     bool isNonBlocking = false;
01196 
01197     if (NULLPTR == socket)
01198     {
01199         status = -1;
01200         goto finish;
01201     }
01202 
01203     status = pal_isNonBlocking(localSocket->socket, &isNonBlocking);
01204     if (PAL_SUCCESS != status)
01205     {
01206         goto finish;
01207     }
01208 
01209     if (PAL_TLS_MODE == localSocket->transportationMode)
01210     {
01211         status = pal_recv(localSocket->socket, buf, len, &recievedDataSize);
01212         if (PAL_SUCCESS == status)
01213         {
01214             status = recievedDataSize;
01215         }
01216         else if (PAL_ERR_SOCKET_WOULD_BLOCK  == status)
01217         {
01218             status = MBEDTLS_ERR_SSL_WANT_READ;
01219         }
01220     }
01221     else if (PAL_DTLS_MODE == localSocket->transportationMode)
01222     {
01223         if (false == isNonBlocking) // timeout is relevant only if socket is blocking
01224         {
01225             status = pal_setSocketOptions(localSocket->socket, PAL_SO_RCVTIMEO, &localTimeOut, sizeof(localTimeOut));
01226             if (PAL_SUCCESS != status)
01227             {
01228                 goto finish;
01229             }
01230         }
01231 
01232         status = pal_receiveFrom(localSocket->socket, buf, len, localSocket->socketAddress, &localSocket->addressLength, &recievedDataSize);
01233 
01234         if (PAL_SUCCESS == status)
01235         {
01236             if (0 != recievedDataSize)
01237             {
01238                 status = recievedDataSize;
01239             }
01240             else
01241             {
01242                 status = MBEDTLS_ERR_SSL_WANT_READ;
01243             }
01244         }
01245         else if (PAL_ERR_SOCKET_WOULD_BLOCK  == status)
01246         {
01247             status = MBEDTLS_ERR_SSL_TIMEOUT;
01248         }
01249     }
01250     else
01251     {
01252         PAL_LOG_ERR("TLS BIO recv timeout error");
01253         status = PAL_ERR_GENERIC_FAILURE ;
01254     }
01255 
01256 finish:
01257     return status;
01258 }
01259 
01260 #if PAL_USE_SECURE_TIME
01261 #ifdef MBEDTLS_PLATFORM_TIME_ALT
01262 PAL_PRIVATE mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer)
01263 {
01264     palStatus_t status = PAL_SUCCESS;
01265     mbedtls_time_t mbedtlsTime = 0;
01266 
01267     status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
01268     if (PAL_SUCCESS != status)
01269     {
01270         PAL_LOG_ERR("Failed to get TLS time Mutex error: %" PRId32 ".", status);
01271         goto finish;
01272     }
01273 
01274     if (0 != g_timeFromHS)
01275     {
01276         mbedtlsTime = g_timeFromHS;
01277     }
01278     else
01279     {
01280         uint64_t currentTime = pal_osGetTime();
01281         //mbedtls_time_t is defined to time_t, so we can do a safe copy since till 2038 the value in currentTime is less than MAX_TIME_T_VALUE
01282         mbedtlsTime = (mbedtls_time_t)currentTime;
01283     }
01284     status = pal_osMutexRelease(g_palTLSTimeMutex);
01285     if (PAL_SUCCESS != status)
01286     {
01287         PAL_LOG_ERR("Failed to release TLS time Mutex error: %" PRId32 ".", status);
01288     }
01289 finish:
01290     if (PAL_SUCCESS != status)
01291     {
01292         mbedtlsTime = 0;
01293     }
01294     return mbedtlsTime;
01295 }
01296 #endif
01297 #endif //PAL_USE_SECURE_TIME
01298 
01299 PAL_PRIVATE void palDebug(void *ctx, int debugLevel, const char *fileName, int line, const char *message)
01300 {
01301     (void)ctx;
01302     PAL_LOG_DBG("%s: %d: %s", fileName, line, message);
01303 }
01304 
01305 #ifdef MBEDTLS_ENTROPY_NV_SEED
01306 int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
01307 {
01308     palStatus_t status = PAL_SUCCESS;
01309     status = pal_osRandomBuffer(buf, buf_len);
01310     if (PAL_SUCCESS != status)
01311     {
01312         return -1;
01313     }
01314     return 0;
01315 }
01316 
01317 int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len )
01318 {
01319     return 0;
01320 }
01321 #endif //MBEDTLS_ENTROPY_NV_SEED