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