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