blob: d34bc3d636af7ef286fde8b694c7558cb4ae75b2 [file] [log] [blame]
Paul Bakker0a597072012-09-25 21:55:46 +00001/*
2 * SSL session cache implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker0a597072012-09-25 21:55:46 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker0a597072012-09-25 21:55:46 +000020 */
21/*
22 * These session callbacks use a simple chained list
23 * to store and retrieve the session information.
24 */
25
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000027#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020028#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#endif
Paul Bakker0a597072012-09-25 21:55:46 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_SSL_CACHE_C)
Paul Bakker0a597072012-09-25 21:55:46 +000033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020036#else
Rich Evans00ab4702015-02-06 13:43:58 +000037#include <stdlib.h>
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020038#define mbedtls_calloc calloc
SimonBd5800b72016-04-26 07:43:27 +010039#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020040#endif
41
SimonBd5800b72016-04-26 07:43:27 +010042#include "mbedtls/ssl_cache.h"
43
44#include <string.h>
45
Ron Eldore1a9a4a2017-10-17 18:15:41 +030046/* Implementation that should never be optimized out by the compiler */
47static void mbedtls_zeroize( void *v, size_t n ) {
48 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
49}
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )
Paul Bakker0a597072012-09-25 21:55:46 +000052{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053 memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );
Paul Bakker0a597072012-09-25 21:55:46 +000054
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055 cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
56 cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
Paul Bakkerc5598842013-09-28 15:01:27 +020057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_THREADING_C)
59 mbedtls_mutex_init( &cache->mutex );
Paul Bakkerc5598842013-09-28 15:01:27 +020060#endif
Paul Bakker0a597072012-09-25 21:55:46 +000061}
62
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
Paul Bakker0a597072012-09-25 21:55:46 +000064{
Paul Bakkerc5598842013-09-28 15:01:27 +020065 int ret = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066#if defined(MBEDTLS_HAVE_TIME)
SimonBd5800b72016-04-26 07:43:27 +010067 mbedtls_time_t t = mbedtls_time( NULL );
Paul Bakkerfa9b1002013-07-03 15:31:03 +020068#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069 mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
70 mbedtls_ssl_cache_entry *cur, *entry;
Paul Bakker0a597072012-09-25 21:55:46 +000071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#if defined(MBEDTLS_THREADING_C)
73 if( mbedtls_mutex_lock( &cache->mutex ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +020074 return( 1 );
75#endif
76
Paul Bakker0a597072012-09-25 21:55:46 +000077 cur = cache->chain;
78 entry = NULL;
79
80 while( cur != NULL )
81 {
82 entry = cur;
83 cur = cur->next;
84
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker0a597072012-09-25 21:55:46 +000086 if( cache->timeout != 0 &&
87 (int) ( t - entry->timestamp ) > cache->timeout )
88 continue;
Paul Bakkerfa9b1002013-07-03 15:31:03 +020089#endif
Paul Bakker0a597072012-09-25 21:55:46 +000090
91 if( session->ciphersuite != entry->session.ciphersuite ||
92 session->compression != entry->session.compression ||
Manuel Pégourié-Gonnard12ad7982015-06-18 15:50:37 +020093 session->id_len != entry->session.id_len )
Paul Bakker0a597072012-09-25 21:55:46 +000094 continue;
95
96 if( memcmp( session->id, entry->session.id,
Manuel Pégourié-Gonnard12ad7982015-06-18 15:50:37 +020097 entry->session.id_len ) != 0 )
Paul Bakker0a597072012-09-25 21:55:46 +000098 continue;
99
100 memcpy( session->master, entry->session.master, 48 );
Paul Bakkere81beda2013-03-06 17:40:46 +0100101
Manuel Pégourié-Gonnard38d1eba2013-08-23 10:44:29 +0200102 session->verify_result = entry->session.verify_result;
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104#if defined(MBEDTLS_X509_CRT_PARSE_C)
Paul Bakkere81beda2013-03-06 17:40:46 +0100105 /*
106 * Restore peer certificate (without rest of the original chain)
107 */
108 if( entry->peer_cert.p != NULL )
109 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200110 if( ( session->peer_cert = mbedtls_calloc( 1,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 sizeof(mbedtls_x509_crt) ) ) == NULL )
Paul Bakkerc5598842013-09-28 15:01:27 +0200112 {
113 ret = 1;
114 goto exit;
115 }
Paul Bakkere81beda2013-03-06 17:40:46 +0100116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 mbedtls_x509_crt_init( session->peer_cert );
118 if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p,
Paul Bakkerddf26b42013-09-18 13:46:23 +0200119 entry->peer_cert.len ) != 0 )
Paul Bakkere81beda2013-03-06 17:40:46 +0100120 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_free( session->peer_cert );
Paul Bakkere81beda2013-03-06 17:40:46 +0100122 session->peer_cert = NULL;
Paul Bakkerc5598842013-09-28 15:01:27 +0200123 ret = 1;
124 goto exit;
Paul Bakkere81beda2013-03-06 17:40:46 +0100125 }
126 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127#endif /* MBEDTLS_X509_CRT_PARSE_C */
Paul Bakkere81beda2013-03-06 17:40:46 +0100128
Paul Bakkerc5598842013-09-28 15:01:27 +0200129 ret = 0;
130 goto exit;
Paul Bakker0a597072012-09-25 21:55:46 +0000131 }
132
Paul Bakkerc5598842013-09-28 15:01:27 +0200133exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134#if defined(MBEDTLS_THREADING_C)
135 if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +0200136 ret = 1;
137#endif
138
139 return( ret );
Paul Bakker0a597072012-09-25 21:55:46 +0000140}
141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
Paul Bakker0a597072012-09-25 21:55:46 +0000143{
Paul Bakkerc5598842013-09-28 15:01:27 +0200144 int ret = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145#if defined(MBEDTLS_HAVE_TIME)
Simon Butchera55e0842017-07-28 23:46:43 +0100146 mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_ssl_cache_entry *old = NULL;
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200148#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
150 mbedtls_ssl_cache_entry *cur, *prv;
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000151 int count = 0;
Paul Bakker0a597072012-09-25 21:55:46 +0000152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153#if defined(MBEDTLS_THREADING_C)
154 if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +0200155 return( ret );
156#endif
157
Paul Bakker0a597072012-09-25 21:55:46 +0000158 cur = cache->chain;
159 prv = NULL;
160
161 while( cur != NULL )
162 {
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000163 count++;
164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker0a597072012-09-25 21:55:46 +0000166 if( cache->timeout != 0 &&
167 (int) ( t - cur->timestamp ) > cache->timeout )
168 {
169 cur->timestamp = t;
170 break; /* expired, reuse this slot, update timestamp */
171 }
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200172#endif
Paul Bakker0a597072012-09-25 21:55:46 +0000173
Manuel Pégourié-Gonnard12ad7982015-06-18 15:50:37 +0200174 if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 )
Paul Bakker0a597072012-09-25 21:55:46 +0000175 break; /* client reconnected, keep timestamp for session id */
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177#if defined(MBEDTLS_HAVE_TIME)
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000178 if( oldest == 0 || cur->timestamp < oldest )
179 {
180 oldest = cur->timestamp;
181 old = cur;
182 }
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200183#endif
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000184
Paul Bakker0a597072012-09-25 21:55:46 +0000185 prv = cur;
186 cur = cur->next;
187 }
188
189 if( cur == NULL )
190 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191#if defined(MBEDTLS_HAVE_TIME)
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000192 /*
193 * Reuse oldest entry if max_entries reached
194 */
Manuel Pégourié-Gonnard274a12e2014-02-20 21:32:08 +0100195 if( count >= cache->max_entries )
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000196 {
Manuel Pégourié-Gonnard274a12e2014-02-20 21:32:08 +0100197 if( old == NULL )
198 {
199 ret = 1;
200 goto exit;
201 }
202
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000203 cur = old;
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000204 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205#else /* MBEDTLS_HAVE_TIME */
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200206 /*
207 * Reuse first entry in chain if max_entries reached,
208 * but move to last place
209 */
210 if( count >= cache->max_entries )
211 {
212 if( cache->chain == NULL )
Paul Bakkerc5598842013-09-28 15:01:27 +0200213 {
214 ret = 1;
215 goto exit;
216 }
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200217
218 cur = cache->chain;
219 cache->chain = cur->next;
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100220 cur->next = NULL;
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200221 prv->next = cur;
222 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223#endif /* MBEDTLS_HAVE_TIME */
Paul Bakker0a597072012-09-25 21:55:46 +0000224 else
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000225 {
Manuel Pégourié-Gonnard274a12e2014-02-20 21:32:08 +0100226 /*
227 * max_entries not reached, create new entry
228 */
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200229 cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) );
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000230 if( cur == NULL )
Paul Bakkerc5598842013-09-28 15:01:27 +0200231 {
232 ret = 1;
233 goto exit;
234 }
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000235
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000236 if( prv == NULL )
237 cache->chain = cur;
238 else
239 prv->next = cur;
240 }
Paul Bakker0a597072012-09-25 21:55:46 +0000241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker0a597072012-09-25 21:55:46 +0000243 cur->timestamp = t;
Paul Bakkerfa9b1002013-07-03 15:31:03 +0200244#endif
Paul Bakker0a597072012-09-25 21:55:46 +0000245 }
246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) );
Paul Bakkered27a042013-04-18 22:46:23 +0200248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249#if defined(MBEDTLS_X509_CRT_PARSE_C)
Paul Bakkere81beda2013-03-06 17:40:46 +0100250 /*
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100251 * If we're reusing an entry, free its certificate first
252 */
253 if( cur->peer_cert.p != NULL )
254 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 mbedtls_free( cur->peer_cert.p );
256 memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100257 }
258
259 /*
Paul Bakkere81beda2013-03-06 17:40:46 +0100260 * Store peer certificate
261 */
262 if( session->peer_cert != NULL )
263 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200264 cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len );
Paul Bakkere81beda2013-03-06 17:40:46 +0100265 if( cur->peer_cert.p == NULL )
Paul Bakkerc5598842013-09-28 15:01:27 +0200266 {
267 ret = 1;
268 goto exit;
269 }
Paul Bakkere81beda2013-03-06 17:40:46 +0100270
271 memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
272 session->peer_cert->raw.len );
273 cur->peer_cert.len = session->peer_cert->raw.len;
274
275 cur->session.peer_cert = NULL;
276 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200277#endif /* MBEDTLS_X509_CRT_PARSE_C */
Paul Bakker0a597072012-09-25 21:55:46 +0000278
Paul Bakkerc5598842013-09-28 15:01:27 +0200279 ret = 0;
280
281exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282#if defined(MBEDTLS_THREADING_C)
283 if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +0200284 ret = 1;
285#endif
286
287 return( ret );
Paul Bakker0a597072012-09-25 21:55:46 +0000288}
289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290#if defined(MBEDTLS_HAVE_TIME)
291void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout )
Paul Bakker0a597072012-09-25 21:55:46 +0000292{
293 if( timeout < 0 ) timeout = 0;
294
295 cache->timeout = timeout;
296}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297#endif /* MBEDTLS_HAVE_TIME */
Paul Bakker0a597072012-09-25 21:55:46 +0000298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max )
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000300{
301 if( max < 0 ) max = 0;
302
303 cache->max_entries = max;
304}
305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
Paul Bakker0a597072012-09-25 21:55:46 +0000307{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 mbedtls_ssl_cache_entry *cur, *prv;
Paul Bakker0a597072012-09-25 21:55:46 +0000309
310 cur = cache->chain;
311
312 while( cur != NULL )
313 {
314 prv = cur;
315 cur = cur->next;
316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 mbedtls_ssl_session_free( &prv->session );
Paul Bakkere81beda2013-03-06 17:40:46 +0100318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319#if defined(MBEDTLS_X509_CRT_PARSE_C)
320 mbedtls_free( prv->peer_cert.p );
321#endif /* MBEDTLS_X509_CRT_PARSE_C */
Paul Bakkere81beda2013-03-06 17:40:46 +0100322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 mbedtls_free( prv );
Paul Bakker0a597072012-09-25 21:55:46 +0000324 }
Paul Bakkerc5598842013-09-28 15:01:27 +0200325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326#if defined(MBEDTLS_THREADING_C)
327 mbedtls_mutex_free( &cache->mutex );
Paul Bakkerc5598842013-09-28 15:01:27 +0200328#endif
Ron Eldore1a9a4a2017-10-17 18:15:41 +0300329
330 mbedtls_zeroize( cache, sizeof(mbedtls_ssl_cache_context) );
Paul Bakker0a597072012-09-25 21:55:46 +0000331}
332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333#endif /* MBEDTLS_SSL_CACHE_C */