quickjs-tart

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

ssl_ticket.c (16924B)


      1 /*
      2  *  TLS server tickets 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 #include "common.h"
      9 
     10 #if defined(MBEDTLS_SSL_TICKET_C)
     11 
     12 #include "mbedtls/platform.h"
     13 
     14 #include "ssl_misc.h"
     15 #include "mbedtls/ssl_ticket.h"
     16 #include "mbedtls/error.h"
     17 #include "mbedtls/platform_util.h"
     18 
     19 #include <string.h>
     20 
     21 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     22 /* Define a local translating function to save code size by not using too many
     23  * arguments in each translating place. */
     24 static int local_err_translation(psa_status_t status)
     25 {
     26     return psa_status_to_mbedtls(status, psa_to_ssl_errors,
     27                                  ARRAY_LENGTH(psa_to_ssl_errors),
     28                                  psa_generic_status_to_mbedtls);
     29 }
     30 #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
     31 #endif
     32 
     33 /*
     34  * Initialize context
     35  */
     36 void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
     37 {
     38     memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
     39 
     40 #if defined(MBEDTLS_THREADING_C)
     41     mbedtls_mutex_init(&ctx->mutex);
     42 #endif
     43 }
     44 
     45 #define MAX_KEY_BYTES           MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
     46 
     47 #define TICKET_KEY_NAME_BYTES   MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
     48 #define TICKET_IV_BYTES         12
     49 #define TICKET_CRYPT_LEN_BYTES   2
     50 #define TICKET_AUTH_TAG_BYTES   16
     51 
     52 #define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES  +        \
     53                         TICKET_IV_BYTES        +        \
     54                         TICKET_CRYPT_LEN_BYTES +        \
     55                         TICKET_AUTH_TAG_BYTES)
     56 #define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES  +        \
     57                              TICKET_IV_BYTES        +        \
     58                              TICKET_CRYPT_LEN_BYTES)
     59 
     60 /*
     61  * Generate/update a key
     62  */
     63 MBEDTLS_CHECK_RETURN_CRITICAL
     64 static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
     65                               unsigned char index)
     66 {
     67     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     68     unsigned char buf[MAX_KEY_BYTES] = { 0 };
     69     mbedtls_ssl_ticket_key *key = ctx->keys + index;
     70 
     71 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     72     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     73 #endif
     74 
     75 #if defined(MBEDTLS_HAVE_TIME)
     76     key->generation_time = mbedtls_time(NULL);
     77 #endif
     78     /* The lifetime of a key is the configured lifetime of the tickets when
     79      * the key is created.
     80      */
     81     key->lifetime = ctx->ticket_lifetime;
     82 
     83     if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
     84         return ret;
     85     }
     86 
     87     if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
     88         return ret;
     89     }
     90 
     91 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     92     psa_set_key_usage_flags(&attributes,
     93                             PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
     94     psa_set_key_algorithm(&attributes, key->alg);
     95     psa_set_key_type(&attributes, key->key_type);
     96     psa_set_key_bits(&attributes, key->key_bits);
     97 
     98     ret = PSA_TO_MBEDTLS_ERR(
     99         psa_import_key(&attributes, buf,
    100                        PSA_BITS_TO_BYTES(key->key_bits),
    101                        &key->key));
    102 #else
    103     /* With GCM and CCM, same context can encrypt & decrypt */
    104     ret = mbedtls_cipher_setkey(&key->ctx, buf,
    105                                 mbedtls_cipher_get_key_bitlen(&key->ctx),
    106                                 MBEDTLS_ENCRYPT);
    107 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    108 
    109     mbedtls_platform_zeroize(buf, sizeof(buf));
    110 
    111     return ret;
    112 }
    113 
    114 /*
    115  * Rotate/generate keys if necessary
    116  */
    117 MBEDTLS_CHECK_RETURN_CRITICAL
    118 static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
    119 {
    120 #if !defined(MBEDTLS_HAVE_TIME)
    121     ((void) ctx);
    122 #else
    123     mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
    124     if (key->lifetime != 0) {
    125         mbedtls_time_t current_time = mbedtls_time(NULL);
    126         mbedtls_time_t key_time = key->generation_time;
    127 
    128 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    129         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    130 #endif
    131 
    132         if (current_time >= key_time &&
    133             (uint64_t) (current_time - key_time) < key->lifetime) {
    134             return 0;
    135         }
    136 
    137         ctx->active = 1 - ctx->active;
    138 
    139 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    140         if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
    141             return PSA_TO_MBEDTLS_ERR(status);
    142         }
    143 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    144 
    145         return ssl_ticket_gen_key(ctx, ctx->active);
    146     } else
    147 #endif /* MBEDTLS_HAVE_TIME */
    148     return 0;
    149 }
    150 
    151 /*
    152  * Rotate active session ticket encryption key
    153  */
    154 int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
    155                               const unsigned char *name, size_t nlength,
    156                               const unsigned char *k, size_t klength,
    157                               uint32_t lifetime)
    158 {
    159     const unsigned char idx = 1 - ctx->active;
    160     mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
    161     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    162 
    163 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    164     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    165     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
    166     const size_t bitlen = key->key_bits;
    167 #else
    168     const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
    169 #endif
    170 
    171     if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
    172         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
    173     }
    174 
    175 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    176     if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
    177         ret = PSA_TO_MBEDTLS_ERR(status);
    178         return ret;
    179     }
    180 
    181     psa_set_key_usage_flags(&attributes,
    182                             PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
    183     psa_set_key_algorithm(&attributes, key->alg);
    184     psa_set_key_type(&attributes, key->key_type);
    185     psa_set_key_bits(&attributes, key->key_bits);
    186 
    187     if ((status = psa_import_key(&attributes, k,
    188                                  PSA_BITS_TO_BYTES(key->key_bits),
    189                                  &key->key)) != PSA_SUCCESS) {
    190         ret = PSA_TO_MBEDTLS_ERR(status);
    191         return ret;
    192     }
    193 #else
    194     ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
    195     if (ret != 0) {
    196         return ret;
    197     }
    198 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    199 
    200     ctx->active = idx;
    201     ctx->ticket_lifetime = lifetime;
    202     memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
    203 #if defined(MBEDTLS_HAVE_TIME)
    204     key->generation_time = mbedtls_time(NULL);
    205 #endif
    206     key->lifetime = lifetime;
    207 
    208     return 0;
    209 }
    210 
    211 /*
    212  * Setup context for actual use
    213  */
    214 int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
    215                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
    216                              mbedtls_cipher_type_t cipher,
    217                              uint32_t lifetime)
    218 {
    219     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    220     size_t key_bits;
    221 
    222 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    223     psa_algorithm_t alg;
    224     psa_key_type_t key_type;
    225 #else
    226     const mbedtls_cipher_info_t *cipher_info;
    227 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    228 
    229 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    230     if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,
    231                                   &alg, &key_type, &key_bits) != PSA_SUCCESS) {
    232         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    233     }
    234 
    235     if (PSA_ALG_IS_AEAD(alg) == 0) {
    236         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    237     }
    238 #else
    239     cipher_info = mbedtls_cipher_info_from_type(cipher);
    240 
    241     if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM &&
    242         mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM &&
    243         mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) {
    244         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    245     }
    246 
    247     key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info);
    248 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    249 
    250     if (key_bits > 8 * MAX_KEY_BYTES) {
    251         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    252     }
    253 
    254     ctx->f_rng = f_rng;
    255     ctx->p_rng = p_rng;
    256 
    257     ctx->ticket_lifetime = lifetime;
    258 
    259 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    260     ctx->keys[0].alg = alg;
    261     ctx->keys[0].key_type = key_type;
    262     ctx->keys[0].key_bits = key_bits;
    263 
    264     ctx->keys[1].alg = alg;
    265     ctx->keys[1].key_type = key_type;
    266     ctx->keys[1].key_bits = key_bits;
    267 #else
    268     if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
    269         return ret;
    270     }
    271 
    272     if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {
    273         return ret;
    274     }
    275 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    276 
    277     if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
    278         (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
    279         return ret;
    280     }
    281 
    282     return 0;
    283 }
    284 
    285 /*
    286  * Create session ticket, with the following structure:
    287  *
    288  *    struct {
    289  *        opaque key_name[4];
    290  *        opaque iv[12];
    291  *        opaque encrypted_state<0..2^16-1>;
    292  *        opaque tag[16];
    293  *    } ticket;
    294  *
    295  * The key_name, iv, and length of encrypted_state are the additional
    296  * authenticated data.
    297  */
    298 
    299 int mbedtls_ssl_ticket_write(void *p_ticket,
    300                              const mbedtls_ssl_session *session,
    301                              unsigned char *start,
    302                              const unsigned char *end,
    303                              size_t *tlen,
    304                              uint32_t *ticket_lifetime)
    305 {
    306     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    307     mbedtls_ssl_ticket_context *ctx = p_ticket;
    308     mbedtls_ssl_ticket_key *key;
    309     unsigned char *key_name = start;
    310     unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
    311     unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
    312     unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
    313     size_t clear_len, ciph_len;
    314 
    315 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    316     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    317 #endif
    318 
    319     *tlen = 0;
    320 
    321     if (ctx == NULL || ctx->f_rng == NULL) {
    322         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    323     }
    324 
    325     /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
    326      * in addition to session itself, that will be checked when writing it. */
    327     MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
    328 
    329 #if defined(MBEDTLS_THREADING_C)
    330     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
    331         return ret;
    332     }
    333 #endif
    334 
    335     if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
    336         goto cleanup;
    337     }
    338 
    339     key = &ctx->keys[ctx->active];
    340 
    341     *ticket_lifetime = key->lifetime;
    342 
    343     memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
    344 
    345     if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
    346         goto cleanup;
    347     }
    348 
    349     /* Dump session state */
    350     if ((ret = mbedtls_ssl_session_save(session,
    351                                         state, (size_t) (end - state),
    352                                         &clear_len)) != 0 ||
    353         (unsigned long) clear_len > 65535) {
    354         goto cleanup;
    355     }
    356     MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
    357 
    358     /* Encrypt and authenticate */
    359 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    360     if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
    361                                    key_name, TICKET_ADD_DATA_LEN,
    362                                    state, clear_len,
    363                                    state, end - state,
    364                                    &ciph_len)) != PSA_SUCCESS) {
    365         ret = PSA_TO_MBEDTLS_ERR(status);
    366         goto cleanup;
    367     }
    368 #else
    369     if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,
    370                                                iv, TICKET_IV_BYTES,
    371                                                /* Additional data: key name, IV and length */
    372                                                key_name, TICKET_ADD_DATA_LEN,
    373                                                state, clear_len,
    374                                                state, (size_t) (end - state), &ciph_len,
    375                                                TICKET_AUTH_TAG_BYTES)) != 0) {
    376         goto cleanup;
    377     }
    378 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    379 
    380     if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
    381         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
    382         goto cleanup;
    383     }
    384 
    385     *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES;
    386 
    387 cleanup:
    388 #if defined(MBEDTLS_THREADING_C)
    389     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
    390         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
    391     }
    392 #endif
    393 
    394     return ret;
    395 }
    396 
    397 /*
    398  * Select key based on name
    399  */
    400 static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
    401     mbedtls_ssl_ticket_context *ctx,
    402     const unsigned char name[4])
    403 {
    404     unsigned char i;
    405 
    406     for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
    407         if (memcmp(name, ctx->keys[i].name, 4) == 0) {
    408             return &ctx->keys[i];
    409         }
    410     }
    411 
    412     return NULL;
    413 }
    414 
    415 /*
    416  * Load session ticket (see mbedtls_ssl_ticket_write for structure)
    417  */
    418 int mbedtls_ssl_ticket_parse(void *p_ticket,
    419                              mbedtls_ssl_session *session,
    420                              unsigned char *buf,
    421                              size_t len)
    422 {
    423     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    424     mbedtls_ssl_ticket_context *ctx = p_ticket;
    425     mbedtls_ssl_ticket_key *key;
    426     unsigned char *key_name = buf;
    427     unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
    428     unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
    429     unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
    430     size_t enc_len, clear_len;
    431 
    432 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    433     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    434 #endif
    435 
    436     if (ctx == NULL || ctx->f_rng == NULL) {
    437         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    438     }
    439 
    440     if (len < TICKET_MIN_LEN) {
    441         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    442     }
    443 
    444 #if defined(MBEDTLS_THREADING_C)
    445     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
    446         return ret;
    447     }
    448 #endif
    449 
    450     if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
    451         goto cleanup;
    452     }
    453 
    454     enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
    455 
    456     if (len != TICKET_MIN_LEN + enc_len) {
    457         ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    458         goto cleanup;
    459     }
    460 
    461     /* Select key */
    462     if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
    463         /* We can't know for sure but this is a likely option unless we're
    464          * under attack - this is only informative anyway */
    465         ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
    466         goto cleanup;
    467     }
    468 
    469     /* Decrypt and authenticate */
    470 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    471     if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
    472                                    key_name, TICKET_ADD_DATA_LEN,
    473                                    ticket, enc_len + TICKET_AUTH_TAG_BYTES,
    474                                    ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
    475         ret = PSA_TO_MBEDTLS_ERR(status);
    476         goto cleanup;
    477     }
    478 #else
    479     if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,
    480                                                iv, TICKET_IV_BYTES,
    481                                                /* Additional data: key name, IV and length */
    482                                                key_name, TICKET_ADD_DATA_LEN,
    483                                                ticket, enc_len + TICKET_AUTH_TAG_BYTES,
    484                                                ticket, enc_len, &clear_len,
    485                                                TICKET_AUTH_TAG_BYTES)) != 0) {
    486         if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
    487             ret = MBEDTLS_ERR_SSL_INVALID_MAC;
    488         }
    489 
    490         goto cleanup;
    491     }
    492 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    493 
    494     if (clear_len != enc_len) {
    495         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
    496         goto cleanup;
    497     }
    498 
    499     /* Actually load session */
    500     if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
    501         goto cleanup;
    502     }
    503 
    504 #if defined(MBEDTLS_HAVE_TIME)
    505     mbedtls_ms_time_t ticket_creation_time, ticket_age;
    506     mbedtls_ms_time_t ticket_lifetime =
    507         (mbedtls_ms_time_t) key->lifetime * 1000;
    508 
    509     ret = mbedtls_ssl_session_get_ticket_creation_time(session,
    510                                                        &ticket_creation_time);
    511     if (ret != 0) {
    512         goto cleanup;
    513     }
    514 
    515     ticket_age = mbedtls_ms_time() - ticket_creation_time;
    516     if (ticket_age < 0 || ticket_age > ticket_lifetime) {
    517         ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
    518         goto cleanup;
    519     }
    520 #endif
    521 
    522 cleanup:
    523 #if defined(MBEDTLS_THREADING_C)
    524     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
    525         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
    526     }
    527 #endif
    528 
    529     return ret;
    530 }
    531 
    532 /*
    533  * Free context
    534  */
    535 void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
    536 {
    537     if (ctx == NULL) {
    538         return;
    539     }
    540 
    541 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    542     psa_destroy_key(ctx->keys[0].key);
    543     psa_destroy_key(ctx->keys[1].key);
    544 #else
    545     mbedtls_cipher_free(&ctx->keys[0].ctx);
    546     mbedtls_cipher_free(&ctx->keys[1].ctx);
    547 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    548 
    549 #if defined(MBEDTLS_THREADING_C)
    550     mbedtls_mutex_free(&ctx->mutex);
    551 #endif
    552 
    553     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
    554 }
    555 
    556 #endif /* MBEDTLS_SSL_TICKET_C */