quickjs-tart

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

cert_app.c (14988B)


      1 /*
      2  *  Certificate reading application
      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_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     13     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
     14     !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) ||         \
     15     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
     16     !defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_X509_REMOVE_INFO)
     17 int main(void)
     18 {
     19     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
     20                    "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
     21                    "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
     22                    "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
     23                    "MBEDTLS_CTR_DRBG_C not defined and/or MBEDTLS_X509_REMOVE_INFO defined.\n");
     24     mbedtls_exit(0);
     25 }
     26 #else
     27 
     28 #include "mbedtls/entropy.h"
     29 #include "mbedtls/ctr_drbg.h"
     30 #include "mbedtls/net_sockets.h"
     31 #include "mbedtls/ssl.h"
     32 #include "mbedtls/x509.h"
     33 #include "mbedtls/debug.h"
     34 
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 
     39 #define MODE_NONE               0
     40 #define MODE_FILE               1
     41 #define MODE_SSL                2
     42 
     43 #define DFL_MODE                MODE_NONE
     44 #define DFL_FILENAME            "cert.crt"
     45 #define DFL_CA_FILE             ""
     46 #define DFL_CRL_FILE            ""
     47 #define DFL_CA_PATH             ""
     48 #define DFL_SERVER_NAME         "localhost"
     49 #define DFL_SERVER_PORT         "4433"
     50 #define DFL_DEBUG_LEVEL         0
     51 #define DFL_PERMISSIVE          0
     52 
     53 #define USAGE_IO \
     54     "    ca_file=%%s          The single file containing the top-level CA(s) you fully trust\n" \
     55     "                        default: \"\" (none)\n" \
     56     "    crl_file=%%s         The single CRL file you want to use\n" \
     57     "                        default: \"\" (none)\n" \
     58     "    ca_path=%%s          The path containing the top-level CA(s) you fully trust\n" \
     59     "                        default: \"\" (none) (overrides ca_file)\n"
     60 
     61 #define USAGE \
     62     "\n usage: cert_app param=<>...\n"                  \
     63     "\n acceptable parameters:\n"                       \
     64     "    mode=file|ssl       default: none\n"           \
     65     "    filename=%%s         default: cert.crt\n"      \
     66     USAGE_IO                                            \
     67     "    server_name=%%s      default: localhost\n"     \
     68     "    server_port=%%d      default: 4433\n"          \
     69     "    debug_level=%%d      default: 0 (disabled)\n"  \
     70     "    permissive=%%d       default: 0 (disabled)\n"  \
     71     "\n"
     72 
     73 
     74 /*
     75  * global options
     76  */
     77 struct options {
     78     int mode;                   /* the mode to run the application in   */
     79     const char *filename;       /* filename of the certificate file     */
     80     const char *ca_file;        /* the file with the CA certificate(s)  */
     81     const char *crl_file;       /* the file with the CRL to use         */
     82     const char *ca_path;        /* the path with the CA certificate(s) reside */
     83     const char *server_name;    /* hostname of the server (client only) */
     84     const char *server_port;    /* port on which the ssl service runs   */
     85     int debug_level;            /* level of debugging                   */
     86     int permissive;             /* permissive parsing                   */
     87 } opt;
     88 
     89 static void my_debug(void *ctx, int level,
     90                      const char *file, int line,
     91                      const char *str)
     92 {
     93     ((void) level);
     94 
     95     mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
     96     fflush((FILE *) ctx);
     97 }
     98 
     99 static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
    100 {
    101     char buf[1024];
    102     ((void) data);
    103 
    104     mbedtls_printf("\nVerify requested for (Depth %d):\n", depth);
    105     mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
    106     mbedtls_printf("%s", buf);
    107 
    108     if ((*flags) == 0) {
    109         mbedtls_printf("  This certificate has no flags\n");
    110     } else {
    111         mbedtls_x509_crt_verify_info(buf, sizeof(buf), "  ! ", *flags);
    112         mbedtls_printf("%s\n", buf);
    113     }
    114 
    115     return 0;
    116 }
    117 
    118 int main(int argc, char *argv[])
    119 {
    120     int ret = 1;
    121     int exit_code = MBEDTLS_EXIT_FAILURE;
    122     mbedtls_net_context server_fd;
    123     unsigned char buf[1024];
    124     mbedtls_entropy_context entropy;
    125     mbedtls_ctr_drbg_context ctr_drbg;
    126     mbedtls_ssl_context ssl;
    127     mbedtls_ssl_config conf;
    128     mbedtls_x509_crt cacert;
    129     mbedtls_x509_crl cacrl;
    130     int i, j;
    131     uint32_t flags;
    132     int verify = 0;
    133     char *p, *q;
    134     const char *pers = "cert_app";
    135 
    136     /*
    137      * Set to sane values
    138      */
    139     mbedtls_net_init(&server_fd);
    140     mbedtls_ctr_drbg_init(&ctr_drbg);
    141     mbedtls_ssl_init(&ssl);
    142     mbedtls_ssl_config_init(&conf);
    143     mbedtls_x509_crt_init(&cacert);
    144     mbedtls_entropy_init(&entropy);
    145 #if defined(MBEDTLS_X509_CRL_PARSE_C)
    146     mbedtls_x509_crl_init(&cacrl);
    147 #else
    148     /* Zeroize structure as CRL parsing is not supported and we have to pass
    149        it to the verify function */
    150     memset(&cacrl, 0, sizeof(mbedtls_x509_crl));
    151 #endif
    152 
    153 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    154     psa_status_t status = psa_crypto_init();
    155     if (status != PSA_SUCCESS) {
    156         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
    157                         (int) status);
    158         goto exit;
    159     }
    160 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    161 
    162     if (argc < 2) {
    163 usage:
    164         mbedtls_printf(USAGE);
    165         goto exit;
    166     }
    167 
    168     opt.mode                = DFL_MODE;
    169     opt.filename            = DFL_FILENAME;
    170     opt.ca_file             = DFL_CA_FILE;
    171     opt.crl_file            = DFL_CRL_FILE;
    172     opt.ca_path             = DFL_CA_PATH;
    173     opt.server_name         = DFL_SERVER_NAME;
    174     opt.server_port         = DFL_SERVER_PORT;
    175     opt.debug_level         = DFL_DEBUG_LEVEL;
    176     opt.permissive          = DFL_PERMISSIVE;
    177 
    178     for (i = 1; i < argc; i++) {
    179         p = argv[i];
    180         if ((q = strchr(p, '=')) == NULL) {
    181             goto usage;
    182         }
    183         *q++ = '\0';
    184 
    185         for (j = 0; p + j < q; j++) {
    186             if (argv[i][j] >= 'A' && argv[i][j] <= 'Z') {
    187                 argv[i][j] |= 0x20;
    188             }
    189         }
    190 
    191         if (strcmp(p, "mode") == 0) {
    192             if (strcmp(q, "file") == 0) {
    193                 opt.mode = MODE_FILE;
    194             } else if (strcmp(q, "ssl") == 0) {
    195                 opt.mode = MODE_SSL;
    196             } else {
    197                 goto usage;
    198             }
    199         } else if (strcmp(p, "filename") == 0) {
    200             opt.filename = q;
    201         } else if (strcmp(p, "ca_file") == 0) {
    202             opt.ca_file = q;
    203         } else if (strcmp(p, "crl_file") == 0) {
    204             opt.crl_file = q;
    205         } else if (strcmp(p, "ca_path") == 0) {
    206             opt.ca_path = q;
    207         } else if (strcmp(p, "server_name") == 0) {
    208             opt.server_name = q;
    209         } else if (strcmp(p, "server_port") == 0) {
    210             opt.server_port = q;
    211         } else if (strcmp(p, "debug_level") == 0) {
    212             opt.debug_level = atoi(q);
    213             if (opt.debug_level < 0 || opt.debug_level > 65535) {
    214                 goto usage;
    215             }
    216         } else if (strcmp(p, "permissive") == 0) {
    217             opt.permissive = atoi(q);
    218             if (opt.permissive < 0 || opt.permissive > 1) {
    219                 goto usage;
    220             }
    221         } else {
    222             goto usage;
    223         }
    224     }
    225 
    226     /*
    227      * 1.1. Load the trusted CA
    228      */
    229     mbedtls_printf("  . Loading the CA root certificate ...");
    230     fflush(stdout);
    231 
    232     if (strlen(opt.ca_path)) {
    233         if ((ret = mbedtls_x509_crt_parse_path(&cacert, opt.ca_path)) < 0) {
    234             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_path returned -0x%x\n\n",
    235                            (unsigned int) -ret);
    236             goto exit;
    237         }
    238 
    239         verify = 1;
    240     } else if (strlen(opt.ca_file)) {
    241         if ((ret = mbedtls_x509_crt_parse_file(&cacert, opt.ca_file)) < 0) {
    242             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_file returned -0x%x\n\n",
    243                            (unsigned int) -ret);
    244             goto exit;
    245         }
    246 
    247         verify = 1;
    248     }
    249 
    250     mbedtls_printf(" ok (%d skipped)\n", ret);
    251 
    252 #if defined(MBEDTLS_X509_CRL_PARSE_C)
    253     if (strlen(opt.crl_file)) {
    254         if ((ret = mbedtls_x509_crl_parse_file(&cacrl, opt.crl_file)) != 0) {
    255             mbedtls_printf(" failed\n  !  mbedtls_x509_crl_parse returned -0x%x\n\n",
    256                            (unsigned int) -ret);
    257             goto exit;
    258         }
    259 
    260         verify = 1;
    261     }
    262 #endif
    263 
    264     if (opt.mode == MODE_FILE) {
    265         mbedtls_x509_crt crt;
    266         mbedtls_x509_crt *cur = &crt;
    267         mbedtls_x509_crt_init(&crt);
    268 
    269         /*
    270          * 1.1. Load the certificate(s)
    271          */
    272         mbedtls_printf("\n  . Loading the certificate(s) ...");
    273         fflush(stdout);
    274 
    275         ret = mbedtls_x509_crt_parse_file(&crt, opt.filename);
    276 
    277         if (ret < 0) {
    278             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret);
    279             mbedtls_x509_crt_free(&crt);
    280             goto exit;
    281         }
    282 
    283         if (opt.permissive == 0 && ret > 0) {
    284             mbedtls_printf(
    285                 " failed\n  !  mbedtls_x509_crt_parse failed to parse %d certificates\n\n",
    286                 ret);
    287             mbedtls_x509_crt_free(&crt);
    288             goto exit;
    289         }
    290 
    291         mbedtls_printf(" ok\n");
    292 
    293         /*
    294          * 1.2 Print the certificate(s)
    295          */
    296         while (cur != NULL) {
    297             mbedtls_printf("  . Peer certificate information    ...\n");
    298             ret = mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ",
    299                                         cur);
    300             if (ret == -1) {
    301                 mbedtls_printf(" failed\n  !  mbedtls_x509_crt_info returned %d\n\n", ret);
    302                 mbedtls_x509_crt_free(&crt);
    303                 goto exit;
    304             }
    305 
    306             mbedtls_printf("%s\n", buf);
    307 
    308             cur = cur->next;
    309         }
    310 
    311         /*
    312          * 1.3 Verify the certificate
    313          */
    314         if (verify) {
    315             mbedtls_printf("  . Verifying X.509 certificate...");
    316 
    317             if ((ret = mbedtls_x509_crt_verify(&crt, &cacert, &cacrl, NULL, &flags,
    318                                                my_verify, NULL)) != 0) {
    319                 char vrfy_buf[512];
    320 
    321                 mbedtls_printf(" failed\n");
    322 
    323                 mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
    324 
    325                 mbedtls_printf("%s\n", vrfy_buf);
    326             } else {
    327                 mbedtls_printf(" ok\n");
    328             }
    329         }
    330 
    331         mbedtls_x509_crt_free(&crt);
    332     } else if (opt.mode == MODE_SSL) {
    333         /*
    334          * 1. Initialize the RNG and the session data
    335          */
    336         mbedtls_printf("\n  . Seeding the random number generator...");
    337         fflush(stdout);
    338 
    339         if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
    340                                          (const unsigned char *) pers,
    341                                          strlen(pers))) != 0) {
    342             mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
    343             goto ssl_exit;
    344         }
    345 
    346         mbedtls_printf(" ok\n");
    347 
    348 #if defined(MBEDTLS_DEBUG_C)
    349         mbedtls_debug_set_threshold(opt.debug_level);
    350 #endif
    351 
    352         /*
    353          * 2. Start the connection
    354          */
    355         mbedtls_printf("  . SSL connection to tcp/%s/%s...", opt.server_name,
    356                        opt.server_port);
    357         fflush(stdout);
    358 
    359         if ((ret = mbedtls_net_connect(&server_fd, opt.server_name,
    360                                        opt.server_port, MBEDTLS_NET_PROTO_TCP)) != 0) {
    361             mbedtls_printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
    362             goto ssl_exit;
    363         }
    364 
    365         /*
    366          * 3. Setup stuff
    367          */
    368         if ((ret = mbedtls_ssl_config_defaults(&conf,
    369                                                MBEDTLS_SSL_IS_CLIENT,
    370                                                MBEDTLS_SSL_TRANSPORT_STREAM,
    371                                                MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
    372             mbedtls_printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
    373             goto exit;
    374         }
    375 
    376         if (verify) {
    377             mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    378             mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    379             mbedtls_ssl_conf_verify(&conf, my_verify, NULL);
    380         } else {
    381             mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
    382         }
    383 
    384         mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
    385         mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
    386 
    387         if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
    388             mbedtls_printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
    389             goto ssl_exit;
    390         }
    391 
    392         if ((ret = mbedtls_ssl_set_hostname(&ssl, opt.server_name)) != 0) {
    393             mbedtls_printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
    394             goto ssl_exit;
    395         }
    396 
    397         mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
    398 
    399         /*
    400          * 4. Handshake
    401          */
    402         while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
    403             if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
    404                 mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned %d\n\n", ret);
    405                 goto ssl_exit;
    406             }
    407         }
    408 
    409         mbedtls_printf(" ok\n");
    410 
    411         /*
    412          * 5. Print the certificate
    413          */
    414 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
    415         mbedtls_printf("  . Peer certificate information    ... skipped\n");
    416 #else
    417         mbedtls_printf("  . Peer certificate information    ...\n");
    418         ret = mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ",
    419                                     mbedtls_ssl_get_peer_cert(&ssl));
    420         if (ret == -1) {
    421             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_info returned %d\n\n", ret);
    422             goto ssl_exit;
    423         }
    424 
    425         mbedtls_printf("%s\n", buf);
    426 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
    427 
    428         mbedtls_ssl_close_notify(&ssl);
    429 
    430 ssl_exit:
    431         mbedtls_ssl_free(&ssl);
    432         mbedtls_ssl_config_free(&conf);
    433     } else {
    434         goto usage;
    435     }
    436 
    437     exit_code = MBEDTLS_EXIT_SUCCESS;
    438 
    439 exit:
    440 
    441     mbedtls_net_free(&server_fd);
    442     mbedtls_x509_crt_free(&cacert);
    443 #if defined(MBEDTLS_X509_CRL_PARSE_C)
    444     mbedtls_x509_crl_free(&cacrl);
    445 #endif
    446     mbedtls_ctr_drbg_free(&ctr_drbg);
    447     mbedtls_entropy_free(&entropy);
    448 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    449     mbedtls_psa_crypto_free();
    450 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    451 
    452     mbedtls_exit(exit_code);
    453 }
    454 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
    455           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
    456           MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */