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