joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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 "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