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-2024 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 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_cache.h"
37 #include "tls_misc.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  osMemset(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 >= TLS_VERSION_1_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 &&
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 >= TLS_VERSION_1_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  osMemcmp(session->sessionId, context->sessionId, session->sessionIdLen) == 0)
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  {
240  error = tlsSaveSessionId(context, firstFreeEntry);
241  }
242  else if(oldestEntry != NULL)
243  {
244  error = tlsSaveSessionId(context, oldestEntry);
245  }
246  else
247  {
248  error = NO_ERROR;
249  }
250 
251  //Release exclusive access to the session cache
252  osReleaseMutex(&context->cache->mutex);
253 
254  //Return status code
255  return error;
256 #else
257  //Not implemented
258  return ERROR_NOT_IMPLEMENTED;
259 #endif
260 }
261 
262 
263 /**
264  * @brief Remove current session from cache
265  * @param[in] context TLS context
266  * @return Error code
267  **/
268 
270 {
271 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
272  uint_t i;
273  TlsSessionState *session;
274 
275  //Check parameters
276  if(context == NULL)
278 
279  //Check whether session caching is supported
280  if(context->cache == NULL)
281  return ERROR_FAILURE;
282 
283  //Ensure the session ID is valid
284  if(context->sessionIdLen == 0)
285  return NO_ERROR;
286 
287  //Acquire exclusive access to the session cache
288  osAcquireMutex(&context->cache->mutex);
289 
290  //Search the cache for the specified session ID
291  for(i = 0; i < context->cache->size; i++)
292  {
293  //Point to the current entry
294  session = &context->cache->sessions[i];
295 
296  //Check whether the current identifier matches the specified session ID
297  if(session->sessionIdLen == context->sessionIdLen &&
298  osMemcmp(session->sessionId, context->sessionId, session->sessionIdLen) == 0)
299  {
300  //Drop current entry
301  tlsFreeSessionState(session);
302  }
303  }
304 
305  //Release exclusive access to the session cache
306  osReleaseMutex(&context->cache->mutex);
307 #endif
308 
309  //Successful processing
310  return NO_ERROR;
311 }
312 
313 
314 /**
315  * @brief Properly dispose a session cache
316  * @param[in] cache Pointer to the session cache to be released
317  **/
318 
319 void tlsFreeCache(TlsCache *cache)
320 {
321  uint_t i;
322 
323  //Valid session cache?
324  if(cache != NULL)
325  {
326  //Loop through the session cache
327  for(i = 0; i < cache->size; i++)
328  {
329  //Release current entry
330  tlsFreeSessionState(&cache->sessions[i]);
331  }
332 
333  //Release mutex object
334  osDeleteMutex(&cache->mutex);
335 
336  //Properly dispose the session cache
337  tlsFreeMem(cache);
338  }
339 }
340 
341 #endif
#define tlsAllocMem(size)
Definition: tls.h:853
TLS helper functions.
error_t tlsSaveToCache(TlsContext *context)
Save current session in cache.
Definition: tls_cache.c:164
uint8_t sessionId[]
Definition: tls.h:1773
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:2041
void tlsFreeCache(TlsCache *cache)
Properly dispose a session cache.
Definition: tls_cache.c:319
error_t tlsSaveSessionId(const TlsContext *context, TlsSessionState *session)
Save session ID.
Definition: tls_misc.c:428
Session cache management.
size_t sessionIdLen
Length of the session identifier.
Definition: tls.h:2045
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
OsMutex mutex
Mutex preventing simultaneous access to the cache.
Definition: tls.h:2070
Session cache.
Definition: tls.h:2069
void tlsFreeSessionState(TlsSessionState *session)
Properly dispose a session state.
Definition: tls.c:2753
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:1772
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t tlsRemoveFromCache(TlsContext *context)
Remove current session from cache.
Definition: tls_cache.c:269
uint_t size
Maximum number of entries.
Definition: tls.h:2071
uint32_t systime_t
System time.
uint32_t time
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
TLS session state.
Definition: tls.h:2038
uint8_t n
uint8_t sessionId[32]
Session identifier.
Definition: tls.h:2044
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
#define TLS_SESSION_CACHE_LIFETIME
Definition: tls.h:143
TlsSessionState sessions[]
Cache entries.
Definition: tls.h:2072
TLS (Transport Layer Security)
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
#define tlsFreeMem(p)
Definition: tls.h:858
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
systime_t osGetSystemTime(void)
Retrieve system time.