Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ssl_cache.c Source File

ssl_cache.c

00001 /*
00002  *  SSL session cache implementation
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  * These session callbacks use a simple chained list
00023  * to store and retrieve the session information.
00024  */
00025 
00026 #if !defined(MBEDTLS_CONFIG_FILE)
00027 #include "mbedtls/config.h"
00028 #else
00029 #include MBEDTLS_CONFIG_FILE
00030 #endif
00031 
00032 #if defined(MBEDTLS_SSL_CACHE_C)
00033 
00034 #if defined(MBEDTLS_PLATFORM_C)
00035 #include "mbedtls/platform.h"
00036 #else
00037 #include <stdlib.h>
00038 #define mbedtls_calloc    calloc
00039 #define mbedtls_free      free
00040 #endif
00041 
00042 #include "mbedtls/ssl_cache.h"
00043 #include "mbedtls/ssl_internal.h"
00044 
00045 #include <string.h>
00046 
00047 void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )
00048 {
00049     memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );
00050 
00051     cache->timeout  = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
00052     cache->max_entries  = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
00053 
00054 #if defined(MBEDTLS_THREADING_C)
00055     mbedtls_mutex_init( &cache->mutex  );
00056 #endif
00057 }
00058 
00059 int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
00060 {
00061     int ret = 1;
00062 #if defined(MBEDTLS_HAVE_TIME)
00063     mbedtls_time_t t = mbedtls_time( NULL );
00064 #endif
00065     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
00066     mbedtls_ssl_cache_entry *cur, *entry;
00067 
00068 #if defined(MBEDTLS_THREADING_C)
00069     if( mbedtls_mutex_lock( &cache->mutex  ) != 0 )
00070         return( 1 );
00071 #endif
00072 
00073     cur = cache->chain ;
00074     entry = NULL;
00075 
00076     while( cur != NULL )
00077     {
00078         entry = cur;
00079         cur = cur->next ;
00080 
00081 #if defined(MBEDTLS_HAVE_TIME)
00082         if( cache->timeout  != 0 &&
00083             (int) ( t - entry->timestamp  ) > cache->timeout  )
00084             continue;
00085 #endif
00086 
00087         if( session->ciphersuite != entry->session .ciphersuite ||
00088             session->compression != entry->session .compression ||
00089             session->id_len != entry->session .id_len )
00090             continue;
00091 
00092         if( memcmp( session->id, entry->session .id,
00093                     entry->session .id_len ) != 0 )
00094             continue;
00095 
00096         ret = mbedtls_ssl_session_copy( session, &entry->session  );
00097         if( ret != 0 )
00098         {
00099             ret = 1;
00100             goto exit;
00101         }
00102 
00103 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
00104     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
00105         /*
00106          * Restore peer certificate (without rest of the original chain)
00107          */
00108         if( entry->peer_cert .p != NULL )
00109         {
00110             /* `session->peer_cert` is NULL after the call to
00111              * mbedtls_ssl_session_copy(), because cache entries
00112              * have the `peer_cert` field set to NULL. */
00113 
00114             if( ( session->peer_cert = mbedtls_calloc( 1,
00115                                  sizeof(mbedtls_x509_crt) ) ) == NULL )
00116             {
00117                 ret = 1;
00118                 goto exit;
00119             }
00120 
00121             mbedtls_x509_crt_init( session->peer_cert );
00122             if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert .p,
00123                                 entry->peer_cert .len ) != 0 )
00124             {
00125                 mbedtls_free( session->peer_cert );
00126                 session->peer_cert = NULL;
00127                 ret = 1;
00128                 goto exit;
00129             }
00130         }
00131 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
00132 
00133         ret = 0;
00134         goto exit;
00135     }
00136 
00137 exit:
00138 #if defined(MBEDTLS_THREADING_C)
00139     if( mbedtls_mutex_unlock( &cache->mutex  ) != 0 )
00140         ret = 1;
00141 #endif
00142 
00143     return( ret );
00144 }
00145 
00146 int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
00147 {
00148     int ret = 1;
00149 #if defined(MBEDTLS_HAVE_TIME)
00150     mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0;
00151     mbedtls_ssl_cache_entry *old = NULL;
00152 #endif
00153     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
00154     mbedtls_ssl_cache_entry *cur, *prv;
00155     int count = 0;
00156 
00157 #if defined(MBEDTLS_THREADING_C)
00158     if( ( ret = mbedtls_mutex_lock( &cache->mutex  ) ) != 0 )
00159         return( ret );
00160 #endif
00161 
00162     cur = cache->chain ;
00163     prv = NULL;
00164 
00165     while( cur != NULL )
00166     {
00167         count++;
00168 
00169 #if defined(MBEDTLS_HAVE_TIME)
00170         if( cache->timeout  != 0 &&
00171             (int) ( t - cur->timestamp  ) > cache->timeout  )
00172         {
00173             cur->timestamp  = t;
00174             break; /* expired, reuse this slot, update timestamp */
00175         }
00176 #endif
00177 
00178         if( memcmp( session->id, cur->session .id, cur->session .id_len ) == 0 )
00179             break; /* client reconnected, keep timestamp for session id */
00180 
00181 #if defined(MBEDTLS_HAVE_TIME)
00182         if( oldest == 0 || cur->timestamp  < oldest )
00183         {
00184             oldest = cur->timestamp ;
00185             old = cur;
00186         }
00187 #endif
00188 
00189         prv = cur;
00190         cur = cur->next ;
00191     }
00192 
00193     if( cur == NULL )
00194     {
00195 #if defined(MBEDTLS_HAVE_TIME)
00196         /*
00197          * Reuse oldest entry if max_entries reached
00198          */
00199         if( count >= cache->max_entries  )
00200         {
00201             if( old == NULL )
00202             {
00203                 ret = 1;
00204                 goto exit;
00205             }
00206 
00207             cur = old;
00208         }
00209 #else /* MBEDTLS_HAVE_TIME */
00210         /*
00211          * Reuse first entry in chain if max_entries reached,
00212          * but move to last place
00213          */
00214         if( count >= cache->max_entries  )
00215         {
00216             if( cache->chain  == NULL )
00217             {
00218                 ret = 1;
00219                 goto exit;
00220             }
00221 
00222             cur = cache->chain ;
00223             cache->chain  = cur->next ;
00224             cur->next  = NULL;
00225             prv->next  = cur;
00226         }
00227 #endif /* MBEDTLS_HAVE_TIME */
00228         else
00229         {
00230             /*
00231              * max_entries not reached, create new entry
00232              */
00233             cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) );
00234             if( cur == NULL )
00235             {
00236                 ret = 1;
00237                 goto exit;
00238             }
00239 
00240             if( prv == NULL )
00241                 cache->chain  = cur;
00242             else
00243                 prv->next  = cur;
00244         }
00245 
00246 #if defined(MBEDTLS_HAVE_TIME)
00247         cur->timestamp  = t;
00248 #endif
00249     }
00250 
00251 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
00252     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
00253     /*
00254      * If we're reusing an entry, free its certificate first
00255      */
00256     if( cur->peer_cert .p != NULL )
00257     {
00258         mbedtls_free( cur->peer_cert .p );
00259         memset( &cur->peer_cert , 0, sizeof(mbedtls_x509_buf) );
00260     }
00261 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
00262 
00263     /* Copy the entire session; this temporarily makes a copy of the
00264      * X.509 CRT structure even though we only want to store the raw CRT.
00265      * This inefficiency will go away as soon as we implement on-demand
00266      * parsing of CRTs, in which case there's no need for the `peer_cert`
00267      * field anymore in the first place, and we're done after this call. */
00268     ret = mbedtls_ssl_session_copy( &cur->session , session );
00269     if( ret != 0 )
00270     {
00271         ret = 1;
00272         goto exit;
00273     }
00274 
00275 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
00276     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
00277     /* If present, free the X.509 structure and only store the raw CRT data. */
00278     if( cur->session .peer_cert != NULL )
00279     {
00280         cur->peer_cert .p =
00281             mbedtls_calloc( 1, cur->session .peer_cert->raw.len );
00282         if( cur->peer_cert .p == NULL )
00283         {
00284             ret = 1;
00285             goto exit;
00286         }
00287 
00288         memcpy( cur->peer_cert .p,
00289                 cur->session .peer_cert->raw.p,
00290                 cur->session .peer_cert->raw.len );
00291         cur->peer_cert .len = session->peer_cert->raw.len;
00292 
00293         mbedtls_x509_crt_free( cur->session .peer_cert );
00294         mbedtls_free( cur->session .peer_cert );
00295         cur->session .peer_cert = NULL;
00296     }
00297 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
00298 
00299     ret = 0;
00300 
00301 exit:
00302 #if defined(MBEDTLS_THREADING_C)
00303     if( mbedtls_mutex_unlock( &cache->mutex  ) != 0 )
00304         ret = 1;
00305 #endif
00306 
00307     return( ret );
00308 }
00309 
00310 #if defined(MBEDTLS_HAVE_TIME)
00311 void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout )
00312 {
00313     if( timeout < 0 ) timeout = 0;
00314 
00315     cache->timeout  = timeout;
00316 }
00317 #endif /* MBEDTLS_HAVE_TIME */
00318 
00319 void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max )
00320 {
00321     if( max < 0 ) max = 0;
00322 
00323     cache->max_entries  = max;
00324 }
00325 
00326 void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
00327 {
00328     mbedtls_ssl_cache_entry *cur, *prv;
00329 
00330     cur = cache->chain ;
00331 
00332     while( cur != NULL )
00333     {
00334         prv = cur;
00335         cur = cur->next ;
00336 
00337         mbedtls_ssl_session_free( &prv->session  );
00338 
00339 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
00340     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
00341         mbedtls_free( prv->peer_cert .p );
00342 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
00343 
00344         mbedtls_free( prv );
00345     }
00346 
00347 #if defined(MBEDTLS_THREADING_C)
00348     mbedtls_mutex_free( &cache->mutex  );
00349 #endif
00350     cache->chain  = NULL;
00351 }
00352 
00353 #endif /* MBEDTLS_SSL_CACHE_C */