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