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.
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 21:20:26 by
