quickjs-tart

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

psa_crypto_ffdh.c (10839B)


      1 /*
      2  *  PSA FFDH layer on top of Mbed TLS crypto
      3  */
      4 /*
      5  *  Copyright The Mbed TLS Contributors
      6  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      7  */
      8 
      9 #include "common.h"
     10 
     11 #if defined(MBEDTLS_PSA_CRYPTO_C)
     12 
     13 /* This header is only needed because it defines
     14  * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in
     15  * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module
     16  * only uses bignum functions for arithmetic. */
     17 #include <mbedtls/dhm.h>
     18 
     19 #include <psa/crypto.h>
     20 #include "psa_crypto_core.h"
     21 #include "psa_crypto_ffdh.h"
     22 #include "psa_crypto_random_impl.h"
     23 #include "mbedtls/platform.h"
     24 #include "mbedtls/error.h"
     25 
     26 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||   \
     27     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) ||   \
     28     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \
     29     defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
     30 static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size,
     31                                                          mbedtls_mpi *P,
     32                                                          mbedtls_mpi *G)
     33 {
     34     const unsigned char *dhm_P = NULL;
     35     const unsigned char *dhm_G = NULL;
     36     size_t dhm_size_P = 0;
     37     size_t dhm_size_G = 0;
     38     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     39 
     40     if (P == NULL && G == NULL) {
     41         return PSA_ERROR_INVALID_ARGUMENT;
     42     }
     43 
     44 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
     45     static const unsigned char dhm_P_2048[] =
     46         MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
     47     static const unsigned char dhm_G_2048[] =
     48         MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
     49 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
     50 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
     51     static const unsigned char dhm_P_3072[] =
     52         MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
     53     static const unsigned char dhm_G_3072[] =
     54         MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
     55 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
     56 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
     57     static const unsigned char dhm_P_4096[] =
     58         MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
     59     static const unsigned char dhm_G_4096[] =
     60         MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
     61 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
     62 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
     63     static const unsigned char dhm_P_6144[] =
     64         MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
     65     static const unsigned char dhm_G_6144[] =
     66         MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;
     67 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
     68 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
     69     static const unsigned char dhm_P_8192[] =
     70         MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
     71     static const unsigned char dhm_G_8192[] =
     72         MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;
     73 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
     74 
     75     switch (key_size) {
     76 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
     77         case sizeof(dhm_P_2048):
     78             dhm_P = dhm_P_2048;
     79             dhm_G = dhm_G_2048;
     80             dhm_size_P = sizeof(dhm_P_2048);
     81             dhm_size_G = sizeof(dhm_G_2048);
     82             break;
     83 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
     84 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
     85         case sizeof(dhm_P_3072):
     86             dhm_P = dhm_P_3072;
     87             dhm_G = dhm_G_3072;
     88             dhm_size_P = sizeof(dhm_P_3072);
     89             dhm_size_G = sizeof(dhm_G_3072);
     90             break;
     91 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
     92 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
     93         case sizeof(dhm_P_4096):
     94             dhm_P = dhm_P_4096;
     95             dhm_G = dhm_G_4096;
     96             dhm_size_P = sizeof(dhm_P_4096);
     97             dhm_size_G = sizeof(dhm_G_4096);
     98             break;
     99 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
    100 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
    101         case sizeof(dhm_P_6144):
    102             dhm_P = dhm_P_6144;
    103             dhm_G = dhm_G_6144;
    104             dhm_size_P = sizeof(dhm_P_6144);
    105             dhm_size_G = sizeof(dhm_G_6144);
    106             break;
    107 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
    108 #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
    109         case sizeof(dhm_P_8192):
    110             dhm_P = dhm_P_8192;
    111             dhm_G = dhm_G_8192;
    112             dhm_size_P = sizeof(dhm_P_8192);
    113             dhm_size_G = sizeof(dhm_G_8192);
    114             break;
    115 #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
    116         default:
    117             return PSA_ERROR_INVALID_ARGUMENT;
    118     }
    119 
    120     if (P != NULL) {
    121         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P,
    122                                                 dhm_size_P));
    123     }
    124     if (G != NULL) {
    125         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G,
    126                                                 dhm_size_G));
    127     }
    128 
    129 cleanup:
    130     if (ret != 0) {
    131         return mbedtls_to_psa_error(ret);
    132     }
    133 
    134     return PSA_SUCCESS;
    135 }
    136 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
    137           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE ||
    138           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
    139           MBEDTLS_PSA_BUILTIN_ALG_FFDH */
    140 
    141 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
    142     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
    143 psa_status_t mbedtls_psa_ffdh_export_public_key(
    144     const psa_key_attributes_t *attributes,
    145     const uint8_t *key_buffer,
    146     size_t key_buffer_size,
    147     uint8_t *data,
    148     size_t data_size,
    149     size_t *data_length)
    150 {
    151     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    152     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    153     mbedtls_mpi GX, G, X, P;
    154     psa_key_type_t type = attributes->type;
    155 
    156     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
    157         if (key_buffer_size > data_size) {
    158             return PSA_ERROR_BUFFER_TOO_SMALL;
    159         }
    160         memcpy(data, key_buffer, key_buffer_size);
    161         memset(data + key_buffer_size, 0,
    162                data_size - key_buffer_size);
    163         *data_length = key_buffer_size;
    164         return PSA_SUCCESS;
    165     }
    166 
    167     mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);
    168     mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);
    169 
    170     size_t key_len = PSA_BITS_TO_BYTES(attributes->bits);
    171 
    172     status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G);
    173 
    174     if (status != PSA_SUCCESS) {
    175         goto cleanup;
    176     }
    177 
    178     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
    179                                             key_buffer_size));
    180 
    181     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL));
    182     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len));
    183 
    184     *data_length = key_len;
    185 
    186     ret = 0;
    187 cleanup:
    188     mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
    189     mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX);
    190 
    191     if (status == PSA_SUCCESS && ret != 0) {
    192         status = mbedtls_to_psa_error(ret);
    193     }
    194 
    195     return status;
    196 }
    197 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
    198           MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */
    199 
    200 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
    201 psa_status_t mbedtls_psa_ffdh_generate_key(
    202     const psa_key_attributes_t *attributes,
    203     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
    204 {
    205     mbedtls_mpi X, P;
    206     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    207     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    208     mbedtls_mpi_init(&P); mbedtls_mpi_init(&X);
    209     (void) attributes;
    210 
    211     status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL);
    212 
    213     if (status != PSA_SUCCESS) {
    214         goto cleanup;
    215     }
    216 
    217     /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their
    218         secret exponent from the range [2, P-2].
    219         Select random value in range [3, P-1] and decrease it by 1. */
    220     MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random,
    221                                        MBEDTLS_PSA_RANDOM_STATE));
    222     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1));
    223     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size));
    224     *key_buffer_length = key_buffer_size;
    225 
    226 cleanup:
    227     mbedtls_mpi_free(&P); mbedtls_mpi_free(&X);
    228     if (status == PSA_SUCCESS && ret != 0) {
    229         return mbedtls_to_psa_error(ret);
    230     }
    231 
    232     return status;
    233 }
    234 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */
    235 
    236 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT)
    237 psa_status_t mbedtls_psa_ffdh_import_key(
    238     const psa_key_attributes_t *attributes,
    239     const uint8_t *data, size_t data_length,
    240     uint8_t *key_buffer, size_t key_buffer_size,
    241     size_t *key_buffer_length, size_t *bits)
    242 {
    243     (void) attributes;
    244 
    245     if (key_buffer_size < data_length) {
    246         return PSA_ERROR_BUFFER_TOO_SMALL;
    247     }
    248     memcpy(key_buffer, data, data_length);
    249     *key_buffer_length = data_length;
    250     *bits = PSA_BYTES_TO_BITS(data_length);
    251 
    252     return PSA_SUCCESS;
    253 }
    254 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */
    255 
    256 #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
    257 psa_status_t mbedtls_psa_ffdh_key_agreement(
    258     const psa_key_attributes_t *attributes,
    259     const uint8_t *peer_key,
    260     size_t peer_key_length,
    261     const uint8_t *key_buffer,
    262     size_t key_buffer_size,
    263     uint8_t *shared_secret,
    264     size_t shared_secret_size,
    265     size_t *shared_secret_length)
    266 {
    267     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    268     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    269     mbedtls_mpi P, G, X, GY, K;
    270     const size_t calculated_shared_secret_size = peer_key_length;
    271 
    272     if (peer_key_length != key_buffer_size ||
    273         calculated_shared_secret_size > shared_secret_size) {
    274         return PSA_ERROR_INVALID_ARGUMENT;
    275     }
    276 
    277     if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) {
    278         return PSA_ERROR_INVALID_ARGUMENT;
    279     }
    280 
    281     mbedtls_mpi_init(&P); mbedtls_mpi_init(&G);
    282     mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY);
    283     mbedtls_mpi_init(&K);
    284 
    285     status = mbedtls_psa_ffdh_set_prime_generator(
    286         PSA_BITS_TO_BYTES(attributes->bits), &P, &G);
    287 
    288     if (status != PSA_SUCCESS) {
    289         goto cleanup;
    290     }
    291 
    292     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
    293                                             key_buffer_size));
    294 
    295     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key,
    296                                             peer_key_length));
    297 
    298     /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */
    299     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL));
    300 
    301     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret,
    302                                              calculated_shared_secret_size));
    303 
    304     *shared_secret_length = calculated_shared_secret_size;
    305 
    306     ret = 0;
    307 
    308 cleanup:
    309     mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
    310     mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY);
    311     mbedtls_mpi_free(&K);
    312 
    313     if (status == PSA_SUCCESS && ret != 0) {
    314         status = mbedtls_to_psa_error(ret);
    315     }
    316 
    317     return status;
    318 }
    319 #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
    320 
    321 #endif /* MBEDTLS_PSA_CRYPTO_C */