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