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-2022 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.2.0
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 "tls_misc.h"
39 #include "debug.h"
40 
41 //Check TLS library configuration
42 #if (TLS_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Session cache initialization
47  * @param[in] size Maximum number of cache entries
48  * @return Handle referencing the fully initialized session cache
49  **/
50 
52 {
53  size_t n;
54  TlsCache *cache;
55 
56  //Make sure the parameter is acceptable
57  if(size < 1)
58  return NULL;
59 
60  //Size of the memory required
61  n = sizeof(TlsCache) + size * sizeof(TlsSessionState);
62 
63  //Allocate a memory buffer to hold the session cache
64  cache = tlsAllocMem(n);
65  //Failed to allocate memory?
66  if(cache == NULL)
67  return NULL;
68 
69  //Clear memory
70  osMemset(cache, 0, n);
71 
72  //Create a mutex to prevent simultaneous access to the cache
73  if(!osCreateMutex(&cache->mutex))
74  {
75  //Clean up side effects
76  tlsFreeMem(cache);
77  //Report an error
78  return NULL;
79  }
80 
81  //Save the maximum number of cache entries
82  cache->size = size;
83 
84  //Return a pointer to the newly created cache
85  return cache;
86 }
87 
88 
89 /**
90  * @brief Search the session cache for a given session ID
91  * @param[in] cache Pointer to the session cache
92  * @param[in] sessionId Expected session ID
93  * @param[in] sessionIdLen Length of the session ID
94  * @return A pointer to the matching session is returned. NULL is returned
95  * if the specified ID could not be found in the session cache
96  **/
97 
99  size_t sessionIdLen)
100 {
101 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
102  uint_t i;
103  systime_t time;
104  TlsSessionState *session;
105 
106  //Check parameters
107  if(cache == NULL || sessionId == NULL || sessionIdLen == 0)
108  return NULL;
109 
110  //Initialize session state
111  session = NULL;
112 
113  //Get current time
114  time = osGetSystemTime();
115 
116  //Acquire exclusive access to the session cache
117  osAcquireMutex(&cache->mutex);
118 
119  //Flush expired entries
120  for(i = 0; i < cache->size; i++)
121  {
122  //Skip unused entries
123  if(cache->sessions[i].sessionIdLen != 0)
124  {
125  //Outdated entry?
127  {
128  //This session is no more valid and should be removed from the cache
129  tlsFreeSessionState(&cache->sessions[i]);
130  }
131  }
132  }
133 
134  //Search the cache for the specified session ID
135  for(i = 0; i < cache->size; i++)
136  {
137  //Check whether the current identifier matches the specified session ID
138  if(cache->sessions[i].sessionIdLen == sessionIdLen &&
140  {
141  //A matching session has been found
142  session = &cache->sessions[i];
143  break;
144  }
145  }
146 
147  //Release exclusive access to the session cache
148  osReleaseMutex(&cache->mutex);
149 
150  //Return a pointer to the matching session, if any
151  return session;
152 #else
153  //Not implemented
154  return NULL;
155 #endif
156 }
157 
158 
159 /**
160  * @brief Save current session in cache
161  * @param[in] context TLS context
162  * @return Error code
163  **/
164 
166 {
167 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
168  error_t error;
169  uint_t i;
170  systime_t time;
171  TlsSessionState *session;
172  TlsSessionState *firstFreeEntry;
173  TlsSessionState *oldestEntry;
174 
175  //Check parameters
176  if(context == NULL)
178 
179  //Check whether session caching is supported
180  if(context->cache == NULL)
181  return ERROR_FAILURE;
182 
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  !osMemcmp(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  {
241  error = tlsSaveSessionId(context, firstFreeEntry);
242  }
243  else if(oldestEntry != NULL)
244  {
245  error = tlsSaveSessionId(context, oldestEntry);
246  }
247  else
248  {
249  error = NO_ERROR;
250  }
251 
252  //Release exclusive access to the session cache
253  osReleaseMutex(&context->cache->mutex);
254 
255  //Return status code
256  return error;
257 #else
258  //Not implemented
259  return ERROR_NOT_IMPLEMENTED;
260 #endif
261 }
262 
263 
264 /**
265  * @brief Remove current session from cache
266  * @param[in] context TLS context
267  * @return Error code
268  **/
269 
271 {
272 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
273  uint_t i;
274  TlsSessionState *session;
275 
276  //Check parameters
277  if(context == NULL)
279 
280  //Check whether session caching is supported
281  if(context->cache == NULL)
282  return ERROR_FAILURE;
283 
284  //Ensure the session ID is valid
285  if(context->sessionIdLen == 0)
286  return NO_ERROR;
287 
288  //Acquire exclusive access to the session cache
289  osAcquireMutex(&context->cache->mutex);
290 
291  //Search the cache for the specified session ID
292  for(i = 0; i < context->cache->size; i++)
293  {
294  //Point to the current entry
295  session = &context->cache->sessions[i];
296 
297  //Check whether the current identifier matches the specified session ID
298  if(session->sessionIdLen == context->sessionIdLen &&
299  !osMemcmp(session->sessionId, context->sessionId, session->sessionIdLen))
300  {
301  //Drop current entry
302  tlsFreeSessionState(session);
303  }
304  }
305 
306  //Release exclusive access to the session cache
307  osReleaseMutex(&context->cache->mutex);
308 #endif
309 
310  //Successful processing
311  return NO_ERROR;
312 }
313 
314 
315 /**
316  * @brief Properly dispose a session cache
317  * @param[in] cache Pointer to the session cache to be released
318  **/
319 
320 void tlsFreeCache(TlsCache *cache)
321 {
322  uint_t i;
323 
324  //Valid session cache?
325  if(cache != NULL)
326  {
327  //Loop through the session cache
328  for(i = 0; i < cache->size; i++)
329  {
330  //Release current entry
331  tlsFreeSessionState(&cache->sessions[i]);
332  }
333 
334  //Release mutex object
335  osDeleteMutex(&cache->mutex);
336 
337  //Properly dispose the session cache
338  tlsFreeMem(cache);
339  }
340 }
341 
342 #endif
#define tlsAllocMem(size)
Definition: tls.h:806
TLS helper functions.
error_t tlsSaveToCache(TlsContext *context)
Save current session in cache.
Definition: tls_cache.c:165
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:1946
void tlsFreeCache(TlsCache *cache)
Properly dispose a session cache.
Definition: tls_cache.c:320
error_t tlsSaveSessionId(const TlsContext *context, TlsSessionState *session)
Save session ID.
Definition: tls_misc.c:409
Session cache management.
size_t sessionIdLen
Length of the session identifier.
Definition: tls.h:1950
#define osMemcmp(p1, p2, length)
Definition: os_port.h:149
OsMutex mutex
Mutex preventing simultaneous access to the cache.
Definition: tls.h:1975
Session cache.
Definition: tls.h:1974
void tlsFreeSessionState(TlsSessionState *session)
Properly dispose a session state.
Definition: tls.c:2608
TlsSessionState * tlsFindCache(TlsCache *cache, const uint8_t *sessionId, size_t sessionIdLen)
Search the session cache for a given session ID.
Definition: tls_cache.c:98
uint8_t sessionIdLen
Definition: tls.h:1686
@ 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:270
uint_t size
Maximum number of entries.
Definition: tls.h:1976
uint32_t systime_t
System time.
uint32_t time
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
TLS session state.
Definition: tls.h:1943
uint8_t n
uint8_t sessionId[32]
Session identifier.
Definition: tls.h:1949
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:51
uint8_t sessionId[]
Definition: tls.h:1687
#define TLS_SESSION_CACHE_LIFETIME
Definition: tls.h:145
TlsSessionState sessions[]
Cache entries.
Definition: tls.h:1977
TLS (Transport Layer Security)
unsigned int uint_t
Definition: compiler_port.h:45
#define osMemset(p, value, length)
Definition: os_port.h:131
#define tlsFreeMem(p)
Definition: tls.h:811
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
systime_t osGetSystemTime(void)
Retrieve system time.