PolarSSL v1.3.7
ssl_cache.c
Go to the documentation of this file.
1 /*
2  * SSL session cache implementation
3  *
4  * Copyright (C) 2006-2014, 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 #if !defined(POLARSSL_CONFIG_FILE)
31 #include "polarssl/config.h"
32 #else
33 #include POLARSSL_CONFIG_FILE
34 #endif
35 
36 #if defined(POLARSSL_SSL_CACHE_C)
37 
38 #include "polarssl/ssl_cache.h"
39 
40 #if defined(POLARSSL_PLATFORM_C)
41 #include "polarssl/platform.h"
42 #else
43 #define polarssl_malloc malloc
44 #define polarssl_free free
45 #endif
46 
47 #include <stdlib.h>
48 
49 void ssl_cache_init( ssl_cache_context *cache )
50 {
51  memset( cache, 0, sizeof( ssl_cache_context ) );
52 
55 
56 #if defined(POLARSSL_THREADING_C)
57  polarssl_mutex_init( &cache->mutex );
58 #endif
59 }
60 
61 int ssl_cache_get( void *data, ssl_session *session )
62 {
63  int ret = 1;
64 #if defined(POLARSSL_HAVE_TIME)
65  time_t t = time( NULL );
66 #endif
67  ssl_cache_context *cache = (ssl_cache_context *) data;
68  ssl_cache_entry *cur, *entry;
69 
70 #if defined(POLARSSL_THREADING_C)
71  if( polarssl_mutex_lock( &cache->mutex ) != 0 )
72  return( 1 );
73 #endif
74 
75  cur = cache->chain;
76  entry = NULL;
77 
78  while( cur != NULL )
79  {
80  entry = cur;
81  cur = cur->next;
82 
83 #if defined(POLARSSL_HAVE_TIME)
84  if( cache->timeout != 0 &&
85  (int) ( t - entry->timestamp ) > cache->timeout )
86  continue;
87 #endif
88 
89  if( session->ciphersuite != entry->session.ciphersuite ||
90  session->compression != entry->session.compression ||
91  session->length != entry->session.length )
92  continue;
93 
94  if( memcmp( session->id, entry->session.id,
95  entry->session.length ) != 0 )
96  continue;
97 
98  memcpy( session->master, entry->session.master, 48 );
99 
100  session->verify_result = entry->session.verify_result;
101 
102 #if defined(POLARSSL_X509_CRT_PARSE_C)
103  /*
104  * Restore peer certificate (without rest of the original chain)
105  */
106  if( entry->peer_cert.p != NULL )
107  {
108  session->peer_cert =
109  (x509_crt *) polarssl_malloc( sizeof(x509_crt) );
110 
111  if( session->peer_cert == NULL )
112  {
113  ret = 1;
114  goto exit;
115  }
116 
117  x509_crt_init( session->peer_cert );
118  if( x509_crt_parse( session->peer_cert, entry->peer_cert.p,
119  entry->peer_cert.len ) != 0 )
120  {
121  polarssl_free( session->peer_cert );
122  session->peer_cert = NULL;
123  ret = 1;
124  goto exit;
125  }
126  }
127 #endif /* POLARSSL_X509_CRT_PARSE_C */
128 
129  ret = 0;
130  goto exit;
131  }
132 
133 exit:
134 #if defined(POLARSSL_THREADING_C)
135  if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
136  ret = 1;
137 #endif
138 
139  return( ret );
140 }
141 
142 int ssl_cache_set( void *data, const ssl_session *session )
143 {
144  int ret = 1;
145 #if defined(POLARSSL_HAVE_TIME)
146  time_t t = time( NULL ), oldest = 0;
147  ssl_cache_entry *old = NULL;
148 #endif
149  ssl_cache_context *cache = (ssl_cache_context *) data;
150  ssl_cache_entry *cur, *prv;
151  int count = 0;
152 
153 #if defined(POLARSSL_THREADING_C)
154  if( ( ret = polarssl_mutex_lock( &cache->mutex ) ) != 0 )
155  return( ret );
156 #endif
157 
158  cur = cache->chain;
159  prv = NULL;
160 
161  while( cur != NULL )
162  {
163  count++;
164 
165 #if defined(POLARSSL_HAVE_TIME)
166  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  }
172 #endif
173 
174  if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 )
175  break; /* client reconnected, keep timestamp for session id */
176 
177 #if defined(POLARSSL_HAVE_TIME)
178  if( oldest == 0 || cur->timestamp < oldest )
179  {
180  oldest = cur->timestamp;
181  old = cur;
182  }
183 #endif
184 
185  prv = cur;
186  cur = cur->next;
187  }
188 
189  if( cur == NULL )
190  {
191 #if defined(POLARSSL_HAVE_TIME)
192  /*
193  * Reuse oldest entry if max_entries reached
194  */
195  if( count >= cache->max_entries )
196  {
197  if( old == NULL )
198  {
199  ret = 1;
200  goto exit;
201  }
202 
203  cur = old;
204  }
205 #else /* POLARSSL_HAVE_TIME */
206  /*
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 )
213  {
214  ret = 1;
215  goto exit;
216  }
217 
218  cur = cache->chain;
219  cache->chain = cur->next;
220  cur->next = NULL;
221  prv->next = cur;
222  }
223 #endif /* POLARSSL_HAVE_TIME */
224  else
225  {
226  /*
227  * max_entries not reached, create new entry
228  */
229  cur = (ssl_cache_entry *)
230  polarssl_malloc( sizeof(ssl_cache_entry) );
231  if( cur == NULL )
232  {
233  ret = 1;
234  goto exit;
235  }
236 
237  memset( cur, 0, sizeof(ssl_cache_entry) );
238 
239  if( prv == NULL )
240  cache->chain = cur;
241  else
242  prv->next = cur;
243  }
244 
245 #if defined(POLARSSL_HAVE_TIME)
246  cur->timestamp = t;
247 #endif
248  }
249 
250  memcpy( &cur->session, session, sizeof( ssl_session ) );
251 
252 #if defined(POLARSSL_X509_CRT_PARSE_C)
253  /*
254  * If we're reusing an entry, free its certificate first
255  */
256  if( cur->peer_cert.p != NULL )
257  {
258  polarssl_free( cur->peer_cert.p );
259  memset( &cur->peer_cert, 0, sizeof(x509_buf) );
260  }
261 
262  /*
263  * Store peer certificate
264  */
265  if( session->peer_cert != NULL )
266  {
267  cur->peer_cert.p = (unsigned char *)
268  polarssl_malloc( session->peer_cert->raw.len );
269  if( cur->peer_cert.p == NULL )
270  {
271  ret = 1;
272  goto exit;
273  }
274 
275  memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
276  session->peer_cert->raw.len );
277  cur->peer_cert.len = session->peer_cert->raw.len;
278 
279  cur->session.peer_cert = NULL;
280  }
281 #endif /* POLARSSL_X509_CRT_PARSE_C */
282 
283  ret = 0;
284 
285 exit:
286 #if defined(POLARSSL_THREADING_C)
287  if( polarssl_mutex_unlock( &cache->mutex ) != 0 )
288  ret = 1;
289 #endif
290 
291  return( ret );
292 }
293 
294 #if defined(POLARSSL_HAVE_TIME)
295 void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout )
296 {
297  if( timeout < 0 ) timeout = 0;
298 
299  cache->timeout = timeout;
300 }
301 #endif /* POLARSSL_HAVE_TIME */
302 
303 void ssl_cache_set_max_entries( ssl_cache_context *cache, int max )
304 {
305  if( max < 0 ) max = 0;
306 
307  cache->max_entries = max;
308 }
309 
310 void ssl_cache_free( ssl_cache_context *cache )
311 {
312  ssl_cache_entry *cur, *prv;
313 
314  cur = cache->chain;
315 
316  while( cur != NULL )
317  {
318  prv = cur;
319  cur = cur->next;
320 
321  ssl_session_free( &prv->session );
322 
323 #if defined(POLARSSL_X509_CRT_PARSE_C)
324  if( prv->peer_cert.p != NULL )
325  polarssl_free( prv->peer_cert.p );
326 #endif /* POLARSSL_X509_CRT_PARSE_C */
327 
328  polarssl_free( prv );
329  }
330 
331 #if defined(POLARSSL_THREADING_C)
332  polarssl_mutex_free( &cache->mutex );
333 #endif
334 }
335 
336 #endif /* POLARSSL_SSL_CACHE_C */
size_t length
Definition: ssl.h:452
int ciphersuite
Definition: ssl.h:450
int(* polarssl_mutex_lock)(threading_mutex_t *mutex)
void ssl_cache_init(ssl_cache_context *cache)
Initialize an SSL cache context.
int compression
Definition: ssl.h:451
ssl_cache_entry * next
Definition: ssl_cache.h:73
unsigned char master[48]
Definition: ssl.h:454
x509_buf raw
The raw certificate data (DER).
Definition: x509_crt.h:59
#define SSL_CACHE_DEFAULT_TIMEOUT
Definition: ssl_cache.h:45
SSL session cache implementation.
ssl_cache_entry * chain
Definition: ssl_cache.h:81
#define polarssl_free
Definition: platform.h:91
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) ...
PolarSSL Platform abstraction layer.
x509_buf peer_cert
Definition: ssl_cache.h:71
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:453
int verify_result
Definition: ssl.h:459
Cache context.
Definition: ssl_cache.h:79
This structure is used for storing cache entries.
Definition: ssl_cache.h:64
Container for an X.509 certificate.
Definition: x509_crt.h:57
void x509_crt_init(x509_crt *crt)
Initialize a certificate (chain)
unsigned char * p
ASN1 data, e.g.
Definition: asn1.h:124
ssl_session session
Definition: ssl_cache.h:69
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:120
size_t len
ASN1 length, e.g.
Definition: asn1.h:123
#define SSL_CACHE_DEFAULT_MAX_ENTRIES
Definition: ssl_cache.h:49
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:67
int(* polarssl_mutex_init)(threading_mutex_t *mutex)
#define polarssl_malloc
Definition: platform.h:90
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:457