]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/mbedtls/library/ssl_cache.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / mbedtls / library / ssl_cache.c
1 /*\r
2  *  SSL session cache implementation\r
3  *\r
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
5  *  SPDX-License-Identifier: Apache-2.0\r
6  *\r
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may\r
8  *  not use this file except in compliance with the License.\r
9  *  You may obtain a copy of the License at\r
10  *\r
11  *  http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  *  Unless required by applicable law or agreed to in writing, software\r
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  *  See the License for the specific language governing permissions and\r
17  *  limitations under the License.\r
18  *\r
19  *  This file is part of mbed TLS (https://tls.mbed.org)\r
20  */\r
21 /*\r
22  * These session callbacks use a simple chained list\r
23  * to store and retrieve the session information.\r
24  */\r
25 \r
26 #if !defined(MBEDTLS_CONFIG_FILE)\r
27 #include "mbedtls/config.h"\r
28 #else\r
29 #include MBEDTLS_CONFIG_FILE\r
30 #endif\r
31 \r
32 #if defined(MBEDTLS_SSL_CACHE_C)\r
33 \r
34 #if defined(MBEDTLS_PLATFORM_C)\r
35 #include "mbedtls/platform.h"\r
36 #else\r
37 #include <stdlib.h>\r
38 #define mbedtls_calloc    calloc\r
39 #define mbedtls_free      free\r
40 #endif\r
41 \r
42 #include "mbedtls/ssl_cache.h"\r
43 #include "mbedtls/ssl_internal.h"\r
44 \r
45 #include <string.h>\r
46 \r
47 void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )\r
48 {\r
49     memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );\r
50 \r
51     cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;\r
52     cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;\r
53 \r
54 #if defined(MBEDTLS_THREADING_C)\r
55     mbedtls_mutex_init( &cache->mutex );\r
56 #endif\r
57 }\r
58 \r
59 int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )\r
60 {\r
61     int ret = 1;\r
62 #if defined(MBEDTLS_HAVE_TIME)\r
63     mbedtls_time_t t = mbedtls_time( NULL );\r
64 #endif\r
65     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;\r
66     mbedtls_ssl_cache_entry *cur, *entry;\r
67 \r
68 #if defined(MBEDTLS_THREADING_C)\r
69     if( mbedtls_mutex_lock( &cache->mutex ) != 0 )\r
70         return( 1 );\r
71 #endif\r
72 \r
73     cur = cache->chain;\r
74     entry = NULL;\r
75 \r
76     while( cur != NULL )\r
77     {\r
78         entry = cur;\r
79         cur = cur->next;\r
80 \r
81 #if defined(MBEDTLS_HAVE_TIME)\r
82         if( cache->timeout != 0 &&\r
83             (int) ( t - entry->timestamp ) > cache->timeout )\r
84             continue;\r
85 #endif\r
86 \r
87         if( session->ciphersuite != entry->session.ciphersuite ||\r
88             session->compression != entry->session.compression ||\r
89             session->id_len != entry->session.id_len )\r
90             continue;\r
91 \r
92         if( memcmp( session->id, entry->session.id,\r
93                     entry->session.id_len ) != 0 )\r
94             continue;\r
95 \r
96         ret = mbedtls_ssl_session_copy( session, &entry->session );\r
97         if( ret != 0 )\r
98         {\r
99             ret = 1;\r
100             goto exit;\r
101         }\r
102 \r
103 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \\r
104     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\r
105         /*\r
106          * Restore peer certificate (without rest of the original chain)\r
107          */\r
108         if( entry->peer_cert.p != NULL )\r
109         {\r
110             /* `session->peer_cert` is NULL after the call to\r
111              * mbedtls_ssl_session_copy(), because cache entries\r
112              * have the `peer_cert` field set to NULL. */\r
113 \r
114             if( ( session->peer_cert = mbedtls_calloc( 1,\r
115                                  sizeof(mbedtls_x509_crt) ) ) == NULL )\r
116             {\r
117                 ret = 1;\r
118                 goto exit;\r
119             }\r
120 \r
121             mbedtls_x509_crt_init( session->peer_cert );\r
122             if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p,\r
123                                 entry->peer_cert.len ) != 0 )\r
124             {\r
125                 mbedtls_free( session->peer_cert );\r
126                 session->peer_cert = NULL;\r
127                 ret = 1;\r
128                 goto exit;\r
129             }\r
130         }\r
131 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\r
132 \r
133         ret = 0;\r
134         goto exit;\r
135     }\r
136 \r
137 exit:\r
138 #if defined(MBEDTLS_THREADING_C)\r
139     if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )\r
140         ret = 1;\r
141 #endif\r
142 \r
143     return( ret );\r
144 }\r
145 \r
146 int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )\r
147 {\r
148     int ret = 1;\r
149 #if defined(MBEDTLS_HAVE_TIME)\r
150     mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0;\r
151     mbedtls_ssl_cache_entry *old = NULL;\r
152 #endif\r
153     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;\r
154     mbedtls_ssl_cache_entry *cur, *prv;\r
155     int count = 0;\r
156 \r
157 #if defined(MBEDTLS_THREADING_C)\r
158     if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 )\r
159         return( ret );\r
160 #endif\r
161 \r
162     cur = cache->chain;\r
163     prv = NULL;\r
164 \r
165     while( cur != NULL )\r
166     {\r
167         count++;\r
168 \r
169 #if defined(MBEDTLS_HAVE_TIME)\r
170         if( cache->timeout != 0 &&\r
171             (int) ( t - cur->timestamp ) > cache->timeout )\r
172         {\r
173             cur->timestamp = t;\r
174             break; /* expired, reuse this slot, update timestamp */\r
175         }\r
176 #endif\r
177 \r
178         if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 )\r
179             break; /* client reconnected, keep timestamp for session id */\r
180 \r
181 #if defined(MBEDTLS_HAVE_TIME)\r
182         if( oldest == 0 || cur->timestamp < oldest )\r
183         {\r
184             oldest = cur->timestamp;\r
185             old = cur;\r
186         }\r
187 #endif\r
188 \r
189         prv = cur;\r
190         cur = cur->next;\r
191     }\r
192 \r
193     if( cur == NULL )\r
194     {\r
195 #if defined(MBEDTLS_HAVE_TIME)\r
196         /*\r
197          * Reuse oldest entry if max_entries reached\r
198          */\r
199         if( count >= cache->max_entries )\r
200         {\r
201             if( old == NULL )\r
202             {\r
203                 ret = 1;\r
204                 goto exit;\r
205             }\r
206 \r
207             cur = old;\r
208         }\r
209 #else /* MBEDTLS_HAVE_TIME */\r
210         /*\r
211          * Reuse first entry in chain if max_entries reached,\r
212          * but move to last place\r
213          */\r
214         if( count >= cache->max_entries )\r
215         {\r
216             if( cache->chain == NULL )\r
217             {\r
218                 ret = 1;\r
219                 goto exit;\r
220             }\r
221 \r
222             cur = cache->chain;\r
223             cache->chain = cur->next;\r
224             cur->next = NULL;\r
225             prv->next = cur;\r
226         }\r
227 #endif /* MBEDTLS_HAVE_TIME */\r
228         else\r
229         {\r
230             /*\r
231              * max_entries not reached, create new entry\r
232              */\r
233             cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) );\r
234             if( cur == NULL )\r
235             {\r
236                 ret = 1;\r
237                 goto exit;\r
238             }\r
239 \r
240             if( prv == NULL )\r
241                 cache->chain = cur;\r
242             else\r
243                 prv->next = cur;\r
244         }\r
245 \r
246 #if defined(MBEDTLS_HAVE_TIME)\r
247         cur->timestamp = t;\r
248 #endif\r
249     }\r
250 \r
251 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \\r
252     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\r
253     /*\r
254      * If we're reusing an entry, free its certificate first\r
255      */\r
256     if( cur->peer_cert.p != NULL )\r
257     {\r
258         mbedtls_free( cur->peer_cert.p );\r
259         memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );\r
260     }\r
261 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\r
262 \r
263     /* Copy the entire session; this temporarily makes a copy of the\r
264      * X.509 CRT structure even though we only want to store the raw CRT.\r
265      * This inefficiency will go away as soon as we implement on-demand\r
266      * parsing of CRTs, in which case there's no need for the `peer_cert`\r
267      * field anymore in the first place, and we're done after this call. */\r
268     ret = mbedtls_ssl_session_copy( &cur->session, session );\r
269     if( ret != 0 )\r
270     {\r
271         ret = 1;\r
272         goto exit;\r
273     }\r
274 \r
275 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \\r
276     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\r
277     /* If present, free the X.509 structure and only store the raw CRT data. */\r
278     if( cur->session.peer_cert != NULL )\r
279     {\r
280         cur->peer_cert.p =\r
281             mbedtls_calloc( 1, cur->session.peer_cert->raw.len );\r
282         if( cur->peer_cert.p == NULL )\r
283         {\r
284             ret = 1;\r
285             goto exit;\r
286         }\r
287 \r
288         memcpy( cur->peer_cert.p,\r
289                 cur->session.peer_cert->raw.p,\r
290                 cur->session.peer_cert->raw.len );\r
291         cur->peer_cert.len = session->peer_cert->raw.len;\r
292 \r
293         mbedtls_x509_crt_free( cur->session.peer_cert );\r
294         mbedtls_free( cur->session.peer_cert );\r
295         cur->session.peer_cert = NULL;\r
296     }\r
297 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\r
298 \r
299     ret = 0;\r
300 \r
301 exit:\r
302 #if defined(MBEDTLS_THREADING_C)\r
303     if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )\r
304         ret = 1;\r
305 #endif\r
306 \r
307     return( ret );\r
308 }\r
309 \r
310 #if defined(MBEDTLS_HAVE_TIME)\r
311 void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout )\r
312 {\r
313     if( timeout < 0 ) timeout = 0;\r
314 \r
315     cache->timeout = timeout;\r
316 }\r
317 #endif /* MBEDTLS_HAVE_TIME */\r
318 \r
319 void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max )\r
320 {\r
321     if( max < 0 ) max = 0;\r
322 \r
323     cache->max_entries = max;\r
324 }\r
325 \r
326 void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )\r
327 {\r
328     mbedtls_ssl_cache_entry *cur, *prv;\r
329 \r
330     cur = cache->chain;\r
331 \r
332     while( cur != NULL )\r
333     {\r
334         prv = cur;\r
335         cur = cur->next;\r
336 \r
337         mbedtls_ssl_session_free( &prv->session );\r
338 \r
339 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \\r
340     defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)\r
341         mbedtls_free( prv->peer_cert.p );\r
342 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */\r
343 \r
344         mbedtls_free( prv );\r
345     }\r
346 \r
347 #if defined(MBEDTLS_THREADING_C)\r
348     mbedtls_mutex_free( &cache->mutex );\r
349 #endif\r
350     cache->chain = NULL;\r
351 }\r
352 \r
353 #endif /* MBEDTLS_SSL_CACHE_C */\r