blob: b47af861339879233c222e7d25270419e377e622 [file] [log] [blame]
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +02001/*
2 * TLS server tickets callbacks implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +02006 */
7
Gilles Peskinedb09ef62020-06-03 01:43:33 +02008#include "common.h"
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +02009
10#if defined(MBEDTLS_SSL_TICKET_C)
11
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020012#include "mbedtls/platform.h"
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020013
Chris Jones84a773f2021-03-05 18:38:47 +000014#include "ssl_misc.h"
SimonBd5800b72016-04-26 07:43:27 +010015#include "mbedtls/ssl_ticket.h"
Janos Follath865b3eb2019-12-16 11:46:15 +000016#include "mbedtls/error.h"
Janos Follath73c616b2019-12-18 15:07:04 +000017#include "mbedtls/platform_util.h"
SimonBd5800b72016-04-26 07:43:27 +010018
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020019#include <string.h>
20
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050021#if defined(MBEDTLS_USE_PSA_CRYPTO)
Andrzej Kurek00644842023-05-30 05:45:00 -040022/* Define a local translating function to save code size by not using too many
23 * arguments in each translating place. */
24static int local_err_translation(psa_status_t status)
25{
26 return psa_status_to_mbedtls(status, psa_to_ssl_errors,
Andrzej Kurek1e4a0302023-05-30 09:45:17 -040027 ARRAY_LENGTH(psa_to_ssl_errors),
Andrzej Kurek00644842023-05-30 05:45:00 -040028 psa_generic_status_to_mbedtls);
29}
30#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050031#endif
32
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020033/*
Shaun Case8b0ecbc2021-12-20 21:14:10 -080034 * Initialize context
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020035 */
Gilles Peskine449bd832023-01-11 14:50:10 +010036void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020037{
Gilles Peskine449bd832023-01-11 14:50:10 +010038 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020039
40#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010041 mbedtls_mutex_init(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020042#endif
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020043}
44
Glenn Straussa941b622022-02-09 15:24:56 -050045#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020046
Glenn Straussa941b622022-02-09 15:24:56 -050047#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
Hanno Beckerd140d082018-11-17 21:18:01 +000048#define TICKET_IV_BYTES 12
49#define TICKET_CRYPT_LEN_BYTES 2
50#define TICKET_AUTH_TAG_BYTES 16
51
Gilles Peskine449bd832023-01-11 14:50:10 +010052#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)
Hanno Beckerd140d082018-11-17 21:18:01 +000059
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020060/*
61 * Generate/update a key
62 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +020063MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +010064static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
65 unsigned char index)
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020066{
Janos Follath865b3eb2019-12-16 11:46:15 +000067 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +010068 unsigned char buf[MAX_KEY_BYTES] = { 0 };
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020069 mbedtls_ssl_ticket_key *key = ctx->keys + index;
70
Gabor Mezei2a020512022-03-10 15:15:46 +010071#if defined(MBEDTLS_USE_PSA_CRYPTO)
72 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
73#endif
74
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020075#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +010076 key->generation_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020077#endif
78
Gilles Peskine449bd832023-01-11 14:50:10 +010079 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
80 return ret;
81 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020082
Gilles Peskine449bd832023-01-11 14:50:10 +010083 if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
84 return ret;
85 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020086
Gabor Mezei2a020512022-03-10 15:15:46 +010087#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +010088 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);
Gabor Mezei2a020512022-03-10 15:15:46 +010093
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050094 ret = PSA_TO_MBEDTLS_ERR(
Gilles Peskine449bd832023-01-11 14:50:10 +010095 psa_import_key(&attributes, buf,
96 PSA_BITS_TO_BYTES(key->key_bits),
97 &key->key));
Gabor Mezei2a020512022-03-10 15:15:46 +010098#else
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020099 /* With GCM and CCM, same context can encrypt & decrypt */
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 ret = mbedtls_cipher_setkey(&key->ctx, buf,
101 mbedtls_cipher_get_key_bitlen(&key->ctx),
102 MBEDTLS_ENCRYPT);
Gabor Mezei2a020512022-03-10 15:15:46 +0100103#endif /* MBEDTLS_USE_PSA_CRYPTO */
104
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 mbedtls_platform_zeroize(buf, sizeof(buf));
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200106
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 return ret;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200108}
109
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200110/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200111 * Rotate/generate keys if necessary
112 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +0200113MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +0100114static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200115{
116#if !defined(MBEDTLS_HAVE_TIME)
117 ((void) ctx);
118#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 if (ctx->ticket_lifetime != 0) {
120 mbedtls_time_t current_time = mbedtls_time(NULL);
Dave Rodgman392f7142022-08-17 11:19:41 +0100121 mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200122
Gabor Mezei2a020512022-03-10 15:15:46 +0100123#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100124 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100125#endif
126
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 if (current_time >= key_time &&
128 (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
129 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200130 }
131
132 ctx->active = 1 - ctx->active;
133
Gabor Mezei2a020512022-03-10 15:15:46 +0100134#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500136 return PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100137 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100138#endif /* MBEDTLS_USE_PSA_CRYPTO */
139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 return ssl_ticket_gen_key(ctx, ctx->active);
141 } else
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200142#endif /* MBEDTLS_HAVE_TIME */
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200144}
145
146/*
Glenn Straussa9509382022-02-02 23:32:18 -0500147 * Rotate active session ticket encryption key
148 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100149int 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)
Glenn Straussa9509382022-02-02 23:32:18 -0500153{
154 const unsigned char idx = 1 - ctx->active;
155 mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
Gabor Mezei2a020512022-03-10 15:15:46 +0100156 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
157
158#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100159 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100160 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gabor Mezei36c9f512022-03-16 12:55:32 +0100161 const size_t bitlen = key->key_bits;
Gabor Mezei2a020512022-03-10 15:15:46 +0100162#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100164#endif
165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
167 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
168 }
Glenn Straussa9509382022-02-02 23:32:18 -0500169
Gabor Mezei2a020512022-03-10 15:15:46 +0100170#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500172 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100174 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 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);
Gabor Mezei2a020512022-03-10 15:15:46 +0100181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 if ((status = psa_import_key(&attributes, k,
183 PSA_BITS_TO_BYTES(key->key_bits),
184 &key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500185 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100187 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100188#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
190 if (ret != 0) {
191 return ret;
192 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100193#endif /* MBEDTLS_USE_PSA_CRYPTO */
194
Glenn Straussa9509382022-02-02 23:32:18 -0500195 ctx->active = idx;
196 ctx->ticket_lifetime = lifetime;
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
Glenn Straussa9509382022-02-02 23:32:18 -0500198#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 key->generation_time = mbedtls_time(NULL);
Glenn Straussa9509382022-02-02 23:32:18 -0500200#endif
201 return 0;
202}
203
204/*
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200205 * Setup context for actual use
206 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100207int 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)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200211{
Janos Follath865b3eb2019-12-16 11:46:15 +0000212 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200213 size_t key_bits;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200214
Gabor Mezei2a020512022-03-10 15:15:46 +0100215#if defined(MBEDTLS_USE_PSA_CRYPTO)
216 psa_algorithm_t alg;
217 psa_key_type_t key_type;
Neil Armstrong858581e2022-04-01 18:03:15 +0200218#else
219 const mbedtls_cipher_info_t *cipher_info;
220#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100221
Neil Armstrong858581e2022-04-01 18:03:15 +0200222#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 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;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200226 }
227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 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);
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200241#endif /* MBEDTLS_USE_PSA_CRYPTO */
242
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 if (key_bits > 8 * MAX_KEY_BYTES) {
244 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
245 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200246
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200247 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
262 return ret;
Manuel Pégourié-Gonnarda0adc1b2015-05-25 10:35:16 +0200263 }
264
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 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;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200276}
277
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200278/*
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200279 * Create session ticket, with the following structure:
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200280 *
281 * struct {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200282 * opaque key_name[4];
283 * opaque iv[12];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200284 * opaque encrypted_state<0..2^16-1>;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200285 * opaque tag[16];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200286 * } ticket;
287 *
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200288 * The key_name, iv, and length of encrypted_state are the additional
289 * authenticated data.
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200290 */
Hanno Beckerd140d082018-11-17 21:18:01 +0000291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292int 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)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200298{
Janos Follath865b3eb2019-12-16 11:46:15 +0000299 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200300 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200301 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200302 unsigned char *key_name = start;
Hanno Beckerd140d082018-11-17 21:18:01 +0000303 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;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200306 size_t clear_len, ciph_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200307
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100308#if defined(MBEDTLS_USE_PSA_CRYPTO)
309 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
310#endif
311
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200312 *tlen = 0;
313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 if (ctx == NULL || ctx->f_rng == NULL) {
315 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
316 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200317
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200318 /* 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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200321
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200322#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
324 return ret;
325 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200326#endif
327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200329 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200331
332 key = &ctx->keys[ctx->active];
333
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200334 *ticket_lifetime = ctx->ticket_lifetime;
335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200337
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200339 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200341
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200342 /* Dump session state */
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if ((ret = mbedtls_ssl_session_save(session,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000344 state, (size_t) (end - state),
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 &clear_len)) != 0 ||
346 (unsigned long) clear_len > 65535) {
347 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200348 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200350
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200351 /* Encrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100352#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100353 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) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500358 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100359 goto cleanup;
360 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100361#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 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,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000367 state, (size_t) (end - state), &ciph_len,
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 TICKET_AUTH_TAG_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200369 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200370 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100371#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200374 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200375 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200376 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200377
Manuel Pégourié-Gonnardf5cf71e2020-12-01 11:43:40 +0100378 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200379
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200380cleanup:
381#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
383 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
384 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200385#endif
386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200388}
389
390/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200391 * Select key based on name
392 */
393static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 mbedtls_ssl_ticket_context *ctx,
395 const unsigned char name[4])
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200396{
397 unsigned char i;
398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 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 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 return NULL;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200406}
407
408/*
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200409 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
410 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100411int mbedtls_ssl_ticket_parse(void *p_ticket,
412 mbedtls_ssl_session *session,
413 unsigned char *buf,
414 size_t len)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200415{
Janos Follath865b3eb2019-12-16 11:46:15 +0000416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200417 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200418 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200419 unsigned char *key_name = buf;
Hanno Beckerd140d082018-11-17 21:18:01 +0000420 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;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200423 size_t enc_len, clear_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200424
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100425#if defined(MBEDTLS_USE_PSA_CRYPTO)
426 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
427#endif
428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (ctx == NULL || ctx->f_rng == NULL) {
430 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
431 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 if (len < TICKET_MIN_LEN) {
434 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
435 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200436
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200437#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
439 return ret;
440 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200441#endif
442
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200444 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200446
Dave Rodgmana3d0f612023-11-03 23:34:02 +0000447 enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if (len != TICKET_MIN_LEN + enc_len) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200450 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
451 goto cleanup;
452 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200453
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200454 /* Select key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200456 /* 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;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200459 goto cleanup;
460 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200461
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200462 /* Decrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100463#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 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) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500468 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100469 goto cleanup;
470 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100471#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 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) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200480 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200482
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200483 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200484 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100485#endif /* MBEDTLS_USE_PSA_CRYPTO */
486
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 if (clear_len != enc_len) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200488 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200489 goto cleanup;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200490 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200491
492 /* Actually load session */
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200494 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200496
497#if defined(MBEDTLS_HAVE_TIME)
Jerry Yucebffc32022-12-15 18:00:05 +0800498#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
499 if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
500 /* Check for expiration */
Jerry Yu472a6922023-11-14 11:25:24 +0800501 mbedtls_ms_time_t ticket_age = -1;
Jerry Yu472a6922023-11-14 11:25:24 +0800502 if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
503 ticket_age = mbedtls_ms_time() - session->ticket_creation_time;
504 }
David Horstmann47490072023-12-06 17:22:53 +0000505 mbedtls_ms_time_t ticket_lifetime =
506 (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
Jerry Yucebffc32022-12-15 18:00:05 +0800507
508 if (ticket_age < 0 || ticket_age > ticket_lifetime) {
509 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
510 goto cleanup;
511 }
Jerry Yuec6d0782023-10-31 14:42:20 +0800512 }
Jerry Yucebffc32022-12-15 18:00:05 +0800513#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
Jerry Yuec6d0782023-10-31 14:42:20 +0800514#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
515 if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200516 /* Check for expiration */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 mbedtls_time_t current_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200518
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 if (current_time < session->start ||
520 (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200521 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
522 goto cleanup;
523 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200524 }
Jerry Yu31b601a2023-11-10 11:27:21 +0800525#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
Jerry Yucebffc32022-12-15 18:00:05 +0800526#endif /* MBEDTLS_HAVE_TIME */
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200527
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200528cleanup:
529#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
531 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
532 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200533#endif
534
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200536}
537
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200538/*
539 * Free context
540 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100541void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200542{
Gabor Mezei2a020512022-03-10 15:15:46 +0100543#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 psa_destroy_key(ctx->keys[0].key);
545 psa_destroy_key(ctx->keys[1].key);
Gabor Mezei2a020512022-03-10 15:15:46 +0100546#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 mbedtls_cipher_free(&ctx->keys[0].ctx);
548 mbedtls_cipher_free(&ctx->keys[1].ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100549#endif /* MBEDTLS_USE_PSA_CRYPTO */
550
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200551#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 mbedtls_mutex_free(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200553#endif
554
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200556}
557
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +0200558#endif /* MBEDTLS_SSL_TICKET_C */