blob: 615b37fd647e4448f5617080144e94e887298610 [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
Harry Ramsey0f6bc412024-10-04 10:36:54 +01008#include "ssl_misc.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
SimonBd5800b72016-04-26 07:43:27 +010014#include "mbedtls/ssl_ticket.h"
Janos Follath865b3eb2019-12-16 11:46:15 +000015#include "mbedtls/error.h"
Janos Follath73c616b2019-12-18 15:07:04 +000016#include "mbedtls/platform_util.h"
SimonBd5800b72016-04-26 07:43:27 +010017
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020018#include <string.h>
19
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050020#if defined(MBEDTLS_USE_PSA_CRYPTO)
Andrzej Kurek00644842023-05-30 05:45:00 -040021/* Define a local translating function to save code size by not using too many
22 * arguments in each translating place. */
23static int local_err_translation(psa_status_t status)
24{
25 return psa_status_to_mbedtls(status, psa_to_ssl_errors,
Andrzej Kurek1e4a0302023-05-30 09:45:17 -040026 ARRAY_LENGTH(psa_to_ssl_errors),
Andrzej Kurek00644842023-05-30 05:45:00 -040027 psa_generic_status_to_mbedtls);
28}
29#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050030#endif
31
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020032/*
Shaun Case8b0ecbc2021-12-20 21:14:10 -080033 * Initialize context
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020034 */
Gilles Peskine449bd832023-01-11 14:50:10 +010035void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020036{
Gilles Peskine449bd832023-01-11 14:50:10 +010037 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020038
39#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010040 mbedtls_mutex_init(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020041#endif
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020042}
43
Glenn Straussa941b622022-02-09 15:24:56 -050044#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020045
Glenn Straussa941b622022-02-09 15:24:56 -050046#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
Hanno Beckerd140d082018-11-17 21:18:01 +000047#define TICKET_IV_BYTES 12
48#define TICKET_CRYPT_LEN_BYTES 2
49#define TICKET_AUTH_TAG_BYTES 16
50
Gilles Peskine449bd832023-01-11 14:50:10 +010051#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \
52 TICKET_IV_BYTES + \
53 TICKET_CRYPT_LEN_BYTES + \
54 TICKET_AUTH_TAG_BYTES)
55#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \
56 TICKET_IV_BYTES + \
57 TICKET_CRYPT_LEN_BYTES)
Hanno Beckerd140d082018-11-17 21:18:01 +000058
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020059/*
60 * Generate/update a key
61 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +020062MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +010063static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
64 unsigned char index)
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020065{
Janos Follath865b3eb2019-12-16 11:46:15 +000066 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +010067 unsigned char buf[MAX_KEY_BYTES] = { 0 };
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020068 mbedtls_ssl_ticket_key *key = ctx->keys + index;
69
Gabor Mezei2a020512022-03-10 15:15:46 +010070#if defined(MBEDTLS_USE_PSA_CRYPTO)
71 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
72#endif
73
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020074#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +010075 key->generation_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020076#endif
Ronald Cronba5165e2023-11-21 13:53:18 +010077 /* The lifetime of a key is the configured lifetime of the tickets when
78 * the key is created.
79 */
80 key->lifetime = ctx->ticket_lifetime;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020081
Gilles Peskine449bd832023-01-11 14:50:10 +010082 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
83 return ret;
84 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020085
Gilles Peskine449bd832023-01-11 14:50:10 +010086 if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
87 return ret;
88 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020089
Gabor Mezei2a020512022-03-10 15:15:46 +010090#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +010091 psa_set_key_usage_flags(&attributes,
92 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
93 psa_set_key_algorithm(&attributes, key->alg);
94 psa_set_key_type(&attributes, key->key_type);
95 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +010096
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050097 ret = PSA_TO_MBEDTLS_ERR(
Gilles Peskine449bd832023-01-11 14:50:10 +010098 psa_import_key(&attributes, buf,
99 PSA_BITS_TO_BYTES(key->key_bits),
100 &key->key));
Gabor Mezei2a020512022-03-10 15:15:46 +0100101#else
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200102 /* With GCM and CCM, same context can encrypt & decrypt */
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 ret = mbedtls_cipher_setkey(&key->ctx, buf,
104 mbedtls_cipher_get_key_bitlen(&key->ctx),
105 MBEDTLS_ENCRYPT);
Gabor Mezei2a020512022-03-10 15:15:46 +0100106#endif /* MBEDTLS_USE_PSA_CRYPTO */
107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 mbedtls_platform_zeroize(buf, sizeof(buf));
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 return ret;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200111}
112
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200113/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200114 * Rotate/generate keys if necessary
115 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +0200116MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +0100117static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200118{
119#if !defined(MBEDTLS_HAVE_TIME)
120 ((void) ctx);
121#else
Ronald Cronba5165e2023-11-21 13:53:18 +0100122 mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
123 if (key->lifetime != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100124 mbedtls_time_t current_time = mbedtls_time(NULL);
Ronald Cronba5165e2023-11-21 13:53:18 +0100125 mbedtls_time_t key_time = key->generation_time;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200126
Gabor Mezei2a020512022-03-10 15:15:46 +0100127#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100128 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100129#endif
130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (current_time >= key_time &&
Ronald Cronba5165e2023-11-21 13:53:18 +0100132 (uint64_t) (current_time - key_time) < key->lifetime) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200134 }
135
136 ctx->active = 1 - ctx->active;
137
Gabor Mezei2a020512022-03-10 15:15:46 +0100138#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500140 return PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100141 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100142#endif /* MBEDTLS_USE_PSA_CRYPTO */
143
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 return ssl_ticket_gen_key(ctx, ctx->active);
145 } else
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200146#endif /* MBEDTLS_HAVE_TIME */
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200148}
149
150/*
Glenn Straussa9509382022-02-02 23:32:18 -0500151 * Rotate active session ticket encryption key
152 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100153int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
154 const unsigned char *name, size_t nlength,
155 const unsigned char *k, size_t klength,
156 uint32_t lifetime)
Glenn Straussa9509382022-02-02 23:32:18 -0500157{
158 const unsigned char idx = 1 - ctx->active;
159 mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
Gabor Mezei2a020512022-03-10 15:15:46 +0100160 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
161
162#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100163 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100164 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gabor Mezei36c9f512022-03-16 12:55:32 +0100165 const size_t bitlen = key->key_bits;
Gabor Mezei2a020512022-03-10 15:15:46 +0100166#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100168#endif
169
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
171 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
172 }
Glenn Straussa9509382022-02-02 23:32:18 -0500173
Gabor Mezei2a020512022-03-10 15:15:46 +0100174#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500176 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100178 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 psa_set_key_usage_flags(&attributes,
181 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
182 psa_set_key_algorithm(&attributes, key->alg);
183 psa_set_key_type(&attributes, key->key_type);
184 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +0100185
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 if ((status = psa_import_key(&attributes, k,
187 PSA_BITS_TO_BYTES(key->key_bits),
188 &key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500189 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100191 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100192#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
194 if (ret != 0) {
195 return ret;
196 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100197#endif /* MBEDTLS_USE_PSA_CRYPTO */
198
Glenn Straussa9509382022-02-02 23:32:18 -0500199 ctx->active = idx;
200 ctx->ticket_lifetime = lifetime;
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
Glenn Straussa9509382022-02-02 23:32:18 -0500202#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 key->generation_time = mbedtls_time(NULL);
Glenn Straussa9509382022-02-02 23:32:18 -0500204#endif
Ronald Cronba5165e2023-11-21 13:53:18 +0100205 key->lifetime = lifetime;
206
Glenn Straussa9509382022-02-02 23:32:18 -0500207 return 0;
208}
209
210/*
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200211 * Setup context for actual use
212 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100213int 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)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200217{
Janos Follath865b3eb2019-12-16 11:46:15 +0000218 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200219 size_t key_bits;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200220
Gabor Mezei2a020512022-03-10 15:15:46 +0100221#if defined(MBEDTLS_USE_PSA_CRYPTO)
222 psa_algorithm_t alg;
223 psa_key_type_t key_type;
Neil Armstrong858581e2022-04-01 18:03:15 +0200224#else
225 const mbedtls_cipher_info_t *cipher_info;
226#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100227
Neil Armstrong858581e2022-04-01 18:03:15 +0200228#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 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;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200232 }
233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 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);
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200247#endif /* MBEDTLS_USE_PSA_CRYPTO */
248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 if (key_bits > 8 * MAX_KEY_BYTES) {
250 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
251 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200252
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200253 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
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
268 return ret;
Manuel Pégourié-Gonnarda0adc1b2015-05-25 10:35:16 +0200269 }
270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 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;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200282}
283
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200284/*
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200285 * Create session ticket, with the following structure:
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200286 *
287 * struct {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200288 * opaque key_name[4];
289 * opaque iv[12];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200290 * opaque encrypted_state<0..2^16-1>;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200291 * opaque tag[16];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200292 * } ticket;
293 *
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200294 * The key_name, iv, and length of encrypted_state are the additional
295 * authenticated data.
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200296 */
Hanno Beckerd140d082018-11-17 21:18:01 +0000297
Gilles Peskine449bd832023-01-11 14:50:10 +0100298int 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)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200304{
Janos Follath865b3eb2019-12-16 11:46:15 +0000305 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200306 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200307 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200308 unsigned char *key_name = start;
Hanno Beckerd140d082018-11-17 21:18:01 +0000309 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;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200312 size_t clear_len, ciph_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200313
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100314#if defined(MBEDTLS_USE_PSA_CRYPTO)
315 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
316#endif
317
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200318 *tlen = 0;
319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 if (ctx == NULL || ctx->f_rng == NULL) {
321 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
322 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200323
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200324 /* 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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200327
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200328#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
330 return ret;
331 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200332#endif
333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200335 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200337
338 key = &ctx->keys[ctx->active];
339
Ronald Cronba5165e2023-11-21 13:53:18 +0100340 *ticket_lifetime = key->lifetime;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200341
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200343
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200345 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200347
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200348 /* Dump session state */
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 if ((ret = mbedtls_ssl_session_save(session,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000350 state, (size_t) (end - state),
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 &clear_len)) != 0 ||
352 (unsigned long) clear_len > 65535) {
353 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200354 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200356
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200357 /* Encrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100358#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 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) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500364 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100365 goto cleanup;
366 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100367#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 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,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000373 state, (size_t) (end - state), &ciph_len,
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 TICKET_AUTH_TAG_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200375 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200376 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100377#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200380 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200381 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200382 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200383
Manuel Pégourié-Gonnardf5cf71e2020-12-01 11:43:40 +0100384 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200385
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200386cleanup:
387#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
389 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
390 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200391#endif
392
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200394}
395
396/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200397 * Select key based on name
398 */
399static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 mbedtls_ssl_ticket_context *ctx,
401 const unsigned char name[4])
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200402{
403 unsigned char i;
404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 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 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 return NULL;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200412}
413
414/*
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200415 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
416 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100417int mbedtls_ssl_ticket_parse(void *p_ticket,
418 mbedtls_ssl_session *session,
419 unsigned char *buf,
420 size_t len)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200421{
Janos Follath865b3eb2019-12-16 11:46:15 +0000422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200423 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200424 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200425 unsigned char *key_name = buf;
Hanno Beckerd140d082018-11-17 21:18:01 +0000426 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;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200429 size_t enc_len, clear_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200430
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100431#if defined(MBEDTLS_USE_PSA_CRYPTO)
432 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
433#endif
434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 if (ctx == NULL || ctx->f_rng == NULL) {
436 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
437 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200438
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (len < TICKET_MIN_LEN) {
440 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
441 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200442
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200443#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
445 return ret;
446 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200447#endif
448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200450 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200452
Dave Rodgmana3d0f612023-11-03 23:34:02 +0000453 enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (len != TICKET_MIN_LEN + enc_len) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200456 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
457 goto cleanup;
458 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200459
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200460 /* Select key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200462 /* 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;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200465 goto cleanup;
466 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200467
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200468 /* Decrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100469#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 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) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500474 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100475 goto cleanup;
476 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100477#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 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) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200486 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200488
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200489 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200490 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100491#endif /* MBEDTLS_USE_PSA_CRYPTO */
492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (clear_len != enc_len) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200494 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200495 goto cleanup;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200496 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200497
498 /* Actually load session */
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200500 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200502
503#if defined(MBEDTLS_HAVE_TIME)
Ronald Cron3c0072b2023-11-22 10:00:14 +0100504 mbedtls_ms_time_t ticket_creation_time, ticket_age;
505 mbedtls_ms_time_t ticket_lifetime =
Ronald Cron97dfc722024-03-08 16:34:59 +0100506 (mbedtls_ms_time_t) key->lifetime * 1000;
Jerry Yucebffc32022-12-15 18:00:05 +0800507
Ronald Cron3c0072b2023-11-22 10:00:14 +0100508 ret = mbedtls_ssl_session_get_ticket_creation_time(session,
509 &ticket_creation_time);
510 if (ret != 0) {
511 goto cleanup;
Jerry Yuec6d0782023-10-31 14:42:20 +0800512 }
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200513
Ronald Cron3c0072b2023-11-22 10:00:14 +0100514 ticket_age = mbedtls_ms_time() - ticket_creation_time;
515 if (ticket_age < 0 || ticket_age > ticket_lifetime) {
516 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
517 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200518 }
Ronald Cron3c0072b2023-11-22 10:00:14 +0100519#endif
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200520
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200521cleanup:
522#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
524 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
525 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200526#endif
527
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200529}
530
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200531/*
532 * Free context
533 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100534void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200535{
Troy-Butler9ac3e232024-03-22 14:46:04 -0400536 if (ctx == NULL) {
537 return;
538 }
539
Gabor Mezei2a020512022-03-10 15:15:46 +0100540#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 psa_destroy_key(ctx->keys[0].key);
542 psa_destroy_key(ctx->keys[1].key);
Gabor Mezei2a020512022-03-10 15:15:46 +0100543#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 mbedtls_cipher_free(&ctx->keys[0].ctx);
545 mbedtls_cipher_free(&ctx->keys[1].ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100546#endif /* MBEDTLS_USE_PSA_CRYPTO */
547
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200548#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 mbedtls_mutex_free(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200550#endif
551
Gilles Peskine449bd832023-01-11 14:50:10 +0100552 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200553}
554
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +0200555#endif /* MBEDTLS_SSL_TICKET_C */