2 * SSL session cache implementation
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 * These session callbacks use a simple chained list
25 * to store and retrieve the session information.
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
31 #include MBEDTLS_CONFIG_FILE
34 #if defined(MBEDTLS_SSL_CACHE_C)
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
40 #define mbedtls_calloc calloc
41 #define mbedtls_free free
44 #include "mbedtls/ssl_cache.h"
48 void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context
*cache
)
50 memset( cache
, 0, sizeof( mbedtls_ssl_cache_context
) );
52 cache
->timeout
= MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT
;
53 cache
->max_entries
= MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES
;
55 #if defined(MBEDTLS_THREADING_C)
56 mbedtls_mutex_init( &cache
->mutex
);
60 int mbedtls_ssl_cache_get( void *data
, mbedtls_ssl_session
*session
)
63 #if defined(MBEDTLS_HAVE_TIME)
64 mbedtls_time_t t
= mbedtls_time( NULL
);
66 mbedtls_ssl_cache_context
*cache
= (mbedtls_ssl_cache_context
*) data
;
67 mbedtls_ssl_cache_entry
*cur
, *entry
;
69 #if defined(MBEDTLS_THREADING_C)
70 if( mbedtls_mutex_lock( &cache
->mutex
) != 0 )
82 #if defined(MBEDTLS_HAVE_TIME)
83 if( cache
->timeout
!= 0 &&
84 (int) ( t
- entry
->timestamp
) > cache
->timeout
)
88 if( session
->ciphersuite
!= entry
->session
.ciphersuite
||
89 session
->compression
!= entry
->session
.compression
||
90 session
->id_len
!= entry
->session
.id_len
)
93 if( memcmp( session
->id
, entry
->session
.id
,
94 entry
->session
.id_len
) != 0 )
97 memcpy( session
->master
, entry
->session
.master
, 48 );
99 session
->verify_result
= entry
->session
.verify_result
;
101 #if defined(MBEDTLS_X509_CRT_PARSE_C)
103 * Restore peer certificate (without rest of the original chain)
105 if( entry
->peer_cert
.p
!= NULL
)
107 if( ( session
->peer_cert
= mbedtls_calloc( 1,
108 sizeof(mbedtls_x509_crt
) ) ) == NULL
)
114 mbedtls_x509_crt_init( session
->peer_cert
);
115 if( mbedtls_x509_crt_parse( session
->peer_cert
, entry
->peer_cert
.p
,
116 entry
->peer_cert
.len
) != 0 )
118 mbedtls_free( session
->peer_cert
);
119 session
->peer_cert
= NULL
;
124 #endif /* MBEDTLS_X509_CRT_PARSE_C */
131 #if defined(MBEDTLS_THREADING_C)
132 if( mbedtls_mutex_unlock( &cache
->mutex
) != 0 )
139 int mbedtls_ssl_cache_set( void *data
, const mbedtls_ssl_session
*session
)
142 #if defined(MBEDTLS_HAVE_TIME)
143 mbedtls_time_t t
= time( NULL
), oldest
= 0;
144 mbedtls_ssl_cache_entry
*old
= NULL
;
146 mbedtls_ssl_cache_context
*cache
= (mbedtls_ssl_cache_context
*) data
;
147 mbedtls_ssl_cache_entry
*cur
, *prv
;
150 #if defined(MBEDTLS_THREADING_C)
151 if( ( ret
= mbedtls_mutex_lock( &cache
->mutex
) ) != 0 )
162 #if defined(MBEDTLS_HAVE_TIME)
163 if( cache
->timeout
!= 0 &&
164 (int) ( t
- cur
->timestamp
) > cache
->timeout
)
167 break; /* expired, reuse this slot, update timestamp */
171 if( memcmp( session
->id
, cur
->session
.id
, cur
->session
.id_len
) == 0 )
172 break; /* client reconnected, keep timestamp for session id */
174 #if defined(MBEDTLS_HAVE_TIME)
175 if( oldest
== 0 || cur
->timestamp
< oldest
)
177 oldest
= cur
->timestamp
;
188 #if defined(MBEDTLS_HAVE_TIME)
190 * Reuse oldest entry if max_entries reached
192 if( count
>= cache
->max_entries
)
202 #else /* MBEDTLS_HAVE_TIME */
204 * Reuse first entry in chain if max_entries reached,
205 * but move to last place
207 if( count
>= cache
->max_entries
)
209 if( cache
->chain
== NULL
)
216 cache
->chain
= cur
->next
;
220 #endif /* MBEDTLS_HAVE_TIME */
224 * max_entries not reached, create new entry
226 cur
= mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry
) );
239 #if defined(MBEDTLS_HAVE_TIME)
244 memcpy( &cur
->session
, session
, sizeof( mbedtls_ssl_session
) );
246 #if defined(MBEDTLS_X509_CRT_PARSE_C)
248 * If we're reusing an entry, free its certificate first
250 if( cur
->peer_cert
.p
!= NULL
)
252 mbedtls_free( cur
->peer_cert
.p
);
253 memset( &cur
->peer_cert
, 0, sizeof(mbedtls_x509_buf
) );
257 * Store peer certificate
259 if( session
->peer_cert
!= NULL
)
261 cur
->peer_cert
.p
= mbedtls_calloc( 1, session
->peer_cert
->raw
.len
);
262 if( cur
->peer_cert
.p
== NULL
)
268 memcpy( cur
->peer_cert
.p
, session
->peer_cert
->raw
.p
,
269 session
->peer_cert
->raw
.len
);
270 cur
->peer_cert
.len
= session
->peer_cert
->raw
.len
;
272 cur
->session
.peer_cert
= NULL
;
274 #endif /* MBEDTLS_X509_CRT_PARSE_C */
279 #if defined(MBEDTLS_THREADING_C)
280 if( mbedtls_mutex_unlock( &cache
->mutex
) != 0 )
287 #if defined(MBEDTLS_HAVE_TIME)
288 void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context
*cache
, int timeout
)
290 if( timeout
< 0 ) timeout
= 0;
292 cache
->timeout
= timeout
;
294 #endif /* MBEDTLS_HAVE_TIME */
296 void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context
*cache
, int max
)
298 if( max
< 0 ) max
= 0;
300 cache
->max_entries
= max
;
303 void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context
*cache
)
305 mbedtls_ssl_cache_entry
*cur
, *prv
;
314 mbedtls_ssl_session_free( &prv
->session
);
316 #if defined(MBEDTLS_X509_CRT_PARSE_C)
317 mbedtls_free( prv
->peer_cert
.p
);
318 #endif /* MBEDTLS_X509_CRT_PARSE_C */
323 #if defined(MBEDTLS_THREADING_C)
324 mbedtls_mutex_free( &cache
->mutex
);
328 #endif /* MBEDTLS_SSL_CACHE_C */