1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  SSL session cache implementation
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci/*
8a8e1175bSopenharmony_ci * These session callbacks use a simple chained list
9a8e1175bSopenharmony_ci * to store and retrieve the session information.
10a8e1175bSopenharmony_ci */
11a8e1175bSopenharmony_ci
12a8e1175bSopenharmony_ci#include "common.h"
13a8e1175bSopenharmony_ci
14a8e1175bSopenharmony_ci#if defined(MBEDTLS_SSL_CACHE_C)
15a8e1175bSopenharmony_ci
16a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
17a8e1175bSopenharmony_ci
18a8e1175bSopenharmony_ci#include "mbedtls/ssl_cache.h"
19a8e1175bSopenharmony_ci#include "ssl_misc.h"
20a8e1175bSopenharmony_ci#include "mbedtls/error.h"
21a8e1175bSopenharmony_ci
22a8e1175bSopenharmony_ci#include <string.h>
23a8e1175bSopenharmony_ci
24a8e1175bSopenharmony_civoid mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache)
25a8e1175bSopenharmony_ci{
26a8e1175bSopenharmony_ci    memset(cache, 0, sizeof(mbedtls_ssl_cache_context));
27a8e1175bSopenharmony_ci
28a8e1175bSopenharmony_ci    cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
29a8e1175bSopenharmony_ci    cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
30a8e1175bSopenharmony_ci
31a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
32a8e1175bSopenharmony_ci    mbedtls_mutex_init(&cache->mutex);
33a8e1175bSopenharmony_ci#endif
34a8e1175bSopenharmony_ci}
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ciMBEDTLS_CHECK_RETURN_CRITICAL
37a8e1175bSopenharmony_cistatic int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache,
38a8e1175bSopenharmony_ci                                unsigned char const *session_id,
39a8e1175bSopenharmony_ci                                size_t session_id_len,
40a8e1175bSopenharmony_ci                                mbedtls_ssl_cache_entry **dst)
41a8e1175bSopenharmony_ci{
42a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND;
43a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
44a8e1175bSopenharmony_ci    mbedtls_time_t t = mbedtls_time(NULL);
45a8e1175bSopenharmony_ci#endif
46a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *cur;
47a8e1175bSopenharmony_ci
48a8e1175bSopenharmony_ci    for (cur = cache->chain; cur != NULL; cur = cur->next) {
49a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
50a8e1175bSopenharmony_ci        if (cache->timeout != 0 &&
51a8e1175bSopenharmony_ci            (int) (t - cur->timestamp) > cache->timeout) {
52a8e1175bSopenharmony_ci            continue;
53a8e1175bSopenharmony_ci        }
54a8e1175bSopenharmony_ci#endif
55a8e1175bSopenharmony_ci
56a8e1175bSopenharmony_ci        if (session_id_len != cur->session_id_len ||
57a8e1175bSopenharmony_ci            memcmp(session_id, cur->session_id,
58a8e1175bSopenharmony_ci                   cur->session_id_len) != 0) {
59a8e1175bSopenharmony_ci            continue;
60a8e1175bSopenharmony_ci        }
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci        break;
63a8e1175bSopenharmony_ci    }
64a8e1175bSopenharmony_ci
65a8e1175bSopenharmony_ci    if (cur != NULL) {
66a8e1175bSopenharmony_ci        *dst = cur;
67a8e1175bSopenharmony_ci        ret = 0;
68a8e1175bSopenharmony_ci    }
69a8e1175bSopenharmony_ci
70a8e1175bSopenharmony_ci    return ret;
71a8e1175bSopenharmony_ci}
72a8e1175bSopenharmony_ci
73a8e1175bSopenharmony_ci
74a8e1175bSopenharmony_ciint mbedtls_ssl_cache_get(void *data,
75a8e1175bSopenharmony_ci                          unsigned char const *session_id,
76a8e1175bSopenharmony_ci                          size_t session_id_len,
77a8e1175bSopenharmony_ci                          mbedtls_ssl_session *session)
78a8e1175bSopenharmony_ci{
79a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
80a8e1175bSopenharmony_ci    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
81a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *entry;
82a8e1175bSopenharmony_ci
83a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
84a8e1175bSopenharmony_ci    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
85a8e1175bSopenharmony_ci        return ret;
86a8e1175bSopenharmony_ci    }
87a8e1175bSopenharmony_ci#endif
88a8e1175bSopenharmony_ci
89a8e1175bSopenharmony_ci    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);
90a8e1175bSopenharmony_ci    if (ret != 0) {
91a8e1175bSopenharmony_ci        goto exit;
92a8e1175bSopenharmony_ci    }
93a8e1175bSopenharmony_ci
94a8e1175bSopenharmony_ci    ret = mbedtls_ssl_session_load(session,
95a8e1175bSopenharmony_ci                                   entry->session,
96a8e1175bSopenharmony_ci                                   entry->session_len);
97a8e1175bSopenharmony_ci    if (ret != 0) {
98a8e1175bSopenharmony_ci        goto exit;
99a8e1175bSopenharmony_ci    }
100a8e1175bSopenharmony_ci
101a8e1175bSopenharmony_ci    ret = 0;
102a8e1175bSopenharmony_ci
103a8e1175bSopenharmony_ciexit:
104a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
105a8e1175bSopenharmony_ci    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
106a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
107a8e1175bSopenharmony_ci    }
108a8e1175bSopenharmony_ci#endif
109a8e1175bSopenharmony_ci
110a8e1175bSopenharmony_ci    return ret;
111a8e1175bSopenharmony_ci}
112a8e1175bSopenharmony_ci
113a8e1175bSopenharmony_ci/* zeroize a cache entry */
114a8e1175bSopenharmony_cistatic void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry)
115a8e1175bSopenharmony_ci{
116a8e1175bSopenharmony_ci    if (entry == NULL) {
117a8e1175bSopenharmony_ci        return;
118a8e1175bSopenharmony_ci    }
119a8e1175bSopenharmony_ci
120a8e1175bSopenharmony_ci    /* zeroize and free session structure */
121a8e1175bSopenharmony_ci    if (entry->session != NULL) {
122a8e1175bSopenharmony_ci        mbedtls_zeroize_and_free(entry->session, entry->session_len);
123a8e1175bSopenharmony_ci    }
124a8e1175bSopenharmony_ci
125a8e1175bSopenharmony_ci    /* zeroize the whole entry structure */
126a8e1175bSopenharmony_ci    mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry));
127a8e1175bSopenharmony_ci}
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ciMBEDTLS_CHECK_RETURN_CRITICAL
130a8e1175bSopenharmony_cistatic int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache,
131a8e1175bSopenharmony_ci                                       unsigned char const *session_id,
132a8e1175bSopenharmony_ci                                       size_t session_id_len,
133a8e1175bSopenharmony_ci                                       mbedtls_ssl_cache_entry **dst)
134a8e1175bSopenharmony_ci{
135a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
136a8e1175bSopenharmony_ci    mbedtls_time_t t = mbedtls_time(NULL), oldest = 0;
137a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME */
138a8e1175bSopenharmony_ci
139a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *old = NULL;
140a8e1175bSopenharmony_ci    int count = 0;
141a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *cur, *last;
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci    /* Check 1: Is there already an entry with the given session ID?
144a8e1175bSopenharmony_ci     *
145a8e1175bSopenharmony_ci     * If yes, overwrite it.
146a8e1175bSopenharmony_ci     *
147a8e1175bSopenharmony_ci     * If not, `count` will hold the size of the session cache
148a8e1175bSopenharmony_ci     * at the end of this loop, and `last` will point to the last
149a8e1175bSopenharmony_ci     * entry, both of which will be used later. */
150a8e1175bSopenharmony_ci
151a8e1175bSopenharmony_ci    last = NULL;
152a8e1175bSopenharmony_ci    for (cur = cache->chain; cur != NULL; cur = cur->next) {
153a8e1175bSopenharmony_ci        count++;
154a8e1175bSopenharmony_ci        if (session_id_len == cur->session_id_len &&
155a8e1175bSopenharmony_ci            memcmp(session_id, cur->session_id, cur->session_id_len) == 0) {
156a8e1175bSopenharmony_ci            goto found;
157a8e1175bSopenharmony_ci        }
158a8e1175bSopenharmony_ci        last = cur;
159a8e1175bSopenharmony_ci    }
160a8e1175bSopenharmony_ci
161a8e1175bSopenharmony_ci    /* Check 2: Is there an outdated entry in the cache?
162a8e1175bSopenharmony_ci     *
163a8e1175bSopenharmony_ci     * If so, overwrite it.
164a8e1175bSopenharmony_ci     *
165a8e1175bSopenharmony_ci     * If not, remember the oldest entry in `old` for later.
166a8e1175bSopenharmony_ci     */
167a8e1175bSopenharmony_ci
168a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
169a8e1175bSopenharmony_ci    for (cur = cache->chain; cur != NULL; cur = cur->next) {
170a8e1175bSopenharmony_ci        if (cache->timeout != 0 &&
171a8e1175bSopenharmony_ci            (int) (t - cur->timestamp) > cache->timeout) {
172a8e1175bSopenharmony_ci            goto found;
173a8e1175bSopenharmony_ci        }
174a8e1175bSopenharmony_ci
175a8e1175bSopenharmony_ci        if (oldest == 0 || cur->timestamp < oldest) {
176a8e1175bSopenharmony_ci            oldest = cur->timestamp;
177a8e1175bSopenharmony_ci            old = cur;
178a8e1175bSopenharmony_ci        }
179a8e1175bSopenharmony_ci    }
180a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME */
181a8e1175bSopenharmony_ci
182a8e1175bSopenharmony_ci    /* Check 3: Is there free space in the cache? */
183a8e1175bSopenharmony_ci
184a8e1175bSopenharmony_ci    if (count < cache->max_entries) {
185a8e1175bSopenharmony_ci        /* Create new entry */
186a8e1175bSopenharmony_ci        cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));
187a8e1175bSopenharmony_ci        if (cur == NULL) {
188a8e1175bSopenharmony_ci            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
189a8e1175bSopenharmony_ci        }
190a8e1175bSopenharmony_ci
191a8e1175bSopenharmony_ci        /* Append to the end of the linked list. */
192a8e1175bSopenharmony_ci        if (last == NULL) {
193a8e1175bSopenharmony_ci            cache->chain = cur;
194a8e1175bSopenharmony_ci        } else {
195a8e1175bSopenharmony_ci            last->next = cur;
196a8e1175bSopenharmony_ci        }
197a8e1175bSopenharmony_ci
198a8e1175bSopenharmony_ci        goto found;
199a8e1175bSopenharmony_ci    }
200a8e1175bSopenharmony_ci
201a8e1175bSopenharmony_ci    /* Last resort: The cache is full and doesn't contain any outdated
202a8e1175bSopenharmony_ci     * elements. In this case, we evict the oldest one, judged by timestamp
203a8e1175bSopenharmony_ci     * (if present) or cache-order. */
204a8e1175bSopenharmony_ci
205a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
206a8e1175bSopenharmony_ci    if (old == NULL) {
207a8e1175bSopenharmony_ci        /* This should only happen on an ill-configured cache
208a8e1175bSopenharmony_ci         * with max_entries == 0. */
209a8e1175bSopenharmony_ci        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
210a8e1175bSopenharmony_ci    }
211a8e1175bSopenharmony_ci#else /* MBEDTLS_HAVE_TIME */
212a8e1175bSopenharmony_ci    /* Reuse first entry in chain, but move to last place. */
213a8e1175bSopenharmony_ci    if (cache->chain == NULL) {
214a8e1175bSopenharmony_ci        /* This should never happen */
215a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
216a8e1175bSopenharmony_ci    }
217a8e1175bSopenharmony_ci
218a8e1175bSopenharmony_ci    old = cache->chain;
219a8e1175bSopenharmony_ci    cache->chain = old->next;
220a8e1175bSopenharmony_ci    old->next = NULL;
221a8e1175bSopenharmony_ci    last->next = old;
222a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME */
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci    /* Now `old` points to the oldest entry to be overwritten. */
225a8e1175bSopenharmony_ci    cur = old;
226a8e1175bSopenharmony_ci
227a8e1175bSopenharmony_cifound:
228a8e1175bSopenharmony_ci
229a8e1175bSopenharmony_ci    /* If we're reusing an entry, free it first. */
230a8e1175bSopenharmony_ci    if (cur->session != NULL) {
231a8e1175bSopenharmony_ci        /* `ssl_cache_entry_zeroize` would break the chain,
232a8e1175bSopenharmony_ci         * so we reuse `old` to record `next` temporarily. */
233a8e1175bSopenharmony_ci        old = cur->next;
234a8e1175bSopenharmony_ci        ssl_cache_entry_zeroize(cur);
235a8e1175bSopenharmony_ci        cur->next = old;
236a8e1175bSopenharmony_ci    }
237a8e1175bSopenharmony_ci
238a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
239a8e1175bSopenharmony_ci    cur->timestamp = t;
240a8e1175bSopenharmony_ci#endif
241a8e1175bSopenharmony_ci
242a8e1175bSopenharmony_ci    *dst = cur;
243a8e1175bSopenharmony_ci    return 0;
244a8e1175bSopenharmony_ci}
245a8e1175bSopenharmony_ci
246a8e1175bSopenharmony_ciint mbedtls_ssl_cache_set(void *data,
247a8e1175bSopenharmony_ci                          unsigned char const *session_id,
248a8e1175bSopenharmony_ci                          size_t session_id_len,
249a8e1175bSopenharmony_ci                          const mbedtls_ssl_session *session)
250a8e1175bSopenharmony_ci{
251a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
252a8e1175bSopenharmony_ci    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
253a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *cur;
254a8e1175bSopenharmony_ci
255a8e1175bSopenharmony_ci    size_t session_serialized_len = 0;
256a8e1175bSopenharmony_ci    unsigned char *session_serialized = NULL;
257a8e1175bSopenharmony_ci
258a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
259a8e1175bSopenharmony_ci    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
260a8e1175bSopenharmony_ci        return ret;
261a8e1175bSopenharmony_ci    }
262a8e1175bSopenharmony_ci#endif
263a8e1175bSopenharmony_ci
264a8e1175bSopenharmony_ci    ret = ssl_cache_pick_writing_slot(cache,
265a8e1175bSopenharmony_ci                                      session_id, session_id_len,
266a8e1175bSopenharmony_ci                                      &cur);
267a8e1175bSopenharmony_ci    if (ret != 0) {
268a8e1175bSopenharmony_ci        goto exit;
269a8e1175bSopenharmony_ci    }
270a8e1175bSopenharmony_ci
271a8e1175bSopenharmony_ci    /* Check how much space we need to serialize the session
272a8e1175bSopenharmony_ci     * and allocate a sufficiently large buffer. */
273a8e1175bSopenharmony_ci    ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len);
274a8e1175bSopenharmony_ci    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
275a8e1175bSopenharmony_ci        goto exit;
276a8e1175bSopenharmony_ci    }
277a8e1175bSopenharmony_ci
278a8e1175bSopenharmony_ci    session_serialized = mbedtls_calloc(1, session_serialized_len);
279a8e1175bSopenharmony_ci    if (session_serialized == NULL) {
280a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
281a8e1175bSopenharmony_ci        goto exit;
282a8e1175bSopenharmony_ci    }
283a8e1175bSopenharmony_ci
284a8e1175bSopenharmony_ci    /* Now serialize the session into the allocated buffer. */
285a8e1175bSopenharmony_ci    ret = mbedtls_ssl_session_save(session,
286a8e1175bSopenharmony_ci                                   session_serialized,
287a8e1175bSopenharmony_ci                                   session_serialized_len,
288a8e1175bSopenharmony_ci                                   &session_serialized_len);
289a8e1175bSopenharmony_ci    if (ret != 0) {
290a8e1175bSopenharmony_ci        goto exit;
291a8e1175bSopenharmony_ci    }
292a8e1175bSopenharmony_ci
293a8e1175bSopenharmony_ci    if (session_id_len > sizeof(cur->session_id)) {
294a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
295a8e1175bSopenharmony_ci        goto exit;
296a8e1175bSopenharmony_ci    }
297a8e1175bSopenharmony_ci    cur->session_id_len = session_id_len;
298a8e1175bSopenharmony_ci    memcpy(cur->session_id, session_id, session_id_len);
299a8e1175bSopenharmony_ci
300a8e1175bSopenharmony_ci    cur->session = session_serialized;
301a8e1175bSopenharmony_ci    cur->session_len = session_serialized_len;
302a8e1175bSopenharmony_ci    session_serialized = NULL;
303a8e1175bSopenharmony_ci
304a8e1175bSopenharmony_ci    ret = 0;
305a8e1175bSopenharmony_ci
306a8e1175bSopenharmony_ciexit:
307a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
308a8e1175bSopenharmony_ci    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
309a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
310a8e1175bSopenharmony_ci    }
311a8e1175bSopenharmony_ci#endif
312a8e1175bSopenharmony_ci
313a8e1175bSopenharmony_ci    if (session_serialized != NULL) {
314a8e1175bSopenharmony_ci        mbedtls_zeroize_and_free(session_serialized, session_serialized_len);
315a8e1175bSopenharmony_ci        session_serialized = NULL;
316a8e1175bSopenharmony_ci    }
317a8e1175bSopenharmony_ci
318a8e1175bSopenharmony_ci    return ret;
319a8e1175bSopenharmony_ci}
320a8e1175bSopenharmony_ci
321a8e1175bSopenharmony_ciint mbedtls_ssl_cache_remove(void *data,
322a8e1175bSopenharmony_ci                             unsigned char const *session_id,
323a8e1175bSopenharmony_ci                             size_t session_id_len)
324a8e1175bSopenharmony_ci{
325a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326a8e1175bSopenharmony_ci    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
327a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *entry;
328a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *prev;
329a8e1175bSopenharmony_ci
330a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
331a8e1175bSopenharmony_ci    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
332a8e1175bSopenharmony_ci        return ret;
333a8e1175bSopenharmony_ci    }
334a8e1175bSopenharmony_ci#endif
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);
337a8e1175bSopenharmony_ci    /* No valid entry found, exit with success */
338a8e1175bSopenharmony_ci    if (ret != 0) {
339a8e1175bSopenharmony_ci        ret = 0;
340a8e1175bSopenharmony_ci        goto exit;
341a8e1175bSopenharmony_ci    }
342a8e1175bSopenharmony_ci
343a8e1175bSopenharmony_ci    /* Now we remove the entry from the chain */
344a8e1175bSopenharmony_ci    if (entry == cache->chain) {
345a8e1175bSopenharmony_ci        cache->chain = entry->next;
346a8e1175bSopenharmony_ci        goto free;
347a8e1175bSopenharmony_ci    }
348a8e1175bSopenharmony_ci    for (prev = cache->chain; prev->next != NULL; prev = prev->next) {
349a8e1175bSopenharmony_ci        if (prev->next == entry) {
350a8e1175bSopenharmony_ci            prev->next = entry->next;
351a8e1175bSopenharmony_ci            break;
352a8e1175bSopenharmony_ci        }
353a8e1175bSopenharmony_ci    }
354a8e1175bSopenharmony_ci
355a8e1175bSopenharmony_cifree:
356a8e1175bSopenharmony_ci    ssl_cache_entry_zeroize(entry);
357a8e1175bSopenharmony_ci    mbedtls_free(entry);
358a8e1175bSopenharmony_ci    ret = 0;
359a8e1175bSopenharmony_ci
360a8e1175bSopenharmony_ciexit:
361a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
362a8e1175bSopenharmony_ci    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
363a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
364a8e1175bSopenharmony_ci    }
365a8e1175bSopenharmony_ci#endif
366a8e1175bSopenharmony_ci
367a8e1175bSopenharmony_ci    return ret;
368a8e1175bSopenharmony_ci}
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
371a8e1175bSopenharmony_civoid mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout)
372a8e1175bSopenharmony_ci{
373a8e1175bSopenharmony_ci    if (timeout < 0) {
374a8e1175bSopenharmony_ci        timeout = 0;
375a8e1175bSopenharmony_ci    }
376a8e1175bSopenharmony_ci
377a8e1175bSopenharmony_ci    cache->timeout = timeout;
378a8e1175bSopenharmony_ci}
379a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME */
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_civoid mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)
382a8e1175bSopenharmony_ci{
383a8e1175bSopenharmony_ci    if (max < 0) {
384a8e1175bSopenharmony_ci        max = 0;
385a8e1175bSopenharmony_ci    }
386a8e1175bSopenharmony_ci
387a8e1175bSopenharmony_ci    cache->max_entries = max;
388a8e1175bSopenharmony_ci}
389a8e1175bSopenharmony_ci
390a8e1175bSopenharmony_civoid mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache)
391a8e1175bSopenharmony_ci{
392a8e1175bSopenharmony_ci    mbedtls_ssl_cache_entry *cur, *prv;
393a8e1175bSopenharmony_ci
394a8e1175bSopenharmony_ci    cur = cache->chain;
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_ci    while (cur != NULL) {
397a8e1175bSopenharmony_ci        prv = cur;
398a8e1175bSopenharmony_ci        cur = cur->next;
399a8e1175bSopenharmony_ci
400a8e1175bSopenharmony_ci        ssl_cache_entry_zeroize(prv);
401a8e1175bSopenharmony_ci        mbedtls_free(prv);
402a8e1175bSopenharmony_ci    }
403a8e1175bSopenharmony_ci
404a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_C)
405a8e1175bSopenharmony_ci    mbedtls_mutex_free(&cache->mutex);
406a8e1175bSopenharmony_ci#endif
407a8e1175bSopenharmony_ci    cache->chain = NULL;
408a8e1175bSopenharmony_ci}
409a8e1175bSopenharmony_ci
410a8e1175bSopenharmony_ci#endif /* MBEDTLS_SSL_CACHE_C */
411