quickjs-tart

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

gen_key.c (14725B)


      1 /*
      2  *  Key generation 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_PK_WRITE_C) || !defined(MBEDTLS_PEM_WRITE_C) ||    \
     13     !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_ENTROPY_C) ||           \
     14     !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_BIGNUM_C)
     15 int main(void)
     16 {
     17     mbedtls_printf("MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO and/or "
     18                    "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
     19                    "MBEDTLS_PEM_WRITE_C and/or MBEDTLS_BIGNUM_C "
     20                    "not defined.\n");
     21     mbedtls_exit(0);
     22 }
     23 #else
     24 
     25 #include "mbedtls/error.h"
     26 #include "mbedtls/pk.h"
     27 #include "mbedtls/ecdsa.h"
     28 #include "mbedtls/rsa.h"
     29 #include "mbedtls/error.h"
     30 #include "mbedtls/entropy.h"
     31 #include "mbedtls/ctr_drbg.h"
     32 
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 
     37 #if !defined(_WIN32)
     38 #include <unistd.h>
     39 
     40 #define DEV_RANDOM_THRESHOLD        32
     41 
     42 static int dev_random_entropy_poll(void *data, unsigned char *output,
     43                                    size_t len, size_t *olen)
     44 {
     45     FILE *file;
     46     size_t ret, left = len;
     47     unsigned char *p = output;
     48     ((void) data);
     49 
     50     *olen = 0;
     51 
     52     file = fopen("/dev/random", "rb");
     53     if (file == NULL) {
     54         return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     55     }
     56 
     57     while (left > 0) {
     58         /* /dev/random can return much less than requested. If so, try again */
     59         ret = fread(p, 1, left, file);
     60         if (ret == 0 && ferror(file)) {
     61             fclose(file);
     62             return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     63         }
     64 
     65         p += ret;
     66         left -= ret;
     67         sleep(1);
     68     }
     69     fclose(file);
     70     *olen = len;
     71 
     72     return 0;
     73 }
     74 #endif /* !_WIN32 */
     75 
     76 #if defined(MBEDTLS_ECP_C)
     77 #define DFL_EC_CURVE            mbedtls_ecp_curve_list()->grp_id
     78 #else
     79 #define DFL_EC_CURVE            0
     80 #endif
     81 
     82 #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
     83 #define USAGE_DEV_RANDOM \
     84     "    use_dev_random=0|1    default: 0\n"
     85 #else
     86 #define USAGE_DEV_RANDOM ""
     87 #endif /* !_WIN32 && MBEDTLS_FS_IO */
     88 
     89 #define FORMAT_PEM              0
     90 #define FORMAT_DER              1
     91 
     92 #define DFL_TYPE                MBEDTLS_PK_RSA
     93 #define DFL_RSA_KEYSIZE         4096
     94 #define DFL_FILENAME            "keyfile.key"
     95 #define DFL_FORMAT              FORMAT_PEM
     96 #define DFL_USE_DEV_RANDOM      0
     97 
     98 #define USAGE \
     99     "\n usage: gen_key param=<>...\n"                   \
    100     "\n acceptable parameters:\n"                       \
    101     "    type=rsa|ec           default: rsa\n"          \
    102     "    rsa_keysize=%%d        default: 4096\n"        \
    103     "    ec_curve=%%s           see below\n"            \
    104     "    filename=%%s           default: keyfile.key\n" \
    105     "    format=pem|der        default: pem\n"          \
    106     USAGE_DEV_RANDOM                                    \
    107     "\n"
    108 
    109 
    110 /*
    111  * global options
    112  */
    113 struct options {
    114     int type;                   /* the type of key to generate          */
    115     int rsa_keysize;            /* length of key in bits                */
    116     int ec_curve;               /* curve identifier for EC keys         */
    117     const char *filename;       /* filename of the key file             */
    118     int format;                 /* the output format to use             */
    119     int use_dev_random;         /* use /dev/random as entropy source    */
    120 } opt;
    121 
    122 static int write_private_key(mbedtls_pk_context *key, const char *output_file)
    123 {
    124     int ret;
    125     FILE *f;
    126     unsigned char output_buf[16000];
    127     unsigned char *c = output_buf;
    128     size_t len = 0;
    129 
    130     memset(output_buf, 0, 16000);
    131     if (opt.format == FORMAT_PEM) {
    132         if ((ret = mbedtls_pk_write_key_pem(key, output_buf, 16000)) != 0) {
    133             return ret;
    134         }
    135 
    136         len = strlen((char *) output_buf);
    137     } else {
    138         if ((ret = mbedtls_pk_write_key_der(key, output_buf, 16000)) < 0) {
    139             return ret;
    140         }
    141 
    142         len = ret;
    143         c = output_buf + sizeof(output_buf) - len;
    144     }
    145 
    146     if ((f = fopen(output_file, "wb")) == NULL) {
    147         return -1;
    148     }
    149 
    150     if (fwrite(c, 1, len, f) != len) {
    151         fclose(f);
    152         return -1;
    153     }
    154 
    155     fclose(f);
    156 
    157     return 0;
    158 }
    159 
    160 #if defined(MBEDTLS_ECP_C)
    161 static int show_ecp_key(const mbedtls_ecp_keypair *ecp, int has_private)
    162 {
    163     int ret = 0;
    164 
    165     const mbedtls_ecp_curve_info *curve_info =
    166         mbedtls_ecp_curve_info_from_grp_id(
    167             mbedtls_ecp_keypair_get_group_id(ecp));
    168     mbedtls_printf("curve: %s\n", curve_info->name);
    169 
    170     mbedtls_ecp_group grp;
    171     mbedtls_ecp_group_init(&grp);
    172     mbedtls_mpi D;
    173     mbedtls_mpi_init(&D);
    174     mbedtls_ecp_point pt;
    175     mbedtls_ecp_point_init(&pt);
    176     mbedtls_mpi X, Y;
    177     mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y);
    178 
    179     MBEDTLS_MPI_CHK(mbedtls_ecp_export(ecp, &grp,
    180                                        (has_private ? &D : NULL),
    181                                        &pt));
    182 
    183     unsigned char point_bin[MBEDTLS_ECP_MAX_PT_LEN];
    184     size_t len = 0;
    185     MBEDTLS_MPI_CHK(mbedtls_ecp_point_write_binary(
    186                         &grp, &pt, MBEDTLS_ECP_PF_UNCOMPRESSED,
    187                         &len, point_bin, sizeof(point_bin)));
    188     switch (mbedtls_ecp_get_type(&grp)) {
    189         case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
    190             if ((len & 1) == 0 || point_bin[0] != 0x04) {
    191                 /* Point in an unxepected format. This shouldn't happen. */
    192                 ret = -1;
    193                 goto cleanup;
    194             }
    195             MBEDTLS_MPI_CHK(
    196                 mbedtls_mpi_read_binary(&X, point_bin + 1, len / 2));
    197             MBEDTLS_MPI_CHK(
    198                 mbedtls_mpi_read_binary(&Y, point_bin + 1 + len / 2, len / 2));
    199             mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
    200             mbedtls_mpi_write_file("Y_Q:   ", &Y, 16, NULL);
    201             break;
    202         case MBEDTLS_ECP_TYPE_MONTGOMERY:
    203             MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, point_bin, len));
    204             mbedtls_mpi_write_file("X_Q:   ", &X, 16, NULL);
    205             break;
    206         default:
    207             mbedtls_printf(
    208                 "This program does not yet support listing coordinates for this curve type.\n");
    209             break;
    210     }
    211 
    212     if (has_private) {
    213         mbedtls_mpi_write_file("D:     ", &D, 16, NULL);
    214     }
    215 
    216 cleanup:
    217     mbedtls_ecp_group_free(&grp);
    218     mbedtls_mpi_free(&D);
    219     mbedtls_ecp_point_free(&pt);
    220     mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y);
    221     return ret;
    222 }
    223 #endif
    224 
    225 int main(int argc, char *argv[])
    226 {
    227     int ret = 1;
    228     int exit_code = MBEDTLS_EXIT_FAILURE;
    229     mbedtls_pk_context key;
    230     char buf[1024];
    231     int i;
    232     char *p, *q;
    233 #if defined(MBEDTLS_RSA_C)
    234     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
    235 #endif /* MBEDTLS_RSA_C */
    236     mbedtls_entropy_context entropy;
    237     mbedtls_ctr_drbg_context ctr_drbg;
    238     const char *pers = "gen_key";
    239 #if defined(MBEDTLS_ECP_C)
    240     const mbedtls_ecp_curve_info *curve_info;
    241 #endif
    242 
    243     /*
    244      * Set to sane values
    245      */
    246 #if defined(MBEDTLS_RSA_C)
    247     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
    248     mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
    249     mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
    250 #endif /* MBEDTLS_RSA_C */
    251 
    252     mbedtls_entropy_init(&entropy);
    253     mbedtls_pk_init(&key);
    254     mbedtls_ctr_drbg_init(&ctr_drbg);
    255     memset(buf, 0, sizeof(buf));
    256 
    257 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    258     psa_status_t status = psa_crypto_init();
    259     if (status != PSA_SUCCESS) {
    260         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
    261                         (int) status);
    262         goto exit;
    263     }
    264 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    265 
    266     if (argc < 2) {
    267 usage:
    268         mbedtls_printf(USAGE);
    269 #if defined(MBEDTLS_ECP_C)
    270         mbedtls_printf(" available ec_curve values:\n");
    271         curve_info = mbedtls_ecp_curve_list();
    272         mbedtls_printf("    %s (default)\n", curve_info->name);
    273         while ((++curve_info)->name != NULL) {
    274             mbedtls_printf("    %s\n", curve_info->name);
    275         }
    276 #endif /* MBEDTLS_ECP_C */
    277         goto exit;
    278     }
    279 
    280     opt.type                = DFL_TYPE;
    281     opt.rsa_keysize         = DFL_RSA_KEYSIZE;
    282     opt.ec_curve            = DFL_EC_CURVE;
    283     opt.filename            = DFL_FILENAME;
    284     opt.format              = DFL_FORMAT;
    285     opt.use_dev_random      = DFL_USE_DEV_RANDOM;
    286 
    287     for (i = 1; i < argc; i++) {
    288         p = argv[i];
    289         if ((q = strchr(p, '=')) == NULL) {
    290             goto usage;
    291         }
    292         *q++ = '\0';
    293 
    294         if (strcmp(p, "type") == 0) {
    295             if (strcmp(q, "rsa") == 0) {
    296                 opt.type = MBEDTLS_PK_RSA;
    297             } else if (strcmp(q, "ec") == 0) {
    298                 opt.type = MBEDTLS_PK_ECKEY;
    299             } else {
    300                 goto usage;
    301             }
    302         } else if (strcmp(p, "format") == 0) {
    303             if (strcmp(q, "pem") == 0) {
    304                 opt.format = FORMAT_PEM;
    305             } else if (strcmp(q, "der") == 0) {
    306                 opt.format = FORMAT_DER;
    307             } else {
    308                 goto usage;
    309             }
    310         } else if (strcmp(p, "rsa_keysize") == 0) {
    311             opt.rsa_keysize = atoi(q);
    312             if (opt.rsa_keysize < 1024 ||
    313                 opt.rsa_keysize > MBEDTLS_MPI_MAX_BITS) {
    314                 goto usage;
    315             }
    316         }
    317 #if defined(MBEDTLS_ECP_C)
    318         else if (strcmp(p, "ec_curve") == 0) {
    319             if ((curve_info = mbedtls_ecp_curve_info_from_name(q)) == NULL) {
    320                 goto usage;
    321             }
    322             opt.ec_curve = curve_info->grp_id;
    323         }
    324 #endif
    325         else if (strcmp(p, "filename") == 0) {
    326             opt.filename = q;
    327         } else if (strcmp(p, "use_dev_random") == 0) {
    328             opt.use_dev_random = atoi(q);
    329             if (opt.use_dev_random < 0 || opt.use_dev_random > 1) {
    330                 goto usage;
    331             }
    332         } else {
    333             goto usage;
    334         }
    335     }
    336 
    337     mbedtls_printf("\n  . Seeding the random number generator...");
    338     fflush(stdout);
    339 
    340 #if !defined(_WIN32) && defined(MBEDTLS_FS_IO)
    341     if (opt.use_dev_random) {
    342         if ((ret = mbedtls_entropy_add_source(&entropy, dev_random_entropy_poll,
    343                                               NULL, DEV_RANDOM_THRESHOLD,
    344                                               MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0) {
    345             mbedtls_printf(" failed\n  ! mbedtls_entropy_add_source returned -0x%04x\n",
    346                            (unsigned int) -ret);
    347             goto exit;
    348         }
    349 
    350         mbedtls_printf("\n    Using /dev/random, so can take a long time! ");
    351         fflush(stdout);
    352     }
    353 #endif /* !_WIN32 && MBEDTLS_FS_IO */
    354 
    355     if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
    356                                      (const unsigned char *) pers,
    357                                      strlen(pers))) != 0) {
    358         mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned -0x%04x\n",
    359                        (unsigned int) -ret);
    360         goto exit;
    361     }
    362 
    363     /*
    364      * 1.1. Generate the key
    365      */
    366     mbedtls_printf("\n  . Generating the private key ...");
    367     fflush(stdout);
    368 
    369     if ((ret = mbedtls_pk_setup(&key,
    370                                 mbedtls_pk_info_from_type((mbedtls_pk_type_t) opt.type))) != 0) {
    371         mbedtls_printf(" failed\n  !  mbedtls_pk_setup returned -0x%04x", (unsigned int) -ret);
    372         goto exit;
    373     }
    374 
    375 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
    376     if (opt.type == MBEDTLS_PK_RSA) {
    377         ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(key), mbedtls_ctr_drbg_random, &ctr_drbg,
    378                                   opt.rsa_keysize, 65537);
    379         if (ret != 0) {
    380             mbedtls_printf(" failed\n  !  mbedtls_rsa_gen_key returned -0x%04x",
    381                            (unsigned int) -ret);
    382             goto exit;
    383         }
    384     } else
    385 #endif /* MBEDTLS_RSA_C */
    386 #if defined(MBEDTLS_ECP_C)
    387     if (opt.type == MBEDTLS_PK_ECKEY) {
    388         ret = mbedtls_ecp_gen_key((mbedtls_ecp_group_id) opt.ec_curve,
    389                                   mbedtls_pk_ec(key),
    390                                   mbedtls_ctr_drbg_random, &ctr_drbg);
    391         if (ret != 0) {
    392             mbedtls_printf(" failed\n  !  mbedtls_ecp_gen_key returned -0x%04x",
    393                            (unsigned int) -ret);
    394             goto exit;
    395         }
    396     } else
    397 #endif /* MBEDTLS_ECP_C */
    398     {
    399         mbedtls_printf(" failed\n  !  key type not supported\n");
    400         goto exit;
    401     }
    402 
    403     /*
    404      * 1.2 Print the key
    405      */
    406     mbedtls_printf(" ok\n  . Key information:\n");
    407 
    408 #if defined(MBEDTLS_RSA_C)
    409     if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) {
    410         mbedtls_rsa_context *rsa = mbedtls_pk_rsa(key);
    411 
    412         if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
    413             (ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP))      != 0) {
    414             mbedtls_printf(" failed\n  ! could not export RSA parameters\n\n");
    415             goto exit;
    416         }
    417 
    418         mbedtls_mpi_write_file("N:  ",  &N,  16, NULL);
    419         mbedtls_mpi_write_file("E:  ",  &E,  16, NULL);
    420         mbedtls_mpi_write_file("D:  ",  &D,  16, NULL);
    421         mbedtls_mpi_write_file("P:  ",  &P,  16, NULL);
    422         mbedtls_mpi_write_file("Q:  ",  &Q,  16, NULL);
    423         mbedtls_mpi_write_file("DP: ",  &DP, 16, NULL);
    424         mbedtls_mpi_write_file("DQ:  ", &DQ, 16, NULL);
    425         mbedtls_mpi_write_file("QP:  ", &QP, 16, NULL);
    426     } else
    427 #endif
    428 #if defined(MBEDTLS_ECP_C)
    429     if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) {
    430         if (show_ecp_key(mbedtls_pk_ec(key), 1) != 0) {
    431             mbedtls_printf(" failed\n  ! could not export ECC parameters\n\n");
    432             goto exit;
    433         }
    434     } else
    435 #endif
    436     mbedtls_printf("  ! key type not supported\n");
    437 
    438     /*
    439      * 1.3 Export key
    440      */
    441     mbedtls_printf("  . Writing key to file...");
    442 
    443     if ((ret = write_private_key(&key, opt.filename)) != 0) {
    444         mbedtls_printf(" failed\n");
    445         goto exit;
    446     }
    447 
    448     mbedtls_printf(" ok\n");
    449 
    450     exit_code = MBEDTLS_EXIT_SUCCESS;
    451 
    452 exit:
    453 
    454     if (exit_code != MBEDTLS_EXIT_SUCCESS) {
    455 #ifdef MBEDTLS_ERROR_C
    456         mbedtls_strerror(ret, buf, sizeof(buf));
    457         mbedtls_printf(" - %s\n", buf);
    458 #else
    459         mbedtls_printf("\n");
    460 #endif
    461     }
    462 
    463 #if defined(MBEDTLS_RSA_C)
    464     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
    465     mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
    466     mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
    467 #endif /* MBEDTLS_RSA_C */
    468 
    469     mbedtls_pk_free(&key);
    470     mbedtls_ctr_drbg_free(&ctr_drbg);
    471     mbedtls_entropy_free(&entropy);
    472 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    473     mbedtls_psa_crypto_free();
    474 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    475 
    476     mbedtls_exit(exit_code);
    477 }
    478 #endif /* program viability conditions */