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