NCBI C++ ToolKit
ssl_cache.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /*
2  * SSL session cache implementation
3  *
4  * Copyright The Mbed TLS Contributors
5  * SPDX-License-Identifier: Apache-2.0
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may
8  * not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 /*
20  * These session callbacks use a simple chained list
21  * to store and retrieve the session information.
22  */
23 
24 #include "common.h"
25 
26 #if defined(MBEDTLS_SSL_CACHE_C)
27 
28 #include "mbedtls/platform.h"
29 
30 #include "mbedtls/ssl_cache.h"
31 #include "mbedtls/ssl_internal.h"
32 
33 #include <string.h>
34 
36 {
37  memset(cache, 0, sizeof(mbedtls_ssl_cache_context));
38 
41 
42 #if defined(MBEDTLS_THREADING_C)
43  mbedtls_mutex_init(&cache->mutex);
44 #endif
45 }
46 
47 int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session)
48 {
49  int ret = 1;
50 #if defined(MBEDTLS_HAVE_TIME)
52 #endif
54  mbedtls_ssl_cache_entry *cur, *entry;
55 
56 #if defined(MBEDTLS_THREADING_C)
57  if (mbedtls_mutex_lock(&cache->mutex) != 0) {
58  return 1;
59  }
60 #endif
61 
62  cur = cache->chain;
63  entry = NULL;
64 
65  while (cur != NULL) {
66  entry = cur;
67  cur = cur->next;
68 
69 #if defined(MBEDTLS_HAVE_TIME)
70  if (cache->timeout != 0 &&
71  (int) (t - entry->timestamp) > cache->timeout) {
72  continue;
73  }
74 #endif
75 
76  if (session->id_len != entry->session.id_len ||
77  memcmp(session->id, entry->session.id,
78  entry->session.id_len) != 0) {
79  continue;
80  }
81 
82  ret = mbedtls_ssl_session_copy(session, &entry->session);
83  if (ret != 0) {
84  ret = 1;
85  goto exit;
86  }
87 
88 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
89  defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
90  /*
91  * Restore peer certificate (without rest of the original chain)
92  */
93  if (entry->peer_cert.p != NULL) {
94  /* `session->peer_cert` is NULL after the call to
95  * mbedtls_ssl_session_copy(), because cache entries
96  * have the `peer_cert` field set to NULL. */
97 
98  if ((session->peer_cert = mbedtls_calloc(1,
99  sizeof(mbedtls_x509_crt))) == NULL) {
100  ret = 1;
101  goto exit;
102  }
103 
104  mbedtls_x509_crt_init(session->peer_cert);
105  if (mbedtls_x509_crt_parse(session->peer_cert, entry->peer_cert.p,
106  entry->peer_cert.len) != 0) {
107  mbedtls_free(session->peer_cert);
108  session->peer_cert = NULL;
109  ret = 1;
110  goto exit;
111  }
112  }
113 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
114 
115  ret = 0;
116  goto exit;
117  }
118 
119 exit:
120 #if defined(MBEDTLS_THREADING_C)
121  if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
122  ret = 1;
123  }
124 #endif
125 
126  return ret;
127 }
128 
129 int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session)
130 {
131  int ret = 1;
132 #if defined(MBEDTLS_HAVE_TIME)
133  mbedtls_time_t t = mbedtls_time(NULL), oldest = 0;
135 #endif
137  mbedtls_ssl_cache_entry *cur, *prv;
138  int count = 0;
139 
140 #if defined(MBEDTLS_THREADING_C)
141  if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
142  return ret;
143  }
144 #endif
145 
146  cur = cache->chain;
147  prv = NULL;
148 
149  while (cur != NULL) {
150  count++;
151 
152 #if defined(MBEDTLS_HAVE_TIME)
153  if (cache->timeout != 0 &&
154  (int) (t - cur->timestamp) > cache->timeout) {
155  cur->timestamp = t;
156  break; /* expired, reuse this slot, update timestamp */
157  }
158 #endif
159 
160  if (memcmp(session->id, cur->session.id, cur->session.id_len) == 0) {
161  break; /* client reconnected, keep timestamp for session id */
162 
163  }
164 #if defined(MBEDTLS_HAVE_TIME)
165  if (oldest == 0 || cur->timestamp < oldest) {
166  oldest = cur->timestamp;
167  old = cur;
168  }
169 #endif
170 
171  prv = cur;
172  cur = cur->next;
173  }
174 
175  if (cur == NULL) {
176 #if defined(MBEDTLS_HAVE_TIME)
177  /*
178  * Reuse oldest entry if max_entries reached
179  */
180  if (count >= cache->max_entries) {
181  if (old == NULL) {
182  ret = 1;
183  goto exit;
184  }
185 
186  cur = old;
187  }
188 #else /* MBEDTLS_HAVE_TIME */
189  /*
190  * Reuse first entry in chain if max_entries reached,
191  * but move to last place
192  */
193  if (count >= cache->max_entries) {
194  if (cache->chain == NULL) {
195  ret = 1;
196  goto exit;
197  }
198 
199  cur = cache->chain;
200  cache->chain = cur->next;
201  cur->next = NULL;
202  prv->next = cur;
203  }
204 #endif /* MBEDTLS_HAVE_TIME */
205  else {
206  /*
207  * max_entries not reached, create new entry
208  */
209  cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));
210  if (cur == NULL) {
211  ret = 1;
212  goto exit;
213  }
214 
215  if (prv == NULL) {
216  cache->chain = cur;
217  } else {
218  prv->next = cur;
219  }
220  }
221 
222 #if defined(MBEDTLS_HAVE_TIME)
223  cur->timestamp = t;
224 #endif
225  }
226 
227 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
228  defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
229  /*
230  * If we're reusing an entry, free its certificate first
231  */
232  if (cur->peer_cert.p != NULL) {
233  mbedtls_free(cur->peer_cert.p);
234  memset(&cur->peer_cert, 0, sizeof(mbedtls_x509_buf));
235  }
236 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
237 
238  /* Copy the entire session; this temporarily makes a copy of the
239  * X.509 CRT structure even though we only want to store the raw CRT.
240  * This inefficiency will go away as soon as we implement on-demand
241  * parsing of CRTs, in which case there's no need for the `peer_cert`
242  * field anymore in the first place, and we're done after this call. */
243  ret = mbedtls_ssl_session_copy(&cur->session, session);
244  if (ret != 0) {
245  ret = 1;
246  goto exit;
247  }
248 
249 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
250  defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
251  /* If present, free the X.509 structure and only store the raw CRT data. */
252  if (cur->session.peer_cert != NULL) {
253  cur->peer_cert.p =
254  mbedtls_calloc(1, cur->session.peer_cert->raw.len);
255  if (cur->peer_cert.p == NULL) {
256  ret = 1;
257  goto exit;
258  }
259 
260  memcpy(cur->peer_cert.p,
261  cur->session.peer_cert->raw.p,
262  cur->session.peer_cert->raw.len);
263  cur->peer_cert.len = session->peer_cert->raw.len;
264 
265  mbedtls_x509_crt_free(cur->session.peer_cert);
266  mbedtls_free(cur->session.peer_cert);
267  cur->session.peer_cert = NULL;
268  }
269 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
270 
271  ret = 0;
272 
273 exit:
274 #if defined(MBEDTLS_THREADING_C)
275  if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
276  ret = 1;
277  }
278 #endif
279 
280  return ret;
281 }
282 
283 #if defined(MBEDTLS_HAVE_TIME)
285 {
286  if (timeout < 0) {
287  timeout = 0;
288  }
289 
290  cache->timeout = timeout;
291 }
292 #endif /* MBEDTLS_HAVE_TIME */
293 
295 {
296  if (max < 0) {
297  max = 0;
298  }
299 
300  cache->max_entries = max;
301 }
302 
304 {
305  mbedtls_ssl_cache_entry *cur, *prv;
306 
307  cur = cache->chain;
308 
309  while (cur != NULL) {
310  prv = cur;
311  cur = cur->next;
312 
314 
315 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
316  defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
317  mbedtls_free(prv->peer_cert.p);
318 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
319 
320  mbedtls_free(prv);
321  }
322 
323 #if defined(MBEDTLS_THREADING_C)
324  mbedtls_mutex_free(&cache->mutex);
325 #endif
326  cache->chain = NULL;
327 }
328 
329 #endif /* MBEDTLS_SSL_CACHE_C */
#define NULL
Definition: ncbistd.hpp:225
exit(2)
EIPRangeType t
Definition: ncbi_localip.c:101
#define mbedtls_mutex_init
#define mbedtls_x509_crt_init
#define mbedtls_mutex_free
#define mbedtls_x509_crt_free
#define mbedtls_x509_crt_parse
#define mbedtls_ssl_cache_set_timeout
#define mbedtls_mutex_lock
#define mbedtls_mutex_unlock
T max(T x_, T y_)
This file contains the definitions and functions of the Mbed TLS platform abstraction layer.
#define mbedtls_free
Definition: platform.h:168
#define mbedtls_calloc
Definition: platform.h:169
#define mbedtls_time
Definition: platform_time.h:64
time_t mbedtls_time_t
Definition: platform_time.h:43
void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
Free referenced items in an SSL session including the peer certificate and clear memory.
SSL session cache implementation.
#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT
Definition: ssl_cache.h:46
#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES
Definition: ssl_cache.h:50
int mbedtls_ssl_cache_set(void *data, const mbedtls_ssl_session *session)
Cache set callback implementation (Thread-safe if MBEDTLS_THREADING_C is enabled)
void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache)
Initialize an SSL cache context.
void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache)
Free referenced items in a cache context and clear memory.
void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)
Set the maximum number of cache entries (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
int mbedtls_ssl_cache_get(void *data, mbedtls_ssl_session *session)
Cache get callback implementation (Thread-safe if MBEDTLS_THREADING_C is enabled)
Internal functions shared by the SSL modules.
MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src)
Type-length-value structure that allows for ASN1 using DER.
Definition: asn1.h:155
Cache context.
Definition: ssl_cache.h:80
mbedtls_ssl_cache_entry * chain
Definition: ssl_cache.h:81
This structure is used for storing cache entries.
Definition: ssl_cache.h:65
mbedtls_ssl_cache_entry * next
Definition: ssl_cache.h:74
mbedtls_ssl_session session
Definition: ssl_cache.h:69
unsigned char id[32]
Definition: ssl.h:984
size_t id_len
Definition: ssl.h:983
Container for an X.509 certificate.
Definition: x509_crt.h:52
Modified on Tue Dec 05 02:16:54 2023 by modify_doxy.py rev. 669887