1 /* 2 * DTLS cookie callbacks implementation 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 /* 8 * These session callbacks use a simple chained list 9 * to store and retrieve the session information. 10 */ 11 12 #include "common.h" 13 14 #if defined(MBEDTLS_SSL_COOKIE_C) 15 16 #include "mbedtls/platform.h" 17 18 #include "mbedtls/ssl_cookie.h" 19 #include "ssl_misc.h" 20 #include "mbedtls/error.h" 21 #include "mbedtls/platform_util.h" 22 #include "mbedtls/constant_time.h" 23 24 #include <string.h> 25 26 #if defined(MBEDTLS_USE_PSA_CRYPTO) 27 #include "mbedtls/psa_util.h" 28 /* Define a local translating function to save code size by not using too many 29 * arguments in each translating place. */ 30 static int local_err_translation(psa_status_t status) 31 { 32 return psa_status_to_mbedtls(status, psa_to_ssl_errors, 33 ARRAY_LENGTH(psa_to_ssl_errors), 34 psa_generic_status_to_mbedtls); 35 } 36 #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) 37 #endif 38 39 /* 40 * If DTLS is in use, then at least one of SHA-256 or SHA-384 is 41 * available. Try SHA-256 first as 384 wastes resources 42 */ 43 #if defined(MBEDTLS_MD_CAN_SHA256) 44 #define COOKIE_MD MBEDTLS_MD_SHA256 45 #define COOKIE_MD_OUTLEN 32 46 #define COOKIE_HMAC_LEN 28 47 #elif defined(MBEDTLS_MD_CAN_SHA384) 48 #define COOKIE_MD MBEDTLS_MD_SHA384 49 #define COOKIE_MD_OUTLEN 48 50 #define COOKIE_HMAC_LEN 28 51 #else 52 #error "DTLS hello verify needs SHA-256 or SHA-384" 53 #endif 54 55 /* 56 * Cookies are formed of a 4-bytes timestamp (or serial number) and 57 * an HMAC of timestamp and client ID. 58 */ 59 #define COOKIE_LEN (4 + COOKIE_HMAC_LEN) 60 61 void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx) 62 { 63 #if defined(MBEDTLS_USE_PSA_CRYPTO) 64 ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; 65 #else 66 mbedtls_md_init(&ctx->hmac_ctx); 67 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 68 #if !defined(MBEDTLS_HAVE_TIME) 69 ctx->serial = 0; 70 #endif 71 ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; 72 73 #if !defined(MBEDTLS_USE_PSA_CRYPTO) 74 #if defined(MBEDTLS_THREADING_C) 75 mbedtls_mutex_init(&ctx->mutex); 76 #endif 77 #endif /* !MBEDTLS_USE_PSA_CRYPTO */ 78 } 79 80 void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay) 81 { 82 ctx->timeout = delay; 83 } 84 85 void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx) 86 { 87 if (ctx == NULL) { 88 return; 89 } 90 91 #if defined(MBEDTLS_USE_PSA_CRYPTO) 92 psa_destroy_key(ctx->psa_hmac_key); 93 #else 94 mbedtls_md_free(&ctx->hmac_ctx); 95 96 #if defined(MBEDTLS_THREADING_C) 97 mbedtls_mutex_free(&ctx->mutex); 98 #endif 99 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 100 101 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx)); 102 } 103 104 int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, 105 int (*f_rng)(void *, unsigned char *, size_t), 106 void *p_rng) 107 { 108 #if defined(MBEDTLS_USE_PSA_CRYPTO) 109 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 110 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 111 psa_algorithm_t alg; 112 113 (void) f_rng; 114 (void) p_rng; 115 116 alg = mbedtls_md_psa_alg_from_type(COOKIE_MD); 117 if (alg == 0) { 118 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; 119 } 120 121 ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg), 122 COOKIE_HMAC_LEN); 123 124 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | 125 PSA_KEY_USAGE_SIGN_MESSAGE); 126 psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg); 127 psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); 128 psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN)); 129 130 if ((status = psa_generate_key(&attributes, 131 &ctx->psa_hmac_key)) != PSA_SUCCESS) { 132 return PSA_TO_MBEDTLS_ERR(status); 133 } 134 #else 135 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 136 unsigned char key[COOKIE_MD_OUTLEN]; 137 138 if ((ret = f_rng(p_rng, key, sizeof(key))) != 0) { 139 return ret; 140 } 141 142 ret = mbedtls_md_setup(&ctx->hmac_ctx, mbedtls_md_info_from_type(COOKIE_MD), 1); 143 if (ret != 0) { 144 return ret; 145 } 146 147 ret = mbedtls_md_hmac_starts(&ctx->hmac_ctx, key, sizeof(key)); 148 if (ret != 0) { 149 return ret; 150 } 151 152 mbedtls_platform_zeroize(key, sizeof(key)); 153 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 154 155 return 0; 156 } 157 158 #if !defined(MBEDTLS_USE_PSA_CRYPTO) 159 /* 160 * Generate the HMAC part of a cookie 161 */ 162 MBEDTLS_CHECK_RETURN_CRITICAL 163 static int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx, 164 const unsigned char time[4], 165 unsigned char **p, unsigned char *end, 166 const unsigned char *cli_id, size_t cli_id_len) 167 { 168 unsigned char hmac_out[COOKIE_MD_OUTLEN]; 169 170 MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_HMAC_LEN); 171 172 if (mbedtls_md_hmac_reset(hmac_ctx) != 0 || 173 mbedtls_md_hmac_update(hmac_ctx, time, 4) != 0 || 174 mbedtls_md_hmac_update(hmac_ctx, cli_id, cli_id_len) != 0 || 175 mbedtls_md_hmac_finish(hmac_ctx, hmac_out) != 0) { 176 return MBEDTLS_ERR_SSL_INTERNAL_ERROR; 177 } 178 179 memcpy(*p, hmac_out, COOKIE_HMAC_LEN); 180 *p += COOKIE_HMAC_LEN; 181 182 return 0; 183 } 184 #endif /* !MBEDTLS_USE_PSA_CRYPTO */ 185 186 /* 187 * Generate cookie for DTLS ClientHello verification 188 */ 189 int mbedtls_ssl_cookie_write(void *p_ctx, 190 unsigned char **p, unsigned char *end, 191 const unsigned char *cli_id, size_t cli_id_len) 192 { 193 #if defined(MBEDTLS_USE_PSA_CRYPTO) 194 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; 195 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 196 size_t sign_mac_length = 0; 197 #endif 198 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 199 mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; 200 unsigned long t; 201 202 if (ctx == NULL || cli_id == NULL) { 203 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; 204 } 205 206 MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_LEN); 207 208 #if defined(MBEDTLS_HAVE_TIME) 209 t = (unsigned long) mbedtls_time(NULL); 210 #else 211 t = ctx->serial++; 212 #endif 213 214 MBEDTLS_PUT_UINT32_BE(t, *p, 0); 215 *p += 4; 216 217 #if defined(MBEDTLS_USE_PSA_CRYPTO) 218 status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key, 219 ctx->psa_hmac_alg); 220 if (status != PSA_SUCCESS) { 221 ret = PSA_TO_MBEDTLS_ERR(status); 222 goto exit; 223 } 224 225 status = psa_mac_update(&operation, *p - 4, 4); 226 if (status != PSA_SUCCESS) { 227 ret = PSA_TO_MBEDTLS_ERR(status); 228 goto exit; 229 } 230 231 status = psa_mac_update(&operation, cli_id, cli_id_len); 232 if (status != PSA_SUCCESS) { 233 ret = PSA_TO_MBEDTLS_ERR(status); 234 goto exit; 235 } 236 237 status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN, 238 &sign_mac_length); 239 if (status != PSA_SUCCESS) { 240 ret = PSA_TO_MBEDTLS_ERR(status); 241 goto exit; 242 } 243 244 *p += COOKIE_HMAC_LEN; 245 246 ret = 0; 247 #else 248 #if defined(MBEDTLS_THREADING_C) 249 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { 250 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); 251 } 252 #endif 253 254 ret = ssl_cookie_hmac(&ctx->hmac_ctx, *p - 4, 255 p, end, cli_id, cli_id_len); 256 257 #if defined(MBEDTLS_THREADING_C) 258 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { 259 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, 260 MBEDTLS_ERR_THREADING_MUTEX_ERROR); 261 } 262 #endif 263 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 264 265 #if defined(MBEDTLS_USE_PSA_CRYPTO) 266 exit: 267 status = psa_mac_abort(&operation); 268 if (status != PSA_SUCCESS) { 269 ret = PSA_TO_MBEDTLS_ERR(status); 270 } 271 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 272 return ret; 273 } 274 275 /* 276 * Check a cookie 277 */ 278 int mbedtls_ssl_cookie_check(void *p_ctx, 279 const unsigned char *cookie, size_t cookie_len, 280 const unsigned char *cli_id, size_t cli_id_len) 281 { 282 #if defined(MBEDTLS_USE_PSA_CRYPTO) 283 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; 284 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 285 #else 286 unsigned char ref_hmac[COOKIE_HMAC_LEN]; 287 unsigned char *p = ref_hmac; 288 #endif 289 int ret = 0; 290 mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; 291 unsigned long cur_time, cookie_time; 292 293 if (ctx == NULL || cli_id == NULL) { 294 return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; 295 } 296 297 if (cookie_len != COOKIE_LEN) { 298 return -1; 299 } 300 301 #if defined(MBEDTLS_USE_PSA_CRYPTO) 302 status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key, 303 ctx->psa_hmac_alg); 304 if (status != PSA_SUCCESS) { 305 ret = PSA_TO_MBEDTLS_ERR(status); 306 goto exit; 307 } 308 309 status = psa_mac_update(&operation, cookie, 4); 310 if (status != PSA_SUCCESS) { 311 ret = PSA_TO_MBEDTLS_ERR(status); 312 goto exit; 313 } 314 315 status = psa_mac_update(&operation, cli_id, 316 cli_id_len); 317 if (status != PSA_SUCCESS) { 318 ret = PSA_TO_MBEDTLS_ERR(status); 319 goto exit; 320 } 321 322 status = psa_mac_verify_finish(&operation, cookie + 4, 323 COOKIE_HMAC_LEN); 324 if (status != PSA_SUCCESS) { 325 ret = PSA_TO_MBEDTLS_ERR(status); 326 goto exit; 327 } 328 329 ret = 0; 330 #else 331 #if defined(MBEDTLS_THREADING_C) 332 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { 333 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); 334 } 335 #endif 336 337 if (ssl_cookie_hmac(&ctx->hmac_ctx, cookie, 338 &p, p + sizeof(ref_hmac), 339 cli_id, cli_id_len) != 0) { 340 ret = -1; 341 } 342 343 #if defined(MBEDTLS_THREADING_C) 344 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { 345 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, 346 MBEDTLS_ERR_THREADING_MUTEX_ERROR); 347 } 348 #endif 349 350 if (ret != 0) { 351 goto exit; 352 } 353 354 if (mbedtls_ct_memcmp(cookie + 4, ref_hmac, sizeof(ref_hmac)) != 0) { 355 ret = -1; 356 goto exit; 357 } 358 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 359 360 #if defined(MBEDTLS_HAVE_TIME) 361 cur_time = (unsigned long) mbedtls_time(NULL); 362 #else 363 cur_time = ctx->serial; 364 #endif 365 366 cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0); 367 368 if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) { 369 ret = -1; 370 goto exit; 371 } 372 373 exit: 374 #if defined(MBEDTLS_USE_PSA_CRYPTO) 375 status = psa_mac_abort(&operation); 376 if (status != PSA_SUCCESS) { 377 ret = PSA_TO_MBEDTLS_ERR(status); 378 } 379 #else 380 mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac)); 381 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 382 return ret; 383 } 384 #endif /* MBEDTLS_SSL_COOKIE_C */ 385