blob: 3a2df0cc5bf3506d8535b2d45910d42e3a0e4bd9 [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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020026#include "common.h"
Paul Bakker0a597072012-09-25 21:55:46 +000027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if defined(MBEDTLS_SSL_CACHE_C)
Paul Bakker0a597072012-09-25 21:55:46 +000029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020032#else
Rich Evans00ab4702015-02-06 13:43:58 +000033#include <stdlib.h>
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020034#define mbedtls_calloc calloc
SimonBd5800b72016-04-26 07:43:27 +010035#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020036#endif
37
SimonBd5800b72016-04-26 07:43:27 +010038#include "mbedtls/ssl_cache.h"
Hanno Beckeraee87172019-02-06 14:53:19 +000039#include "mbedtls/ssl_internal.h"
SimonBd5800b72016-04-26 07:43:27 +010040
41#include <string.h>
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )
Paul Bakker0a597072012-09-25 21:55:46 +000044{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045 memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );
Paul Bakker0a597072012-09-25 21:55:46 +000046
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047 cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
48 cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
Paul Bakkerc5598842013-09-28 15:01:27 +020049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#if defined(MBEDTLS_THREADING_C)
51 mbedtls_mutex_init( &cache->mutex );
Paul Bakkerc5598842013-09-28 15:01:27 +020052#endif
Paul Bakker0a597072012-09-25 21:55:46 +000053}
54
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
Paul Bakker0a597072012-09-25 21:55:46 +000056{
Paul Bakkerc5598842013-09-28 15:01:27 +020057 int ret = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_HAVE_TIME)
SimonBd5800b72016-04-26 07:43:27 +010059 mbedtls_time_t t = mbedtls_time( NULL );
Paul Bakkerfa9b1002013-07-03 15:31:03 +020060#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061 mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
62 mbedtls_ssl_cache_entry *cur, *entry;
Paul Bakker0a597072012-09-25 21:55:46 +000063
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064#if defined(MBEDTLS_THREADING_C)
65 if( mbedtls_mutex_lock( &cache->mutex ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +020066 return( 1 );
67#endif
68
Paul Bakker0a597072012-09-25 21:55:46 +000069 cur = cache->chain;
70 entry = NULL;
71
72 while( cur != NULL )
73 {
74 entry = cur;
75 cur = cur->next;
76
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077#if defined(MBEDTLS_HAVE_TIME)
Paul Bakker0a597072012-09-25 21:55:46 +000078 if( cache->timeout != 0 &&
79 (int) ( t - entry->timestamp ) > cache->timeout )
80 continue;
Paul Bakkerfa9b1002013-07-03 15:31:03 +020081#endif
Paul Bakker0a597072012-09-25 21:55:46 +000082
83 if( session->ciphersuite != entry->session.ciphersuite ||
84 session->compression != entry->session.compression ||
Manuel Pégourié-Gonnard12ad7982015-06-18 15:50:37 +020085 session->id_len != entry->session.id_len )
Paul Bakker0a597072012-09-25 21:55:46 +000086 continue;
87
88 if( memcmp( session->id, entry->session.id,
Manuel Pégourié-Gonnard12ad7982015-06-18 15:50:37 +020089 entry->session.id_len ) != 0 )
Paul Bakker0a597072012-09-25 21:55:46 +000090 continue;
91
Hanno Beckeraee87172019-02-06 14:53:19 +000092 ret = mbedtls_ssl_session_copy( session, &entry->session );
93 if( ret != 0 )
94 {
95 ret = 1;
96 goto exit;
97 }
Manuel Pégourié-Gonnard38d1eba2013-08-23 10:44:29 +020098
Hanno Beckera887d1a2019-02-06 15:57:49 +000099#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
100 defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Paul Bakkere81beda2013-03-06 17:40:46 +0100101 /*
102 * Restore peer certificate (without rest of the original chain)
103 */
104 if( entry->peer_cert.p != NULL )
105 {
Hanno Beckeraee87172019-02-06 14:53:19 +0000106 /* `session->peer_cert` is NULL after the call to
107 * mbedtls_ssl_session_copy(), because cache entries
108 * have the `peer_cert` field set to 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 }
Hanno Beckera887d1a2019-02-06 15:57:49 +0000127#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
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
Hanno Beckera887d1a2019-02-06 15:57:49 +0000247#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
248 defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Paul Bakkere81beda2013-03-06 17:40:46 +0100249 /*
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100250 * If we're reusing an entry, free its certificate first
251 */
252 if( cur->peer_cert.p != NULL )
253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_free( cur->peer_cert.p );
255 memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100256 }
Hanno Beckera887d1a2019-02-06 15:57:49 +0000257#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
Manuel Pégourié-Gonnard84c30c72014-02-26 17:38:55 +0100258
Hanno Beckeraee87172019-02-06 14:53:19 +0000259 /* Copy the entire session; this temporarily makes a copy of the
260 * X.509 CRT structure even though we only want to store the raw CRT.
261 * This inefficiency will go away as soon as we implement on-demand
262 * parsing of CRTs, in which case there's no need for the `peer_cert`
263 * field anymore in the first place, and we're done after this call. */
264 ret = mbedtls_ssl_session_copy( &cur->session, session );
265 if( ret != 0 )
Paul Bakkere81beda2013-03-06 17:40:46 +0100266 {
Hanno Beckeraee87172019-02-06 14:53:19 +0000267 ret = 1;
268 goto exit;
269 }
270
Hanno Beckera887d1a2019-02-06 15:57:49 +0000271#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
272 defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Hanno Beckeraee87172019-02-06 14:53:19 +0000273 /* If present, free the X.509 structure and only store the raw CRT data. */
274 if( cur->session.peer_cert != NULL )
275 {
276 cur->peer_cert.p =
277 mbedtls_calloc( 1, cur->session.peer_cert->raw.len );
Paul Bakkere81beda2013-03-06 17:40:46 +0100278 if( cur->peer_cert.p == NULL )
Paul Bakkerc5598842013-09-28 15:01:27 +0200279 {
280 ret = 1;
281 goto exit;
282 }
Paul Bakkere81beda2013-03-06 17:40:46 +0100283
Hanno Beckeraee87172019-02-06 14:53:19 +0000284 memcpy( cur->peer_cert.p,
285 cur->session.peer_cert->raw.p,
286 cur->session.peer_cert->raw.len );
Paul Bakkere81beda2013-03-06 17:40:46 +0100287 cur->peer_cert.len = session->peer_cert->raw.len;
288
Hanno Beckeraee87172019-02-06 14:53:19 +0000289 mbedtls_x509_crt_free( cur->session.peer_cert );
290 mbedtls_free( cur->session.peer_cert );
Paul Bakkere81beda2013-03-06 17:40:46 +0100291 cur->session.peer_cert = NULL;
292 }
Hanno Beckera887d1a2019-02-06 15:57:49 +0000293#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
Paul Bakker0a597072012-09-25 21:55:46 +0000294
Paul Bakkerc5598842013-09-28 15:01:27 +0200295 ret = 0;
296
297exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298#if defined(MBEDTLS_THREADING_C)
299 if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )
Paul Bakkerc5598842013-09-28 15:01:27 +0200300 ret = 1;
301#endif
302
303 return( ret );
Paul Bakker0a597072012-09-25 21:55:46 +0000304}
305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306#if defined(MBEDTLS_HAVE_TIME)
307void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout )
Paul Bakker0a597072012-09-25 21:55:46 +0000308{
309 if( timeout < 0 ) timeout = 0;
310
311 cache->timeout = timeout;
312}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313#endif /* MBEDTLS_HAVE_TIME */
Paul Bakker0a597072012-09-25 21:55:46 +0000314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max )
Paul Bakkerba26e9e2012-10-23 22:18:28 +0000316{
317 if( max < 0 ) max = 0;
318
319 cache->max_entries = max;
320}
321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
Paul Bakker0a597072012-09-25 21:55:46 +0000323{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 mbedtls_ssl_cache_entry *cur, *prv;
Paul Bakker0a597072012-09-25 21:55:46 +0000325
326 cur = cache->chain;
327
328 while( cur != NULL )
329 {
330 prv = cur;
331 cur = cur->next;
332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 mbedtls_ssl_session_free( &prv->session );
Paul Bakkere81beda2013-03-06 17:40:46 +0100334
Hanno Beckera887d1a2019-02-06 15:57:49 +0000335#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
336 defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 mbedtls_free( prv->peer_cert.p );
Hanno Beckera887d1a2019-02-06 15:57:49 +0000338#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
Paul Bakkere81beda2013-03-06 17:40:46 +0100339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 mbedtls_free( prv );
Paul Bakker0a597072012-09-25 21:55:46 +0000341 }
Paul Bakkerc5598842013-09-28 15:01:27 +0200342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343#if defined(MBEDTLS_THREADING_C)
344 mbedtls_mutex_free( &cache->mutex );
Paul Bakkerc5598842013-09-28 15:01:27 +0200345#endif
Ron Eldor22360822017-10-29 17:53:52 +0200346 cache->chain = NULL;
Paul Bakker0a597072012-09-25 21:55:46 +0000347}
348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349#endif /* MBEDTLS_SSL_CACHE_C */