xref: /aosp_15_r20/external/mbedtls/library/ssl_ticket.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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