Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ssl_ticket.c
00001 /* 00002 * TLS server tickets callbacks implementation 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 #if !defined(MBEDTLS_CONFIG_FILE) 00023 #include "mbedtls/config.h" 00024 #else 00025 #include MBEDTLS_CONFIG_FILE 00026 #endif 00027 00028 #if defined(MBEDTLS_SSL_TICKET_C) 00029 00030 #if defined(MBEDTLS_PLATFORM_C) 00031 #include "mbedtls/platform.h" 00032 #else 00033 #include <stdlib.h> 00034 #define mbedtls_calloc calloc 00035 #define mbedtls_free free 00036 #endif 00037 00038 #include "mbedtls/ssl_ticket.h" 00039 #include "mbedtls/platform_util.h" 00040 00041 #include <string.h> 00042 00043 /* 00044 * Initialze context 00045 */ 00046 void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) 00047 { 00048 memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); 00049 00050 #if defined(MBEDTLS_THREADING_C) 00051 mbedtls_mutex_init( &ctx->mutex ); 00052 #endif 00053 } 00054 00055 #define MAX_KEY_BYTES 32 /* 256 bits */ 00056 00057 #define TICKET_KEY_NAME_BYTES 4 00058 #define TICKET_IV_BYTES 12 00059 #define TICKET_CRYPT_LEN_BYTES 2 00060 #define TICKET_AUTH_TAG_BYTES 16 00061 00062 #define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ 00063 TICKET_IV_BYTES + \ 00064 TICKET_CRYPT_LEN_BYTES + \ 00065 TICKET_AUTH_TAG_BYTES ) 00066 #define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ 00067 TICKET_IV_BYTES + \ 00068 TICKET_CRYPT_LEN_BYTES ) 00069 00070 /* 00071 * Generate/update a key 00072 */ 00073 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, 00074 unsigned char index ) 00075 { 00076 int ret; 00077 unsigned char buf[MAX_KEY_BYTES]; 00078 mbedtls_ssl_ticket_key *key = ctx->keys + index; 00079 00080 #if defined(MBEDTLS_HAVE_TIME) 00081 key->generation_time = (uint32_t) mbedtls_time( NULL ); 00082 #endif 00083 00084 if( ( ret = ctx->f_rng( ctx->p_rng , key->name , sizeof( key->name ) ) ) != 0 ) 00085 return( ret ); 00086 00087 if( ( ret = ctx->f_rng( ctx->p_rng , buf, sizeof( buf ) ) ) != 0 ) 00088 return( ret ); 00089 00090 /* With GCM and CCM, same context can encrypt & decrypt */ 00091 ret = mbedtls_cipher_setkey( &key->ctx , buf, 00092 mbedtls_cipher_get_key_bitlen( &key->ctx ), 00093 MBEDTLS_ENCRYPT ); 00094 00095 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00096 00097 return( ret ); 00098 } 00099 00100 /* 00101 * Rotate/generate keys if necessary 00102 */ 00103 static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) 00104 { 00105 #if !defined(MBEDTLS_HAVE_TIME) 00106 ((void) ctx); 00107 #else 00108 if( ctx->ticket_lifetime != 0 ) 00109 { 00110 uint32_t current_time = (uint32_t) mbedtls_time( NULL ); 00111 uint32_t key_time = ctx->keys [ctx->active ].generation_time ; 00112 00113 if( current_time >= key_time && 00114 current_time - key_time < ctx->ticket_lifetime ) 00115 { 00116 return( 0 ); 00117 } 00118 00119 ctx->active = 1 - ctx->active ; 00120 00121 return( ssl_ticket_gen_key( ctx, ctx->active ) ); 00122 } 00123 else 00124 #endif /* MBEDTLS_HAVE_TIME */ 00125 return( 0 ); 00126 } 00127 00128 /* 00129 * Setup context for actual use 00130 */ 00131 int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, 00132 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, 00133 mbedtls_cipher_type_t cipher, 00134 uint32_t lifetime ) 00135 { 00136 int ret; 00137 const mbedtls_cipher_info_t *cipher_info; 00138 00139 ctx->f_rng = f_rng; 00140 ctx->p_rng = p_rng; 00141 00142 ctx->ticket_lifetime = lifetime; 00143 00144 cipher_info = mbedtls_cipher_info_from_type( cipher); 00145 if( cipher_info == NULL ) 00146 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00147 00148 if( cipher_info->mode != MBEDTLS_MODE_GCM && 00149 cipher_info->mode != MBEDTLS_MODE_CCM ) 00150 { 00151 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00152 } 00153 00154 if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) 00155 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00156 00157 #if defined(MBEDTLS_USE_PSA_CRYPTO) 00158 ret = mbedtls_cipher_setup_psa( &ctx->keys [0].ctx , 00159 cipher_info, TICKET_AUTH_TAG_BYTES ); 00160 if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 00161 return( ret ); 00162 /* We don't yet expect to support all ciphers through PSA, 00163 * so allow fallback to ordinary mbedtls_cipher_setup(). */ 00164 if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 00165 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 00166 if( ( ret = mbedtls_cipher_setup( &ctx->keys [0].ctx , cipher_info ) ) != 0 ) 00167 return( ret ); 00168 00169 #if defined(MBEDTLS_USE_PSA_CRYPTO) 00170 ret = mbedtls_cipher_setup_psa( &ctx->keys [1].ctx , 00171 cipher_info, TICKET_AUTH_TAG_BYTES ); 00172 if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 00173 return( ret ); 00174 if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) 00175 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 00176 if( ( ret = mbedtls_cipher_setup( &ctx->keys [1].ctx , cipher_info ) ) != 0 ) 00177 return( ret ); 00178 00179 if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || 00180 ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) 00181 { 00182 return( ret ); 00183 } 00184 00185 return( 0 ); 00186 } 00187 00188 /* 00189 * Create session ticket, with the following structure: 00190 * 00191 * struct { 00192 * opaque key_name[4]; 00193 * opaque iv[12]; 00194 * opaque encrypted_state<0..2^16-1>; 00195 * opaque tag[16]; 00196 * } ticket; 00197 * 00198 * The key_name, iv, and length of encrypted_state are the additional 00199 * authenticated data. 00200 */ 00201 00202 int mbedtls_ssl_ticket_write( void *p_ticket, 00203 const mbedtls_ssl_session *session, 00204 unsigned char *start, 00205 const unsigned char *end, 00206 size_t *tlen, 00207 uint32_t *ticket_lifetime ) 00208 { 00209 int ret; 00210 mbedtls_ssl_ticket_context *ctx = p_ticket; 00211 mbedtls_ssl_ticket_key *key; 00212 unsigned char *key_name = start; 00213 unsigned char *iv = start + TICKET_KEY_NAME_BYTES; 00214 unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; 00215 unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; 00216 unsigned char *tag; 00217 size_t clear_len, ciph_len; 00218 00219 *tlen = 0; 00220 00221 if( ctx == NULL || ctx->f_rng == NULL ) 00222 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00223 00224 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, 00225 * in addition to session itself, that will be checked when writing it. */ 00226 if( end - start < TICKET_MIN_LEN ) 00227 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); 00228 00229 #if defined(MBEDTLS_THREADING_C) 00230 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00231 return( ret ); 00232 #endif 00233 00234 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) 00235 goto cleanup; 00236 00237 key = &ctx->keys [ctx->active ]; 00238 00239 *ticket_lifetime = ctx->ticket_lifetime ; 00240 00241 memcpy( key_name, key->name , TICKET_KEY_NAME_BYTES ); 00242 00243 if( ( ret = ctx->f_rng( ctx->p_rng , iv, TICKET_IV_BYTES ) ) != 0 ) 00244 goto cleanup; 00245 00246 /* Dump session state */ 00247 if( ( ret = mbedtls_ssl_session_save( session, 00248 state, end - state, 00249 &clear_len ) ) != 0 || 00250 (unsigned long) clear_len > 65535 ) 00251 { 00252 goto cleanup; 00253 } 00254 state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; 00255 state_len_bytes[1] = ( clear_len ) & 0xff; 00256 00257 /* Encrypt and authenticate */ 00258 tag = state + clear_len; 00259 if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx , 00260 iv, TICKET_IV_BYTES, 00261 /* Additional data: key name, IV and length */ 00262 key_name, TICKET_ADD_DATA_LEN, 00263 state, clear_len, state, &ciph_len, 00264 tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) 00265 { 00266 goto cleanup; 00267 } 00268 if( ciph_len != clear_len ) 00269 { 00270 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; 00271 goto cleanup; 00272 } 00273 00274 *tlen = TICKET_MIN_LEN + ciph_len; 00275 00276 cleanup: 00277 #if defined(MBEDTLS_THREADING_C) 00278 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00279 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00280 #endif 00281 00282 return( ret ); 00283 } 00284 00285 /* 00286 * Select key based on name 00287 */ 00288 static mbedtls_ssl_ticket_key *ssl_ticket_select_key( 00289 mbedtls_ssl_ticket_context *ctx, 00290 const unsigned char name[4] ) 00291 { 00292 unsigned char i; 00293 00294 for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) 00295 if( memcmp( name, ctx->keys [i].name , 4 ) == 0 ) 00296 return( &ctx->keys [i] ); 00297 00298 return( NULL ); 00299 } 00300 00301 /* 00302 * Load session ticket (see mbedtls_ssl_ticket_write for structure) 00303 */ 00304 int mbedtls_ssl_ticket_parse( void *p_ticket, 00305 mbedtls_ssl_session *session, 00306 unsigned char *buf, 00307 size_t len ) 00308 { 00309 int ret; 00310 mbedtls_ssl_ticket_context *ctx = p_ticket; 00311 mbedtls_ssl_ticket_key *key; 00312 unsigned char *key_name = buf; 00313 unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; 00314 unsigned char *enc_len_p = iv + TICKET_IV_BYTES; 00315 unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; 00316 unsigned char *tag; 00317 size_t enc_len, clear_len; 00318 00319 if( ctx == NULL || ctx->f_rng == NULL ) 00320 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00321 00322 if( len < TICKET_MIN_LEN ) 00323 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 00324 00325 #if defined(MBEDTLS_THREADING_C) 00326 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00327 return( ret ); 00328 #endif 00329 00330 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) 00331 goto cleanup; 00332 00333 enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; 00334 tag = ticket + enc_len; 00335 00336 if( len != TICKET_MIN_LEN + enc_len ) 00337 { 00338 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; 00339 goto cleanup; 00340 } 00341 00342 /* Select key */ 00343 if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) 00344 { 00345 /* We can't know for sure but this is a likely option unless we're 00346 * under attack - this is only informative anyway */ 00347 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; 00348 goto cleanup; 00349 } 00350 00351 /* Decrypt and authenticate */ 00352 if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx , 00353 iv, TICKET_IV_BYTES, 00354 /* Additional data: key name, IV and length */ 00355 key_name, TICKET_ADD_DATA_LEN, 00356 ticket, enc_len, 00357 ticket, &clear_len, 00358 tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) 00359 { 00360 if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) 00361 ret = MBEDTLS_ERR_SSL_INVALID_MAC; 00362 00363 goto cleanup; 00364 } 00365 if( clear_len != enc_len ) 00366 { 00367 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; 00368 goto cleanup; 00369 } 00370 00371 /* Actually load session */ 00372 if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) 00373 goto cleanup; 00374 00375 #if defined(MBEDTLS_HAVE_TIME) 00376 { 00377 /* Check for expiration */ 00378 mbedtls_time_t current_time = mbedtls_time( NULL ); 00379 00380 if( current_time < session->start || 00381 (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) 00382 { 00383 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; 00384 goto cleanup; 00385 } 00386 } 00387 #endif 00388 00389 cleanup: 00390 #if defined(MBEDTLS_THREADING_C) 00391 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00392 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00393 #endif 00394 00395 return( ret ); 00396 } 00397 00398 /* 00399 * Free context 00400 */ 00401 void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) 00402 { 00403 mbedtls_cipher_free( &ctx->keys [0].ctx ); 00404 mbedtls_cipher_free( &ctx->keys [1].ctx ); 00405 00406 #if defined(MBEDTLS_THREADING_C) 00407 mbedtls_mutex_free( &ctx->mutex ); 00408 #endif 00409 00410 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); 00411 } 00412 00413 #endif /* MBEDTLS_SSL_TICKET_C */
Generated on Tue Jul 12 2022 13:54:53 by
