quickjs-tart

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

dtls_client.c (9785B)


      1 /*
      2  *  Simple DTLS client demonstration program
      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 
     12 #if !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||      \
     13     !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_CLI_C) ||           \
     14     !defined(MBEDTLS_TIMING_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ||   \
     15     !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_X509_CRT_PARSE_C)
     16 int main(void)
     17 {
     18     mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
     19                    "MBEDTLS_NET_C and/or MBEDTLS_SSL_CLI_C and/or "
     20                    "MBEDTLS_TIMING_C and/or MBEDTLS_SSL_PROTO_DTLS and/or "
     21                    "MBEDTLS_PEM_PARSE_C and/or MBEDTLS_X509_CRT_PARSE_C "
     22                    "not defined.\n");
     23     mbedtls_exit(0);
     24 }
     25 #else
     26 
     27 #include <string.h>
     28 
     29 #include "mbedtls/net_sockets.h"
     30 #include "mbedtls/debug.h"
     31 #include "mbedtls/ssl.h"
     32 #include "mbedtls/entropy.h"
     33 #include "mbedtls/ctr_drbg.h"
     34 #include "mbedtls/error.h"
     35 #include "mbedtls/timing.h"
     36 #include "test/certs.h"
     37 
     38 /* Uncomment out the following line to default to IPv4 and disable IPv6 */
     39 //#define FORCE_IPV4
     40 
     41 #define SERVER_PORT "4433"
     42 #define SERVER_NAME "localhost"
     43 
     44 #ifdef FORCE_IPV4
     45 #define SERVER_ADDR "127.0.0.1"     /* Forces IPv4 */
     46 #else
     47 #define SERVER_ADDR SERVER_NAME
     48 #endif
     49 
     50 #define MESSAGE     "Echo this"
     51 
     52 #define READ_TIMEOUT_MS 1000
     53 #define MAX_RETRY       5
     54 
     55 #define DEBUG_LEVEL 0
     56 
     57 
     58 static void my_debug(void *ctx, int level,
     59                      const char *file, int line,
     60                      const char *str)
     61 {
     62     ((void) level);
     63 
     64     mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
     65     fflush((FILE *) ctx);
     66 }
     67 
     68 int main(int argc, char *argv[])
     69 {
     70     int ret, len;
     71     mbedtls_net_context server_fd;
     72     uint32_t flags;
     73     unsigned char buf[1024];
     74     const char *pers = "dtls_client";
     75     int retry_left = MAX_RETRY;
     76 
     77     mbedtls_entropy_context entropy;
     78     mbedtls_ctr_drbg_context ctr_drbg;
     79     mbedtls_ssl_context ssl;
     80     mbedtls_ssl_config conf;
     81     mbedtls_x509_crt cacert;
     82     mbedtls_timing_delay_context timer;
     83 
     84     ((void) argc);
     85     ((void) argv);
     86 
     87 #if defined(MBEDTLS_DEBUG_C)
     88     mbedtls_debug_set_threshold(DEBUG_LEVEL);
     89 #endif
     90 
     91     /*
     92      * 0. Initialize the RNG and the session data
     93      */
     94     mbedtls_net_init(&server_fd);
     95     mbedtls_ssl_init(&ssl);
     96     mbedtls_ssl_config_init(&conf);
     97     mbedtls_x509_crt_init(&cacert);
     98     mbedtls_ctr_drbg_init(&ctr_drbg);
     99     mbedtls_entropy_init(&entropy);
    100 
    101 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    102     psa_status_t status = psa_crypto_init();
    103     if (status != PSA_SUCCESS) {
    104         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
    105                         (int) status);
    106         ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
    107         goto exit;
    108     }
    109 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    110 
    111     mbedtls_printf("\n  . Seeding the random number generator...");
    112     fflush(stdout);
    113 
    114     if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
    115                                      (const unsigned char *) pers,
    116                                      strlen(pers))) != 0) {
    117         mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
    118         goto exit;
    119     }
    120 
    121     mbedtls_printf(" ok\n");
    122 
    123     /*
    124      * 0. Load certificates
    125      */
    126     mbedtls_printf("  . Loading the CA root certificate ...");
    127     fflush(stdout);
    128 
    129     ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_cas_pem,
    130                                  mbedtls_test_cas_pem_len);
    131     if (ret < 0) {
    132         mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n",
    133                        (unsigned int) -ret);
    134         goto exit;
    135     }
    136 
    137     mbedtls_printf(" ok (%d skipped)\n", ret);
    138 
    139     /*
    140      * 1. Start the connection
    141      */
    142     mbedtls_printf("  . Connecting to udp/%s/%s...", SERVER_NAME, SERVER_PORT);
    143     fflush(stdout);
    144 
    145     if ((ret = mbedtls_net_connect(&server_fd, SERVER_ADDR,
    146                                    SERVER_PORT, MBEDTLS_NET_PROTO_UDP)) != 0) {
    147         mbedtls_printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
    148         goto exit;
    149     }
    150 
    151     mbedtls_printf(" ok\n");
    152 
    153     /*
    154      * 2. Setup stuff
    155      */
    156     mbedtls_printf("  . Setting up the DTLS structure...");
    157     fflush(stdout);
    158 
    159     if ((ret = mbedtls_ssl_config_defaults(&conf,
    160                                            MBEDTLS_SSL_IS_CLIENT,
    161                                            MBEDTLS_SSL_TRANSPORT_DATAGRAM,
    162                                            MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
    163         mbedtls_printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
    164         goto exit;
    165     }
    166 
    167     /* OPTIONAL is usually a bad choice for security, but makes interop easier
    168      * in this simplified example, in which the ca chain is hardcoded.
    169      * Production code should set a proper ca chain and use REQUIRED. */
    170     mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
    171     mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    172     mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
    173     mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
    174     mbedtls_ssl_conf_read_timeout(&conf, READ_TIMEOUT_MS);
    175 
    176     if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
    177         mbedtls_printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
    178         goto exit;
    179     }
    180 
    181     if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {
    182         mbedtls_printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
    183         goto exit;
    184     }
    185 
    186     mbedtls_ssl_set_bio(&ssl, &server_fd,
    187                         mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
    188 
    189     mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay,
    190                              mbedtls_timing_get_delay);
    191 
    192     mbedtls_printf(" ok\n");
    193 
    194     /*
    195      * 4. Handshake
    196      */
    197     mbedtls_printf("  . Performing the DTLS handshake...");
    198     fflush(stdout);
    199 
    200     do {
    201         ret = mbedtls_ssl_handshake(&ssl);
    202     } while (ret == MBEDTLS_ERR_SSL_WANT_READ ||
    203              ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    204 
    205     if (ret != 0) {
    206         mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n",
    207                        (unsigned int) -ret);
    208         goto exit;
    209     }
    210 
    211     mbedtls_printf(" ok\n");
    212 
    213     /*
    214      * 5. Verify the server certificate
    215      */
    216     mbedtls_printf("  . Verifying peer X.509 certificate...");
    217 
    218     /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the
    219      * handshake would not succeed if the peer's cert is bad.  Even if we used
    220      * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */
    221     if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) {
    222 #if !defined(MBEDTLS_X509_REMOVE_INFO)
    223         char vrfy_buf[512];
    224 #endif
    225 
    226         mbedtls_printf(" failed\n");
    227 
    228 #if !defined(MBEDTLS_X509_REMOVE_INFO)
    229         mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
    230 
    231         mbedtls_printf("%s\n", vrfy_buf);
    232 #endif
    233     } else {
    234         mbedtls_printf(" ok\n");
    235     }
    236 
    237     /*
    238      * 6. Write the echo request
    239      */
    240 send_request:
    241     mbedtls_printf("  > Write to server:");
    242     fflush(stdout);
    243 
    244     len = sizeof(MESSAGE) - 1;
    245 
    246     do {
    247         ret = mbedtls_ssl_write(&ssl, (unsigned char *) MESSAGE, len);
    248     } while (ret == MBEDTLS_ERR_SSL_WANT_READ ||
    249              ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    250 
    251     if (ret < 0) {
    252         mbedtls_printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
    253         goto exit;
    254     }
    255 
    256     len = ret;
    257     mbedtls_printf(" %d bytes written\n\n%s\n\n", len, MESSAGE);
    258 
    259     /*
    260      * 7. Read the echo response
    261      */
    262     mbedtls_printf("  < Read from server:");
    263     fflush(stdout);
    264 
    265     len = sizeof(buf) - 1;
    266     memset(buf, 0, sizeof(buf));
    267 
    268     do {
    269         ret = mbedtls_ssl_read(&ssl, buf, len);
    270     } while (ret == MBEDTLS_ERR_SSL_WANT_READ ||
    271              ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    272 
    273     if (ret <= 0) {
    274         switch (ret) {
    275             case MBEDTLS_ERR_SSL_TIMEOUT:
    276                 mbedtls_printf(" timeout\n\n");
    277                 if (retry_left-- > 0) {
    278                     goto send_request;
    279                 }
    280                 goto exit;
    281 
    282             case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
    283                 mbedtls_printf(" connection was closed gracefully\n");
    284                 goto close_notify;
    285 
    286             default:
    287                 mbedtls_printf(" mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret);
    288                 goto exit;
    289         }
    290     }
    291 
    292     len = ret;
    293     mbedtls_printf(" %d bytes read\n\n%s\n\n", len, buf);
    294 
    295     /*
    296      * 8. Done, cleanly close the connection
    297      */
    298 close_notify:
    299     mbedtls_printf("  . Closing the connection...");
    300 
    301     /* No error checking, the connection might be closed already */
    302     do {
    303         ret = mbedtls_ssl_close_notify(&ssl);
    304     } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
    305     ret = 0;
    306 
    307     mbedtls_printf(" done\n");
    308 
    309     /*
    310      * 9. Final clean-ups and exit
    311      */
    312 exit:
    313 
    314 #ifdef MBEDTLS_ERROR_C
    315     if (ret != 0) {
    316         char error_buf[100];
    317         mbedtls_strerror(ret, error_buf, 100);
    318         mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf);
    319     }
    320 #endif
    321 
    322     mbedtls_net_free(&server_fd);
    323     mbedtls_x509_crt_free(&cacert);
    324     mbedtls_ssl_free(&ssl);
    325     mbedtls_ssl_config_free(&conf);
    326     mbedtls_ctr_drbg_free(&ctr_drbg);
    327     mbedtls_entropy_free(&entropy);
    328 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    329     mbedtls_psa_crypto_free();
    330 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    331 
    332     /* Shell can not handle large exit numbers -> 1 for errors */
    333     if (ret < 0) {
    334         ret = 1;
    335     }
    336 
    337     mbedtls_exit(ret);
    338 }
    339 
    340 #endif /* configuration allows running this program */