blob: 1adaa07fe25bb319e7d38e9a6b3590fe003c2a67 [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020018 */
19
Gilles Peskinedb09ef62020-06-03 01:43:33 +020020#include "common.h"
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020021
22#if defined(MBEDTLS_SSL_TICKET_C)
23
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020024#include "mbedtls/platform.h"
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020025
Chris Jones84a773f2021-03-05 18:38:47 +000026#include "ssl_misc.h"
SimonBd5800b72016-04-26 07:43:27 +010027#include "mbedtls/ssl_ticket.h"
Janos Follath865b3eb2019-12-16 11:46:15 +000028#include "mbedtls/error.h"
Janos Follath73c616b2019-12-18 15:07:04 +000029#include "mbedtls/platform_util.h"
SimonBd5800b72016-04-26 07:43:27 +010030
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +020031#include <string.h>
32
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050033#if defined(MBEDTLS_USE_PSA_CRYPTO)
Andrzej Kurek00644842023-05-30 05:45:00 -040034/* Define a local translating function to save code size by not using too many
35 * arguments in each translating place. */
36static int local_err_translation(psa_status_t status)
37{
38 return psa_status_to_mbedtls(status, psa_to_ssl_errors,
Andrzej Kurek1e4a0302023-05-30 09:45:17 -040039 ARRAY_LENGTH(psa_to_ssl_errors),
Andrzej Kurek00644842023-05-30 05:45:00 -040040 psa_generic_status_to_mbedtls);
41}
42#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050043#endif
44
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020045/*
Shaun Case8b0ecbc2021-12-20 21:14:10 -080046 * Initialize context
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020047 */
Gilles Peskine449bd832023-01-11 14:50:10 +010048void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020049{
Gilles Peskine449bd832023-01-11 14:50:10 +010050 memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020051
52#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010053 mbedtls_mutex_init(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +020054#endif
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +020055}
56
Glenn Straussa941b622022-02-09 15:24:56 -050057#define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020058
Glenn Straussa941b622022-02-09 15:24:56 -050059#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
Hanno Beckerd140d082018-11-17 21:18:01 +000060#define TICKET_IV_BYTES 12
61#define TICKET_CRYPT_LEN_BYTES 2
62#define TICKET_AUTH_TAG_BYTES 16
63
Gilles Peskine449bd832023-01-11 14:50:10 +010064#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \
65 TICKET_IV_BYTES + \
66 TICKET_CRYPT_LEN_BYTES + \
67 TICKET_AUTH_TAG_BYTES)
68#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \
69 TICKET_IV_BYTES + \
70 TICKET_CRYPT_LEN_BYTES)
Hanno Beckerd140d082018-11-17 21:18:01 +000071
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020072/*
73 * Generate/update a key
74 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +020075MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +010076static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
77 unsigned char index)
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020078{
Janos Follath865b3eb2019-12-16 11:46:15 +000079 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +010080 unsigned char buf[MAX_KEY_BYTES] = { 0 };
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020081 mbedtls_ssl_ticket_key *key = ctx->keys + index;
82
Gabor Mezei2a020512022-03-10 15:15:46 +010083#if defined(MBEDTLS_USE_PSA_CRYPTO)
84 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
85#endif
86
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020087#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +010088 key->generation_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020089#endif
90
Gilles Peskine449bd832023-01-11 14:50:10 +010091 if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
92 return ret;
93 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020094
Gilles Peskine449bd832023-01-11 14:50:10 +010095 if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
96 return ret;
97 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +020098
Gabor Mezei2a020512022-03-10 15:15:46 +010099#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 psa_set_key_usage_flags(&attributes,
101 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
102 psa_set_key_algorithm(&attributes, key->alg);
103 psa_set_key_type(&attributes, key->key_type);
104 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +0100105
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500106 ret = PSA_TO_MBEDTLS_ERR(
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 psa_import_key(&attributes, buf,
108 PSA_BITS_TO_BYTES(key->key_bits),
109 &key->key));
Gabor Mezei2a020512022-03-10 15:15:46 +0100110#else
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200111 /* With GCM and CCM, same context can encrypt & decrypt */
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 ret = mbedtls_cipher_setkey(&key->ctx, buf,
113 mbedtls_cipher_get_key_bitlen(&key->ctx),
114 MBEDTLS_ENCRYPT);
Gabor Mezei2a020512022-03-10 15:15:46 +0100115#endif /* MBEDTLS_USE_PSA_CRYPTO */
116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 mbedtls_platform_zeroize(buf, sizeof(buf));
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 return ret;
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200120}
121
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200122/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200123 * Rotate/generate keys if necessary
124 */
Manuel Pégourié-Gonnarda3115dc2022-06-17 10:52:54 +0200125MBEDTLS_CHECK_RETURN_CRITICAL
Gilles Peskine449bd832023-01-11 14:50:10 +0100126static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200127{
128#if !defined(MBEDTLS_HAVE_TIME)
129 ((void) ctx);
130#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (ctx->ticket_lifetime != 0) {
132 mbedtls_time_t current_time = mbedtls_time(NULL);
Dave Rodgman392f7142022-08-17 11:19:41 +0100133 mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200134
Gabor Mezei2a020512022-03-10 15:15:46 +0100135#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100136 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100137#endif
138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 if (current_time >= key_time &&
140 (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
141 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200142 }
143
144 ctx->active = 1 - ctx->active;
145
Gabor Mezei2a020512022-03-10 15:15:46 +0100146#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500148 return PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100149 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100150#endif /* MBEDTLS_USE_PSA_CRYPTO */
151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 return ssl_ticket_gen_key(ctx, ctx->active);
153 } else
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200154#endif /* MBEDTLS_HAVE_TIME */
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 return 0;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200156}
157
158/*
Glenn Straussa9509382022-02-02 23:32:18 -0500159 * Rotate active session ticket encryption key
160 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100161int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
162 const unsigned char *name, size_t nlength,
163 const unsigned char *k, size_t klength,
164 uint32_t lifetime)
Glenn Straussa9509382022-02-02 23:32:18 -0500165{
166 const unsigned char idx = 1 - ctx->active;
167 mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
Gabor Mezei2a020512022-03-10 15:15:46 +0100168 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
169
170#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100171 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Gabor Mezei2a020512022-03-10 15:15:46 +0100172 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Gabor Mezei36c9f512022-03-16 12:55:32 +0100173 const size_t bitlen = key->key_bits;
Gabor Mezei2a020512022-03-10 15:15:46 +0100174#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100176#endif
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
179 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
180 }
Glenn Straussa9509382022-02-02 23:32:18 -0500181
Gabor Mezei2a020512022-03-10 15:15:46 +0100182#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500184 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100186 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100187
Gilles Peskine449bd832023-01-11 14:50:10 +0100188 psa_set_key_usage_flags(&attributes,
189 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
190 psa_set_key_algorithm(&attributes, key->alg);
191 psa_set_key_type(&attributes, key->key_type);
192 psa_set_key_bits(&attributes, key->key_bits);
Gabor Mezei2a020512022-03-10 15:15:46 +0100193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 if ((status = psa_import_key(&attributes, k,
195 PSA_BITS_TO_BYTES(key->key_bits),
196 &key->key)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500197 ret = PSA_TO_MBEDTLS_ERR(status);
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 return ret;
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100199 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100200#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
202 if (ret != 0) {
203 return ret;
204 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100205#endif /* MBEDTLS_USE_PSA_CRYPTO */
206
Glenn Straussa9509382022-02-02 23:32:18 -0500207 ctx->active = idx;
208 ctx->ticket_lifetime = lifetime;
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
Glenn Straussa9509382022-02-02 23:32:18 -0500210#if defined(MBEDTLS_HAVE_TIME)
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 key->generation_time = mbedtls_time(NULL);
Glenn Straussa9509382022-02-02 23:32:18 -0500212#endif
213 return 0;
214}
215
216/*
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200217 * Setup context for actual use
218 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100219int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
220 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
221 mbedtls_cipher_type_t cipher,
222 uint32_t lifetime)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200223{
Janos Follath865b3eb2019-12-16 11:46:15 +0000224 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200225 size_t key_bits;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200226
Gabor Mezei2a020512022-03-10 15:15:46 +0100227#if defined(MBEDTLS_USE_PSA_CRYPTO)
228 psa_algorithm_t alg;
229 psa_key_type_t key_type;
Neil Armstrong858581e2022-04-01 18:03:15 +0200230#else
231 const mbedtls_cipher_info_t *cipher_info;
232#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100233
Neil Armstrong858581e2022-04-01 18:03:15 +0200234#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,
236 &alg, &key_type, &key_bits) != PSA_SUCCESS) {
237 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200238 }
239
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 if (PSA_ALG_IS_AEAD(alg) == 0) {
241 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
242 }
243#else
244 cipher_info = mbedtls_cipher_info_from_type(cipher);
245
246 if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM &&
247 mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM &&
248 mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) {
249 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
250 }
251
252 key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info);
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200253#endif /* MBEDTLS_USE_PSA_CRYPTO */
254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 if (key_bits > 8 * MAX_KEY_BYTES) {
256 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
257 }
Manuel Pégourié-Gonnard887674a2015-05-25 11:00:19 +0200258
Neil Armstrong3bf040e2022-04-27 10:35:24 +0200259 ctx->f_rng = f_rng;
260 ctx->p_rng = p_rng;
261
262 ctx->ticket_lifetime = lifetime;
263
264#if defined(MBEDTLS_USE_PSA_CRYPTO)
265 ctx->keys[0].alg = alg;
266 ctx->keys[0].key_type = key_type;
267 ctx->keys[0].key_bits = key_bits;
268
269 ctx->keys[1].alg = alg;
270 ctx->keys[1].key_type = key_type;
271 ctx->keys[1].key_bits = key_bits;
272#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
274 return ret;
Manuel Pégourié-Gonnarda0adc1b2015-05-25 10:35:16 +0200275 }
276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {
278 return ret;
279 }
280#endif /* MBEDTLS_USE_PSA_CRYPTO */
281
282 if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
283 (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
284 return ret;
285 }
286
287 return 0;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200288}
289
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200290/*
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200291 * Create session ticket, with the following structure:
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200292 *
293 * struct {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200294 * opaque key_name[4];
295 * opaque iv[12];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200296 * opaque encrypted_state<0..2^16-1>;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200297 * opaque tag[16];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200298 * } ticket;
299 *
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200300 * The key_name, iv, and length of encrypted_state are the additional
301 * authenticated data.
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200302 */
Hanno Beckerd140d082018-11-17 21:18:01 +0000303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304int mbedtls_ssl_ticket_write(void *p_ticket,
305 const mbedtls_ssl_session *session,
306 unsigned char *start,
307 const unsigned char *end,
308 size_t *tlen,
309 uint32_t *ticket_lifetime)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200310{
Janos Follath865b3eb2019-12-16 11:46:15 +0000311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200312 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200313 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200314 unsigned char *key_name = start;
Hanno Beckerd140d082018-11-17 21:18:01 +0000315 unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
316 unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
317 unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200318 size_t clear_len, ciph_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200319
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100320#if defined(MBEDTLS_USE_PSA_CRYPTO)
321 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
322#endif
323
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200324 *tlen = 0;
325
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 if (ctx == NULL || ctx->f_rng == NULL) {
327 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
328 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200329
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200330 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
331 * in addition to session itself, that will be checked when writing it. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200333
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200334#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
336 return ret;
337 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200338#endif
339
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200341 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200343
344 key = &ctx->keys[ctx->active];
345
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200346 *ticket_lifetime = ctx->ticket_lifetime;
347
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200351 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200353
Manuel Pégourié-Gonnard69f17282015-05-18 14:35:08 +0200354 /* Dump session state */
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 if ((ret = mbedtls_ssl_session_save(session,
356 state, end - state,
357 &clear_len)) != 0 ||
358 (unsigned long) clear_len > 65535) {
359 goto cleanup;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200360 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200362
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200363 /* Encrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100364#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
366 key_name, TICKET_ADD_DATA_LEN,
367 state, clear_len,
368 state, end - state,
369 &ciph_len)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500370 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100371 goto cleanup;
372 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100373#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,
375 iv, TICKET_IV_BYTES,
376 /* Additional data: key name, IV and length */
377 key_name, TICKET_ADD_DATA_LEN,
378 state, clear_len,
379 state, end - state, &ciph_len,
380 TICKET_AUTH_TAG_BYTES)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200381 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200382 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100383#endif /* MBEDTLS_USE_PSA_CRYPTO */
Gabor Mezei2a020512022-03-10 15:15:46 +0100384
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200386 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200387 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200388 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200389
Manuel Pégourié-Gonnardf5cf71e2020-12-01 11:43:40 +0100390 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200391
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200392cleanup:
393#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
395 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
396 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200397#endif
398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200400}
401
402/*
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200403 * Select key based on name
404 */
405static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 mbedtls_ssl_ticket_context *ctx,
407 const unsigned char name[4])
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200408{
409 unsigned char i;
410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
412 if (memcmp(name, ctx->keys[i].name, 4) == 0) {
413 return &ctx->keys[i];
414 }
415 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 return NULL;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200418}
419
420/*
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200421 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
422 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100423int mbedtls_ssl_ticket_parse(void *p_ticket,
424 mbedtls_ssl_session *session,
425 unsigned char *buf,
426 size_t len)
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200427{
Janos Follath865b3eb2019-12-16 11:46:15 +0000428 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200429 mbedtls_ssl_ticket_context *ctx = p_ticket;
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200430 mbedtls_ssl_ticket_key *key;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200431 unsigned char *key_name = buf;
Hanno Beckerd140d082018-11-17 21:18:01 +0000432 unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
433 unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
434 unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200435 size_t enc_len, clear_len;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200436
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100437#if defined(MBEDTLS_USE_PSA_CRYPTO)
438 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
439#endif
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (ctx == NULL || ctx->f_rng == NULL) {
442 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
443 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 if (len < TICKET_MIN_LEN) {
446 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
447 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200448
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200449#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
451 return ret;
452 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200453#endif
454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200456 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 enc_len = (enc_len_p[0] << 8) | enc_len_p[1];
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200460
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 if (len != TICKET_MIN_LEN + enc_len) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200462 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
463 goto cleanup;
464 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200465
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200466 /* Select key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200468 /* We can't know for sure but this is a likely option unless we're
469 * under attack - this is only informative anyway */
470 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200471 goto cleanup;
472 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200473
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200474 /* Decrypt and authenticate */
Gabor Mezei2a020512022-03-10 15:15:46 +0100475#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
477 key_name, TICKET_ADD_DATA_LEN,
478 ticket, enc_len + TICKET_AUTH_TAG_BYTES,
479 ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500480 ret = PSA_TO_MBEDTLS_ERR(status);
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100481 goto cleanup;
482 }
Gabor Mezei2a020512022-03-10 15:15:46 +0100483#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,
485 iv, TICKET_IV_BYTES,
486 /* Additional data: key name, IV and length */
487 key_name, TICKET_ADD_DATA_LEN,
488 ticket, enc_len + TICKET_AUTH_TAG_BYTES,
489 ticket, enc_len, &clear_len,
490 TICKET_AUTH_TAG_BYTES)) != 0) {
491 if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200492 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 }
Manuel Pégourié-Gonnard1e9c4db2015-05-25 14:07:08 +0200494
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200495 goto cleanup;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200496 }
Gabor Mezei5b8b8902022-03-16 12:56:58 +0100497#endif /* MBEDTLS_USE_PSA_CRYPTO */
498
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 if (clear_len != enc_len) {
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200500 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200501 goto cleanup;
Manuel Pégourié-Gonnard1041a392015-05-20 19:59:39 +0200502 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200503
504 /* Actually load session */
Gilles Peskine449bd832023-01-11 14:50:10 +0100505 if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200506 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200508
509#if defined(MBEDTLS_HAVE_TIME)
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200510 {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200511 /* Check for expiration */
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 mbedtls_time_t current_time = mbedtls_time(NULL);
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 if (current_time < session->start ||
515 (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
Manuel Pégourié-Gonnard8eff5122015-05-20 11:41:36 +0200516 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
517 goto cleanup;
518 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200519 }
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200520#endif
521
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200522cleanup:
523#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
525 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
526 }
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200527#endif
528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 return ret;
Manuel Pégourié-Gonnarda4a47352015-05-15 15:14:54 +0200530}
531
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200532/*
533 * Free context
534 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100535void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200536{
Gabor Mezei2a020512022-03-10 15:15:46 +0100537#if defined(MBEDTLS_USE_PSA_CRYPTO)
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 psa_destroy_key(ctx->keys[0].key);
539 psa_destroy_key(ctx->keys[1].key);
Gabor Mezei2a020512022-03-10 15:15:46 +0100540#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 mbedtls_cipher_free(&ctx->keys[0].ctx);
542 mbedtls_cipher_free(&ctx->keys[1].ctx);
Gabor Mezei2a020512022-03-10 15:15:46 +0100543#endif /* MBEDTLS_USE_PSA_CRYPTO */
544
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200545#if defined(MBEDTLS_THREADING_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100546 mbedtls_mutex_free(&ctx->mutex);
Manuel Pégourié-Gonnard0849a0a2015-05-20 11:34:54 +0200547#endif
548
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
Manuel Pégourié-Gonnardd59675d2015-05-19 15:28:00 +0200550}
551
Manuel Pégourié-Gonnardfd6d8972015-05-15 12:09:00 +0200552#endif /* MBEDTLS_SSL_TICKET_C */