PolarSSL v1.3.2
ssl_cache.c
Go to the documentation of this file.
1 /*
2  * SSL session cache implementation
3  *
4  * Copyright (C) 2006-2012, Brainspark B.V.
5  *
6  * This file is part of PolarSSL (http://www.polarssl.org)
7  * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 /*
26  * These session callbacks use a simple chained list
27  * to store and retrieve the session information.
28  */
29 
30 #include "polarssl/config.h"
31 
32 #if defined(POLARSSL_SSL_CACHE_C)
33 
34 #include "polarssl/ssl_cache.h"
35 
36 #if defined(POLARSSL_MEMORY_C)
37 #include "polarssl/memory.h"
38 #else
39 #define polarssl_malloc malloc
40 #define polarssl_free free
41 #endif
42 
43 #include <stdlib.h>
44 
45 void ssl_cache_init( ssl_cache_context *cache )
46 {
47  memset( cache, 0, sizeof( ssl_cache_context ) );
48 
51 
52 #if defined(POLARSSL_THREADING_C)
53  polarssl_mutex_init( &cache->mutex );
54 #endif
55 }
56 
57 int ssl_cache_get( void *data, ssl_session *session )
58 {
59  int ret = 1;
60 #if defined(POLARSSL_HAVE_TIME)
61  time_t t = time( NULL );
62 #endif
63  ssl_cache_context *cache = (ssl_cache_context *) data;
64  ssl_cache_entry *cur, *entry;
65 
66 #if defined(POLARSSL_THREADING_C)
67  if( polarssl_mutex_lock( &cache->mutex ) != 0 )
68  return( 1 );
69 #endif
70 
71  cur = cache->chain;
72  entry = NULL;
73 
74  while( cur != NULL )
75  {
76  entry = cur;
77  cur = cur->next;
78 
79 #if defined(POLARSSL_HAVE_TIME)
80  if( cache->timeout != 0 &&
81  (int) ( t - entry->timestamp ) > cache->timeout )
82  continue;
83 #endif
84 
85  if( session->ciphersuite != entry->session.ciphersuite ||
86  session->compression != entry->session.compression ||
87  session->length != entry->session.length )
88  continue;
89 
90  if( memcmp( session->id, entry->session.id,
91  entry->session.length ) != 0 )
92  continue;
93 
94  memcpy( session->master, entry->session.master, 48 );
95 
96  session->verify_result = entry->session.verify_result;
97 
98 #if defined(POLARSSL_X509_CRT_PARSE_C)
99  /*
100  * Restore peer certificate (without rest of the original chain)
101  */
102  if( entry->peer_cert.p != NULL )
103  {
104  session->peer_cert = (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
105  if( session->peer_cert == NULL )
106  {
107  ret = 1;
108  goto exit;
109  }
110 
111  x509_crt_init( session->peer_cert );
112  if( x509_crt_parse( session->peer_cert, entry->peer_cert.p,
113  entry->peer_cert.len ) != 0 )
114  {
115  polarssl_free( session->peer_cert );
116  session->peer_cert = NULL;
117  ret = 1;
118  goto exit;
119  }
120  }
121 #endif /* POLARSSL_X509_CRT_PARSE_C */
122 
123  ret = 0;
124  goto exit;
125  }
126 
127 exit:
128 #if defined(POLARSSL_THREADING_C)
129  if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
130  ret = 1;
131 #endif
132 
133  return( ret );
134 }
135 
136 int ssl_cache_set( void *data, const ssl_session *session )
137 {
138  int ret = 1;
139 #if defined(POLARSSL_HAVE_TIME)
140  time_t t = time( NULL ), oldest = 0;
141  ssl_cache_entry *old = NULL;
142 #endif
143  ssl_cache_context *cache = (ssl_cache_context *) data;
144  ssl_cache_entry *cur, *prv;
145  int count = 0;
146 
147 #if defined(POLARSSL_THREADING_C)
148  if( ( ret = polarssl_mutex_lock( &cache->mutex ) ) != 0 )
149  return( ret );
150 #endif
151 
152  cur = cache->chain;
153  prv = NULL;
154 
155  while( cur != NULL )
156  {
157  count++;
158 
159 #if defined(POLARSSL_HAVE_TIME)
160  if( cache->timeout != 0 &&
161  (int) ( t - cur->timestamp ) > cache->timeout )
162  {
163  cur->timestamp = t;
164  break; /* expired, reuse this slot, update timestamp */
165  }
166 #endif
167 
168  if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 )
169  break; /* client reconnected, keep timestamp for session id */
170 
171 #if defined(POLARSSL_HAVE_TIME)
172  if( oldest == 0 || cur->timestamp < oldest )
173  {
174  oldest = cur->timestamp;
175  old = cur;
176  }
177 #endif
178 
179  prv = cur;
180  cur = cur->next;
181  }
182 
183  if( cur == NULL )
184  {
185 #if defined(POLARSSL_HAVE_TIME)
186  /*
187  * Reuse oldest entry if max_entries reached
188  */
189  if( old != NULL && count >= cache->max_entries )
190  {
191  cur = old;
192  memset( &cur->session, 0, sizeof(ssl_session) );
193 #if defined(POLARSSL_X509_CRT_PARSE_C)
194  if( cur->peer_cert.p != NULL )
195  {
196  polarssl_free( cur->peer_cert.p );
197  memset( &cur->peer_cert, 0, sizeof(x509_buf) );
198  }
199 #endif /* POLARSSL_X509_CRT_PARSE_C */
200  }
201 #else /* POLARSSL_HAVE_TIME */
202  /*
203  * Reuse first entry in chain if max_entries reached,
204  * but move to last place
205  */
206  if( count >= cache->max_entries )
207  {
208  if( cache->chain == NULL )
209  {
210  ret = 1;
211  goto exit;
212  }
213 
214  cur = cache->chain;
215  cache->chain = cur->next;
216 
217 #if defined(POLARSSL_X509_CRT_PARSE_C)
218  if( cur->peer_cert.p != NULL )
219  {
220  polarssl_free( cur->peer_cert.p );
221  memset( &cur->peer_cert, 0, sizeof(x509_buf) );
222  }
223 #endif /* POLARSSL_X509_CRT_PARSE_C */
224 
225  memset( cur, 0, sizeof(ssl_cache_entry) );
226  prv->next = cur;
227  }
228 #endif /* POLARSSL_HAVE_TIME */
229  else
230  {
231  cur = (ssl_cache_entry *) polarssl_malloc( sizeof(ssl_cache_entry) );
232  if( cur == NULL )
233  {
234  ret = 1;
235  goto exit;
236  }
237 
238  memset( cur, 0, sizeof(ssl_cache_entry) );
239 
240  if( prv == NULL )
241  cache->chain = cur;
242  else
243  prv->next = cur;
244  }
245 
246 #if defined(POLARSSL_HAVE_TIME)
247  cur->timestamp = t;
248 #endif
249  }
250 
251  memcpy( &cur->session, session, sizeof( ssl_session ) );
252 
253 #if defined(POLARSSL_X509_CRT_PARSE_C)
254  /*
255  * Store peer certificate
256  */
257  if( session->peer_cert != NULL )
258  {
259  cur->peer_cert.p = (unsigned char *) polarssl_malloc( session->peer_cert->raw.len );
260  if( cur->peer_cert.p == NULL )
261  {
262  ret = 1;
263  goto exit;
264  }
265 
266  memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
267  session->peer_cert->raw.len );
268  cur->peer_cert.len = session->peer_cert->raw.len;
269 
270  cur->session.peer_cert = NULL;
271  }
272 #endif /* POLARSSL_X509_CRT_PARSE_C */
273 
274  ret = 0;
275 
276 exit:
277 #if defined(POLARSSL_THREADING_C)
278  if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
279  ret = 1;
280 #endif
281 
282  return( ret );
283 }
284 
285 #if defined(POLARSSL_HAVE_TIME)
286 void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout )
287 {
288  if( timeout < 0 ) timeout = 0;
289 
290  cache->timeout = timeout;
291 }
292 #endif /* POLARSSL_HAVE_TIME */
293 
294 void ssl_cache_set_max_entries( ssl_cache_context *cache, int max )
295 {
296  if( max < 0 ) max = 0;
297 
298  cache->max_entries = max;
299 }
300 
301 void ssl_cache_free( ssl_cache_context *cache )
302 {
303  ssl_cache_entry *cur, *prv;
304 
305  cur = cache->chain;
306 
307  while( cur != NULL )
308  {
309  prv = cur;
310  cur = cur->next;
311 
312  ssl_session_free( &prv->session );
313 
314 #if defined(POLARSSL_X509_CRT_PARSE_C)
315  if( prv->peer_cert.p != NULL )
316  polarssl_free( prv->peer_cert.p );
317 #endif /* POLARSSL_X509_CRT_PARSE_C */
318 
319  polarssl_free( prv );
320  }
321 
322 #if defined(POLARSSL_THREADING_C)
323  polarssl_mutex_free( &cache->mutex );
324 #endif
325 }
326 
327 #endif /* POLARSSL_SSL_CACHE_C */
size_t length
Definition: ssl.h:428
int ciphersuite
Definition: ssl.h:426
Memory allocation layer.
int(* polarssl_mutex_lock)(threading_mutex_t *mutex)
void ssl_cache_init(ssl_cache_context *cache)
Initialize an SSL cache context.
void *(* polarssl_malloc)(size_t len)
int compression
Definition: ssl.h:427
ssl_cache_entry * next
Definition: ssl_cache.h:60
unsigned char master[48]
Definition: ssl.h:430
x509_buf raw
The raw certificate data (DER).
Definition: x509_crt.h:55
#define SSL_CACHE_DEFAULT_TIMEOUT
Definition: ssl_cache.h:37
SSL session cache implementation.
ssl_cache_entry * chain
Definition: ssl_cache.h:68
void ssl_session_free(ssl_session *session)
Free referenced items in an SSL session including the peer certificate and clear memory.
int x509_crt_parse(x509_crt *chain, const unsigned char *buf, size_t buflen)
Parse one or more certificates and add them to the chained list.
Configuration options (set of defines)
int ssl_cache_get(void *data, ssl_session *session)
Cache get callback implementation (Thread-safe if POLARSSL_THREADING_C is enabled) ...
x509_buf peer_cert
Definition: ssl_cache.h:58
void ssl_cache_free(ssl_cache_context *cache)
Free referenced items in a cache context and clear memory.
unsigned char id[32]
Definition: ssl.h:429
int verify_result
Definition: ssl.h:435
Cache context.
Definition: ssl_cache.h:66
This structure is used for storing cache entries.
Definition: ssl_cache.h:51
Container for an X.509 certificate.
Definition: x509_crt.h:53
void x509_crt_init(x509_crt *crt)
Initialize a certificate (chain)
void(* polarssl_free)(void *ptr)
unsigned char * p
ASN1 data, e.g.
Definition: asn1.h:120
ssl_session session
Definition: ssl_cache.h:56
void ssl_cache_set_timeout(ssl_cache_context *cache, int timeout)
Set the cache timeout (Default: SSL_CACHE_DEFAULT_TIMEOUT (1 day))
int(* polarssl_mutex_free)(threading_mutex_t *mutex)
Type-length-value structure that allows for ASN1 using DER.
Definition: asn1.h:116
size_t len
ASN1 length, e.g.
Definition: asn1.h:119
#define SSL_CACHE_DEFAULT_MAX_ENTRIES
Definition: ssl_cache.h:38
void ssl_cache_set_max_entries(ssl_cache_context *cache, int max)
Set the cache timeout (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
int(* polarssl_mutex_unlock)(threading_mutex_t *mutex)
time_t timestamp
Definition: ssl_cache.h:54
int(* polarssl_mutex_init)(threading_mutex_t *mutex)
int ssl_cache_set(void *data, const ssl_session *session)
Cache set callback implementation (Thread-safe if POLARSSL_THREADING_C is enabled) ...
x509_crt * peer_cert
Definition: ssl.h:433