Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
m2mconnectionsecuritypimpl.cpp
00001 /* 00002 * Copyright (c) 2015 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 "mbed-client/m2mconnectionhandler.h" 00018 #include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h" 00019 #include "mbed-client/m2mtimer.h" 00020 #include "mbed-client/m2msecurity.h" 00021 #include "mbed-trace/mbed_trace.h" 00022 #include "mbedtls/debug.h" 00023 #include <string.h> 00024 00025 #define TRACE_GROUP "mClt" 00026 00027 void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); 00028 int mbedtls_timing_get_delay( void *data ); 00029 int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ); 00030 //Point these back to M2MConnectionHandler!!! 00031 int f_send( void *ctx, const unsigned char *buf, size_t len ); 00032 int f_recv(void *ctx, unsigned char *buf, size_t len); 00033 int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t some); 00034 00035 bool cancelled; 00036 random_number_cb __random_number_callback; 00037 entropy_cb __entropy_callback; 00038 00039 //Comment out following define to enable tracing from mbedtls 00040 //#define ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS 00041 #ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS 00042 static void mbedtls_debug( void *ctx, int level, 00043 const char *file, int line, const char *str ) 00044 { 00045 ((void) level); 00046 tr_debug("%s", str); 00047 } 00048 00049 static int verify_cert_chains(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) 00050 { 00051 char buf[1024]; 00052 (void) data; 00053 00054 printf("\nVerifying certificate at depth %d:\n", depth); 00055 mbedtls_x509_crt_info(buf, sizeof (buf) - 1, " ", crt); 00056 printf("%s", buf); 00057 00058 if (*flags == 0) 00059 printf("No verification issue for this certificate\n"); 00060 else 00061 { 00062 mbedtls_x509_crt_verify_info(buf, sizeof (buf), " ! ", *flags); 00063 printf("%s\n", buf); 00064 } 00065 00066 return 0; 00067 } 00068 #endif 00069 00070 M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode) 00071 : _flags(0), 00072 _sec_mode(mode) 00073 { 00074 _init_done = false; 00075 cancelled = true; 00076 _timer = new M2MTimer(*this); 00077 mbedtls_ssl_init( &_ssl ); 00078 mbedtls_ssl_config_init( &_conf ); 00079 mbedtls_x509_crt_init( &_cacert ); 00080 mbedtls_x509_crt_init(&_owncert); 00081 mbedtls_pk_init(&_pkey); 00082 mbedtls_ctr_drbg_init( &_ctr_drbg ); 00083 mbedtls_entropy_init( &_entropy ); 00084 } 00085 00086 M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){ 00087 mbedtls_ssl_config_free(&_conf); 00088 mbedtls_ssl_free(&_ssl); 00089 mbedtls_x509_crt_free(&_cacert); 00090 mbedtls_x509_crt_free(&_owncert); 00091 mbedtls_pk_free(&_pkey); 00092 mbedtls_ctr_drbg_free( &_ctr_drbg ); 00093 mbedtls_entropy_free( &_entropy ); 00094 delete _timer; 00095 } 00096 00097 void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){ 00098 tr_debug("M2MConnectionSecurityPimpl::timer_expired"); 00099 if(type == M2MTimerObserver::Dtls && !cancelled){ 00100 int error = continue_connecting(); 00101 if(MBEDTLS_ERR_SSL_TIMEOUT == error || error == -1) { 00102 tr_error("M2MConnectionSecurityPimpl::timer_expired - handshake timeout"); 00103 if(_ssl.p_bio) { 00104 M2MConnectionHandler* ptr = (M2MConnectionHandler*)_ssl.p_bio; 00105 ptr->handle_connection_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR); 00106 } 00107 reset(); 00108 } 00109 } 00110 } 00111 00112 void M2MConnectionSecurityPimpl::reset(){ 00113 _init_done = false; 00114 cancelled = true; 00115 mbedtls_ssl_config_free(&_conf); 00116 mbedtls_ssl_free(&_ssl); 00117 mbedtls_x509_crt_free(&_cacert); 00118 mbedtls_x509_crt_free(&_owncert); 00119 mbedtls_pk_free(&_pkey); 00120 mbedtls_ctr_drbg_free( &_ctr_drbg ); 00121 mbedtls_entropy_free( &_entropy ); 00122 _timer->stop_timer(); 00123 } 00124 00125 int M2MConnectionSecurityPimpl::init(const M2MSecurity *security) 00126 { 00127 tr_debug("M2MConnectionSecurityPimpl::init"); 00128 int ret = -1; 00129 if (security != NULL) { 00130 const char *pers = "dtls_client"; 00131 mbedtls_ssl_init( &_ssl ); 00132 mbedtls_ssl_config_init( &_conf ); 00133 mbedtls_x509_crt_init( &_cacert ); 00134 mbedtls_x509_crt_init(&_owncert); 00135 mbedtls_pk_init(&_pkey); 00136 mbedtls_ctr_drbg_init( &_ctr_drbg ); 00137 mbedtls_entropy_init( &_entropy ); 00138 00139 int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; 00140 if( _sec_mode == M2MConnectionSecurity::TLS ){ 00141 mode = MBEDTLS_SSL_TRANSPORT_STREAM; 00142 } 00143 00144 if( mbedtls_entropy_add_source( &_entropy, entropy_poll, NULL, 00145 128, 0 ) < 0 ){ 00146 return -1; 00147 } 00148 if(__entropy_callback.entropy_source_ptr) { 00149 if( mbedtls_entropy_add_source( &_entropy, __entropy_callback.entropy_source_ptr, 00150 __entropy_callback.p_source,__entropy_callback.threshold, 00151 __entropy_callback.strong ) < 0 ){ 00152 return -1; 00153 } 00154 } 00155 00156 if( mbedtls_ctr_drbg_seed( &_ctr_drbg, mbedtls_entropy_func, &_entropy, 00157 (const unsigned char *) pers, 00158 strlen( pers ) ) != 0 ) { 00159 return -1; 00160 } 00161 00162 if( mbedtls_ssl_config_defaults( &_conf, 00163 MBEDTLS_SSL_IS_CLIENT, 00164 mode, 0 ) != 0 ) { 00165 return -1; 00166 } 00167 00168 M2MSecurity::SecurityModeType cert_mode = 00169 (M2MSecurity::SecurityModeType)security->resource_value_int(M2MSecurity::SecurityMode); 00170 00171 // Note: these are relatively large buffers, no point to make copy of them here as mbedtls will make a copy of them. 00172 const uint8_t *srv_public_key = NULL; 00173 const uint8_t *public_key = NULL; 00174 const uint8_t *sec_key = NULL; 00175 00176 uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key); 00177 uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key); 00178 uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key); 00179 if( srv_public_key == NULL || public_key == NULL || sec_key == NULL || 00180 srv_public_key_size == 0 || public_key_size == 0 || sec_key_size == 0 ){ 00181 return -1; 00182 } 00183 00184 if( cert_mode == M2MSecurity::Certificate ){ 00185 if ( mbedtls_x509_crt_parse( &_cacert, (const unsigned char *) srv_public_key, 00186 srv_public_key_size + 1) < 0 || 00187 mbedtls_x509_crt_parse( &_owncert, (const unsigned char *) public_key, 00188 public_key_size + 1) < 0 || 00189 mbedtls_pk_parse_key(&_pkey, (const unsigned char *) sec_key, 00190 sec_key_size + 1, NULL, 0 ) < 0 ) { 00191 ret = -1; 00192 } else { 00193 ret = 0; 00194 } 00195 00196 if ( ret == 0 ) { 00197 mbedtls_ssl_conf_own_cert(&_conf, &_owncert, &_pkey); 00198 mbedtls_ssl_conf_authmode( &_conf, MBEDTLS_SSL_VERIFY_REQUIRED ); 00199 mbedtls_ssl_conf_ca_chain( &_conf, &_cacert, NULL ); 00200 } 00201 00202 } else if ( cert_mode == M2MSecurity::Psk ){ 00203 if (mbedtls_ssl_conf_psk(&_conf, sec_key, sec_key_size, public_key, public_key_size) == 0) { 00204 ret = 0; 00205 } 00206 mbedtls_ssl_conf_ciphersuites(&_conf, PSK_SUITES); 00207 } else { 00208 ret = -1; 00209 } 00210 00211 #ifdef ENABLE_MBED_CLIENT_MBED_TLS_DEBUGS 00212 mbedtls_ssl_conf_dbg( &_conf, mbedtls_debug, stdout ); 00213 mbedtls_debug_set_threshold(5); 00214 mbedtls_ssl_conf_verify(&_conf, verify_cert_chains, NULL); 00215 #endif 00216 } 00217 00218 if( ret == 0 ){ 00219 _init_done = true; 00220 } 00221 tr_debug("M2MConnectionSecurityPimpl::init - ret %d", ret); 00222 return ret; 00223 } 00224 00225 00226 int M2MConnectionSecurityPimpl::start_handshake(){ 00227 tr_debug("M2MConnectionSecurityPimpl::start_handshake"); 00228 int ret = -1; 00229 do 00230 { 00231 ret = mbedtls_ssl_handshake( &_ssl ); 00232 } 00233 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00234 ret == MBEDTLS_ERR_SSL_WANT_WRITE); 00235 00236 if( ret != 0 ) { 00237 ret = -1; 00238 }else { 00239 if( ( _flags = mbedtls_ssl_get_verify_result( &_ssl ) ) != 0 ) { 00240 ret = -1; 00241 } 00242 } 00243 tr_debug("M2MConnectionSecurityPimpl::start_handshake - OUT"); 00244 return ret; 00245 } 00246 00247 int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){ 00248 00249 tr_debug("M2MConnectionSecurityPimpl::connect"); 00250 int ret=-1; 00251 if(!_init_done){ 00252 return ret; 00253 } 00254 00255 mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); 00256 00257 if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) { 00258 return -1; 00259 } 00260 00261 mbedtls_ssl_set_bio( &_ssl, connHandler, 00262 f_send, f_recv, f_recv_timeout ); 00263 00264 mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay, 00265 mbedtls_timing_get_delay ); 00266 00267 ret = start_handshake(); 00268 _timer->stop_timer(); 00269 tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d, ssl state: %d", ret, _ssl.state); 00270 return ret; 00271 } 00272 00273 int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler) 00274 { 00275 tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking"); 00276 int ret=-1; 00277 if(!_init_done){ 00278 return ret; 00279 } 00280 00281 int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; 00282 if( _sec_mode == M2MConnectionSecurity::TLS ){ 00283 mode = MBEDTLS_SSL_TRANSPORT_STREAM; 00284 } 00285 00286 if( ( ret = mbedtls_ssl_config_defaults( &_conf, 00287 MBEDTLS_SSL_IS_CLIENT, 00288 mode, 0 ) ) != 0 ) 00289 { 00290 return -1; 00291 } 00292 00293 // This is for non-blocking sockets total timeout is 1+2+4+8+16+29=60 seconds 00294 mbedtls_ssl_conf_handshake_timeout( &_conf, 10000, 29000 ); 00295 mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); 00296 00297 if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) 00298 { 00299 return -1; 00300 } 00301 00302 mbedtls_ssl_set_bio( &_ssl, connHandler, 00303 f_send, f_recv, f_recv_timeout ); 00304 00305 mbedtls_ssl_set_timer_cb( &_ssl, _timer, mbedtls_timing_set_delay, 00306 mbedtls_timing_get_delay ); 00307 00308 ret = mbedtls_ssl_handshake_step( &_ssl ); 00309 if( ret == 0 ){ 00310 ret = mbedtls_ssl_handshake_step( &_ssl ); 00311 } 00312 00313 if( ret >= 0){ 00314 ret = 1; 00315 } else { 00316 ret = -1; 00317 } 00318 tr_debug("M2MConnectionSecurityPimpl::start_connecting_non_blocking - handshake ret: %d, ssl state: %d", ret, _ssl.state); 00319 return ret; 00320 } 00321 00322 int M2MConnectionSecurityPimpl::continue_connecting() 00323 { 00324 tr_debug("M2MConnectionSecurityPimpl::continue_connecting"); 00325 int ret=-1; 00326 while( ret != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ ){ 00327 ret = mbedtls_ssl_handshake_step( &_ssl ); 00328 if( MBEDTLS_ERR_SSL_WANT_READ == ret ){ 00329 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00330 } 00331 else if (ret != 0) { 00332 break; 00333 } 00334 00335 if( _ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){ 00336 return 0; 00337 } 00338 } 00339 tr_debug("M2MConnectionSecurityPimpl::continue_connecting, ret: %d", ret); 00340 return ret; 00341 } 00342 00343 int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){ 00344 tr_debug("M2MConnectionSecurityPimpl::send_message"); 00345 int ret=-1; 00346 if(!_init_done){ 00347 return ret; 00348 } 00349 00350 do ret = mbedtls_ssl_write( &_ssl, (unsigned char *) message, len ); 00351 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00352 ret == MBEDTLS_ERR_SSL_WANT_WRITE ); 00353 00354 tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret); 00355 return ret; //bytes written 00356 } 00357 00358 int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){ 00359 int ret=-1; 00360 if(!_init_done){ 00361 tr_error("M2MConnectionSecurityPimpl::read - init not done!"); 00362 return ret; 00363 } 00364 00365 memset( buffer, 0, len ); 00366 do ret = mbedtls_ssl_read( &_ssl, buffer, len-1 ); 00367 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00368 ret == MBEDTLS_ERR_SSL_WANT_WRITE ); 00369 00370 return ret; //bytes read 00371 } 00372 00373 int f_send( void *ctx, const unsigned char *buf, size_t len){ 00374 M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); 00375 return handler->send_to_socket(buf, len); 00376 } 00377 00378 int f_recv(void *ctx, unsigned char *buf, size_t len){ 00379 M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); 00380 return handler->receive_from_socket(buf, len); 00381 } 00382 00383 int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t /*some*/){ 00384 return f_recv(ctx, buf, len); 00385 } 00386 00387 int entropy_poll( void *, unsigned char *output, size_t len, 00388 size_t *olen ) 00389 { 00390 uint32_t rdm = 0; 00391 if(__random_number_callback) { 00392 rdm = __random_number_callback(); 00393 } else { 00394 rdm = time(NULL); 00395 } 00396 for(uint16_t i=0; i < len; i++){ 00397 srand(rdm); 00398 output[i] = rand() % 256; 00399 } 00400 *olen = len; 00401 00402 return( 0 ); 00403 } 00404 00405 void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ){ 00406 tr_debug("mbedtls_timing_set_delay - intermediate: %d", int_ms); 00407 tr_debug("mbedtls_timing_set_delay - final: %d", fin_ms); 00408 M2MTimer* timer = static_cast<M2MTimer*> (data); 00409 if(!timer) { 00410 return; 00411 } 00412 if( int_ms > 0 && fin_ms > 0 ){ 00413 tr_debug("mbedtls_timing_set_delay - start"); 00414 cancelled = false; 00415 timer->stop_timer(); 00416 timer->start_dtls_timer(int_ms, fin_ms); 00417 }else{ 00418 tr_debug("mbedtls_timing_set_delay - stop"); 00419 cancelled = true; 00420 timer->stop_timer(); 00421 } 00422 } 00423 00424 int mbedtls_timing_get_delay( void *data ){ 00425 tr_debug("mbedtls_timing_get_delay"); 00426 M2MTimer* timer = static_cast<M2MTimer*> (data); 00427 if(!timer){ 00428 return 0; 00429 } 00430 if(true == cancelled) { 00431 tr_debug("mbedtls_timing_get_delay - ret -1"); 00432 return -1; 00433 } else if( timer->is_total_interval_passed() ){ 00434 tr_debug("mbedtls_timing_get_delay - ret 2"); 00435 return 2; 00436 }else if( timer->is_intermediate_interval_passed() ){ 00437 tr_debug("mbedtls_timing_get_delay - ret 1"); 00438 return 1; 00439 }else{ 00440 tr_debug("mbedtls_timing_get_delay - ret 0"); 00441 return 0; 00442 } 00443 } 00444 00445 void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback) 00446 { 00447 __random_number_callback = callback; 00448 } 00449 00450 void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback) 00451 { 00452 __entropy_callback = callback; 00453 } 00454
Generated on Tue Jul 12 2022 12:28:36 by
