blob: b770a8846ba33c2fdfc82977410e1166f024b5a9 [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 Kurek00644842023-05-30 05:45:00 -040020/* Define a local translating function to save code size by not using too many
21 * arguments in each translating place. */
22static int local_err_translation(psa_status_t status)
23{
24 return psa_status_to_mbedtls(status, psa_to_ssl_errors,
Andrzej Kurek1e4a0302023-05-30 09:45:17 -040025 ARRAY_LENGTH(psa_to_ssl_errors),
Andrzej Kurek00644842023-05-30 05:45:00 -040026 psa_generic_status_to_mbedtls);
27}
28#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050029
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020030/*
Shaun Case8b0ecbc2021-12-20 21:14:10 -080031 * Initialize context
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020032 */
Gilles Peskine449bd832023-01-11 14:50:10 +010033void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020034{
Gilles Peskine449bd832023-01-11 14:50:10 +010035 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020036
37#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010038 mbedtls_mutex_init(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020039#endif
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020040}
41
Glenn Straussa941b622022-02-09 15:24:56 -050042#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020043
Glenn Straussa941b622022-02-09 15:24:56 -050044#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
Hanno Beckerd140d082018-11-17 21:18:01 +000045#define TICKET_IV_BYTES 12
46#define TICKET_CRYPT_LEN_BYTES 2
47#define TICKET_AUTH_TAG_BYTES 16
48
Gilles Peskine449bd832023-01-11 14:50:10 +010049#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \
50 TICKET_IV_BYTES + \
51 TICKET_CRYPT_LEN_BYTES + \
52 TICKET_AUTH_TAG_BYTES)
53#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \
54 TICKET_IV_BYTES + \
55 TICKET_CRYPT_LEN_BYTES)
Hanno Beckerd140d082018-11-17 21:18:01 +000056
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020057/*
58 * Generate/update a key
59 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +020060MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +010061static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
62 unsigned char index)
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020063{
Janos Follath865b3eb2019-12-16 11:46:15 +000064 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +010065 unsigned char buf[MAX_KEY_BYTES] = { 0 };
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020066 mbedtls_ssl_ticket_key *key = ctx->keys + index;
67
Gabor Mezei2a020512022-03-10 15:15:46 +010068 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gabor Mezei2a020512022-03-10 15:15:46 +010069
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020070#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +010071 key->generation_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020072#endif
Ronald Cronba5165e2023-11-21 13:53:18 +010073 /* The lifetime of a key is the configured lifetime of the tickets when
74 * the key is created.
75 */
76 key->lifetime = ctx->ticket_lifetime;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020077
Gilles Peskine449bd832023-01-11 14:50:10 +010078 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
79 return ret;
80 }
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, buf, sizeof(buf))) != 0) {
83 return ret;
84 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020085
Gilles Peskine449bd832023-01-11 14:50:10 +010086 psa_set_key_usage_flags(&attributes,
87 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
88 psa_set_key_algorithm(&attributes, key->alg);
89 psa_set_key_type(&attributes, key->key_type);
90 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +010091
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050092 ret = PSA_TO_MBEDTLS_ERR(
Gilles Peskine449bd832023-01-11 14:50:10 +010093 psa_import_key(&attributes, buf,
94 PSA_BITS_TO_BYTES(key->key_bits),
95 &key->key));
Gabor Mezei2a020512022-03-10 15:15:46 +010096
Gilles Peskine449bd832023-01-11 14:50:10 +010097 mbedtls_platform_zeroize(buf, sizeof(buf));
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 return ret;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200100}
101
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200102/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200103 * Rotate/generate keys if necessary
104 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +0200105MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +0100106static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200107{
108#if !defined(MBEDTLS_HAVE_TIME)
109 ((void) ctx);
110#else
Ronald Cronba5165e2023-11-21 13:53:18 +0100111 mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
112 if (key->lifetime != 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 mbedtls_time_t current_time = mbedtls_time(NULL);
Ronald Cronba5165e2023-11-21 13:53:18 +0100114 mbedtls_time_t key_time = key->generation_time;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200115
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100116 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 if (current_time >= key_time &&
Ronald Cronba5165e2023-11-21 13:53:18 +0100119 (uint64_t) (current_time - key_time) < key->lifetime) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200121 }
122
123 ctx->active = 1 - ctx->active;
124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500126 return PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100127 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 return ssl_ticket_gen_key(ctx, ctx->active);
130 } else
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200131#endif /* MBEDTLS_HAVE_TIME */
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200133}
134
135/*
Glenn Straussa9509382022-02-02 23:32:18 -0500136 * Rotate active session ticket encryption key
137 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100138int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
139 const unsigned char *name, size_t nlength,
140 const unsigned char *k, size_t klength,
141 uint32_t lifetime)
Glenn Straussa9509382022-02-02 23:32:18 -0500142{
143 const unsigned char idx = 1 - ctx->active;
144 mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
Gabor Mezei2a020512022-03-10 15:15:46 +0100145 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
146
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100147 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100148 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gabor Mezei36c9f512022-03-16 12:55:32 +0100149 const size_t bitlen = key->key_bits;
Gabor Mezei2a020512022-03-10 15:15:46 +0100150
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
152 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
153 }
Glenn Straussa9509382022-02-02 23:32:18 -0500154
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500156 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100158 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 psa_set_key_usage_flags(&attributes,
161 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
162 psa_set_key_algorithm(&attributes, key->alg);
163 psa_set_key_type(&attributes, key->key_type);
164 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +0100165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if ((status = psa_import_key(&attributes, k,
167 PSA_BITS_TO_BYTES(key->key_bits),
168 &key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500169 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100171 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100172
Glenn Straussa9509382022-02-02 23:32:18 -0500173 ctx->active = idx;
174 ctx->ticket_lifetime = lifetime;
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
Glenn Straussa9509382022-02-02 23:32:18 -0500176#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 key->generation_time = mbedtls_time(NULL);
Glenn Straussa9509382022-02-02 23:32:18 -0500178#endif
Ronald Cronba5165e2023-11-21 13:53:18 +0100179 key->lifetime = lifetime;
180
Glenn Straussa9509382022-02-02 23:32:18 -0500181 return 0;
182}
183
184/*
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200185 * Setup context for actual use
186 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100187int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
188 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
189 mbedtls_cipher_type_t cipher,
190 uint32_t lifetime)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200191{
Janos Follath865b3eb2019-12-16 11:46:15 +0000192 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200193 size_t key_bits;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200194
Gabor Mezei2a020512022-03-10 15:15:46 +0100195 psa_algorithm_t alg;
196 psa_key_type_t key_type;
Gabor Mezei2a020512022-03-10 15:15:46 +0100197
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,
199 &alg, &key_type, &key_bits) != PSA_SUCCESS) {
200 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200201 }
202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 if (PSA_ALG_IS_AEAD(alg) == 0) {
204 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
205 }
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 if (key_bits > 8 * MAX_KEY_BYTES) {
208 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
209 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200210
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200211 ctx->f_rng = f_rng;
212 ctx->p_rng = p_rng;
213
214 ctx->ticket_lifetime = lifetime;
215
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200216 ctx->keys[0].alg = alg;
217 ctx->keys[0].key_type = key_type;
218 ctx->keys[0].key_bits = key_bits;
219
220 ctx->keys[1].alg = alg;
221 ctx->keys[1].key_type = key_type;
222 ctx->keys[1].key_bits = key_bits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100223
224 if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
225 (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
226 return ret;
227 }
228
229 return 0;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200230}
231
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200232/*
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200233 * Create session ticket, with the following structure:
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200234 *
235 * struct {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200236 * opaque key_name[4];
237 * opaque iv[12];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200238 * opaque encrypted_state<0..2^16-1>;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200239 * opaque tag[16];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200240 * } ticket;
241 *
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200242 * The key_name, iv, and length of encrypted_state are the additional
243 * authenticated data.
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200244 */
Hanno Beckerd140d082018-11-17 21:18:01 +0000245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246int mbedtls_ssl_ticket_write(void *p_ticket,
247 const mbedtls_ssl_session *session,
248 unsigned char *start,
249 const unsigned char *end,
250 size_t *tlen,
251 uint32_t *ticket_lifetime)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200252{
Janos Follath865b3eb2019-12-16 11:46:15 +0000253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200254 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200255 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200256 unsigned char *key_name = start;
Hanno Beckerd140d082018-11-17 21:18:01 +0000257 unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
258 unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
259 unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200260 size_t clear_len, ciph_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200261
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100262 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100263
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200264 *tlen = 0;
265
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 if (ctx == NULL || ctx->f_rng == NULL) {
267 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
268 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200269
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200270 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
271 * in addition to session itself, that will be checked when writing it. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200273
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200274#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
276 return ret;
277 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200278#endif
279
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200281 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200283
284 key = &ctx->keys[ctx->active];
285
Ronald Cronba5165e2023-11-21 13:53:18 +0100286 *ticket_lifetime = key->lifetime;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200287
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200289
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200291 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200293
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200294 /* Dump session state */
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if ((ret = mbedtls_ssl_session_save(session,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000296 state, (size_t) (end - state),
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 &clear_len)) != 0 ||
298 (unsigned long) clear_len > 65535) {
299 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200300 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200302
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200303 /* Encrypt and authenticate */
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
305 key_name, TICKET_ADD_DATA_LEN,
306 state, clear_len,
307 state, end - state,
308 &ciph_len)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500309 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100310 goto cleanup;
311 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200314 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200315 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200316 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200317
Manuel Pégourié-Gonnardf5cf71e2020-12-01 11:43:40 +0100318 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200319
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200320cleanup:
321#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
323 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
324 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200325#endif
326
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200328}
329
330/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200331 * Select key based on name
332 */
333static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 mbedtls_ssl_ticket_context *ctx,
335 const unsigned char name[4])
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200336{
337 unsigned char i;
338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
340 if (memcmp(name, ctx->keys[i].name, 4) == 0) {
341 return &ctx->keys[i];
342 }
343 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 return NULL;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200346}
347
348/*
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200349 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
350 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100351int mbedtls_ssl_ticket_parse(void *p_ticket,
352 mbedtls_ssl_session *session,
353 unsigned char *buf,
354 size_t len)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200355{
Janos Follath865b3eb2019-12-16 11:46:15 +0000356 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200357 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200358 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200359 unsigned char *key_name = buf;
Hanno Beckerd140d082018-11-17 21:18:01 +0000360 unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
361 unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
362 unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200363 size_t enc_len, clear_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200364
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100365 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 if (ctx == NULL || ctx->f_rng == NULL) {
368 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
369 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200370
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 if (len < TICKET_MIN_LEN) {
372 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
373 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200374
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200375#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
377 return ret;
378 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200379#endif
380
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200382 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200384
Dave Rodgmana3d0f612023-11-03 23:34:02 +0000385 enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 if (len != TICKET_MIN_LEN + enc_len) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200388 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
389 goto cleanup;
390 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200391
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200392 /* Select key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200394 /* We can't know for sure but this is a likely option unless we're
395 * under attack - this is only informative anyway */
396 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200397 goto cleanup;
398 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200399
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200400 /* Decrypt and authenticate */
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
402 key_name, TICKET_ADD_DATA_LEN,
403 ticket, enc_len + TICKET_AUTH_TAG_BYTES,
404 ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500405 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100406 goto cleanup;
407 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 if (clear_len != enc_len) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200410 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200411 goto cleanup;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200412 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200413
414 /* Actually load session */
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200416 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200418
419#if defined(MBEDTLS_HAVE_TIME)
Ronald Cron3c0072b2023-11-22 10:00:14 +0100420 mbedtls_ms_time_t ticket_creation_time, ticket_age;
421 mbedtls_ms_time_t ticket_lifetime =
Ronald Cron97dfc722024-03-08 16:34:59 +0100422 (mbedtls_ms_time_t) key->lifetime * 1000;
Jerry Yucebffc32022-12-15 18:00:05 +0800423
Ronald Cron3c0072b2023-11-22 10:00:14 +0100424 ret = mbedtls_ssl_session_get_ticket_creation_time(session,
425 &ticket_creation_time);
426 if (ret != 0) {
427 goto cleanup;
Jerry Yuec6d0782023-10-31 14:42:20 +0800428 }
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200429
Ronald Cron3c0072b2023-11-22 10:00:14 +0100430 ticket_age = mbedtls_ms_time() - ticket_creation_time;
431 if (ticket_age < 0 || ticket_age > ticket_lifetime) {
432 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
433 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200434 }
Ronald Cron3c0072b2023-11-22 10:00:14 +0100435#endif
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200436
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200437cleanup:
438#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
440 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
441 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200442#endif
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200445}
446
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200447/*
448 * Free context
449 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100450void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200451{
Troy-Butler9ac3e232024-03-22 14:46:04 -0400452 if (ctx == NULL) {
453 return;
454 }
455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 psa_destroy_key(ctx->keys[0].key);
457 psa_destroy_key(ctx->keys[1].key);
Gabor Mezei2a020512022-03-10 15:15:46 +0100458
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200459#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 mbedtls_mutex_free(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200461#endif
462
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200464}
465
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +0200466#endif /* MBEDTLS_SSL_TICKET_C */