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