Austin Blackstone / Mbed 2 deprecated mbed-client-classic-example-lwip

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of mbed-client-classic-example-lwip by sandbox

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mconnectionsecuritypimpl.cpp Source File

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 }