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