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