blob: f9102904660456a4355f74e1db07c651a3210f35 [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 Rodgman7ff79652023-11-03 12:04:52 +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
Hanno Becker261602c2017-04-12 14:54:42 +010014#include "mbedtls/ssl_internal.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
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020021/*
Shaun Case0e7791f2021-12-20 21:14:10 -080022 * Initialize context
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020023 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010024void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020025{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010026 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020027
28#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010029 mbedtls_mutex_init(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020030#endif
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020031}
32
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020033#define MAX_KEY_BYTES 32 /* 256 bits */
34
Hanno Beckerd140d082018-11-17 21:18:01 +000035#define TICKET_KEY_NAME_BYTES 4
36#define TICKET_IV_BYTES 12
37#define TICKET_CRYPT_LEN_BYTES 2
38#define TICKET_AUTH_TAG_BYTES 16
39
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \
41 TICKET_IV_BYTES + \
42 TICKET_CRYPT_LEN_BYTES + \
43 TICKET_AUTH_TAG_BYTES)
44#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \
45 TICKET_IV_BYTES + \
46 TICKET_CRYPT_LEN_BYTES)
Hanno Beckerd140d082018-11-17 21:18:01 +000047
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020048/*
49 * Generate/update a key
50 */
Manuel Pégourié-Gonnardd904d662022-06-17 10:24:00 +020051MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010052static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
53 unsigned char index)
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020054{
Janos Follath865b3eb2019-12-16 11:46:15 +000055 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020056 unsigned char buf[MAX_KEY_BYTES];
57 mbedtls_ssl_ticket_key *key = ctx->keys + index;
58
59#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060 key->generation_time = (uint32_t) mbedtls_time(NULL);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020061#endif
62
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
64 return ret;
65 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020066
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
68 return ret;
69 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020070
71 /* With GCM and CCM, same context can encrypt & decrypt */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072 ret = mbedtls_cipher_setkey(&key->ctx, buf,
73 mbedtls_cipher_get_key_bitlen(&key->ctx),
74 MBEDTLS_ENCRYPT);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020075
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076 mbedtls_platform_zeroize(buf, sizeof(buf));
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 return ret;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020079}
80
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020081/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +020082 * Rotate/generate keys if necessary
83 */
Manuel Pégourié-Gonnardd904d662022-06-17 10:24:00 +020084MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +020086{
87#if !defined(MBEDTLS_HAVE_TIME)
88 ((void) ctx);
89#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 if (ctx->ticket_lifetime != 0) {
91 uint32_t current_time = (uint32_t) mbedtls_time(NULL);
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +020092 uint32_t key_time = ctx->keys[ctx->active].generation_time;
93
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010094 if (current_time >= key_time &&
95 current_time - key_time < ctx->ticket_lifetime) {
96 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +020097 }
98
99 ctx->active = 1 - ctx->active;
100
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101 return ssl_ticket_gen_key(ctx, ctx->active);
102 } else
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200103#endif /* MBEDTLS_HAVE_TIME */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200105}
106
107/*
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200108 * Setup context for actual use
109 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100110int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
111 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
112 mbedtls_cipher_type_t cipher,
113 uint32_t lifetime)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200114{
Janos Follath865b3eb2019-12-16 11:46:15 +0000115 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200116 const mbedtls_cipher_info_t *cipher_info;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200117
118 ctx->f_rng = f_rng;
119 ctx->p_rng = p_rng;
120
121 ctx->ticket_lifetime = lifetime;
122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 cipher_info = mbedtls_cipher_info_from_type(cipher);
124 if (cipher_info == NULL) {
125 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200126 }
127
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 if (cipher_info->mode != MBEDTLS_MODE_GCM &&
129 cipher_info->mode != MBEDTLS_MODE_CCM) {
130 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
131 }
132
133 if (cipher_info->key_bitlen > 8 * MAX_KEY_BYTES) {
134 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
135 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200136
David Horstmann04020ab2022-10-27 11:30:09 +0100137 int do_mbedtls_cipher_setup = 1;
Hanno Becker679d8ce2018-11-17 21:25:59 +0000138#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 ret = mbedtls_cipher_setup_psa(&ctx->keys[0].ctx,
140 cipher_info, TICKET_AUTH_TAG_BYTES);
David Horstmannbcc18f22022-11-07 14:41:13 +0000141
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100142 switch (ret) {
David Horstmannbcc18f22022-11-07 14:41:13 +0000143 case 0:
144 do_mbedtls_cipher_setup = 0;
145 break;
146 case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
147 /* We don't yet expect to support all ciphers through PSA,
148 * so allow fallback to ordinary mbedtls_cipher_setup(). */
149 do_mbedtls_cipher_setup = 1;
150 break;
151 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 return ret;
David Horstmannbcc18f22022-11-07 14:41:13 +0000153 }
Hanno Becker679d8ce2018-11-17 21:25:59 +0000154#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 if (do_mbedtls_cipher_setup) {
156 if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info))
157 != 0) {
158 return ret;
159 }
160 }
Hanno Becker679d8ce2018-11-17 21:25:59 +0000161
David Horstmann04020ab2022-10-27 11:30:09 +0100162 do_mbedtls_cipher_setup = 1;
Hanno Becker679d8ce2018-11-17 21:25:59 +0000163#if defined(MBEDTLS_USE_PSA_CRYPTO)
David Horstmann04020ab2022-10-27 11:30:09 +0100164 do_mbedtls_cipher_setup = 0;
165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 ret = mbedtls_cipher_setup_psa(&ctx->keys[1].ctx,
167 cipher_info, TICKET_AUTH_TAG_BYTES);
168 if (ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) {
169 return ret;
170 }
171 if (ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) {
David Horstmann04020ab2022-10-27 11:30:09 +0100172 do_mbedtls_cipher_setup = 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173 }
Hanno Becker679d8ce2018-11-17 21:25:59 +0000174#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100175 if (do_mbedtls_cipher_setup) {
176 if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info))
177 != 0) {
178 return ret;
179 }
Manuel Pégourié-Gonnarda0adc1b2015-05-25 10:35:16 +0200180 }
181
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
183 (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
184 return ret;
185 }
186
187 return 0;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200188}
189
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200190/*
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200191 * Create session ticket, with the following structure:
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200192 *
193 * struct {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200194 * opaque key_name[4];
195 * opaque iv[12];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200196 * opaque encrypted_state<0..2^16-1>;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200197 * opaque tag[16];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200198 * } ticket;
199 *
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200200 * The key_name, iv, and length of encrypted_state are the additional
201 * authenticated data.
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200202 */
Hanno Beckerd140d082018-11-17 21:18:01 +0000203
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204int mbedtls_ssl_ticket_write(void *p_ticket,
205 const mbedtls_ssl_session *session,
206 unsigned char *start,
207 const unsigned char *end,
208 size_t *tlen,
209 uint32_t *ticket_lifetime)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200210{
Janos Follath865b3eb2019-12-16 11:46:15 +0000211 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200212 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200213 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200214 unsigned char *key_name = start;
Hanno Beckerd140d082018-11-17 21:18:01 +0000215 unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
216 unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
217 unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200218 size_t clear_len, ciph_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200219
220 *tlen = 0;
221
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 if (ctx == NULL || ctx->f_rng == NULL) {
223 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
224 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200225
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200226 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
227 * in addition to session itself, that will be checked when writing it. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200229
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200230#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
232 return ret;
233 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200234#endif
235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200237 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100238 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200239
240 key = &ctx->keys[ctx->active];
241
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200242 *ticket_lifetime = ctx->ticket_lifetime;
243
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100244 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200245
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200247 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100248 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200249
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200250 /* Dump session state */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100251 if ((ret = mbedtls_ssl_session_save(session,
252 state, end - state,
253 &clear_len)) != 0 ||
254 (unsigned long) clear_len > 65535) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200255 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200256 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100257 MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
258
259 /* Encrypt and authenticate */
260 if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,
261 iv, TICKET_IV_BYTES,
262 /* Additional data: key name, IV and length */
263 key_name, TICKET_ADD_DATA_LEN,
264 state, clear_len,
265 state, end - state, &ciph_len,
266 TICKET_AUTH_TAG_BYTES)) != 0) {
267 goto cleanup;
268 }
269 if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200270 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200271 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200272 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200273
Manuel Pégourié-Gonnardf5cf71e2020-12-01 11:43:40 +0100274 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200275
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200276cleanup:
277#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
279 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
280 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200281#endif
282
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100283 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200284}
285
286/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200287 * Select key based on name
288 */
289static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 mbedtls_ssl_ticket_context *ctx,
291 const unsigned char name[4])
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200292{
293 unsigned char i;
294
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
296 if (memcmp(name, ctx->keys[i].name, 4) == 0) {
297 return &ctx->keys[i];
298 }
299 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 return NULL;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200302}
303
304/*
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200305 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
306 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307int mbedtls_ssl_ticket_parse(void *p_ticket,
308 mbedtls_ssl_session *session,
309 unsigned char *buf,
310 size_t len)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200311{
Janos Follath865b3eb2019-12-16 11:46:15 +0000312 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200313 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200314 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200315 unsigned char *key_name = buf;
Hanno Beckerd140d082018-11-17 21:18:01 +0000316 unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
317 unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
318 unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200319 size_t enc_len, clear_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200320
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321 if (ctx == NULL || ctx->f_rng == NULL) {
322 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
323 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200324
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 if (len < TICKET_MIN_LEN) {
326 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
327 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200328
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200329#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
331 return ret;
332 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200333#endif
334
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100335 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200336 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100337 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200338
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100339 enc_len = (enc_len_p[0] << 8) | enc_len_p[1];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200340
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 if (len != TICKET_MIN_LEN + enc_len) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200342 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
343 goto cleanup;
344 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200345
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200346 /* Select key */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200348 /* We can't know for sure but this is a likely option unless we're
349 * under attack - this is only informative anyway */
350 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200351 goto cleanup;
352 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200353
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200354 /* Decrypt and authenticate */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355 if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,
356 iv, TICKET_IV_BYTES,
357 /* Additional data: key name, IV and length */
358 key_name, TICKET_ADD_DATA_LEN,
359 ticket, enc_len + TICKET_AUTH_TAG_BYTES,
360 ticket, enc_len, &clear_len,
361 TICKET_AUTH_TAG_BYTES)) != 0) {
362 if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200363 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100364 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200365
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200366 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200367 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 if (clear_len != enc_len) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200369 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200370 goto cleanup;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200371 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200372
373 /* Actually load session */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100374 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200375 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200377
378#if defined(MBEDTLS_HAVE_TIME)
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200379 {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200380 /* Check for expiration */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100381 mbedtls_time_t current_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200382
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 if (current_time < session->start ||
384 (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200385 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
386 goto cleanup;
387 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200388 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200389#endif
390
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200391cleanup:
392#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100393 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
394 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
395 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200396#endif
397
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100398 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200399}
400
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200401/*
402 * Free context
403 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100404void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200405{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100406 mbedtls_cipher_free(&ctx->keys[0].ctx);
407 mbedtls_cipher_free(&ctx->keys[1].ctx);
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200408
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200409#if defined(MBEDTLS_THREADING_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410 mbedtls_mutex_free(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200411#endif
412
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100413 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200414}
415
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +0200416#endif /* MBEDTLS_SSL_TICKET_C */