1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * TLS server tickets callbacks implementation
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi #include "common.h"
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SSL_TICKET_C)
11*62c56f98SSadaf Ebrahimi
12*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
13*62c56f98SSadaf Ebrahimi
14*62c56f98SSadaf Ebrahimi #include "ssl_misc.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/ssl_ticket.h"
16*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
17*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
18*62c56f98SSadaf Ebrahimi
19*62c56f98SSadaf Ebrahimi #include <string.h>
20*62c56f98SSadaf Ebrahimi
21*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
22*62c56f98SSadaf Ebrahimi /* Define a local translating function to save code size by not using too many
23*62c56f98SSadaf Ebrahimi * arguments in each translating place. */
local_err_translation(psa_status_t status)24*62c56f98SSadaf Ebrahimi static int local_err_translation(psa_status_t status)
25*62c56f98SSadaf Ebrahimi {
26*62c56f98SSadaf Ebrahimi return psa_status_to_mbedtls(status, psa_to_ssl_errors,
27*62c56f98SSadaf Ebrahimi ARRAY_LENGTH(psa_to_ssl_errors),
28*62c56f98SSadaf Ebrahimi psa_generic_status_to_mbedtls);
29*62c56f98SSadaf Ebrahimi }
30*62c56f98SSadaf Ebrahimi #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
31*62c56f98SSadaf Ebrahimi #endif
32*62c56f98SSadaf Ebrahimi
33*62c56f98SSadaf Ebrahimi /*
34*62c56f98SSadaf Ebrahimi * Initialize context
35*62c56f98SSadaf Ebrahimi */
mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context * ctx)36*62c56f98SSadaf Ebrahimi void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
37*62c56f98SSadaf Ebrahimi {
38*62c56f98SSadaf Ebrahimi memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
39*62c56f98SSadaf Ebrahimi
40*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
41*62c56f98SSadaf Ebrahimi mbedtls_mutex_init(&ctx->mutex);
42*62c56f98SSadaf Ebrahimi #endif
43*62c56f98SSadaf Ebrahimi }
44*62c56f98SSadaf Ebrahimi
45*62c56f98SSadaf Ebrahimi #define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
46*62c56f98SSadaf Ebrahimi
47*62c56f98SSadaf Ebrahimi #define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
48*62c56f98SSadaf Ebrahimi #define TICKET_IV_BYTES 12
49*62c56f98SSadaf Ebrahimi #define TICKET_CRYPT_LEN_BYTES 2
50*62c56f98SSadaf Ebrahimi #define TICKET_AUTH_TAG_BYTES 16
51*62c56f98SSadaf Ebrahimi
52*62c56f98SSadaf Ebrahimi #define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \
53*62c56f98SSadaf Ebrahimi TICKET_IV_BYTES + \
54*62c56f98SSadaf Ebrahimi TICKET_CRYPT_LEN_BYTES + \
55*62c56f98SSadaf Ebrahimi TICKET_AUTH_TAG_BYTES)
56*62c56f98SSadaf Ebrahimi #define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \
57*62c56f98SSadaf Ebrahimi TICKET_IV_BYTES + \
58*62c56f98SSadaf Ebrahimi TICKET_CRYPT_LEN_BYTES)
59*62c56f98SSadaf Ebrahimi
60*62c56f98SSadaf Ebrahimi /*
61*62c56f98SSadaf Ebrahimi * Generate/update a key
62*62c56f98SSadaf Ebrahimi */
63*62c56f98SSadaf Ebrahimi MBEDTLS_CHECK_RETURN_CRITICAL
ssl_ticket_gen_key(mbedtls_ssl_ticket_context * ctx,unsigned char index)64*62c56f98SSadaf Ebrahimi static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
65*62c56f98SSadaf Ebrahimi unsigned char index)
66*62c56f98SSadaf Ebrahimi {
67*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
68*62c56f98SSadaf Ebrahimi unsigned char buf[MAX_KEY_BYTES] = { 0 };
69*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_key *key = ctx->keys + index;
70*62c56f98SSadaf Ebrahimi
71*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
72*62c56f98SSadaf Ebrahimi psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
73*62c56f98SSadaf Ebrahimi #endif
74*62c56f98SSadaf Ebrahimi
75*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME)
76*62c56f98SSadaf Ebrahimi key->generation_time = mbedtls_time(NULL);
77*62c56f98SSadaf Ebrahimi #endif
78*62c56f98SSadaf Ebrahimi
79*62c56f98SSadaf Ebrahimi if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
80*62c56f98SSadaf Ebrahimi return ret;
81*62c56f98SSadaf Ebrahimi }
82*62c56f98SSadaf Ebrahimi
83*62c56f98SSadaf Ebrahimi if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
84*62c56f98SSadaf Ebrahimi return ret;
85*62c56f98SSadaf Ebrahimi }
86*62c56f98SSadaf Ebrahimi
87*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
88*62c56f98SSadaf Ebrahimi psa_set_key_usage_flags(&attributes,
89*62c56f98SSadaf Ebrahimi PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
90*62c56f98SSadaf Ebrahimi psa_set_key_algorithm(&attributes, key->alg);
91*62c56f98SSadaf Ebrahimi psa_set_key_type(&attributes, key->key_type);
92*62c56f98SSadaf Ebrahimi psa_set_key_bits(&attributes, key->key_bits);
93*62c56f98SSadaf Ebrahimi
94*62c56f98SSadaf Ebrahimi ret = PSA_TO_MBEDTLS_ERR(
95*62c56f98SSadaf Ebrahimi psa_import_key(&attributes, buf,
96*62c56f98SSadaf Ebrahimi PSA_BITS_TO_BYTES(key->key_bits),
97*62c56f98SSadaf Ebrahimi &key->key));
98*62c56f98SSadaf Ebrahimi #else
99*62c56f98SSadaf Ebrahimi /* With GCM and CCM, same context can encrypt & decrypt */
100*62c56f98SSadaf Ebrahimi ret = mbedtls_cipher_setkey(&key->ctx, buf,
101*62c56f98SSadaf Ebrahimi mbedtls_cipher_get_key_bitlen(&key->ctx),
102*62c56f98SSadaf Ebrahimi MBEDTLS_ENCRYPT);
103*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
104*62c56f98SSadaf Ebrahimi
105*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
106*62c56f98SSadaf Ebrahimi
107*62c56f98SSadaf Ebrahimi return ret;
108*62c56f98SSadaf Ebrahimi }
109*62c56f98SSadaf Ebrahimi
110*62c56f98SSadaf Ebrahimi /*
111*62c56f98SSadaf Ebrahimi * Rotate/generate keys if necessary
112*62c56f98SSadaf Ebrahimi */
113*62c56f98SSadaf Ebrahimi MBEDTLS_CHECK_RETURN_CRITICAL
ssl_ticket_update_keys(mbedtls_ssl_ticket_context * ctx)114*62c56f98SSadaf Ebrahimi static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
115*62c56f98SSadaf Ebrahimi {
116*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_HAVE_TIME)
117*62c56f98SSadaf Ebrahimi ((void) ctx);
118*62c56f98SSadaf Ebrahimi #else
119*62c56f98SSadaf Ebrahimi if (ctx->ticket_lifetime != 0) {
120*62c56f98SSadaf Ebrahimi mbedtls_time_t current_time = mbedtls_time(NULL);
121*62c56f98SSadaf Ebrahimi mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
122*62c56f98SSadaf Ebrahimi
123*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
124*62c56f98SSadaf Ebrahimi psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
125*62c56f98SSadaf Ebrahimi #endif
126*62c56f98SSadaf Ebrahimi
127*62c56f98SSadaf Ebrahimi if (current_time >= key_time &&
128*62c56f98SSadaf Ebrahimi (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
129*62c56f98SSadaf Ebrahimi return 0;
130*62c56f98SSadaf Ebrahimi }
131*62c56f98SSadaf Ebrahimi
132*62c56f98SSadaf Ebrahimi ctx->active = 1 - ctx->active;
133*62c56f98SSadaf Ebrahimi
134*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
135*62c56f98SSadaf Ebrahimi if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
136*62c56f98SSadaf Ebrahimi return PSA_TO_MBEDTLS_ERR(status);
137*62c56f98SSadaf Ebrahimi }
138*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
139*62c56f98SSadaf Ebrahimi
140*62c56f98SSadaf Ebrahimi return ssl_ticket_gen_key(ctx, ctx->active);
141*62c56f98SSadaf Ebrahimi } else
142*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_HAVE_TIME */
143*62c56f98SSadaf Ebrahimi return 0;
144*62c56f98SSadaf Ebrahimi }
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf Ebrahimi /*
147*62c56f98SSadaf Ebrahimi * Rotate active session ticket encryption key
148*62c56f98SSadaf Ebrahimi */
mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context * ctx,const unsigned char * name,size_t nlength,const unsigned char * k,size_t klength,uint32_t lifetime)149*62c56f98SSadaf Ebrahimi int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
150*62c56f98SSadaf Ebrahimi const unsigned char *name, size_t nlength,
151*62c56f98SSadaf Ebrahimi const unsigned char *k, size_t klength,
152*62c56f98SSadaf Ebrahimi uint32_t lifetime)
153*62c56f98SSadaf Ebrahimi {
154*62c56f98SSadaf Ebrahimi const unsigned char idx = 1 - ctx->active;
155*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
156*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
157*62c56f98SSadaf Ebrahimi
158*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
159*62c56f98SSadaf Ebrahimi psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
160*62c56f98SSadaf Ebrahimi psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
161*62c56f98SSadaf Ebrahimi const size_t bitlen = key->key_bits;
162*62c56f98SSadaf Ebrahimi #else
163*62c56f98SSadaf Ebrahimi const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
164*62c56f98SSadaf Ebrahimi #endif
165*62c56f98SSadaf Ebrahimi
166*62c56f98SSadaf Ebrahimi if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
167*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
168*62c56f98SSadaf Ebrahimi }
169*62c56f98SSadaf Ebrahimi
170*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
171*62c56f98SSadaf Ebrahimi if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
172*62c56f98SSadaf Ebrahimi ret = PSA_TO_MBEDTLS_ERR(status);
173*62c56f98SSadaf Ebrahimi return ret;
174*62c56f98SSadaf Ebrahimi }
175*62c56f98SSadaf Ebrahimi
176*62c56f98SSadaf Ebrahimi psa_set_key_usage_flags(&attributes,
177*62c56f98SSadaf Ebrahimi PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
178*62c56f98SSadaf Ebrahimi psa_set_key_algorithm(&attributes, key->alg);
179*62c56f98SSadaf Ebrahimi psa_set_key_type(&attributes, key->key_type);
180*62c56f98SSadaf Ebrahimi psa_set_key_bits(&attributes, key->key_bits);
181*62c56f98SSadaf Ebrahimi
182*62c56f98SSadaf Ebrahimi if ((status = psa_import_key(&attributes, k,
183*62c56f98SSadaf Ebrahimi PSA_BITS_TO_BYTES(key->key_bits),
184*62c56f98SSadaf Ebrahimi &key->key)) != PSA_SUCCESS) {
185*62c56f98SSadaf Ebrahimi ret = PSA_TO_MBEDTLS_ERR(status);
186*62c56f98SSadaf Ebrahimi return ret;
187*62c56f98SSadaf Ebrahimi }
188*62c56f98SSadaf Ebrahimi #else
189*62c56f98SSadaf Ebrahimi ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
190*62c56f98SSadaf Ebrahimi if (ret != 0) {
191*62c56f98SSadaf Ebrahimi return ret;
192*62c56f98SSadaf Ebrahimi }
193*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
194*62c56f98SSadaf Ebrahimi
195*62c56f98SSadaf Ebrahimi ctx->active = idx;
196*62c56f98SSadaf Ebrahimi ctx->ticket_lifetime = lifetime;
197*62c56f98SSadaf Ebrahimi memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
198*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME)
199*62c56f98SSadaf Ebrahimi key->generation_time = mbedtls_time(NULL);
200*62c56f98SSadaf Ebrahimi #endif
201*62c56f98SSadaf Ebrahimi return 0;
202*62c56f98SSadaf Ebrahimi }
203*62c56f98SSadaf Ebrahimi
204*62c56f98SSadaf Ebrahimi /*
205*62c56f98SSadaf Ebrahimi * Setup context for actual use
206*62c56f98SSadaf Ebrahimi */
mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context * ctx,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_cipher_type_t cipher,uint32_t lifetime)207*62c56f98SSadaf Ebrahimi int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
208*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
209*62c56f98SSadaf Ebrahimi mbedtls_cipher_type_t cipher,
210*62c56f98SSadaf Ebrahimi uint32_t lifetime)
211*62c56f98SSadaf Ebrahimi {
212*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
213*62c56f98SSadaf Ebrahimi size_t key_bits;
214*62c56f98SSadaf Ebrahimi
215*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
216*62c56f98SSadaf Ebrahimi psa_algorithm_t alg;
217*62c56f98SSadaf Ebrahimi psa_key_type_t key_type;
218*62c56f98SSadaf Ebrahimi #else
219*62c56f98SSadaf Ebrahimi const mbedtls_cipher_info_t *cipher_info;
220*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
221*62c56f98SSadaf Ebrahimi
222*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
223*62c56f98SSadaf Ebrahimi if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,
224*62c56f98SSadaf Ebrahimi &alg, &key_type, &key_bits) != PSA_SUCCESS) {
225*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
226*62c56f98SSadaf Ebrahimi }
227*62c56f98SSadaf Ebrahimi
228*62c56f98SSadaf Ebrahimi if (PSA_ALG_IS_AEAD(alg) == 0) {
229*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
230*62c56f98SSadaf Ebrahimi }
231*62c56f98SSadaf Ebrahimi #else
232*62c56f98SSadaf Ebrahimi cipher_info = mbedtls_cipher_info_from_type(cipher);
233*62c56f98SSadaf Ebrahimi
234*62c56f98SSadaf Ebrahimi if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM &&
235*62c56f98SSadaf Ebrahimi mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM &&
236*62c56f98SSadaf Ebrahimi mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) {
237*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
238*62c56f98SSadaf Ebrahimi }
239*62c56f98SSadaf Ebrahimi
240*62c56f98SSadaf Ebrahimi key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info);
241*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
242*62c56f98SSadaf Ebrahimi
243*62c56f98SSadaf Ebrahimi if (key_bits > 8 * MAX_KEY_BYTES) {
244*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
245*62c56f98SSadaf Ebrahimi }
246*62c56f98SSadaf Ebrahimi
247*62c56f98SSadaf Ebrahimi ctx->f_rng = f_rng;
248*62c56f98SSadaf Ebrahimi ctx->p_rng = p_rng;
249*62c56f98SSadaf Ebrahimi
250*62c56f98SSadaf Ebrahimi ctx->ticket_lifetime = lifetime;
251*62c56f98SSadaf Ebrahimi
252*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
253*62c56f98SSadaf Ebrahimi ctx->keys[0].alg = alg;
254*62c56f98SSadaf Ebrahimi ctx->keys[0].key_type = key_type;
255*62c56f98SSadaf Ebrahimi ctx->keys[0].key_bits = key_bits;
256*62c56f98SSadaf Ebrahimi
257*62c56f98SSadaf Ebrahimi ctx->keys[1].alg = alg;
258*62c56f98SSadaf Ebrahimi ctx->keys[1].key_type = key_type;
259*62c56f98SSadaf Ebrahimi ctx->keys[1].key_bits = key_bits;
260*62c56f98SSadaf Ebrahimi #else
261*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
262*62c56f98SSadaf Ebrahimi return ret;
263*62c56f98SSadaf Ebrahimi }
264*62c56f98SSadaf Ebrahimi
265*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {
266*62c56f98SSadaf Ebrahimi return ret;
267*62c56f98SSadaf Ebrahimi }
268*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimi if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
271*62c56f98SSadaf Ebrahimi (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
272*62c56f98SSadaf Ebrahimi return ret;
273*62c56f98SSadaf Ebrahimi }
274*62c56f98SSadaf Ebrahimi
275*62c56f98SSadaf Ebrahimi return 0;
276*62c56f98SSadaf Ebrahimi }
277*62c56f98SSadaf Ebrahimi
278*62c56f98SSadaf Ebrahimi /*
279*62c56f98SSadaf Ebrahimi * Create session ticket, with the following structure:
280*62c56f98SSadaf Ebrahimi *
281*62c56f98SSadaf Ebrahimi * struct {
282*62c56f98SSadaf Ebrahimi * opaque key_name[4];
283*62c56f98SSadaf Ebrahimi * opaque iv[12];
284*62c56f98SSadaf Ebrahimi * opaque encrypted_state<0..2^16-1>;
285*62c56f98SSadaf Ebrahimi * opaque tag[16];
286*62c56f98SSadaf Ebrahimi * } ticket;
287*62c56f98SSadaf Ebrahimi *
288*62c56f98SSadaf Ebrahimi * The key_name, iv, and length of encrypted_state are the additional
289*62c56f98SSadaf Ebrahimi * authenticated data.
290*62c56f98SSadaf Ebrahimi */
291*62c56f98SSadaf Ebrahimi
mbedtls_ssl_ticket_write(void * p_ticket,const mbedtls_ssl_session * session,unsigned char * start,const unsigned char * end,size_t * tlen,uint32_t * ticket_lifetime)292*62c56f98SSadaf Ebrahimi int mbedtls_ssl_ticket_write(void *p_ticket,
293*62c56f98SSadaf Ebrahimi const mbedtls_ssl_session *session,
294*62c56f98SSadaf Ebrahimi unsigned char *start,
295*62c56f98SSadaf Ebrahimi const unsigned char *end,
296*62c56f98SSadaf Ebrahimi size_t *tlen,
297*62c56f98SSadaf Ebrahimi uint32_t *ticket_lifetime)
298*62c56f98SSadaf Ebrahimi {
299*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
300*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_context *ctx = p_ticket;
301*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_key *key;
302*62c56f98SSadaf Ebrahimi unsigned char *key_name = start;
303*62c56f98SSadaf Ebrahimi unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
304*62c56f98SSadaf Ebrahimi unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
305*62c56f98SSadaf Ebrahimi unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
306*62c56f98SSadaf Ebrahimi size_t clear_len, ciph_len;
307*62c56f98SSadaf Ebrahimi
308*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
309*62c56f98SSadaf Ebrahimi psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
310*62c56f98SSadaf Ebrahimi #endif
311*62c56f98SSadaf Ebrahimi
312*62c56f98SSadaf Ebrahimi *tlen = 0;
313*62c56f98SSadaf Ebrahimi
314*62c56f98SSadaf Ebrahimi if (ctx == NULL || ctx->f_rng == NULL) {
315*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
316*62c56f98SSadaf Ebrahimi }
317*62c56f98SSadaf Ebrahimi
318*62c56f98SSadaf Ebrahimi /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
319*62c56f98SSadaf Ebrahimi * in addition to session itself, that will be checked when writing it. */
320*62c56f98SSadaf Ebrahimi MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
321*62c56f98SSadaf Ebrahimi
322*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
323*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
324*62c56f98SSadaf Ebrahimi return ret;
325*62c56f98SSadaf Ebrahimi }
326*62c56f98SSadaf Ebrahimi #endif
327*62c56f98SSadaf Ebrahimi
328*62c56f98SSadaf Ebrahimi if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
329*62c56f98SSadaf Ebrahimi goto cleanup;
330*62c56f98SSadaf Ebrahimi }
331*62c56f98SSadaf Ebrahimi
332*62c56f98SSadaf Ebrahimi key = &ctx->keys[ctx->active];
333*62c56f98SSadaf Ebrahimi
334*62c56f98SSadaf Ebrahimi *ticket_lifetime = ctx->ticket_lifetime;
335*62c56f98SSadaf Ebrahimi
336*62c56f98SSadaf Ebrahimi memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
337*62c56f98SSadaf Ebrahimi
338*62c56f98SSadaf Ebrahimi if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
339*62c56f98SSadaf Ebrahimi goto cleanup;
340*62c56f98SSadaf Ebrahimi }
341*62c56f98SSadaf Ebrahimi
342*62c56f98SSadaf Ebrahimi /* Dump session state */
343*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ssl_session_save(session,
344*62c56f98SSadaf Ebrahimi state, end - state,
345*62c56f98SSadaf Ebrahimi &clear_len)) != 0 ||
346*62c56f98SSadaf Ebrahimi (unsigned long) clear_len > 65535) {
347*62c56f98SSadaf Ebrahimi goto cleanup;
348*62c56f98SSadaf Ebrahimi }
349*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
350*62c56f98SSadaf Ebrahimi
351*62c56f98SSadaf Ebrahimi /* Encrypt and authenticate */
352*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
353*62c56f98SSadaf Ebrahimi if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
354*62c56f98SSadaf Ebrahimi key_name, TICKET_ADD_DATA_LEN,
355*62c56f98SSadaf Ebrahimi state, clear_len,
356*62c56f98SSadaf Ebrahimi state, end - state,
357*62c56f98SSadaf Ebrahimi &ciph_len)) != PSA_SUCCESS) {
358*62c56f98SSadaf Ebrahimi ret = PSA_TO_MBEDTLS_ERR(status);
359*62c56f98SSadaf Ebrahimi goto cleanup;
360*62c56f98SSadaf Ebrahimi }
361*62c56f98SSadaf Ebrahimi #else
362*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,
363*62c56f98SSadaf Ebrahimi iv, TICKET_IV_BYTES,
364*62c56f98SSadaf Ebrahimi /* Additional data: key name, IV and length */
365*62c56f98SSadaf Ebrahimi key_name, TICKET_ADD_DATA_LEN,
366*62c56f98SSadaf Ebrahimi state, clear_len,
367*62c56f98SSadaf Ebrahimi state, end - state, &ciph_len,
368*62c56f98SSadaf Ebrahimi TICKET_AUTH_TAG_BYTES)) != 0) {
369*62c56f98SSadaf Ebrahimi goto cleanup;
370*62c56f98SSadaf Ebrahimi }
371*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
372*62c56f98SSadaf Ebrahimi
373*62c56f98SSadaf Ebrahimi if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
374*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
375*62c56f98SSadaf Ebrahimi goto cleanup;
376*62c56f98SSadaf Ebrahimi }
377*62c56f98SSadaf Ebrahimi
378*62c56f98SSadaf Ebrahimi *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
379*62c56f98SSadaf Ebrahimi
380*62c56f98SSadaf Ebrahimi cleanup:
381*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
382*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
383*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
384*62c56f98SSadaf Ebrahimi }
385*62c56f98SSadaf Ebrahimi #endif
386*62c56f98SSadaf Ebrahimi
387*62c56f98SSadaf Ebrahimi return ret;
388*62c56f98SSadaf Ebrahimi }
389*62c56f98SSadaf Ebrahimi
390*62c56f98SSadaf Ebrahimi /*
391*62c56f98SSadaf Ebrahimi * Select key based on name
392*62c56f98SSadaf Ebrahimi */
ssl_ticket_select_key(mbedtls_ssl_ticket_context * ctx,const unsigned char name[4])393*62c56f98SSadaf Ebrahimi static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
394*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_context *ctx,
395*62c56f98SSadaf Ebrahimi const unsigned char name[4])
396*62c56f98SSadaf Ebrahimi {
397*62c56f98SSadaf Ebrahimi unsigned char i;
398*62c56f98SSadaf Ebrahimi
399*62c56f98SSadaf Ebrahimi for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
400*62c56f98SSadaf Ebrahimi if (memcmp(name, ctx->keys[i].name, 4) == 0) {
401*62c56f98SSadaf Ebrahimi return &ctx->keys[i];
402*62c56f98SSadaf Ebrahimi }
403*62c56f98SSadaf Ebrahimi }
404*62c56f98SSadaf Ebrahimi
405*62c56f98SSadaf Ebrahimi return NULL;
406*62c56f98SSadaf Ebrahimi }
407*62c56f98SSadaf Ebrahimi
408*62c56f98SSadaf Ebrahimi /*
409*62c56f98SSadaf Ebrahimi * Load session ticket (see mbedtls_ssl_ticket_write for structure)
410*62c56f98SSadaf Ebrahimi */
mbedtls_ssl_ticket_parse(void * p_ticket,mbedtls_ssl_session * session,unsigned char * buf,size_t len)411*62c56f98SSadaf Ebrahimi int mbedtls_ssl_ticket_parse(void *p_ticket,
412*62c56f98SSadaf Ebrahimi mbedtls_ssl_session *session,
413*62c56f98SSadaf Ebrahimi unsigned char *buf,
414*62c56f98SSadaf Ebrahimi size_t len)
415*62c56f98SSadaf Ebrahimi {
416*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
417*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_context *ctx = p_ticket;
418*62c56f98SSadaf Ebrahimi mbedtls_ssl_ticket_key *key;
419*62c56f98SSadaf Ebrahimi unsigned char *key_name = buf;
420*62c56f98SSadaf Ebrahimi unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
421*62c56f98SSadaf Ebrahimi unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
422*62c56f98SSadaf Ebrahimi unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
423*62c56f98SSadaf Ebrahimi size_t enc_len, clear_len;
424*62c56f98SSadaf Ebrahimi
425*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
426*62c56f98SSadaf Ebrahimi psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
427*62c56f98SSadaf Ebrahimi #endif
428*62c56f98SSadaf Ebrahimi
429*62c56f98SSadaf Ebrahimi if (ctx == NULL || ctx->f_rng == NULL) {
430*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
431*62c56f98SSadaf Ebrahimi }
432*62c56f98SSadaf Ebrahimi
433*62c56f98SSadaf Ebrahimi if (len < TICKET_MIN_LEN) {
434*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
435*62c56f98SSadaf Ebrahimi }
436*62c56f98SSadaf Ebrahimi
437*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
438*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
439*62c56f98SSadaf Ebrahimi return ret;
440*62c56f98SSadaf Ebrahimi }
441*62c56f98SSadaf Ebrahimi #endif
442*62c56f98SSadaf Ebrahimi
443*62c56f98SSadaf Ebrahimi if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
444*62c56f98SSadaf Ebrahimi goto cleanup;
445*62c56f98SSadaf Ebrahimi }
446*62c56f98SSadaf Ebrahimi
447*62c56f98SSadaf Ebrahimi enc_len = (enc_len_p[0] << 8) | enc_len_p[1];
448*62c56f98SSadaf Ebrahimi
449*62c56f98SSadaf Ebrahimi if (len != TICKET_MIN_LEN + enc_len) {
450*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
451*62c56f98SSadaf Ebrahimi goto cleanup;
452*62c56f98SSadaf Ebrahimi }
453*62c56f98SSadaf Ebrahimi
454*62c56f98SSadaf Ebrahimi /* Select key */
455*62c56f98SSadaf Ebrahimi if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
456*62c56f98SSadaf Ebrahimi /* We can't know for sure but this is a likely option unless we're
457*62c56f98SSadaf Ebrahimi * under attack - this is only informative anyway */
458*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
459*62c56f98SSadaf Ebrahimi goto cleanup;
460*62c56f98SSadaf Ebrahimi }
461*62c56f98SSadaf Ebrahimi
462*62c56f98SSadaf Ebrahimi /* Decrypt and authenticate */
463*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
464*62c56f98SSadaf Ebrahimi if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
465*62c56f98SSadaf Ebrahimi key_name, TICKET_ADD_DATA_LEN,
466*62c56f98SSadaf Ebrahimi ticket, enc_len + TICKET_AUTH_TAG_BYTES,
467*62c56f98SSadaf Ebrahimi ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
468*62c56f98SSadaf Ebrahimi ret = PSA_TO_MBEDTLS_ERR(status);
469*62c56f98SSadaf Ebrahimi goto cleanup;
470*62c56f98SSadaf Ebrahimi }
471*62c56f98SSadaf Ebrahimi #else
472*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,
473*62c56f98SSadaf Ebrahimi iv, TICKET_IV_BYTES,
474*62c56f98SSadaf Ebrahimi /* Additional data: key name, IV and length */
475*62c56f98SSadaf Ebrahimi key_name, TICKET_ADD_DATA_LEN,
476*62c56f98SSadaf Ebrahimi ticket, enc_len + TICKET_AUTH_TAG_BYTES,
477*62c56f98SSadaf Ebrahimi ticket, enc_len, &clear_len,
478*62c56f98SSadaf Ebrahimi TICKET_AUTH_TAG_BYTES)) != 0) {
479*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
480*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_INVALID_MAC;
481*62c56f98SSadaf Ebrahimi }
482*62c56f98SSadaf Ebrahimi
483*62c56f98SSadaf Ebrahimi goto cleanup;
484*62c56f98SSadaf Ebrahimi }
485*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
486*62c56f98SSadaf Ebrahimi
487*62c56f98SSadaf Ebrahimi if (clear_len != enc_len) {
488*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
489*62c56f98SSadaf Ebrahimi goto cleanup;
490*62c56f98SSadaf Ebrahimi }
491*62c56f98SSadaf Ebrahimi
492*62c56f98SSadaf Ebrahimi /* Actually load session */
493*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
494*62c56f98SSadaf Ebrahimi goto cleanup;
495*62c56f98SSadaf Ebrahimi }
496*62c56f98SSadaf Ebrahimi
497*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME)
498*62c56f98SSadaf Ebrahimi {
499*62c56f98SSadaf Ebrahimi /* Check for expiration */
500*62c56f98SSadaf Ebrahimi mbedtls_time_t current_time = mbedtls_time(NULL);
501*62c56f98SSadaf Ebrahimi
502*62c56f98SSadaf Ebrahimi if (current_time < session->start ||
503*62c56f98SSadaf Ebrahimi (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
504*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
505*62c56f98SSadaf Ebrahimi goto cleanup;
506*62c56f98SSadaf Ebrahimi }
507*62c56f98SSadaf Ebrahimi }
508*62c56f98SSadaf Ebrahimi #endif
509*62c56f98SSadaf Ebrahimi
510*62c56f98SSadaf Ebrahimi cleanup:
511*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
512*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
513*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
514*62c56f98SSadaf Ebrahimi }
515*62c56f98SSadaf Ebrahimi #endif
516*62c56f98SSadaf Ebrahimi
517*62c56f98SSadaf Ebrahimi return ret;
518*62c56f98SSadaf Ebrahimi }
519*62c56f98SSadaf Ebrahimi
520*62c56f98SSadaf Ebrahimi /*
521*62c56f98SSadaf Ebrahimi * Free context
522*62c56f98SSadaf Ebrahimi */
mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context * ctx)523*62c56f98SSadaf Ebrahimi void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
524*62c56f98SSadaf Ebrahimi {
525*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
526*62c56f98SSadaf Ebrahimi psa_destroy_key(ctx->keys[0].key);
527*62c56f98SSadaf Ebrahimi psa_destroy_key(ctx->keys[1].key);
528*62c56f98SSadaf Ebrahimi #else
529*62c56f98SSadaf Ebrahimi mbedtls_cipher_free(&ctx->keys[0].ctx);
530*62c56f98SSadaf Ebrahimi mbedtls_cipher_free(&ctx->keys[1].ctx);
531*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
532*62c56f98SSadaf Ebrahimi
533*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
534*62c56f98SSadaf Ebrahimi mbedtls_mutex_free(&ctx->mutex);
535*62c56f98SSadaf Ebrahimi #endif
536*62c56f98SSadaf Ebrahimi
537*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
538*62c56f98SSadaf Ebrahimi }
539*62c56f98SSadaf Ebrahimi
540*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SSL_TICKET_C */
541