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