blob: 6a31b0bee6961cbe704ca6774474474bf0899405 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * TLS server tickets callbacks implementation
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
Jerome Forissier79013242021-07-28 10:24:04 +02008#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +02009
10#if defined(MBEDTLS_SSL_TICKET_C)
11
Jens Wiklander817466c2018-05-22 13:49:31 +020012#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020013
Jens Wiklander32b31802023-10-06 16:59:46 +020014#include "ssl_misc.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020015#include "mbedtls/ssl_ticket.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020016#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010017#include "mbedtls/platform_util.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020018
19#include <string.h>
20
Jens Wiklander32b31802023-10-06 16:59:46 +020021#if defined(MBEDTLS_USE_PSA_CRYPTO)
Tom Van Eyckc1633172024-04-09 18:44:13 +020022/* 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,
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)
Jens Wiklander32b31802023-10-06 16:59:46 +020031#endif
32
Jens Wiklander817466c2018-05-22 13:49:31 +020033/*
Jerome Forissier039e02d2022-08-09 17:10:15 +020034 * Initialize context
Jens Wiklander817466c2018-05-22 13:49:31 +020035 */
Jens Wiklander32b31802023-10-06 16:59:46 +020036void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020037{
Jens Wiklander32b31802023-10-06 16:59:46 +020038 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Jens Wiklander817466c2018-05-22 13:49:31 +020039
40#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020041 mbedtls_mutex_init(&ctx->mutex);
Jens Wiklander817466c2018-05-22 13:49:31 +020042#endif
43}
44
Jens Wiklander32b31802023-10-06 16:59:46 +020045#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
Jens Wiklander817466c2018-05-22 13:49:31 +020046
Jens Wiklander32b31802023-10-06 16:59:46 +020047#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
Jerome Forissier11fa71b2020-04-20 17:17:56 +020048#define TICKET_IV_BYTES 12
49#define TICKET_CRYPT_LEN_BYTES 2
50#define TICKET_AUTH_TAG_BYTES 16
51
Jens Wiklander32b31802023-10-06 16:59:46 +020052#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)
Jerome Forissier11fa71b2020-04-20 17:17:56 +020059
Jens Wiklander817466c2018-05-22 13:49:31 +020060/*
61 * Generate/update a key
62 */
Jerome Forissier039e02d2022-08-09 17:10:15 +020063MBEDTLS_CHECK_RETURN_CRITICAL
Jens Wiklander32b31802023-10-06 16:59:46 +020064static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
65 unsigned char index)
Jens Wiklander817466c2018-05-22 13:49:31 +020066{
Jerome Forissier11fa71b2020-04-20 17:17:56 +020067 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +020068 unsigned char buf[MAX_KEY_BYTES] = { 0 };
Jens Wiklander817466c2018-05-22 13:49:31 +020069 mbedtls_ssl_ticket_key *key = ctx->keys + index;
70
Jens Wiklander32b31802023-10-06 16:59:46 +020071#if defined(MBEDTLS_USE_PSA_CRYPTO)
72 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Jens Wiklander817466c2018-05-22 13:49:31 +020073#endif
74
Jens Wiklander32b31802023-10-06 16:59:46 +020075#if defined(MBEDTLS_HAVE_TIME)
76 key->generation_time = mbedtls_time(NULL);
77#endif
Tom Van Eyckc1633172024-04-09 18:44:13 +020078 /* 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;
Jens Wiklander817466c2018-05-22 13:49:31 +020082
Jens Wiklander32b31802023-10-06 16:59:46 +020083 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
84 return ret;
85 }
Jens Wiklander817466c2018-05-22 13:49:31 +020086
Jens Wiklander32b31802023-10-06 16:59:46 +020087 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
Jens Wiklander817466c2018-05-22 13:49:31 +0200103 /* With GCM and CCM, same context can encrypt & decrypt */
Jens Wiklander32b31802023-10-06 16:59:46 +0200104 ret = mbedtls_cipher_setkey(&key->ctx, buf,
105 mbedtls_cipher_get_key_bitlen(&key->ctx),
106 MBEDTLS_ENCRYPT);
107#endif /* MBEDTLS_USE_PSA_CRYPTO */
Jens Wiklander817466c2018-05-22 13:49:31 +0200108
Jens Wiklander32b31802023-10-06 16:59:46 +0200109 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander817466c2018-05-22 13:49:31 +0200110
Jens Wiklander32b31802023-10-06 16:59:46 +0200111 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200112}
113
114/*
115 * Rotate/generate keys if necessary
116 */
Jerome Forissier039e02d2022-08-09 17:10:15 +0200117MBEDTLS_CHECK_RETURN_CRITICAL
Jens Wiklander32b31802023-10-06 16:59:46 +0200118static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200119{
120#if !defined(MBEDTLS_HAVE_TIME)
121 ((void) ctx);
122#else
Tom Van Eyckc1633172024-04-09 18:44:13 +0200123 mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
124 if (key->lifetime != 0) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200125 mbedtls_time_t current_time = mbedtls_time(NULL);
Tom Van Eyckc1633172024-04-09 18:44:13 +0200126 mbedtls_time_t key_time = key->generation_time;
Jens Wiklander817466c2018-05-22 13:49:31 +0200127
Jens Wiklander32b31802023-10-06 16:59:46 +0200128#if defined(MBEDTLS_USE_PSA_CRYPTO)
129 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
130#endif
131
132 if (current_time >= key_time &&
Tom Van Eyckc1633172024-04-09 18:44:13 +0200133 (uint64_t) (current_time - key_time) < key->lifetime) {
Jens Wiklander32b31802023-10-06 16:59:46 +0200134 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200135 }
136
137 ctx->active = 1 - ctx->active;
138
Jens Wiklander32b31802023-10-06 16:59:46 +0200139#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
Jens Wiklander817466c2018-05-22 13:49:31 +0200147#endif /* MBEDTLS_HAVE_TIME */
Jens Wiklander32b31802023-10-06 16:59:46 +0200148 return 0;
149}
150
151/*
152 * Rotate active session ticket encryption key
153 */
154int 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
Tom Van Eyckc1633172024-04-09 18:44:13 +0200206 key->lifetime = lifetime;
207
Jens Wiklander32b31802023-10-06 16:59:46 +0200208 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200209}
210
211/*
212 * Setup context for actual use
213 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200214int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200218{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200219 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200220 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
Jens Wiklander817466c2018-05-22 13:49:31 +0200226 const mbedtls_cipher_info_t *cipher_info;
Jens Wiklander32b31802023-10-06 16:59:46 +0200227#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 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200253
254 ctx->f_rng = f_rng;
255 ctx->p_rng = p_rng;
256
257 ctx->ticket_lifetime = lifetime;
258
Jens Wiklander32b31802023-10-06 16:59:46 +0200259#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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200263
Jens Wiklander32b31802023-10-06 16:59:46 +0200264 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200270 }
271
Jens Wiklander32b31802023-10-06 16:59:46 +0200272 if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {
273 return ret;
274 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200275#endif /* MBEDTLS_USE_PSA_CRYPTO */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200276
Jens Wiklander32b31802023-10-06 16:59:46 +0200277 if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
278 (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
279 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200280 }
281
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200283}
284
285/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200286 * 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 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200298
Jens Wiklander32b31802023-10-06 16:59:46 +0200299int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +0200305{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200306 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200307 mbedtls_ssl_ticket_context *ctx = p_ticket;
308 mbedtls_ssl_ticket_key *key;
309 unsigned char *key_name = start;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200310 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200313 size_t clear_len, ciph_len;
314
Jens Wiklander32b31802023-10-06 16:59:46 +0200315#if defined(MBEDTLS_USE_PSA_CRYPTO)
316 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
317#endif
318
Jens Wiklander817466c2018-05-22 13:49:31 +0200319 *tlen = 0;
320
Jens Wiklander32b31802023-10-06 16:59:46 +0200321 if (ctx == NULL || ctx->f_rng == NULL) {
322 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
323 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200324
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. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Jens Wiklander817466c2018-05-22 13:49:31 +0200328
329#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200330 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
331 return ret;
332 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200333#endif
334
Jens Wiklander32b31802023-10-06 16:59:46 +0200335 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200336 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200337 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200338
339 key = &ctx->keys[ctx->active];
340
Tom Van Eyckc1633172024-04-09 18:44:13 +0200341 *ticket_lifetime = key->lifetime;
Jens Wiklander817466c2018-05-22 13:49:31 +0200342
Jens Wiklander32b31802023-10-06 16:59:46 +0200343 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Jens Wiklander817466c2018-05-22 13:49:31 +0200344
Jens Wiklander32b31802023-10-06 16:59:46 +0200345 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200346 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200347 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200348
349 /* Dump session state */
Jens Wiklander32b31802023-10-06 16:59:46 +0200350 if ((ret = mbedtls_ssl_session_save(session,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200351 state, (size_t) (end - state),
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 &clear_len)) != 0 ||
353 (unsigned long) clear_len > 65535) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200354 goto cleanup;
355 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200356 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,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200374 state, (size_t) (end - state), &ciph_len,
Jens Wiklander32b31802023-10-06 16:59:46 +0200375 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) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200381 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
382 goto cleanup;
383 }
384
Jerome Forissier79013242021-07-28 10:24:04 +0200385 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Jens Wiklander817466c2018-05-22 13:49:31 +0200386
387cleanup:
388#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200389 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
390 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
391 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200392#endif
393
Jens Wiklander32b31802023-10-06 16:59:46 +0200394 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200395}
396
397/*
398 * Select key based on name
399 */
400static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 mbedtls_ssl_ticket_context *ctx,
402 const unsigned char name[4])
Jens Wiklander817466c2018-05-22 13:49:31 +0200403{
404 unsigned char i;
405
Jens Wiklander32b31802023-10-06 16:59:46 +0200406 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 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200411
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 return NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200413}
414
415/*
416 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
417 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200418int mbedtls_ssl_ticket_parse(void *p_ticket,
419 mbedtls_ssl_session *session,
420 unsigned char *buf,
421 size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200422{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200424 mbedtls_ssl_ticket_context *ctx = p_ticket;
425 mbedtls_ssl_ticket_key *key;
426 unsigned char *key_name = buf;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200427 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200430 size_t enc_len, clear_len;
431
Jens Wiklander32b31802023-10-06 16:59:46 +0200432#if defined(MBEDTLS_USE_PSA_CRYPTO)
433 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200434#endif
435
Jens Wiklander32b31802023-10-06 16:59:46 +0200436 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) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200451 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200452 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200453
Tom Van Eyckc1633172024-04-09 18:44:13 +0200454 enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200455
Jens Wiklander32b31802023-10-06 16:59:46 +0200456 if (len != TICKET_MIN_LEN + enc_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200457 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
458 goto cleanup;
459 }
460
461 /* Select key */
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200463 /* 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 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200470#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) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200487 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
Jens Wiklander32b31802023-10-06 16:59:46 +0200488 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200489
490 goto cleanup;
491 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200492#endif /* MBEDTLS_USE_PSA_CRYPTO */
493
494 if (clear_len != enc_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200495 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
496 goto cleanup;
497 }
498
499 /* Actually load session */
Jens Wiklander32b31802023-10-06 16:59:46 +0200500 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200501 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200502 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200503
504#if defined(MBEDTLS_HAVE_TIME)
Tom Van Eyckc1633172024-04-09 18:44:13 +0200505 mbedtls_ms_time_t ticket_creation_time, ticket_age;
506 mbedtls_ms_time_t ticket_lifetime =
507 (mbedtls_ms_time_t) key->lifetime * 1000;
Jens Wiklander817466c2018-05-22 13:49:31 +0200508
Tom Van Eyckc1633172024-04-09 18:44:13 +0200509 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;
Jens Wiklander817466c2018-05-22 13:49:31 +0200519 }
520#endif
521
522cleanup:
523#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200524 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
525 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
526 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200527#endif
528
Jens Wiklander32b31802023-10-06 16:59:46 +0200529 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200530}
531
532/*
533 * Free context
534 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200535void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200536{
Jens Wiklander32b31802023-10-06 16:59:46 +0200537#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 */
Jens Wiklander817466c2018-05-22 13:49:31 +0200544
545#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200546 mbedtls_mutex_free(&ctx->mutex);
Jens Wiklander817466c2018-05-22 13:49:31 +0200547#endif
548
Jens Wiklander32b31802023-10-06 16:59:46 +0200549 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Jens Wiklander817466c2018-05-22 13:49:31 +0200550}
551
552#endif /* MBEDTLS_SSL_TICKET_C */