1 /*
2  *  TLS server tickets callbacks 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 #include "common.h"
21 
22 #if defined(MBEDTLS_SSL_TICKET_C)
23 
24 #include "mbedtls/platform.h"
25 
26 #include "ssl_misc.h"
27 #include "mbedtls/ssl_ticket.h"
28 #include "mbedtls/error.h"
29 #include "mbedtls/platform_util.h"
30 
31 #include <string.h>
32 
33 /*
34  * Initialize context
35  */
mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context * ctx)36 void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
37 {
38     memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) );
39 
40 #if defined(MBEDTLS_THREADING_C)
41     mbedtls_mutex_init( &ctx->mutex );
42 #endif
43 }
44 
45 #define MAX_KEY_BYTES           MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
46 
47 #define TICKET_KEY_NAME_BYTES   MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
48 #define TICKET_IV_BYTES         12
49 #define TICKET_CRYPT_LEN_BYTES   2
50 #define TICKET_AUTH_TAG_BYTES   16
51 
52 #define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES  +        \
53                          TICKET_IV_BYTES        +        \
54                          TICKET_CRYPT_LEN_BYTES +        \
55                          TICKET_AUTH_TAG_BYTES )
56 #define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES  +        \
57                               TICKET_IV_BYTES        +        \
58                               TICKET_CRYPT_LEN_BYTES )
59 
60 /*
61  * Generate/update a key
62  */
63 MBEDTLS_CHECK_RETURN_CRITICAL
ssl_ticket_gen_key(mbedtls_ssl_ticket_context * ctx,unsigned char index)64 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
65                                unsigned char index )
66 {
67     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
68     unsigned char buf[MAX_KEY_BYTES] = {0};
69     mbedtls_ssl_ticket_key *key = ctx->keys + index;
70 
71 #if defined(MBEDTLS_USE_PSA_CRYPTO)
72     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
73 #endif
74 
75 #if defined(MBEDTLS_HAVE_TIME)
76     key->generation_time = mbedtls_time( NULL );
77 #endif
78 
79     if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 )
80         return( ret );
81 
82     if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 )
83         return( ret );
84 
85 #if defined(MBEDTLS_USE_PSA_CRYPTO)
86     psa_set_key_usage_flags( &attributes,
87                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
88     psa_set_key_algorithm( &attributes, key->alg );
89     psa_set_key_type( &attributes, key->key_type );
90     psa_set_key_bits( &attributes, key->key_bits );
91 
92     ret = psa_ssl_status_to_mbedtls(
93             psa_import_key( &attributes, buf,
94                             PSA_BITS_TO_BYTES( key->key_bits ),
95                             &key->key ) );
96 #else
97     /* With GCM and CCM, same context can encrypt & decrypt */
98     ret = mbedtls_cipher_setkey( &key->ctx, buf,
99                                  mbedtls_cipher_get_key_bitlen( &key->ctx ),
100                                  MBEDTLS_ENCRYPT );
101 #endif /* MBEDTLS_USE_PSA_CRYPTO */
102 
103     mbedtls_platform_zeroize( buf, sizeof( buf ) );
104 
105     return( ret );
106 }
107 
108 /*
109  * Rotate/generate keys if necessary
110  */
111 MBEDTLS_CHECK_RETURN_CRITICAL
ssl_ticket_update_keys(mbedtls_ssl_ticket_context * ctx)112 static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
113 {
114 #if !defined(MBEDTLS_HAVE_TIME)
115     ((void) ctx);
116 #else
117     if( ctx->ticket_lifetime != 0 )
118     {
119         mbedtls_time_t current_time = mbedtls_time( NULL );
120         mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
121 
122 #if defined(MBEDTLS_USE_PSA_CRYPTO)
123         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
124 #endif
125 
126         if( current_time >= key_time &&
127             (uint64_t) ( current_time - key_time ) < ctx->ticket_lifetime )
128         {
129             return( 0 );
130         }
131 
132         ctx->active = 1 - ctx->active;
133 
134 #if defined(MBEDTLS_USE_PSA_CRYPTO)
135         if( ( status = psa_destroy_key( ctx->keys[ctx->active].key ) ) != PSA_SUCCESS )
136         {
137             return psa_ssl_status_to_mbedtls( status );
138         }
139 #endif /* MBEDTLS_USE_PSA_CRYPTO */
140 
141         return( ssl_ticket_gen_key( ctx, ctx->active ) );
142     }
143     else
144 #endif /* MBEDTLS_HAVE_TIME */
145         return( 0 );
146 }
147 
148 /*
149  * Rotate active session ticket encryption key
150  */
mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context * ctx,const unsigned char * name,size_t nlength,const unsigned char * k,size_t klength,uint32_t lifetime)151 int mbedtls_ssl_ticket_rotate( mbedtls_ssl_ticket_context *ctx,
152     const unsigned char *name, size_t nlength,
153     const unsigned char *k, size_t klength,
154     uint32_t lifetime )
155 {
156     const unsigned char idx = 1 - ctx->active;
157     mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
158     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
159 
160 #if defined(MBEDTLS_USE_PSA_CRYPTO)
161     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
162     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
163     const size_t bitlen = key->key_bits;
164 #else
165     const int bitlen = mbedtls_cipher_get_key_bitlen( &key->ctx );
166 #endif
167 
168     if( nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t)bitlen )
169         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
170 
171 #if defined(MBEDTLS_USE_PSA_CRYPTO)
172     if( ( status = psa_destroy_key( key->key ) ) != PSA_SUCCESS )
173     {
174         ret = psa_ssl_status_to_mbedtls( status );
175         return( ret );
176     }
177 
178     psa_set_key_usage_flags( &attributes,
179                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
180     psa_set_key_algorithm( &attributes, key->alg );
181     psa_set_key_type( &attributes, key->key_type );
182     psa_set_key_bits( &attributes, key->key_bits );
183 
184     if( ( status = psa_import_key( &attributes, k,
185                                    PSA_BITS_TO_BYTES( key->key_bits ),
186                                    &key->key ) ) != PSA_SUCCESS )
187     {
188         ret = psa_ssl_status_to_mbedtls( status );
189         return( ret );
190     }
191 #else
192     ret = mbedtls_cipher_setkey( &key->ctx, k, bitlen, MBEDTLS_ENCRYPT );
193     if( ret != 0 )
194         return( ret );
195 #endif /* MBEDTLS_USE_PSA_CRYPTO */
196 
197     ctx->active = idx;
198     ctx->ticket_lifetime = lifetime;
199     memcpy( key->name, name, TICKET_KEY_NAME_BYTES );
200 #if defined(MBEDTLS_HAVE_TIME)
201     key->generation_time = mbedtls_time( NULL );
202 #endif
203     return 0;
204 }
205 
206 /*
207  * Setup context for actual use
208  */
mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context * ctx,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_cipher_type_t cipher,uint32_t lifetime)209 int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
210     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
211     mbedtls_cipher_type_t cipher,
212     uint32_t lifetime )
213 {
214     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
215     size_t key_bits;
216 
217 #if defined(MBEDTLS_USE_PSA_CRYPTO)
218     psa_algorithm_t alg;
219     psa_key_type_t key_type;
220 #else
221     const mbedtls_cipher_info_t *cipher_info;
222 #endif /* MBEDTLS_USE_PSA_CRYPTO */
223 
224 #if defined(MBEDTLS_USE_PSA_CRYPTO)
225     if( mbedtls_ssl_cipher_to_psa( cipher, TICKET_AUTH_TAG_BYTES,
226                                    &alg, &key_type, &key_bits ) != PSA_SUCCESS )
227         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
228 
229     if( PSA_ALG_IS_AEAD( alg ) == 0 )
230         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
231 #else
232     cipher_info = mbedtls_cipher_info_from_type( cipher );
233 
234     if( mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_GCM &&
235         mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CCM &&
236         mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CHACHAPOLY )
237     {
238         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
239     }
240 
241     key_bits = mbedtls_cipher_info_get_key_bitlen( cipher_info );
242 #endif /* MBEDTLS_USE_PSA_CRYPTO */
243 
244     if( key_bits > 8 * MAX_KEY_BYTES )
245         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
246 
247     ctx->f_rng = f_rng;
248     ctx->p_rng = p_rng;
249 
250     ctx->ticket_lifetime = lifetime;
251 
252 #if defined(MBEDTLS_USE_PSA_CRYPTO)
253     ctx->keys[0].alg = alg;
254     ctx->keys[0].key_type = key_type;
255     ctx->keys[0].key_bits = key_bits;
256 
257     ctx->keys[1].alg = alg;
258     ctx->keys[1].key_type = key_type;
259     ctx->keys[1].key_bits = key_bits;
260 #else
261     if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 )
262         return( ret );
263 
264     if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
265         return( ret );
266 #endif /* MBEDTLS_USE_PSA_CRYPTO */
267 
268     if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
269         ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
270     {
271         return( ret );
272     }
273 
274     return( 0 );
275 }
276 
277 /*
278  * Create session ticket, with the following structure:
279  *
280  *    struct {
281  *        opaque key_name[4];
282  *        opaque iv[12];
283  *        opaque encrypted_state<0..2^16-1>;
284  *        opaque tag[16];
285  *    } ticket;
286  *
287  * The key_name, iv, and length of encrypted_state are the additional
288  * authenticated data.
289  */
290 
mbedtls_ssl_ticket_write(void * p_ticket,const mbedtls_ssl_session * session,unsigned char * start,const unsigned char * end,size_t * tlen,uint32_t * ticket_lifetime)291 int mbedtls_ssl_ticket_write( void *p_ticket,
292                               const mbedtls_ssl_session *session,
293                               unsigned char *start,
294                               const unsigned char *end,
295                               size_t *tlen,
296                               uint32_t *ticket_lifetime )
297 {
298     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
299     mbedtls_ssl_ticket_context *ctx = p_ticket;
300     mbedtls_ssl_ticket_key *key;
301     unsigned char *key_name = start;
302     unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
303     unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
304     unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
305     size_t clear_len, ciph_len;
306 
307 #if defined(MBEDTLS_USE_PSA_CRYPTO)
308     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
309 #endif
310 
311     *tlen = 0;
312 
313     if( ctx == NULL || ctx->f_rng == NULL )
314         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
315 
316     /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
317      * in addition to session itself, that will be checked when writing it. */
318     MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN );
319 
320 #if defined(MBEDTLS_THREADING_C)
321     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
322         return( ret );
323 #endif
324 
325     if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
326         goto cleanup;
327 
328     key = &ctx->keys[ctx->active];
329 
330     *ticket_lifetime = ctx->ticket_lifetime;
331 
332     memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES );
333 
334     if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 )
335         goto cleanup;
336 
337     /* Dump session state */
338     if( ( ret = mbedtls_ssl_session_save( session,
339                                           state, end - state,
340                                           &clear_len ) ) != 0 ||
341         (unsigned long) clear_len > 65535 )
342     {
343          goto cleanup;
344     }
345     MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 );
346 
347     /* Encrypt and authenticate */
348 #if defined(MBEDTLS_USE_PSA_CRYPTO)
349     if( ( status = psa_aead_encrypt( key->key, key->alg, iv, TICKET_IV_BYTES,
350                                      key_name, TICKET_ADD_DATA_LEN,
351                                      state, clear_len,
352                                      state, end - state,
353                                      &ciph_len ) ) != PSA_SUCCESS )
354     {
355         ret = psa_ssl_status_to_mbedtls( status );
356         goto cleanup;
357     }
358 #else
359     if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx,
360                     iv, TICKET_IV_BYTES,
361                     /* Additional data: key name, IV and length */
362                     key_name, TICKET_ADD_DATA_LEN,
363                     state, clear_len,
364                     state, end - state, &ciph_len,
365                     TICKET_AUTH_TAG_BYTES ) ) != 0 )
366     {
367         goto cleanup;
368     }
369 #endif /* MBEDTLS_USE_PSA_CRYPTO */
370 
371     if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES )
372     {
373         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
374         goto cleanup;
375     }
376 
377     *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
378 
379 cleanup:
380 #if defined(MBEDTLS_THREADING_C)
381     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
382         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
383 #endif
384 
385     return( ret );
386 }
387 
388 /*
389  * Select key based on name
390  */
ssl_ticket_select_key(mbedtls_ssl_ticket_context * ctx,const unsigned char name[4])391 static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
392         mbedtls_ssl_ticket_context *ctx,
393         const unsigned char name[4] )
394 {
395     unsigned char i;
396 
397     for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ )
398         if( memcmp( name, ctx->keys[i].name, 4 ) == 0 )
399             return( &ctx->keys[i] );
400 
401     return( NULL );
402 }
403 
404 /*
405  * Load session ticket (see mbedtls_ssl_ticket_write for structure)
406  */
mbedtls_ssl_ticket_parse(void * p_ticket,mbedtls_ssl_session * session,unsigned char * buf,size_t len)407 int mbedtls_ssl_ticket_parse( void *p_ticket,
408                               mbedtls_ssl_session *session,
409                               unsigned char *buf,
410                               size_t len )
411 {
412     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
413     mbedtls_ssl_ticket_context *ctx = p_ticket;
414     mbedtls_ssl_ticket_key *key;
415     unsigned char *key_name = buf;
416     unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
417     unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
418     unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
419     size_t enc_len, clear_len;
420 
421 #if defined(MBEDTLS_USE_PSA_CRYPTO)
422     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
423 #endif
424 
425     if( ctx == NULL || ctx->f_rng == NULL )
426         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
427 
428     if( len < TICKET_MIN_LEN )
429         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
430 
431 #if defined(MBEDTLS_THREADING_C)
432     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
433         return( ret );
434 #endif
435 
436     if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
437         goto cleanup;
438 
439     enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
440 
441     if( len != TICKET_MIN_LEN + enc_len )
442     {
443         ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
444         goto cleanup;
445     }
446 
447     /* Select key */
448     if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL )
449     {
450         /* We can't know for sure but this is a likely option unless we're
451          * under attack - this is only informative anyway */
452         ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
453         goto cleanup;
454     }
455 
456     /* Decrypt and authenticate */
457 #if defined(MBEDTLS_USE_PSA_CRYPTO)
458     if( ( status = psa_aead_decrypt( key->key, key->alg, iv, TICKET_IV_BYTES,
459                                      key_name, TICKET_ADD_DATA_LEN,
460                                      ticket, enc_len + TICKET_AUTH_TAG_BYTES,
461                                      ticket, enc_len, &clear_len ) ) != PSA_SUCCESS )
462     {
463         ret = psa_ssl_status_to_mbedtls( status );
464         goto cleanup;
465     }
466 #else
467     if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx,
468                     iv, TICKET_IV_BYTES,
469                     /* Additional data: key name, IV and length */
470                     key_name, TICKET_ADD_DATA_LEN,
471                     ticket, enc_len + TICKET_AUTH_TAG_BYTES,
472                     ticket, enc_len, &clear_len,
473                     TICKET_AUTH_TAG_BYTES ) ) != 0 )
474     {
475         if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
476             ret = MBEDTLS_ERR_SSL_INVALID_MAC;
477 
478         goto cleanup;
479     }
480 #endif /* MBEDTLS_USE_PSA_CRYPTO */
481 
482     if( clear_len != enc_len )
483     {
484         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
485         goto cleanup;
486     }
487 
488     /* Actually load session */
489     if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 )
490         goto cleanup;
491 
492 #if defined(MBEDTLS_HAVE_TIME)
493     {
494         /* Check for expiration */
495         mbedtls_time_t current_time = mbedtls_time( NULL );
496 
497         if( current_time < session->start ||
498             (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime )
499         {
500             ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
501             goto cleanup;
502         }
503     }
504 #endif
505 
506 cleanup:
507 #if defined(MBEDTLS_THREADING_C)
508     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
509         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
510 #endif
511 
512     return( ret );
513 }
514 
515 /*
516  * Free context
517  */
mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context * ctx)518 void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx )
519 {
520 #if defined(MBEDTLS_USE_PSA_CRYPTO)
521     psa_destroy_key( ctx->keys[0].key );
522     psa_destroy_key( ctx->keys[1].key );
523 #else
524     mbedtls_cipher_free( &ctx->keys[0].ctx );
525     mbedtls_cipher_free( &ctx->keys[1].ctx );
526 #endif /* MBEDTLS_USE_PSA_CRYPTO */
527 
528 #if defined(MBEDTLS_THREADING_C)
529     mbedtls_mutex_free( &ctx->mutex );
530 #endif
531 
532     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
533 }
534 
535 #endif /* MBEDTLS_SSL_TICKET_C */
536