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