quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ssl_cookie.c (10718B)


      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 */