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