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 #if defined(MBEDTLS_PLATFORM_C) 25 #include "mbedtls/platform.h" 26 #else 27 #include <stdlib.h> 28 #define mbedtls_calloc calloc 29 #define mbedtls_free free 30 #endif 31 32 #include "mbedtls/ssl_internal.h" 33 #include "mbedtls/ssl_ticket.h" 34 #include "mbedtls/error.h" 35 #include "mbedtls/platform_util.h" 36 37 #include <string.h> 38 39 /* 40 * Initialze 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 32 /* 256 bits */ 52 53 #define TICKET_KEY_NAME_BYTES 4 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 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, 70 unsigned char index ) 71 { 72 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 73 unsigned char buf[MAX_KEY_BYTES]; 74 mbedtls_ssl_ticket_key *key = ctx->keys + index; 75 76 #if defined(MBEDTLS_HAVE_TIME) 77 key->generation_time = (uint32_t) mbedtls_time( NULL ); 78 #endif 79 80 if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) 81 return( ret ); 82 83 if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) 84 return( ret ); 85 86 /* With GCM and CCM, same context can encrypt & decrypt */ 87 ret = mbedtls_cipher_setkey( &key->ctx, buf, 88 mbedtls_cipher_get_key_bitlen( &key->ctx ), 89 MBEDTLS_ENCRYPT ); 90 91 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 92 93 return( ret ); 94 } 95 96 /* 97 * Rotate/generate keys if necessary 98 */ 99 static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) 100 { 101 #if !defined(MBEDTLS_HAVE_TIME) 102 ((void) ctx); 103 #else 104 if( ctx->ticket_lifetime != 0 ) 105 { 106 uint32_t current_time = (uint32_t) mbedtls_time( NULL ); 107 uint32_t key_time = ctx->keys[ctx->active].generation_time; 108 109 if( current_time >= key_time && 110 current_time - key_time < ctx->ticket_lifetime ) 111 { 112 return( 0 ); 113 } 114 115 ctx->active = 1 - ctx->active; 116 117 return( ssl_ticket_gen_key( ctx, ctx->active ) ); 118 } 119 else 120 #endif /* MBEDTLS_HAVE_TIME */ 121 return( 0 ); 122 } 123 124 /* 125 * Setup context for actual use 126 */ 127 int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, 128 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, 129 mbedtls_cipher_type_t cipher, 130 uint32_t lifetime ) 131 { 132 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 133 const mbedtls_cipher_info_t *cipher_info; 134 135 ctx->f_rng = f_rng; 136 ctx->p_rng = p_rng; 137 138 ctx->ticket_lifetime = lifetime; 139 140 cipher_info = mbedtls_cipher_info_from_type( cipher); 141 if( cipher_info == NULL ) 142 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 143 144 if( cipher_info->mode != MBEDTLS_MODE_GCM && 145 cipher_info->mode != MBEDTLS_MODE_CCM ) 146 { 147 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 148 } 149 150 if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) 151 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 152 153 #if defined(MBEDTLS_USE_PSA_CRYPTO) 154 ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx, 155 cipher_info, TICKET_AUTH_TAG_BYTES ); 156 if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 157 return( ret ); 158 /* We don't yet expect to support all ciphers through PSA, 159 * so allow fallback to ordinary mbedtls_cipher_setup(). */ 160 if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 161 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 162 if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ) 163 return( ret ); 164 165 #if defined(MBEDTLS_USE_PSA_CRYPTO) 166 ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx, 167 cipher_info, TICKET_AUTH_TAG_BYTES ); 168 if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 169 return( ret ); 170 if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 171 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 172 if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) 173 return( ret ); 174 175 if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || 176 ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) 177 { 178 return( ret ); 179 } 180 181 return( 0 ); 182 } 183 184 /* 185 * Create session ticket, with the following structure: 186 * 187 * struct { 188 * opaque key_name[4]; 189 * opaque iv[12]; 190 * opaque encrypted_state<0..2^16-1>; 191 * opaque tag[16]; 192 * } ticket; 193 * 194 * The key_name, iv, and length of encrypted_state are the additional 195 * authenticated data. 196 */ 197 198 int mbedtls_ssl_ticket_write( void *p_ticket, 199 const mbedtls_ssl_session *session, 200 unsigned char *start, 201 const unsigned char *end, 202 size_t *tlen, 203 uint32_t *ticket_lifetime ) 204 { 205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 206 mbedtls_ssl_ticket_context *ctx = p_ticket; 207 mbedtls_ssl_ticket_key *key; 208 unsigned char *key_name = start; 209 unsigned char *iv = start + TICKET_KEY_NAME_BYTES; 210 unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; 211 unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; 212 size_t clear_len, ciph_len; 213 214 *tlen = 0; 215 216 if( ctx == NULL || ctx->f_rng == NULL ) 217 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 218 219 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, 220 * in addition to session itself, that will be checked when writing it. */ 221 MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); 222 223 #if defined(MBEDTLS_THREADING_C) 224 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 225 return( ret ); 226 #endif 227 228 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) 229 goto cleanup; 230 231 key = &ctx->keys[ctx->active]; 232 233 *ticket_lifetime = ctx->ticket_lifetime; 234 235 memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); 236 237 if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) 238 goto cleanup; 239 240 /* Dump session state */ 241 if( ( ret = mbedtls_ssl_session_save( session, 242 state, end - state, 243 &clear_len ) ) != 0 || 244 (unsigned long) clear_len > 65535 ) 245 { 246 goto cleanup; 247 } 248 state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; 249 state_len_bytes[1] = ( clear_len ) & 0xff; 250 251 /* Encrypt and authenticate */ 252 if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx, 253 iv, TICKET_IV_BYTES, 254 /* Additional data: key name, IV and length */ 255 key_name, TICKET_ADD_DATA_LEN, 256 state, clear_len, 257 state, end - state, &ciph_len, 258 TICKET_AUTH_TAG_BYTES ) ) != 0 ) 259 { 260 goto cleanup; 261 } 262 if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES ) 263 { 264 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; 265 goto cleanup; 266 } 267 268 *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES; 269 270 cleanup: 271 #if defined(MBEDTLS_THREADING_C) 272 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 273 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 274 #endif 275 276 return( ret ); 277 } 278 279 /* 280 * Select key based on name 281 */ 282 static mbedtls_ssl_ticket_key *ssl_ticket_select_key( 283 mbedtls_ssl_ticket_context *ctx, 284 const unsigned char name[4] ) 285 { 286 unsigned char i; 287 288 for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) 289 if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) 290 return( &ctx->keys[i] ); 291 292 return( NULL ); 293 } 294 295 /* 296 * Load session ticket (see mbedtls_ssl_ticket_write for structure) 297 */ 298 int mbedtls_ssl_ticket_parse( void *p_ticket, 299 mbedtls_ssl_session *session, 300 unsigned char *buf, 301 size_t len ) 302 { 303 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 304 mbedtls_ssl_ticket_context *ctx = p_ticket; 305 mbedtls_ssl_ticket_key *key; 306 unsigned char *key_name = buf; 307 unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; 308 unsigned char *enc_len_p = iv + TICKET_IV_BYTES; 309 unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; 310 size_t enc_len, clear_len; 311 312 if( ctx == NULL || ctx->f_rng == NULL ) 313 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 314 315 if( len < TICKET_MIN_LEN ) 316 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 317 318 #if defined(MBEDTLS_THREADING_C) 319 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 320 return( ret ); 321 #endif 322 323 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) 324 goto cleanup; 325 326 enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; 327 328 if( len != TICKET_MIN_LEN + enc_len ) 329 { 330 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; 331 goto cleanup; 332 } 333 334 /* Select key */ 335 if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) 336 { 337 /* We can't know for sure but this is a likely option unless we're 338 * under attack - this is only informative anyway */ 339 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; 340 goto cleanup; 341 } 342 343 /* Decrypt and authenticate */ 344 if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx, 345 iv, TICKET_IV_BYTES, 346 /* Additional data: key name, IV and length */ 347 key_name, TICKET_ADD_DATA_LEN, 348 ticket, enc_len + TICKET_AUTH_TAG_BYTES, 349 ticket, enc_len, &clear_len, 350 TICKET_AUTH_TAG_BYTES ) ) != 0 ) 351 { 352 if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) 353 ret = MBEDTLS_ERR_SSL_INVALID_MAC; 354 355 goto cleanup; 356 } 357 if( clear_len != enc_len ) 358 { 359 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; 360 goto cleanup; 361 } 362 363 /* Actually load session */ 364 if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) 365 goto cleanup; 366 367 #if defined(MBEDTLS_HAVE_TIME) 368 { 369 /* Check for expiration */ 370 mbedtls_time_t current_time = mbedtls_time( NULL ); 371 372 if( current_time < session->start || 373 (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) 374 { 375 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; 376 goto cleanup; 377 } 378 } 379 #endif 380 381 cleanup: 382 #if defined(MBEDTLS_THREADING_C) 383 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 384 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 385 #endif 386 387 return( ret ); 388 } 389 390 /* 391 * Free context 392 */ 393 void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) 394 { 395 mbedtls_cipher_free( &ctx->keys[0].ctx ); 396 mbedtls_cipher_free( &ctx->keys[1].ctx ); 397 398 #if defined(MBEDTLS_THREADING_C) 399 mbedtls_mutex_free( &ctx->mutex ); 400 #endif 401 402 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); 403 } 404 405 #endif /* MBEDTLS_SSL_TICKET_C */ 406