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: mbed Socket lwip-eth lwip-sys lwip
Fork of mbed-client-classic-example-lwip 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 <string.h> 00022 00023 void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); 00024 int mbedtls_timing_get_delay( void *data ); 00025 int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen ); 00026 //Point these back to M2MConnectionHandler!!! 00027 int f_send( void *ctx, const unsigned char *buf, size_t len ); 00028 int f_recv(void *ctx, unsigned char *buf, size_t len); 00029 int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t some); 00030 00031 bool cancelled; 00032 00033 M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode) 00034 : _flags(0), 00035 _sec_mode(mode), 00036 _is_blocking(false) 00037 { 00038 _init_done = false; 00039 cancelled = true; 00040 _timmer = new M2MTimer(*this); 00041 mbedtls_ssl_init( &_ssl ); 00042 mbedtls_ssl_config_init( &_conf ); 00043 mbedtls_x509_crt_init( &_cacert ); 00044 mbedtls_x509_crt_init(&_owncert); 00045 mbedtls_pk_init(&_pkey); 00046 mbedtls_ctr_drbg_init( &_ctr_drbg ); 00047 mbedtls_entropy_init( &_entropy ); 00048 } 00049 00050 M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl(){ 00051 mbedtls_ssl_config_free(&_conf); 00052 mbedtls_ssl_free(&_ssl); 00053 mbedtls_x509_crt_free(&_cacert); 00054 mbedtls_x509_crt_free(&_owncert); 00055 mbedtls_pk_free(&_pkey); 00056 mbedtls_ctr_drbg_free( &_ctr_drbg ); 00057 mbedtls_entropy_free( &_entropy ); 00058 delete _timmer; 00059 } 00060 00061 void M2MConnectionSecurityPimpl::timer_expired(M2MTimerObserver::Type type){ 00062 if(type == M2MTimerObserver::Dtls && !cancelled && !_is_blocking){ 00063 int error = continue_connecting(); 00064 if(MBEDTLS_ERR_SSL_TIMEOUT == error) { 00065 if(_ssl.p_bio) { 00066 M2MConnectionHandler* ptr = (M2MConnectionHandler*)_ssl.p_bio; 00067 ptr->handle_connection_error(4); 00068 } 00069 } 00070 } else { 00071 if(_ssl.p_bio) { 00072 M2MConnectionHandler* ptr = (M2MConnectionHandler*)_ssl.p_bio; 00073 ptr->handle_connection_error(4); 00074 } 00075 } 00076 } 00077 00078 void M2MConnectionSecurityPimpl::reset(){ 00079 _init_done = false; 00080 cancelled = true; 00081 mbedtls_ssl_config_free(&_conf); 00082 mbedtls_ssl_free(&_ssl); 00083 mbedtls_x509_crt_free(&_cacert); 00084 mbedtls_x509_crt_free(&_owncert); 00085 mbedtls_pk_free(&_pkey); 00086 mbedtls_ctr_drbg_free( &_ctr_drbg ); 00087 mbedtls_entropy_free( &_entropy ); 00088 _timmer->stop_timer(); 00089 } 00090 00091 int M2MConnectionSecurityPimpl::init(const M2MSecurity *security){ 00092 int ret=-1; 00093 if( security != NULL ){ 00094 const char *pers = "dtls_client"; 00095 mbedtls_ssl_init( &_ssl ); 00096 mbedtls_ssl_config_init( &_conf ); 00097 mbedtls_x509_crt_init( &_cacert ); 00098 mbedtls_x509_crt_init(&_owncert); 00099 mbedtls_pk_init(&_pkey); 00100 mbedtls_ctr_drbg_init( &_ctr_drbg ); 00101 00102 mbedtls_entropy_init( &_entropy ); 00103 00104 uint8_t *serPub = 0; 00105 uint32_t serPubSize = security->resource_value_buffer(M2MSecurity::ServerPublicKey, serPub); 00106 00107 uint8_t *pubCert = 0; 00108 uint32_t pubCertSize = security->resource_value_buffer(M2MSecurity::PublicKey, pubCert); 00109 00110 uint8_t *secKey = 0; 00111 uint32_t secKeySize = security->resource_value_buffer(M2MSecurity::Secretkey, secKey); 00112 00113 00114 if( serPub == NULL || pubCert == NULL || secKey == NULL || 00115 serPubSize == 0 || pubCertSize == 0 || secKeySize == 0 ){ 00116 return -1; 00117 } 00118 00119 00120 if( mbedtls_entropy_add_source( &_entropy, entropy_poll, NULL, 00121 128, 0 ) < 0 ){ 00122 free(serPub); 00123 free(pubCert); 00124 free(secKey); 00125 return -1; 00126 } 00127 00128 if( ( ret = mbedtls_ctr_drbg_seed( &_ctr_drbg, mbedtls_entropy_func, &_entropy, 00129 (const unsigned char *) pers, 00130 strlen( pers ) ) ) != 0 ) 00131 { 00132 free(serPub); 00133 free(pubCert); 00134 free(secKey); 00135 return -1; 00136 } 00137 00138 int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; 00139 if( _sec_mode == M2MConnectionSecurity::TLS ){ 00140 mode = MBEDTLS_SSL_TRANSPORT_STREAM; 00141 } 00142 00143 if( ( ret = mbedtls_ssl_config_defaults( &_conf, 00144 MBEDTLS_SSL_IS_CLIENT, 00145 mode, 0 ) ) != 0 ) 00146 { 00147 free(serPub); 00148 free(pubCert); 00149 free(secKey); 00150 return -1; 00151 } 00152 00153 if( security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Certificate ){ 00154 00155 ret = mbedtls_x509_crt_parse( &_cacert, (const unsigned char *) serPub, 00156 serPubSize ); 00157 if( ret < 0 ) 00158 { 00159 free(serPub); 00160 free(pubCert); 00161 free(secKey); 00162 return -1; 00163 } 00164 00165 ret = mbedtls_x509_crt_parse( &_owncert, (const unsigned char *) pubCert, 00166 pubCertSize ); 00167 if( ret < 0 ) 00168 { 00169 00170 free(serPub); 00171 free(pubCert); 00172 free(secKey); 00173 return -1; 00174 } 00175 00176 ret = mbedtls_pk_parse_key(&_pkey, (const unsigned char *) secKey, secKeySize, NULL, 0); 00177 free(serPub); 00178 free(pubCert); 00179 free(secKey); 00180 00181 if( ret < 0 ) 00182 { 00183 return -1; 00184 } 00185 00186 mbedtls_ssl_conf_own_cert(&_conf, &_owncert, &_pkey); 00187 //TODO: use MBEDTLS_SSL_VERIFY_REQUIRED instead of optional 00188 //MBEDTLS_SSL_VERIFY_NONE to test without verification (was MBEDTLS_SSL_VERIFY_OPTIONAL) 00189 mbedtls_ssl_conf_authmode( &_conf, MBEDTLS_SSL_VERIFY_NONE ); 00190 mbedtls_ssl_conf_ca_chain( &_conf, &_cacert, NULL ); 00191 }else if(security->resource_value_int(M2MSecurity::SecurityMode) == M2MSecurity::Psk ){ 00192 ret = mbedtls_ssl_conf_psk(&_conf, secKey, secKeySize, pubCert, pubCertSize); 00193 mbedtls_ssl_conf_ciphersuites(&_conf, PSK_SUITES); 00194 free(serPub); 00195 free(pubCert); 00196 free(secKey); 00197 }else{ 00198 free(serPub); 00199 free(pubCert); 00200 free(secKey); 00201 } 00202 00203 if( ret >= 0 ){ 00204 _init_done = true; 00205 } 00206 } 00207 00208 return ret; 00209 } 00210 00211 int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler){ 00212 int ret=-1; 00213 if(!_init_done){ 00214 return ret; 00215 } 00216 00217 _is_blocking = true; 00218 00219 // This is for blocking sockets timeout happens once at 60 seconds 00220 mbedtls_ssl_conf_handshake_timeout( &_conf, 60000, 61000 ); 00221 mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); 00222 00223 if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) 00224 { 00225 return -1; 00226 } 00227 00228 //TODO: check is this needed 00229 // if( ( ret = mbedtls_ssl_set_hostname( &_ssl, "linux-secure-endpoint" ) ) != 0 ) 00230 // { 00231 // return -1; 00232 // } 00233 00234 mbedtls_ssl_set_bio( &_ssl, connHandler, 00235 f_send, f_recv, f_recv_timeout ); 00236 00237 mbedtls_ssl_set_timer_cb( &_ssl, _timmer, mbedtls_timing_set_delay, 00238 mbedtls_timing_get_delay ); 00239 00240 do ret = mbedtls_ssl_handshake( &_ssl ); 00241 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00242 ret == MBEDTLS_ERR_SSL_WANT_WRITE ); 00243 00244 if( ret != 0 ) 00245 { 00246 ret = -1; 00247 }else{ 00248 if( ( _flags = mbedtls_ssl_get_verify_result( &_ssl ) ) != 0 ) 00249 { 00250 ret = -1; 00251 } 00252 } 00253 return ret; 00254 } 00255 00256 int M2MConnectionSecurityPimpl::start_connecting_non_blocking(M2MConnectionHandler* connHandler) 00257 { 00258 int ret=-1; 00259 if(!_init_done){ 00260 return ret; 00261 } 00262 00263 _is_blocking = false; 00264 int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM; 00265 if( _sec_mode == M2MConnectionSecurity::TLS ){ 00266 mode = MBEDTLS_SSL_TRANSPORT_STREAM; 00267 } 00268 00269 if( ( ret = mbedtls_ssl_config_defaults( &_conf, 00270 MBEDTLS_SSL_IS_CLIENT, 00271 mode, 0 ) ) != 0 ) 00272 { 00273 return -1; 00274 } 00275 00276 // This is for non-blocking sockets total timeout is 1+2+4+8+16+29=60 seconds 00277 mbedtls_ssl_conf_handshake_timeout( &_conf, 10000, 29000 ); 00278 mbedtls_ssl_conf_rng( &_conf, mbedtls_ctr_drbg_random, &_ctr_drbg ); 00279 00280 if( ( ret = mbedtls_ssl_setup( &_ssl, &_conf ) ) != 0 ) 00281 { 00282 return -1; 00283 } 00284 00285 mbedtls_ssl_set_bio( &_ssl, connHandler, 00286 f_send, f_recv, f_recv_timeout ); 00287 00288 mbedtls_ssl_set_timer_cb( &_ssl, _timmer, mbedtls_timing_set_delay, 00289 mbedtls_timing_get_delay ); 00290 00291 ret = mbedtls_ssl_handshake_step( &_ssl ); 00292 if( ret == 0 ){ 00293 ret = mbedtls_ssl_handshake_step( &_ssl ); 00294 } 00295 00296 if( ret >= 0){ 00297 ret = 1; 00298 }else 00299 { 00300 ret = -1; 00301 } 00302 return ret; 00303 } 00304 00305 int M2MConnectionSecurityPimpl::continue_connecting() 00306 { 00307 int ret=-1; 00308 while( ret != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ){ 00309 ret = mbedtls_ssl_handshake_step( &_ssl ); 00310 if( MBEDTLS_ERR_SSL_WANT_READ == ret ){ 00311 ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ; 00312 } 00313 if(MBEDTLS_ERR_SSL_TIMEOUT == ret || 00314 MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO == ret || 00315 MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE == ret || 00316 MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST == ret || 00317 MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE == ret || 00318 MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE == ret || 00319 MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC == ret || 00320 MBEDTLS_ERR_SSL_BAD_HS_FINISHED == ret) { 00321 return MBEDTLS_ERR_SSL_TIMEOUT; 00322 } 00323 if( _ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){ 00324 return 0; 00325 } 00326 } 00327 return ret; 00328 } 00329 00330 int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len){ 00331 int ret=-1; 00332 if(!_init_done){ 00333 return ret; 00334 } 00335 00336 do ret = mbedtls_ssl_write( &_ssl, (unsigned char *) message, len ); 00337 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00338 ret == MBEDTLS_ERR_SSL_WANT_WRITE ); 00339 00340 return ret; //bytes written 00341 } 00342 00343 int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len){ 00344 int ret=-1; 00345 if(!_init_done){ 00346 return 0; 00347 } 00348 00349 memset( buffer, 0, len ); 00350 do ret = mbedtls_ssl_read( &_ssl, buffer, len-1 ); 00351 while( ret == MBEDTLS_ERR_SSL_WANT_READ || 00352 ret == MBEDTLS_ERR_SSL_WANT_WRITE ); 00353 00354 return ret; //bytes read 00355 } 00356 00357 int f_send( void *ctx, const unsigned char *buf, size_t len){ 00358 M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); 00359 return handler->send_to_socket(buf, len); 00360 } 00361 00362 int f_recv(void *ctx, unsigned char *buf, size_t len){ 00363 M2MConnectionHandler* handler = ((M2MConnectionHandler *) ctx); 00364 return handler->receive_from_socket(buf, len); 00365 } 00366 00367 int f_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t /*some*/){ 00368 return f_recv(ctx, buf, len); 00369 } 00370 00371 int entropy_poll( void *, unsigned char *output, size_t len, 00372 size_t *olen ) 00373 { 00374 srand(time(NULL)); 00375 char *c = (char*)malloc(len); 00376 memset(c, 0, len); 00377 for(uint16_t i=0; i < len; i++){ 00378 c[i] = rand() % 256; 00379 } 00380 memmove(output, c, len); 00381 *olen = len; 00382 00383 free(c); 00384 return( 0 ); 00385 } 00386 00387 void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ){ 00388 M2MTimer* timer = (M2MTimer*) data; 00389 if(!timer) { 00390 return; 00391 } 00392 if( int_ms > 0 && fin_ms > 0 ){ 00393 cancelled = false; 00394 timer->start_dtls_timer(int_ms, fin_ms); 00395 }else{ 00396 cancelled = true; 00397 timer->stop_timer(); 00398 } 00399 } 00400 00401 int mbedtls_timing_get_delay( void *data ){ 00402 M2MTimer* timer = (M2MTimer*) data; 00403 if(!timer){ 00404 return 0; 00405 } 00406 if(true == cancelled) { 00407 return -1; 00408 } else if( timer->is_total_interval_passed() ){ 00409 return 2; 00410 }else if( timer->is_intermediate_interval_passed() ){ 00411 return 1; 00412 }else{ 00413 return 0; 00414 } 00415 }
Generated on Tue Jul 12 2022 13:53:46 by
