1 /* 2 * DTLS cookie 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 * These session callbacks use a simple chained list 21 * to store and retrieve the session information. 22 */ 23 24 #include "common.h" 25 26 #if defined(MBEDTLS_SSL_COOKIE_C) 27 28 #if defined(MBEDTLS_PLATFORM_C) 29 #include "mbedtls/platform.h" 30 #else 31 #define mbedtls_calloc calloc 32 #define mbedtls_free free 33 #endif 34 35 #include "mbedtls/ssl_cookie.h" 36 #include "mbedtls/ssl_internal.h" 37 #include "mbedtls/error.h" 38 #include "mbedtls/platform_util.h" 39 40 #include <string.h> 41 42 /* 43 * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is 44 * available. Try SHA-256 first, 512 wastes resources since we need to stay 45 * with max 32 bytes of cookie for DTLS 1.0 46 */ 47 #if defined(MBEDTLS_SHA256_C) 48 #define COOKIE_MD MBEDTLS_MD_SHA224 49 #define COOKIE_MD_OUTLEN 32 50 #define COOKIE_HMAC_LEN 28 51 #elif defined(MBEDTLS_SHA512_C) 52 #define COOKIE_MD MBEDTLS_MD_SHA384 53 #define COOKIE_MD_OUTLEN 48 54 #define COOKIE_HMAC_LEN 28 55 #elif defined(MBEDTLS_SHA1_C) 56 #define COOKIE_MD MBEDTLS_MD_SHA1 57 #define COOKIE_MD_OUTLEN 20 58 #define COOKIE_HMAC_LEN 20 59 #else 60 #error "DTLS hello verify needs SHA-1 or SHA-2" 61 #endif 62 63 /* 64 * Cookies are formed of a 4-bytes timestamp (or serial number) and 65 * an HMAC of timestemp and client ID. 66 */ 67 #define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) 68 69 void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) 70 { 71 mbedtls_md_init( &ctx->hmac_ctx ); 72 #if !defined(MBEDTLS_HAVE_TIME) 73 ctx->serial = 0; 74 #endif 75 ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; 76 77 #if defined(MBEDTLS_THREADING_C) 78 mbedtls_mutex_init( &ctx->mutex ); 79 #endif 80 } 81 82 void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) 83 { 84 ctx->timeout = delay; 85 } 86 87 void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) 88 { 89 mbedtls_md_free( &ctx->hmac_ctx ); 90 91 #if defined(MBEDTLS_THREADING_C) 92 mbedtls_mutex_free( &ctx->mutex ); 93 #endif 94 95 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); 96 } 97 98 int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, 99 int (*f_rng)(void *, unsigned char *, size_t), 100 void *p_rng ) 101 { 102 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 103 unsigned char key[COOKIE_MD_OUTLEN]; 104 105 if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) 106 return( ret ); 107 108 ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); 109 if( ret != 0 ) 110 return( ret ); 111 112 ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); 113 if( ret != 0 ) 114 return( ret ); 115 116 mbedtls_platform_zeroize( key, sizeof( key ) ); 117 118 return( 0 ); 119 } 120 121 /* 122 * Generate the HMAC part of a cookie 123 */ 124 static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, 125 const unsigned char time[4], 126 unsigned char **p, unsigned char *end, 127 const unsigned char *cli_id, size_t cli_id_len ) 128 { 129 unsigned char hmac_out[COOKIE_MD_OUTLEN]; 130 131 MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); 132 133 if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || 134 mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || 135 mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || 136 mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) 137 { 138 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); 139 } 140 141 memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); 142 *p += COOKIE_HMAC_LEN; 143 144 return( 0 ); 145 } 146 147 /* 148 * Generate cookie for DTLS ClientHello verification 149 */ 150 int mbedtls_ssl_cookie_write( void *p_ctx, 151 unsigned char **p, unsigned char *end, 152 const unsigned char *cli_id, size_t cli_id_len ) 153 { 154 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 155 mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; 156 unsigned long t; 157 158 if( ctx == NULL || cli_id == NULL ) 159 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 160 161 MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); 162 163 #if defined(MBEDTLS_HAVE_TIME) 164 t = (unsigned long) mbedtls_time( NULL ); 165 #else 166 t = ctx->serial++; 167 #endif 168 169 (*p)[0] = (unsigned char)( t >> 24 ); 170 (*p)[1] = (unsigned char)( t >> 16 ); 171 (*p)[2] = (unsigned char)( t >> 8 ); 172 (*p)[3] = (unsigned char)( t ); 173 *p += 4; 174 175 #if defined(MBEDTLS_THREADING_C) 176 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 177 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); 178 #endif 179 180 ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, 181 p, end, cli_id, cli_id_len ); 182 183 #if defined(MBEDTLS_THREADING_C) 184 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 185 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, 186 MBEDTLS_ERR_THREADING_MUTEX_ERROR ) ); 187 #endif 188 189 return( ret ); 190 } 191 192 /* 193 * Check a cookie 194 */ 195 int mbedtls_ssl_cookie_check( void *p_ctx, 196 const unsigned char *cookie, size_t cookie_len, 197 const unsigned char *cli_id, size_t cli_id_len ) 198 { 199 unsigned char ref_hmac[COOKIE_HMAC_LEN]; 200 int ret = 0; 201 unsigned char *p = ref_hmac; 202 mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; 203 unsigned long cur_time, cookie_time; 204 205 if( ctx == NULL || cli_id == NULL ) 206 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); 207 208 if( cookie_len != COOKIE_LEN ) 209 return( -1 ); 210 211 #if defined(MBEDTLS_THREADING_C) 212 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 213 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); 214 #endif 215 216 if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, 217 &p, p + sizeof( ref_hmac ), 218 cli_id, cli_id_len ) != 0 ) 219 ret = -1; 220 221 #if defined(MBEDTLS_THREADING_C) 222 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 223 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, 224 MBEDTLS_ERR_THREADING_MUTEX_ERROR ) ); 225 #endif 226 227 if( ret != 0 ) 228 return( ret ); 229 230 if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) 231 return( -1 ); 232 233 #if defined(MBEDTLS_HAVE_TIME) 234 cur_time = (unsigned long) mbedtls_time( NULL ); 235 #else 236 cur_time = ctx->serial; 237 #endif 238 239 cookie_time = ( (unsigned long) cookie[0] << 24 ) | 240 ( (unsigned long) cookie[1] << 16 ) | 241 ( (unsigned long) cookie[2] << 8 ) | 242 ( (unsigned long) cookie[3] ); 243 244 if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) 245 return( -1 ); 246 247 return( 0 ); 248 } 249 #endif /* MBEDTLS_SSL_COOKIE_C */ 250