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