tls_cache.c
Go to the documentation of this file.
1 /**
2  * @file tls_cache.c
3  * @brief Session cache management
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneSSL Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (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
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL TLS_TRACE_LEVEL
31 
32 //Dependencies
33 #include <string.h>
34 #include "tls.h"
35 #include "tls_cache.h"
36 #include "debug.h"
37 
38 //Check TLS library configuration
39 #if (TLS_SUPPORT == ENABLED)
40 
41 
42 /**
43  * @brief Session cache initialization
44  * @param[in] size Maximum number of cache entries
45  * @return Handle referencing the fully initialized session cache
46  **/
47 
49 {
50  size_t n;
51  TlsCache *cache;
52 
53  //Make sure the parameter is acceptable
54  if(size < 1)
55  return NULL;
56 
57  //Size of the memory required
58  n = sizeof(TlsCache) + size * sizeof(TlsSessionState);
59 
60  //Allocate a memory buffer to hold the session cache
61  cache = tlsAllocMem(n);
62  //Failed to allocate memory?
63  if(cache == NULL)
64  return NULL;
65 
66  //Clear memory
67  memset(cache, 0, n);
68 
69  //Create a mutex to prevent simultaneous access to the cache
70  if(!osCreateMutex(&cache->mutex))
71  {
72  //Clean up side effects
73  tlsFreeMem(cache);
74  //Report an error
75  return NULL;
76  }
77 
78  //Save the maximum number of cache entries
79  cache->size = size;
80 
81  //Return a pointer to the newly created cache
82  return cache;
83 }
84 
85 
86 /**
87  * @brief Search the session cache for a given session ID
88  * @param[in] cache Pointer to the session cache
89  * @param[in] sessionId Expected session ID
90  * @param[in] sessionIdLen Length of the session ID
91  * @return A pointer to the matching session is returned. NULL is returned
92  * if the specified ID could not be found in the session cache
93  **/
94 
96  size_t sessionIdLen)
97 {
98 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
99  uint_t i;
100  systime_t time;
101  TlsSessionState *session;
102 
103  //Check whether session caching is supported
104  if(cache == NULL)
105  return NULL;
106 
107  //Ensure the session ID is valid
108  if(sessionId == NULL || sessionIdLen == 0)
109  return NULL;
110 
111  //Get current time
112  time = osGetSystemTime();
113 
114  //Acquire exclusive access to the session cache
115  osAcquireMutex(&cache->mutex);
116 
117  //Flush expired entries
118  for(i = 0; i < cache->size; i++)
119  {
120  //Point to the current entry
121  session = &cache->sessions[i];
122 
123  //Skip unused entries
124  if(session->sessionIdLen != 0)
125  {
126  //Outdated entry?
127  if((time - session->timestamp) >= TLS_SESSION_CACHE_LIFETIME)
128  {
129  //This session is no more valid and should be removed from the cache
130  memset(session, 0, sizeof(TlsSessionState));
131  }
132  }
133  }
134 
135  //Search the cache for the specified session ID
136  for(i = 0; i < cache->size; i++)
137  {
138  //Point to the current entry
139  session = &cache->sessions[i];
140 
141  //Check whether the current identifier matches the specified session ID
142  if(session->sessionIdLen == sessionIdLen &&
143  !memcmp(session->sessionId, sessionId, sessionIdLen))
144  {
145  //Release exclusive access to the session cache
146  osReleaseMutex(&cache->mutex);
147  //Return session parameters
148  return session;
149  }
150  }
151 
152  //Release exclusive access to the session cache
153  osReleaseMutex(&cache->mutex);
154 #endif
155 
156  //No matching entry in session cache
157  return NULL;
158 }
159 
160 
161 /**
162  * @brief Save current session in cache
163  * @param[in] context TLS context
164  * @return Error code
165  **/
166 
168 {
169 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
170  error_t error;
171  uint_t i;
172  systime_t time;
173  TlsSessionState *session;
174  TlsSessionState *firstFreeEntry;
175  TlsSessionState *oldestEntry;
176 
177  //Check parameters
178  if(context == NULL)
180  //Check whether session caching is supported
181  if(context->cache == NULL)
182  return ERROR_FAILURE;
183  //Ensure the session ID is valid
184  if(context->sessionIdLen == 0)
185  return NO_ERROR;
186 
187  //Acquire exclusive access to the session cache
188  osAcquireMutex(&context->cache->mutex);
189 
190  //Get current time
191  time = osGetSystemTime();
192 
193  //Keep track of the first free entry
194  firstFreeEntry = NULL;
195  //Keep track of the oldest entry
196  oldestEntry = NULL;
197 
198  //Search the cache for the specified session ID
199  for(i = 0; i < context->cache->size; i++)
200  {
201  //Point to the current entry
202  session = &context->cache->sessions[i];
203 
204  //If the session ID already exists, we are done
205  if(session->sessionIdLen == context->sessionIdLen &&
206  !memcmp(session->sessionId, context->sessionId, session->sessionIdLen))
207  {
208  //Do not write to session cache
209  firstFreeEntry = NULL;
210  oldestEntry = NULL;
211  //Exit immediately
212  break;
213  }
214 
215  //Check whether current entry is free
216  if(session->sessionIdLen == 0)
217  {
218  //Keep track of the first free entry
219  if(!firstFreeEntry)
220  {
221  firstFreeEntry = session;
222  }
223  }
224  else
225  {
226  //Keep track of the oldest entry in the table
227  if(oldestEntry == NULL)
228  {
229  oldestEntry = session;
230  }
231  else if((time - session->timestamp) > (time - oldestEntry->timestamp))
232  {
233  oldestEntry = session;
234  }
235  }
236  }
237 
238  //Add current session to cache if necessary
239  if(firstFreeEntry != NULL)
240  error = tlsSaveSessionState(context, firstFreeEntry);
241  else if(oldestEntry != NULL)
242  error = tlsSaveSessionState(context, oldestEntry);
243  else
244  error = NO_ERROR;
245 
246  //Release exclusive access to the session cache
247  osReleaseMutex(&context->cache->mutex);
248  //Return status code
249  return error;
250 #else
251  //Not implemented
252  return ERROR_NOT_IMPLEMENTED;
253 #endif
254 }
255 
256 
257 /**
258  * @brief Remove current session from cache
259  * @param[in] context TLS context
260  * @return Error code
261  **/
262 
264 {
265 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
266  uint_t i;
267  TlsSessionState *session;
268 
269  //Check parameters
270  if(context == NULL)
272  //Check whether session caching is supported
273  if(context->cache == NULL)
274  return ERROR_FAILURE;
275 
276  //Ensure the session ID is valid
277  if(context->sessionIdLen == 0)
278  return NO_ERROR;
279 
280  //Acquire exclusive access to the session cache
281  osAcquireMutex(&context->cache->mutex);
282 
283  //Search the cache for the specified session ID
284  for(i = 0; i < context->cache->size; i++)
285  {
286  //Point to the current entry
287  session = &context->cache->sessions[i];
288 
289  //Check whether the current identifier matches the specified session ID
290  if(session->sessionIdLen == context->sessionIdLen &&
291  !memcmp(session->sessionId, context->sessionId, session->sessionIdLen))
292  {
293  //Drop current entry
294  memset(session, 0, sizeof(TlsSessionState));
295  }
296  }
297 
298  //Release exclusive access to the session cache
299  osReleaseMutex(&context->cache->mutex);
300 #endif
301 
302  //Successful processing
303  return NO_ERROR;
304 }
305 
306 
307 /**
308  * @brief Properly dispose a session cache
309  * @param[in] cache Pointer to the session cache to be released
310  **/
311 
312 void tlsFreeCache(TlsCache *cache)
313 {
314  size_t n;
315 
316  //Invalid session cache?
317  if(cache == NULL)
318  return;
319 
320  //Release previously allocated resources
321  osDeleteMutex(&cache->mutex);
322 
323  //Compute the number of bytes allocated for the session cache
324  n = sizeof(TlsCache) + cache->size * sizeof(TlsSessionState);
325 
326  //Clear the session cache before freeing memory
327  memset(cache, 0, n);
328  tlsFreeMem(cache);
329 }
330 
331 #endif
TLS (Transport Layer Security)
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
uint32_t systime_t
Definition: compiler_port.h:44
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
Debugging facilities.
#define tlsFreeMem(p)
Definition: tls.h:760
uint8_t sessionIdLen
Definition: tls.h:1609
Generic error code.
Definition: error.h:43
error_t tlsRemoveFromCache(TlsContext *context)
Remove current session from cache.
Definition: tls_cache.c:263
Invalid parameter.
Definition: error.h:45
Session cache.
Definition: tls.h:1849
uint8_t sessionId[]
Definition: tls.h:1610
TLS session state.
Definition: tls.h:1820
error_t tlsSaveSessionState(const TlsContext *context, TlsSessionState *session)
Save TLS session.
Definition: tls.c:2333
TlsCache * tlsInitCache(uint_t size)
Session cache initialization.
Definition: tls_cache.c:48
OsMutex mutex
Mutex preventing simultaneous access to the cache.
Definition: tls.h:1851
error_t tlsSaveToCache(TlsContext *context)
Save current session in cache.
Definition: tls_cache.c:167
size_t sessionIdLen
Length of the session identifier.
Definition: tls.h:1829
uint8_t sessionId[32]
Session identifier.
Definition: tls.h:1828
#define TLS_SESSION_CACHE_LIFETIME
Definition: tls.h:139
uint_t size
Maximum number of entries.
Definition: tls.h:1852
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
void tlsFreeCache(TlsCache *cache)
Properly dispose a session cache.
Definition: tls_cache.c:312
unsigned int uint_t
Definition: compiler_port.h:43
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
systime_t timestamp
Time stamp to manage entry lifetime.
Definition: tls.h:1825
TlsSessionState * tlsFindCache(TlsCache *cache, const uint8_t *sessionId, size_t sessionIdLen)
Search the session cache for a given session ID.
Definition: tls_cache.c:95
TlsSessionState sessions[]
Cache entries.
Definition: tls.h:1853
#define tlsAllocMem(size)
Definition: tls.h:755
uint8_t n
#define TlsContext
Definition: tls.h:34
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
Session cache management.