quickjs-tart

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

dh_server.c (9531B)


      1 /*
      2  *  Diffie-Hellman-Merkle key exchange (server side)
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 
      8 #include "mbedtls/build_info.h"
      9 
     10 #include "mbedtls/platform.h"
     11 /* md.h is included this early since MD_CAN_XXX macros are defined there. */
     12 #include "mbedtls/md.h"
     13 
     14 #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
     15     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
     16     defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
     17     defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C)
     18 #include "mbedtls/net_sockets.h"
     19 #include "mbedtls/aes.h"
     20 #include "mbedtls/dhm.h"
     21 #include "mbedtls/rsa.h"
     22 #include "mbedtls/sha256.h"
     23 #include "mbedtls/entropy.h"
     24 #include "mbedtls/ctr_drbg.h"
     25 
     26 #include <stdio.h>
     27 #include <string.h>
     28 #endif
     29 
     30 #define SERVER_PORT "11999"
     31 #define PLAINTEXT "==Hello there!=="
     32 
     33 #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) ||     \
     34     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) ||  \
     35     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||    \
     36     !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C)
     37 int main(void)
     38 {
     39     mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
     40                    "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
     41                    "MBEDTLS_MD_CAN_SHA256 and/or MBEDTLS_FS_IO and/or "
     42                    "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_SHA1_C not defined.\n");
     43     mbedtls_exit(0);
     44 }
     45 #else
     46 
     47 
     48 int main(void)
     49 {
     50     FILE *f;
     51 
     52     int ret = 1;
     53     int exit_code = MBEDTLS_EXIT_FAILURE;
     54     unsigned int mdlen;
     55     size_t n, buflen;
     56     mbedtls_net_context listen_fd, client_fd;
     57 
     58     unsigned char buf[2048];
     59     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
     60     unsigned char buf2[2];
     61     const char *pers = "dh_server";
     62 
     63     mbedtls_entropy_context entropy;
     64     mbedtls_ctr_drbg_context ctr_drbg;
     65     mbedtls_rsa_context rsa;
     66     mbedtls_dhm_context dhm;
     67     mbedtls_aes_context aes;
     68 
     69     mbedtls_mpi N, P, Q, D, E, dhm_P, dhm_G;
     70 
     71     mbedtls_net_init(&listen_fd);
     72     mbedtls_net_init(&client_fd);
     73     mbedtls_dhm_init(&dhm);
     74     mbedtls_aes_init(&aes);
     75     mbedtls_ctr_drbg_init(&ctr_drbg);
     76 
     77     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
     78     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&dhm_P);
     79     mbedtls_mpi_init(&dhm_G);
     80     /*
     81      * 1. Setup the RNG
     82      */
     83     mbedtls_printf("\n  . Seeding the random number generator");
     84     fflush(stdout);
     85 
     86     mbedtls_entropy_init(&entropy);
     87     if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
     88                                      (const unsigned char *) pers,
     89                                      strlen(pers))) != 0) {
     90         mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
     91         goto exit;
     92     }
     93 
     94     /*
     95      * 2a. Read the server's private RSA key
     96      */
     97     mbedtls_printf("\n  . Reading private key from rsa_priv.txt");
     98     fflush(stdout);
     99 
    100     if ((f = fopen("rsa_priv.txt", "rb")) == NULL) {
    101         mbedtls_printf(" failed\n  ! Could not open rsa_priv.txt\n" \
    102                        "  ! Please run rsa_genkey first\n\n");
    103         goto exit;
    104     }
    105 
    106     mbedtls_rsa_init(&rsa);
    107 
    108     if ((ret = mbedtls_mpi_read_file(&N, 16, f)) != 0 ||
    109         (ret = mbedtls_mpi_read_file(&E, 16, f)) != 0 ||
    110         (ret = mbedtls_mpi_read_file(&D, 16, f)) != 0 ||
    111         (ret = mbedtls_mpi_read_file(&P, 16, f)) != 0 ||
    112         (ret = mbedtls_mpi_read_file(&Q, 16, f)) != 0) {
    113         mbedtls_printf(" failed\n  ! mbedtls_mpi_read_file returned %d\n\n",
    114                        ret);
    115         fclose(f);
    116         goto exit;
    117     }
    118     fclose(f);
    119 
    120     if ((ret = mbedtls_rsa_import(&rsa, &N, &P, &Q, &D, &E)) != 0) {
    121         mbedtls_printf(" failed\n  ! mbedtls_rsa_import returned %d\n\n",
    122                        ret);
    123         goto exit;
    124     }
    125 
    126     if ((ret = mbedtls_rsa_complete(&rsa)) != 0) {
    127         mbedtls_printf(" failed\n  ! mbedtls_rsa_complete returned %d\n\n",
    128                        ret);
    129         goto exit;
    130     }
    131 
    132     /*
    133      * 2b. Get the DHM modulus and generator
    134      */
    135     mbedtls_printf("\n  . Reading DH parameters from dh_prime.txt");
    136     fflush(stdout);
    137 
    138     if ((f = fopen("dh_prime.txt", "rb")) == NULL) {
    139         mbedtls_printf(" failed\n  ! Could not open dh_prime.txt\n" \
    140                        "  ! Please run dh_genprime first\n\n");
    141         goto exit;
    142     }
    143 
    144     if ((ret = mbedtls_mpi_read_file(&dhm_P, 16, f)) != 0 ||
    145         (ret = mbedtls_mpi_read_file(&dhm_G, 16, f)) != 0 ||
    146         (ret = mbedtls_dhm_set_group(&dhm, &dhm_P, &dhm_G) != 0)) {
    147         mbedtls_printf(" failed\n  ! Invalid DH parameter file\n\n");
    148         fclose(f);
    149         goto exit;
    150     }
    151 
    152     fclose(f);
    153 
    154     /*
    155      * 3. Wait for a client to connect
    156      */
    157     mbedtls_printf("\n  . Waiting for a remote connection");
    158     fflush(stdout);
    159 
    160     if ((ret = mbedtls_net_bind(&listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
    161         mbedtls_printf(" failed\n  ! mbedtls_net_bind returned %d\n\n", ret);
    162         goto exit;
    163     }
    164 
    165     if ((ret = mbedtls_net_accept(&listen_fd, &client_fd,
    166                                   NULL, 0, NULL)) != 0) {
    167         mbedtls_printf(" failed\n  ! mbedtls_net_accept returned %d\n\n", ret);
    168         goto exit;
    169     }
    170 
    171     /*
    172      * 4. Setup the DH parameters (P,G,Ys)
    173      */
    174     mbedtls_printf("\n  . Sending the server's DH parameters");
    175     fflush(stdout);
    176 
    177     memset(buf, 0, sizeof(buf));
    178 
    179     if ((ret =
    180              mbedtls_dhm_make_params(&dhm, (int) mbedtls_dhm_get_len(&dhm), buf, &n,
    181                                      mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
    182         mbedtls_printf(" failed\n  ! mbedtls_dhm_make_params returned %d\n\n", ret);
    183         goto exit;
    184     }
    185 
    186     /*
    187      * 5. Sign the parameters and send them
    188      */
    189 
    190     mdlen = (unsigned int) mbedtls_md_get_size(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256));
    191     if (mdlen == 0) {
    192         mbedtls_printf(" failed\n  ! Invalid digest type\n\n");
    193         goto exit;
    194     }
    195 
    196     if ((ret = mbedtls_sha256(buf, n, hash, 0)) != 0) {
    197         mbedtls_printf(" failed\n  ! mbedtls_sha256 returned %d\n\n", ret);
    198         goto exit;
    199     }
    200 
    201     const size_t rsa_key_len = mbedtls_rsa_get_len(&rsa);
    202     buf[n] = (unsigned char) (rsa_key_len >> 8);
    203     buf[n + 1] = (unsigned char) (rsa_key_len);
    204 
    205     if ((ret = mbedtls_rsa_pkcs1_sign(&rsa, mbedtls_ctr_drbg_random, &ctr_drbg,
    206                                       MBEDTLS_MD_SHA256, mdlen,
    207                                       hash, buf + n + 2)) != 0) {
    208         mbedtls_printf(" failed\n  ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret);
    209         goto exit;
    210     }
    211 
    212     buflen = n + 2 + rsa_key_len;
    213     buf2[0] = (unsigned char) (buflen >> 8);
    214     buf2[1] = (unsigned char) (buflen);
    215 
    216     if ((ret = mbedtls_net_send(&client_fd, buf2, 2)) != 2 ||
    217         (ret = mbedtls_net_send(&client_fd, buf, buflen)) != (int) buflen) {
    218         mbedtls_printf(" failed\n  ! mbedtls_net_send returned %d\n\n", ret);
    219         goto exit;
    220     }
    221 
    222     /*
    223      * 6. Get the client's public value: Yc = G ^ Xc mod P
    224      */
    225     mbedtls_printf("\n  . Receiving the client's public value");
    226     fflush(stdout);
    227 
    228     memset(buf, 0, sizeof(buf));
    229 
    230     n = mbedtls_dhm_get_len(&dhm);
    231     if ((ret = mbedtls_net_recv(&client_fd, buf, n)) != (int) n) {
    232         mbedtls_printf(" failed\n  ! mbedtls_net_recv returned %d\n\n", ret);
    233         goto exit;
    234     }
    235 
    236     if ((ret = mbedtls_dhm_read_public(&dhm, buf, n)) != 0) {
    237         mbedtls_printf(" failed\n  ! mbedtls_dhm_read_public returned %d\n\n", ret);
    238         goto exit;
    239     }
    240 
    241     /*
    242      * 7. Derive the shared secret: K = Ys ^ Xc mod P
    243      */
    244     mbedtls_printf("\n  . Shared secret: ");
    245     fflush(stdout);
    246 
    247     if ((ret = mbedtls_dhm_calc_secret(&dhm, buf, sizeof(buf), &n,
    248                                        mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
    249         mbedtls_printf(" failed\n  ! mbedtls_dhm_calc_secret returned %d\n\n", ret);
    250         goto exit;
    251     }
    252 
    253     for (n = 0; n < 16; n++) {
    254         mbedtls_printf("%02x", buf[n]);
    255     }
    256 
    257     /*
    258      * 8. Setup the AES-256 encryption key
    259      *
    260      * This is an overly simplified example; best practice is
    261      * to hash the shared secret with a random value to derive
    262      * the keying material for the encryption/decryption keys
    263      * and MACs.
    264      */
    265     mbedtls_printf("...\n  . Encrypting and sending the ciphertext");
    266     fflush(stdout);
    267 
    268     ret = mbedtls_aes_setkey_enc(&aes, buf, 256);
    269     if (ret != 0) {
    270         goto exit;
    271     }
    272     memcpy(buf, PLAINTEXT, 16);
    273     ret = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, buf, buf);
    274     if (ret != 0) {
    275         goto exit;
    276     }
    277 
    278     if ((ret = mbedtls_net_send(&client_fd, buf, 16)) != 16) {
    279         mbedtls_printf(" failed\n  ! mbedtls_net_send returned %d\n\n", ret);
    280         goto exit;
    281     }
    282 
    283     mbedtls_printf("\n\n");
    284 
    285     exit_code = MBEDTLS_EXIT_SUCCESS;
    286 
    287 exit:
    288 
    289     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
    290     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&dhm_P);
    291     mbedtls_mpi_free(&dhm_G);
    292 
    293     mbedtls_net_free(&client_fd);
    294     mbedtls_net_free(&listen_fd);
    295 
    296     mbedtls_aes_free(&aes);
    297     mbedtls_rsa_free(&rsa);
    298     mbedtls_dhm_free(&dhm);
    299     mbedtls_ctr_drbg_free(&ctr_drbg);
    300     mbedtls_entropy_free(&entropy);
    301 
    302     mbedtls_exit(exit_code);
    303 }
    304 #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
    305           MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 &&
    306           MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */