Simple interface for Mbed Cloud Client

Dependents:  

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