quickjs-tart

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

cert_write.c (41221B)


      1 /*
      2  *  Certificate generation and signing
      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_X509_CRT_WRITE_C) || \
     15     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
     16     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
     17     !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_MD_CAN_SHA256) || \
     18     !defined(MBEDTLS_PEM_WRITE_C) || !defined(MBEDTLS_MD_C)
     19 int main(void)
     20 {
     21     mbedtls_printf("MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
     22                    "MBEDTLS_FS_IO and/or MBEDTLS_MD_CAN_SHA256 and/or "
     23                    "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
     24                    "MBEDTLS_ERROR_C not defined.\n");
     25     mbedtls_exit(0);
     26 }
     27 #else
     28 
     29 #include "mbedtls/x509_crt.h"
     30 #include "mbedtls/x509_csr.h"
     31 #include "mbedtls/oid.h"
     32 #include "mbedtls/entropy.h"
     33 #include "mbedtls/ctr_drbg.h"
     34 #include "mbedtls/error.h"
     35 #include "test/helpers.h"
     36 
     37 #include <stdio.h>
     38 #include <stdlib.h>
     39 #include <string.h>
     40 #include <errno.h>
     41 
     42 #define SET_OID(x, oid) \
     43     do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char *) oid; } while (0)
     44 
     45 #if defined(MBEDTLS_X509_CSR_PARSE_C)
     46 #define USAGE_CSR                                                           \
     47     "    request_file=%%s         default: (empty)\n"                           \
     48     "                            If request_file is specified, subject_key,\n"  \
     49     "                            subject_pwd and subject_name are ignored!\n"
     50 #else
     51 #define USAGE_CSR ""
     52 #endif /* MBEDTLS_X509_CSR_PARSE_C */
     53 
     54 #define FORMAT_PEM              0
     55 #define FORMAT_DER              1
     56 
     57 #define DFL_ISSUER_CRT          ""
     58 #define DFL_REQUEST_FILE        ""
     59 #define DFL_SUBJECT_KEY         "subject.key"
     60 #define DFL_ISSUER_KEY          "ca.key"
     61 #define DFL_SUBJECT_PWD         ""
     62 #define DFL_ISSUER_PWD          ""
     63 #define DFL_OUTPUT_FILENAME     "cert.crt"
     64 #define DFL_SUBJECT_NAME        "CN=Cert,O=mbed TLS,C=UK"
     65 #define DFL_ISSUER_NAME         "CN=CA,O=mbed TLS,C=UK"
     66 #define DFL_NOT_BEFORE          "20010101000000"
     67 #define DFL_NOT_AFTER           "20301231235959"
     68 #define DFL_SERIAL              "1"
     69 #define DFL_SERIAL_HEX          "1"
     70 #define DFL_EXT_SUBJECTALTNAME  ""
     71 #define DFL_SELFSIGN            0
     72 #define DFL_IS_CA               0
     73 #define DFL_MAX_PATHLEN         -1
     74 #define DFL_SIG_ALG             MBEDTLS_MD_SHA256
     75 #define DFL_KEY_USAGE           0
     76 #define DFL_EXT_KEY_USAGE       NULL
     77 #define DFL_NS_CERT_TYPE        0
     78 #define DFL_VERSION             3
     79 #define DFL_AUTH_IDENT          1
     80 #define DFL_SUBJ_IDENT          1
     81 #define DFL_CONSTRAINTS         1
     82 #define DFL_DIGEST              MBEDTLS_MD_SHA256
     83 #define DFL_FORMAT              FORMAT_PEM
     84 
     85 #define USAGE \
     86     "\n usage: cert_write param=<>...\n"                \
     87     "\n acceptable parameters:\n"                       \
     88     USAGE_CSR                                           \
     89     "    subject_key=%%s          default: subject.key\n"   \
     90     "    subject_pwd=%%s          default: (empty)\n"       \
     91     "    subject_name=%%s         default: CN=Cert,O=mbed TLS,C=UK\n"   \
     92     "\n"                                                \
     93     "    issuer_crt=%%s           default: (empty)\n"       \
     94     "                            If issuer_crt is specified, issuer_name is\n"  \
     95     "                            ignored!\n"                \
     96     "    issuer_name=%%s          default: CN=CA,O=mbed TLS,C=UK\n"     \
     97     "\n"                                                \
     98     "    selfsign=%%d             default: 0 (false)\n"     \
     99     "                            If selfsign is enabled, issuer_name and\n" \
    100     "                            issuer_key are required (issuer_crt and\n" \
    101     "                            subject_* are ignored\n"   \
    102     "    issuer_key=%%s           default: ca.key\n"        \
    103     "    issuer_pwd=%%s           default: (empty)\n"       \
    104     "    output_file=%%s          default: cert.crt\n"      \
    105     "    serial=%%s               default: 1\n"             \
    106     "                            In decimal format; it can be used as\n"     \
    107     "                            alternative to serial_hex, but it's\n"      \
    108     "                            limited in max length to\n"                 \
    109     "                            unsigned long long int\n"                   \
    110     "    serial_hex=%%s           default: 1\n"             \
    111     "                            In hex format; it can be used as\n"         \
    112     "                            alternative to serial\n"                    \
    113     "    not_before=%%s           default: 20010101000000\n" \
    114     "    not_after=%%s            default: 20301231235959\n" \
    115     "    is_ca=%%d                default: 0 (disabled)\n"  \
    116     "    max_pathlen=%%d          default: -1 (none)\n"     \
    117     "    md=%%s                   default: SHA256\n"        \
    118     "                            Supported values (if enabled):\n"      \
    119     "                            MD5, RIPEMD160, SHA1,\n" \
    120     "                            SHA224, SHA256, SHA384, SHA512\n" \
    121     "    version=%%d              default: 3\n"            \
    122     "                            Possible values: 1, 2, 3\n" \
    123     "    subject_identifier=%%s   default: 1\n"             \
    124     "                            Possible values: 0, 1\n"   \
    125     "                            (Considered for v3 only)\n" \
    126     "    san=%%s                   default: (none)\n"       \
    127     "                            Semicolon-separated-list of values:\n" \
    128     "                             DNS:value\n"            \
    129     "                             URI:value\n"            \
    130     "                             RFC822:value\n"         \
    131     "                             IP:value (Only IPv4 is supported)\n" \
    132     "                             DN:list of comma separated key=value pairs\n" \
    133     "    authority_identifier=%%s default: 1\n"             \
    134     "                            Possible values: 0, 1\n"   \
    135     "                            (Considered for v3 only)\n" \
    136     "    basic_constraints=%%d    default: 1\n"             \
    137     "                            Possible values: 0, 1\n"   \
    138     "                            (Considered for v3 only)\n" \
    139     "    key_usage=%%s            default: (empty)\n"       \
    140     "                            Comma-separated-list of values:\n"     \
    141     "                            digital_signature\n"     \
    142     "                            non_repudiation\n"       \
    143     "                            key_encipherment\n"      \
    144     "                            data_encipherment\n"     \
    145     "                            key_agreement\n"         \
    146     "                            key_cert_sign\n"  \
    147     "                            crl_sign\n"              \
    148     "                            (Considered for v3 only)\n" \
    149     "    ext_key_usage=%%s        default: (empty)\n"      \
    150     "                            Comma-separated-list of values:\n"     \
    151     "                            serverAuth\n"             \
    152     "                            clientAuth\n"             \
    153     "                            codeSigning\n"            \
    154     "                            emailProtection\n"        \
    155     "                            timeStamping\n"           \
    156     "                            OCSPSigning\n"            \
    157     "    ns_cert_type=%%s         default: (empty)\n"       \
    158     "                            Comma-separated-list of values:\n"     \
    159     "                            ssl_client\n"            \
    160     "                            ssl_server\n"            \
    161     "                            email\n"                 \
    162     "                            object_signing\n"        \
    163     "                            ssl_ca\n"                \
    164     "                            email_ca\n"              \
    165     "                            object_signing_ca\n"     \
    166     "   format=pem|der           default: pem\n"         \
    167     "\n"
    168 
    169 typedef enum {
    170     SERIAL_FRMT_UNSPEC,
    171     SERIAL_FRMT_DEC,
    172     SERIAL_FRMT_HEX
    173 } serial_format_t;
    174 
    175 /*
    176  * global options
    177  */
    178 struct options {
    179     const char *issuer_crt;     /* filename of the issuer certificate   */
    180     const char *request_file;   /* filename of the certificate request  */
    181     const char *subject_key;    /* filename of the subject key file     */
    182     const char *issuer_key;     /* filename of the issuer key file      */
    183     const char *subject_pwd;    /* password for the subject key file    */
    184     const char *issuer_pwd;     /* password for the issuer key file     */
    185     const char *output_file;    /* where to store the constructed CRT   */
    186     const char *subject_name;   /* subject name for certificate         */
    187     mbedtls_x509_san_list *san_list; /* subjectAltName for certificate  */
    188     const char *issuer_name;    /* issuer name for certificate          */
    189     const char *not_before;     /* validity period not before           */
    190     const char *not_after;      /* validity period not after            */
    191     const char *serial;         /* serial number string (decimal)       */
    192     const char *serial_hex;     /* serial number string (hex)           */
    193     int selfsign;               /* selfsign the certificate             */
    194     int is_ca;                  /* is a CA certificate                  */
    195     int max_pathlen;            /* maximum CA path length               */
    196     int authority_identifier;   /* add authority identifier to CRT      */
    197     int subject_identifier;     /* add subject identifier to CRT        */
    198     int basic_constraints;      /* add basic constraints ext to CRT     */
    199     int version;                /* CRT version                          */
    200     mbedtls_md_type_t md;       /* Hash used for signing                */
    201     unsigned char key_usage;    /* key usage flags                      */
    202     mbedtls_asn1_sequence *ext_key_usage; /* extended key usages        */
    203     unsigned char ns_cert_type; /* NS cert type                         */
    204     int format;                 /* format                               */
    205 } opt;
    206 
    207 static int write_certificate(mbedtls_x509write_cert *crt, const char *output_file,
    208                              int (*f_rng)(void *, unsigned char *, size_t),
    209                              void *p_rng)
    210 {
    211     int ret;
    212     FILE *f;
    213     unsigned char output_buf[4096];
    214     unsigned char *output_start;
    215     size_t len = 0;
    216 
    217     memset(output_buf, 0, 4096);
    218     if (opt.format == FORMAT_DER) {
    219         ret = mbedtls_x509write_crt_der(crt, output_buf, 4096,
    220                                         f_rng, p_rng);
    221         if (ret < 0) {
    222             return ret;
    223         }
    224 
    225         len = ret;
    226         output_start = output_buf + 4096 - len;
    227     } else {
    228         ret = mbedtls_x509write_crt_pem(crt, output_buf, 4096,
    229                                         f_rng, p_rng);
    230         if (ret < 0) {
    231             return ret;
    232         }
    233 
    234         len = strlen((char *) output_buf);
    235         output_start = output_buf;
    236     }
    237 
    238     if ((f = fopen(output_file, "w")) == NULL) {
    239         return -1;
    240     }
    241 
    242     if (fwrite(output_start, 1, len, f) != len) {
    243         fclose(f);
    244         return -1;
    245     }
    246 
    247     fclose(f);
    248 
    249     return 0;
    250 }
    251 
    252 static int parse_serial_decimal_format(unsigned char *obuf, size_t obufmax,
    253                                        const char *ibuf, size_t *len)
    254 {
    255     unsigned long long int dec;
    256     unsigned int remaining_bytes = sizeof(dec);
    257     unsigned char *p = obuf;
    258     unsigned char val;
    259     char *end_ptr = NULL;
    260 
    261     errno = 0;
    262     dec = strtoull(ibuf, &end_ptr, 10);
    263 
    264     if ((errno != 0) || (end_ptr == ibuf)) {
    265         return -1;
    266     }
    267 
    268     *len = 0;
    269 
    270     while (remaining_bytes > 0) {
    271         if (obufmax < (*len + 1)) {
    272             return -1;
    273         }
    274 
    275         val = (dec >> ((remaining_bytes - 1) * 8)) & 0xFF;
    276 
    277         /* Skip leading zeros */
    278         if ((val != 0) || (*len != 0)) {
    279             *p = val;
    280             (*len)++;
    281             p++;
    282         }
    283 
    284         remaining_bytes--;
    285     }
    286 
    287     return 0;
    288 }
    289 
    290 int main(int argc, char *argv[])
    291 {
    292     int ret = 1;
    293     int exit_code = MBEDTLS_EXIT_FAILURE;
    294     mbedtls_x509_crt issuer_crt;
    295     mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
    296     mbedtls_pk_context *issuer_key = &loaded_issuer_key,
    297                        *subject_key = &loaded_subject_key;
    298     char buf[1024];
    299     char issuer_name[256];
    300     int i;
    301     char *p, *q, *r;
    302 #if defined(MBEDTLS_X509_CSR_PARSE_C)
    303     char subject_name[256];
    304     mbedtls_x509_csr csr;
    305 #endif
    306     mbedtls_x509write_cert crt;
    307     serial_format_t serial_frmt = SERIAL_FRMT_UNSPEC;
    308     unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
    309     size_t serial_len;
    310     mbedtls_asn1_sequence *ext_key_usage;
    311     mbedtls_entropy_context entropy;
    312     mbedtls_ctr_drbg_context ctr_drbg;
    313     const char *pers = "crt example app";
    314     mbedtls_x509_san_list *cur, *prev;
    315     uint8_t ip[4] = { 0 };
    316     /*
    317      * Set to sane values
    318      */
    319     mbedtls_x509write_crt_init(&crt);
    320     mbedtls_pk_init(&loaded_issuer_key);
    321     mbedtls_pk_init(&loaded_subject_key);
    322     mbedtls_ctr_drbg_init(&ctr_drbg);
    323     mbedtls_entropy_init(&entropy);
    324 #if defined(MBEDTLS_X509_CSR_PARSE_C)
    325     mbedtls_x509_csr_init(&csr);
    326 #endif
    327     mbedtls_x509_crt_init(&issuer_crt);
    328     memset(buf, 0, sizeof(buf));
    329     memset(serial, 0, sizeof(serial));
    330 
    331 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    332     psa_status_t status = psa_crypto_init();
    333     if (status != PSA_SUCCESS) {
    334         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
    335                         (int) status);
    336         goto exit;
    337     }
    338 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    339 
    340     if (argc < 2) {
    341 usage:
    342         mbedtls_printf(USAGE);
    343         goto exit;
    344     }
    345 
    346     opt.issuer_crt          = DFL_ISSUER_CRT;
    347     opt.request_file        = DFL_REQUEST_FILE;
    348     opt.subject_key         = DFL_SUBJECT_KEY;
    349     opt.issuer_key          = DFL_ISSUER_KEY;
    350     opt.subject_pwd         = DFL_SUBJECT_PWD;
    351     opt.issuer_pwd          = DFL_ISSUER_PWD;
    352     opt.output_file         = DFL_OUTPUT_FILENAME;
    353     opt.subject_name        = DFL_SUBJECT_NAME;
    354     opt.issuer_name         = DFL_ISSUER_NAME;
    355     opt.not_before          = DFL_NOT_BEFORE;
    356     opt.not_after           = DFL_NOT_AFTER;
    357     opt.serial              = DFL_SERIAL;
    358     opt.serial_hex          = DFL_SERIAL_HEX;
    359     opt.selfsign            = DFL_SELFSIGN;
    360     opt.is_ca               = DFL_IS_CA;
    361     opt.max_pathlen         = DFL_MAX_PATHLEN;
    362     opt.key_usage           = DFL_KEY_USAGE;
    363     opt.ext_key_usage       = DFL_EXT_KEY_USAGE;
    364     opt.ns_cert_type        = DFL_NS_CERT_TYPE;
    365     opt.version             = DFL_VERSION - 1;
    366     opt.md                  = DFL_DIGEST;
    367     opt.subject_identifier   = DFL_SUBJ_IDENT;
    368     opt.authority_identifier = DFL_AUTH_IDENT;
    369     opt.basic_constraints    = DFL_CONSTRAINTS;
    370     opt.format              = DFL_FORMAT;
    371     opt.san_list            = NULL;
    372 
    373     for (i = 1; i < argc; i++) {
    374 
    375         p = argv[i];
    376         if ((q = strchr(p, '=')) == NULL) {
    377             goto usage;
    378         }
    379         *q++ = '\0';
    380 
    381         if (strcmp(p, "request_file") == 0) {
    382             opt.request_file = q;
    383         } else if (strcmp(p, "subject_key") == 0) {
    384             opt.subject_key = q;
    385         } else if (strcmp(p, "issuer_key") == 0) {
    386             opt.issuer_key = q;
    387         } else if (strcmp(p, "subject_pwd") == 0) {
    388             opt.subject_pwd = q;
    389         } else if (strcmp(p, "issuer_pwd") == 0) {
    390             opt.issuer_pwd = q;
    391         } else if (strcmp(p, "issuer_crt") == 0) {
    392             opt.issuer_crt = q;
    393         } else if (strcmp(p, "output_file") == 0) {
    394             opt.output_file = q;
    395         } else if (strcmp(p, "subject_name") == 0) {
    396             opt.subject_name = q;
    397         } else if (strcmp(p, "issuer_name") == 0) {
    398             opt.issuer_name = q;
    399         } else if (strcmp(p, "not_before") == 0) {
    400             opt.not_before = q;
    401         } else if (strcmp(p, "not_after") == 0) {
    402             opt.not_after = q;
    403         } else if (strcmp(p, "serial") == 0) {
    404             if (serial_frmt != SERIAL_FRMT_UNSPEC) {
    405                 mbedtls_printf("Invalid attempt to set the serial more than once\n");
    406                 goto usage;
    407             }
    408             serial_frmt = SERIAL_FRMT_DEC;
    409             opt.serial = q;
    410         } else if (strcmp(p, "serial_hex") == 0) {
    411             if (serial_frmt != SERIAL_FRMT_UNSPEC) {
    412                 mbedtls_printf("Invalid attempt to set the serial more than once\n");
    413                 goto usage;
    414             }
    415             serial_frmt = SERIAL_FRMT_HEX;
    416             opt.serial_hex = q;
    417         } else if (strcmp(p, "authority_identifier") == 0) {
    418             opt.authority_identifier = atoi(q);
    419             if (opt.authority_identifier != 0 &&
    420                 opt.authority_identifier != 1) {
    421                 mbedtls_printf("Invalid argument for option %s\n", p);
    422                 goto usage;
    423             }
    424         } else if (strcmp(p, "subject_identifier") == 0) {
    425             opt.subject_identifier = atoi(q);
    426             if (opt.subject_identifier != 0 &&
    427                 opt.subject_identifier != 1) {
    428                 mbedtls_printf("Invalid argument for option %s\n", p);
    429                 goto usage;
    430             }
    431         } else if (strcmp(p, "basic_constraints") == 0) {
    432             opt.basic_constraints = atoi(q);
    433             if (opt.basic_constraints != 0 &&
    434                 opt.basic_constraints != 1) {
    435                 mbedtls_printf("Invalid argument for option %s\n", p);
    436                 goto usage;
    437             }
    438         } else if (strcmp(p, "md") == 0) {
    439             const mbedtls_md_info_t *md_info =
    440                 mbedtls_md_info_from_string(q);
    441             if (md_info == NULL) {
    442                 mbedtls_printf("Invalid argument for option %s\n", p);
    443                 goto usage;
    444             }
    445             opt.md = mbedtls_md_get_type(md_info);
    446         } else if (strcmp(p, "version") == 0) {
    447             opt.version = atoi(q);
    448             if (opt.version < 1 || opt.version > 3) {
    449                 mbedtls_printf("Invalid argument for option %s\n", p);
    450                 goto usage;
    451             }
    452             opt.version--;
    453         } else if (strcmp(p, "selfsign") == 0) {
    454             opt.selfsign = atoi(q);
    455             if (opt.selfsign < 0 || opt.selfsign > 1) {
    456                 mbedtls_printf("Invalid argument for option %s\n", p);
    457                 goto usage;
    458             }
    459         } else if (strcmp(p, "is_ca") == 0) {
    460             opt.is_ca = atoi(q);
    461             if (opt.is_ca < 0 || opt.is_ca > 1) {
    462                 mbedtls_printf("Invalid argument for option %s\n", p);
    463                 goto usage;
    464             }
    465         } else if (strcmp(p, "max_pathlen") == 0) {
    466             opt.max_pathlen = atoi(q);
    467             if (opt.max_pathlen < -1 || opt.max_pathlen > 127) {
    468                 mbedtls_printf("Invalid argument for option %s\n", p);
    469                 goto usage;
    470             }
    471         } else if (strcmp(p, "key_usage") == 0) {
    472             while (q != NULL) {
    473                 if ((r = strchr(q, ',')) != NULL) {
    474                     *r++ = '\0';
    475                 }
    476 
    477                 if (strcmp(q, "digital_signature") == 0) {
    478                     opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
    479                 } else if (strcmp(q, "non_repudiation") == 0) {
    480                     opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
    481                 } else if (strcmp(q, "key_encipherment") == 0) {
    482                     opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
    483                 } else if (strcmp(q, "data_encipherment") == 0) {
    484                     opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
    485                 } else if (strcmp(q, "key_agreement") == 0) {
    486                     opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
    487                 } else if (strcmp(q, "key_cert_sign") == 0) {
    488                     opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
    489                 } else if (strcmp(q, "crl_sign") == 0) {
    490                     opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
    491                 } else {
    492                     mbedtls_printf("Invalid argument for option %s\n", p);
    493                     goto usage;
    494                 }
    495 
    496                 q = r;
    497             }
    498         } else if (strcmp(p, "ext_key_usage") == 0) {
    499             mbedtls_asn1_sequence **tail = &opt.ext_key_usage;
    500 
    501             while (q != NULL) {
    502                 if ((r = strchr(q, ',')) != NULL) {
    503                     *r++ = '\0';
    504                 }
    505 
    506                 ext_key_usage = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
    507                 ext_key_usage->buf.tag = MBEDTLS_ASN1_OID;
    508                 if (strcmp(q, "serverAuth") == 0) {
    509                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_SERVER_AUTH);
    510                 } else if (strcmp(q, "clientAuth") == 0) {
    511                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_CLIENT_AUTH);
    512                 } else if (strcmp(q, "codeSigning") == 0) {
    513                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_CODE_SIGNING);
    514                 } else if (strcmp(q, "emailProtection") == 0) {
    515                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_EMAIL_PROTECTION);
    516                 } else if (strcmp(q, "timeStamping") == 0) {
    517                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_TIME_STAMPING);
    518                 } else if (strcmp(q, "OCSPSigning") == 0) {
    519                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_OCSP_SIGNING);
    520                 } else if (strcmp(q, "any") == 0) {
    521                     SET_OID(ext_key_usage->buf, MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE);
    522                 } else {
    523                     mbedtls_printf("Invalid argument for option %s\n", p);
    524                     goto usage;
    525                 }
    526 
    527                 *tail = ext_key_usage;
    528                 tail = &ext_key_usage->next;
    529 
    530                 q = r;
    531             }
    532         } else if (strcmp(p, "san") == 0) {
    533             char *subtype_value;
    534             prev = NULL;
    535 
    536             while (q != NULL) {
    537                 char *semicolon;
    538                 r = q;
    539 
    540                 /* Find the first non-escaped ; occurrence and remove escaped ones */
    541                 do {
    542                     if ((semicolon = strchr(r, ';')) != NULL) {
    543                         if (*(semicolon-1) != '\\') {
    544                             r = semicolon;
    545                             break;
    546                         }
    547                         /* Remove the escape character */
    548                         size_t size_left = strlen(semicolon);
    549                         memmove(semicolon-1, semicolon, size_left);
    550                         *(semicolon + size_left - 1) = '\0';
    551                         /* r will now point at the character after the semicolon */
    552                         r = semicolon;
    553                     }
    554 
    555                 } while (semicolon != NULL);
    556 
    557                 if (semicolon != NULL) {
    558                     *r++ = '\0';
    559                 } else {
    560                     r = NULL;
    561                 }
    562 
    563                 cur = mbedtls_calloc(1, sizeof(mbedtls_x509_san_list));
    564                 if (cur == NULL) {
    565                     mbedtls_printf("Not enough memory for subjectAltName list\n");
    566                     goto usage;
    567                 }
    568 
    569                 cur->next = NULL;
    570 
    571                 if ((subtype_value = strchr(q, ':')) != NULL) {
    572                     *subtype_value++ = '\0';
    573                 } else {
    574                     mbedtls_printf(
    575                         "Invalid argument for option SAN: Entry must be of the form TYPE:value\n");
    576                     goto usage;
    577                 }
    578                 if (strcmp(q, "RFC822") == 0) {
    579                     cur->node.type = MBEDTLS_X509_SAN_RFC822_NAME;
    580                 } else if (strcmp(q, "URI") == 0) {
    581                     cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
    582                 } else if (strcmp(q, "DNS") == 0) {
    583                     cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
    584                 } else if (strcmp(q, "IP") == 0) {
    585                     size_t ip_addr_len = 0;
    586                     cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
    587                     ip_addr_len = mbedtls_x509_crt_parse_cn_inet_pton(subtype_value, ip);
    588                     if (ip_addr_len == 0) {
    589                         mbedtls_printf("mbedtls_x509_crt_parse_cn_inet_pton failed to parse %s\n",
    590                                        subtype_value);
    591                         goto exit;
    592                     }
    593                     cur->node.san.unstructured_name.p = (unsigned char *) ip;
    594                     cur->node.san.unstructured_name.len = sizeof(ip);
    595                 } else if (strcmp(q, "DN") == 0) {
    596                     cur->node.type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
    597                     /* Work around an API mismatch between string_to_names() and
    598                      * mbedtls_x509_subject_alternative_name, which holds an
    599                      * actual mbedtls_x509_name while a pointer to one would be
    600                      * more convenient here. (Note mbedtls_x509_name and
    601                      * mbedtls_asn1_named_data are synonymous, again
    602                      * string_to_names() uses one while
    603                      * cur->node.san.directory_name is nominally the other.) */
    604                     mbedtls_asn1_named_data *tmp_san_dirname = NULL;
    605                     if ((ret = mbedtls_x509_string_to_names(&tmp_san_dirname,
    606                                                             subtype_value)) != 0) {
    607                         mbedtls_strerror(ret, buf, sizeof(buf));
    608                         mbedtls_printf(
    609                             " failed\n  !  mbedtls_x509_string_to_names "
    610                             "returned -0x%04x - %s\n\n",
    611                             (unsigned int) -ret, buf);
    612                         goto exit;
    613                     }
    614                     cur->node.san.directory_name = *tmp_san_dirname;
    615                     mbedtls_free(tmp_san_dirname);
    616                     tmp_san_dirname = NULL;
    617                 } else {
    618                     mbedtls_free(cur);
    619                     goto usage;
    620                 }
    621 
    622                 if (cur->node.type == MBEDTLS_X509_SAN_RFC822_NAME ||
    623                     cur->node.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER ||
    624                     cur->node.type == MBEDTLS_X509_SAN_DNS_NAME) {
    625                     q = subtype_value;
    626                     cur->node.san.unstructured_name.p = (unsigned char *) q;
    627                     cur->node.san.unstructured_name.len = strlen(q);
    628                 }
    629 
    630                 if (prev == NULL) {
    631                     opt.san_list = cur;
    632                 } else {
    633                     prev->next = cur;
    634                 }
    635 
    636                 prev = cur;
    637                 q = r;
    638             }
    639         } else if (strcmp(p, "ns_cert_type") == 0) {
    640             while (q != NULL) {
    641                 if ((r = strchr(q, ',')) != NULL) {
    642                     *r++ = '\0';
    643                 }
    644 
    645                 if (strcmp(q, "ssl_client") == 0) {
    646                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
    647                 } else if (strcmp(q, "ssl_server") == 0) {
    648                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
    649                 } else if (strcmp(q, "email") == 0) {
    650                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
    651                 } else if (strcmp(q, "object_signing") == 0) {
    652                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
    653                 } else if (strcmp(q, "ssl_ca") == 0) {
    654                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
    655                 } else if (strcmp(q, "email_ca") == 0) {
    656                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
    657                 } else if (strcmp(q, "object_signing_ca") == 0) {
    658                     opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
    659                 } else {
    660                     mbedtls_printf("Invalid argument for option %s\n", p);
    661                     goto usage;
    662                 }
    663 
    664                 q = r;
    665             }
    666         } else if (strcmp(p, "format") == 0) {
    667             if (strcmp(q, "der") == 0) {
    668                 opt.format = FORMAT_DER;
    669             } else if (strcmp(q, "pem") == 0) {
    670                 opt.format = FORMAT_PEM;
    671             } else {
    672                 mbedtls_printf("Invalid argument for option %s\n", p);
    673                 goto usage;
    674             }
    675         } else {
    676             goto usage;
    677         }
    678     }
    679 
    680     mbedtls_printf("\n");
    681 
    682     /*
    683      * 0. Seed the PRNG
    684      */
    685     mbedtls_printf("  . Seeding the random number generator...");
    686     fflush(stdout);
    687 
    688     if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
    689                                      (const unsigned char *) pers,
    690                                      strlen(pers))) != 0) {
    691         mbedtls_strerror(ret, buf, sizeof(buf));
    692         mbedtls_printf(" failed\n  !  mbedtls_ctr_drbg_seed returned %d - %s\n",
    693                        ret, buf);
    694         goto exit;
    695     }
    696 
    697     mbedtls_printf(" ok\n");
    698 
    699     // Parse serial to MPI
    700     //
    701     mbedtls_printf("  . Reading serial number...");
    702     fflush(stdout);
    703 
    704     if (serial_frmt == SERIAL_FRMT_HEX) {
    705         ret = mbedtls_test_unhexify(serial, sizeof(serial),
    706                                     opt.serial_hex, &serial_len);
    707     } else { // SERIAL_FRMT_DEC || SERIAL_FRMT_UNSPEC
    708         ret = parse_serial_decimal_format(serial, sizeof(serial),
    709                                           opt.serial, &serial_len);
    710     }
    711 
    712     if (ret != 0) {
    713         mbedtls_printf(" failed\n  !  Unable to parse serial\n");
    714         goto exit;
    715     }
    716 
    717     mbedtls_printf(" ok\n");
    718 
    719     // Parse issuer certificate if present
    720     //
    721     if (!opt.selfsign && strlen(opt.issuer_crt)) {
    722         /*
    723          * 1.0.a. Load the certificates
    724          */
    725         mbedtls_printf("  . Loading the issuer certificate ...");
    726         fflush(stdout);
    727 
    728         if ((ret = mbedtls_x509_crt_parse_file(&issuer_crt, opt.issuer_crt)) != 0) {
    729             mbedtls_strerror(ret, buf, sizeof(buf));
    730             mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse_file "
    731                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    732             goto exit;
    733         }
    734 
    735         ret = mbedtls_x509_dn_gets(issuer_name, sizeof(issuer_name),
    736                                    &issuer_crt.subject);
    737         if (ret < 0) {
    738             mbedtls_strerror(ret, buf, sizeof(buf));
    739             mbedtls_printf(" failed\n  !  mbedtls_x509_dn_gets "
    740                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    741             goto exit;
    742         }
    743 
    744         opt.issuer_name = issuer_name;
    745 
    746         mbedtls_printf(" ok\n");
    747     }
    748 
    749 #if defined(MBEDTLS_X509_CSR_PARSE_C)
    750     // Parse certificate request if present
    751     //
    752     if (!opt.selfsign && strlen(opt.request_file)) {
    753         /*
    754          * 1.0.b. Load the CSR
    755          */
    756         mbedtls_printf("  . Loading the certificate request ...");
    757         fflush(stdout);
    758 
    759         if ((ret = mbedtls_x509_csr_parse_file(&csr, opt.request_file)) != 0) {
    760             mbedtls_strerror(ret, buf, sizeof(buf));
    761             mbedtls_printf(" failed\n  !  mbedtls_x509_csr_parse_file "
    762                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    763             goto exit;
    764         }
    765 
    766         ret = mbedtls_x509_dn_gets(subject_name, sizeof(subject_name),
    767                                    &csr.subject);
    768         if (ret < 0) {
    769             mbedtls_strerror(ret, buf, sizeof(buf));
    770             mbedtls_printf(" failed\n  !  mbedtls_x509_dn_gets "
    771                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    772             goto exit;
    773         }
    774 
    775         opt.subject_name = subject_name;
    776         subject_key = &csr.pk;
    777 
    778         mbedtls_printf(" ok\n");
    779     }
    780 #endif /* MBEDTLS_X509_CSR_PARSE_C */
    781 
    782     /*
    783      * 1.1. Load the keys
    784      */
    785     if (!opt.selfsign && !strlen(opt.request_file)) {
    786         mbedtls_printf("  . Loading the subject key ...");
    787         fflush(stdout);
    788 
    789         ret = mbedtls_pk_parse_keyfile(&loaded_subject_key, opt.subject_key,
    790                                        opt.subject_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
    791         if (ret != 0) {
    792             mbedtls_strerror(ret, buf, sizeof(buf));
    793             mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile "
    794                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    795             goto exit;
    796         }
    797 
    798         mbedtls_printf(" ok\n");
    799     }
    800 
    801     mbedtls_printf("  . Loading the issuer key ...");
    802     fflush(stdout);
    803 
    804     ret = mbedtls_pk_parse_keyfile(&loaded_issuer_key, opt.issuer_key,
    805                                    opt.issuer_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
    806     if (ret != 0) {
    807         mbedtls_strerror(ret, buf, sizeof(buf));
    808         mbedtls_printf(" failed\n  !  mbedtls_pk_parse_keyfile "
    809                        "returned -x%02x - %s\n\n", (unsigned int) -ret, buf);
    810         goto exit;
    811     }
    812 
    813     // Check if key and issuer certificate match
    814     //
    815     if (strlen(opt.issuer_crt)) {
    816         if (mbedtls_pk_check_pair(&issuer_crt.pk, issuer_key,
    817                                   mbedtls_ctr_drbg_random, &ctr_drbg) != 0) {
    818             mbedtls_printf(" failed\n  !  issuer_key does not match "
    819                            "issuer certificate\n\n");
    820             goto exit;
    821         }
    822     }
    823 
    824     mbedtls_printf(" ok\n");
    825 
    826     if (opt.selfsign) {
    827         opt.subject_name = opt.issuer_name;
    828         subject_key = issuer_key;
    829     }
    830 
    831     mbedtls_x509write_crt_set_subject_key(&crt, subject_key);
    832     mbedtls_x509write_crt_set_issuer_key(&crt, issuer_key);
    833 
    834     /*
    835      * 1.0. Check the names for validity
    836      */
    837     if ((ret = mbedtls_x509write_crt_set_subject_name(&crt, opt.subject_name)) != 0) {
    838         mbedtls_strerror(ret, buf, sizeof(buf));
    839         mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_subject_name "
    840                        "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    841         goto exit;
    842     }
    843 
    844     if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt, opt.issuer_name)) != 0) {
    845         mbedtls_strerror(ret, buf, sizeof(buf));
    846         mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_issuer_name "
    847                        "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    848         goto exit;
    849     }
    850 
    851     mbedtls_printf("  . Setting certificate values ...");
    852     fflush(stdout);
    853 
    854     mbedtls_x509write_crt_set_version(&crt, opt.version);
    855     mbedtls_x509write_crt_set_md_alg(&crt, opt.md);
    856 
    857     ret = mbedtls_x509write_crt_set_serial_raw(&crt, serial, serial_len);
    858     if (ret != 0) {
    859         mbedtls_strerror(ret, buf, sizeof(buf));
    860         mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_serial_raw "
    861                        "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    862         goto exit;
    863     }
    864 
    865     ret = mbedtls_x509write_crt_set_validity(&crt, opt.not_before, opt.not_after);
    866     if (ret != 0) {
    867         mbedtls_strerror(ret, buf, sizeof(buf));
    868         mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_validity "
    869                        "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    870         goto exit;
    871     }
    872 
    873     mbedtls_printf(" ok\n");
    874 
    875     if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
    876         opt.basic_constraints != 0) {
    877         mbedtls_printf("  . Adding the Basic Constraints extension ...");
    878         fflush(stdout);
    879 
    880         ret = mbedtls_x509write_crt_set_basic_constraints(&crt, opt.is_ca,
    881                                                           opt.max_pathlen);
    882         if (ret != 0) {
    883             mbedtls_strerror(ret, buf, sizeof(buf));
    884             mbedtls_printf(" failed\n  !  x509write_crt_set_basic_constraints "
    885                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    886             goto exit;
    887         }
    888 
    889         mbedtls_printf(" ok\n");
    890     }
    891 
    892 #if defined(MBEDTLS_MD_CAN_SHA1)
    893     if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
    894         opt.subject_identifier != 0) {
    895         mbedtls_printf("  . Adding the Subject Key Identifier ...");
    896         fflush(stdout);
    897 
    898         ret = mbedtls_x509write_crt_set_subject_key_identifier(&crt);
    899         if (ret != 0) {
    900             mbedtls_strerror(ret, buf, sizeof(buf));
    901             mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_subject"
    902                            "_key_identifier returned -0x%04x - %s\n\n",
    903                            (unsigned int) -ret, buf);
    904             goto exit;
    905         }
    906 
    907         mbedtls_printf(" ok\n");
    908     }
    909 
    910     if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
    911         opt.authority_identifier != 0) {
    912         mbedtls_printf("  . Adding the Authority Key Identifier ...");
    913         fflush(stdout);
    914 
    915         ret = mbedtls_x509write_crt_set_authority_key_identifier(&crt);
    916         if (ret != 0) {
    917             mbedtls_strerror(ret, buf, sizeof(buf));
    918             mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_authority_"
    919                            "key_identifier returned -0x%04x - %s\n\n",
    920                            (unsigned int) -ret, buf);
    921             goto exit;
    922         }
    923 
    924         mbedtls_printf(" ok\n");
    925     }
    926 #endif /* MBEDTLS_MD_CAN_SHA1 */
    927 
    928     if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
    929         opt.key_usage != 0) {
    930         mbedtls_printf("  . Adding the Key Usage extension ...");
    931         fflush(stdout);
    932 
    933         ret = mbedtls_x509write_crt_set_key_usage(&crt, opt.key_usage);
    934         if (ret != 0) {
    935             mbedtls_strerror(ret, buf, sizeof(buf));
    936             mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_key_usage "
    937                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    938             goto exit;
    939         }
    940 
    941         mbedtls_printf(" ok\n");
    942     }
    943 
    944     if (opt.san_list != NULL) {
    945         ret = mbedtls_x509write_crt_set_subject_alternative_name(&crt, opt.san_list);
    946 
    947         if (ret != 0) {
    948             mbedtls_printf(
    949                 " failed\n  !  mbedtls_x509write_crt_set_subject_alternative_name returned %d",
    950                 ret);
    951             goto exit;
    952         }
    953     }
    954 
    955     if (opt.ext_key_usage) {
    956         mbedtls_printf("  . Adding the Extended Key Usage extension ...");
    957         fflush(stdout);
    958 
    959         ret = mbedtls_x509write_crt_set_ext_key_usage(&crt, opt.ext_key_usage);
    960         if (ret != 0) {
    961             mbedtls_strerror(ret, buf, sizeof(buf));
    962             mbedtls_printf(
    963                 " failed\n  !  mbedtls_x509write_crt_set_ext_key_usage returned -0x%02x - %s\n\n",
    964                 (unsigned int) -ret,
    965                 buf);
    966             goto exit;
    967         }
    968 
    969         mbedtls_printf(" ok\n");
    970     }
    971 
    972     if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
    973         opt.ns_cert_type != 0) {
    974         mbedtls_printf("  . Adding the NS Cert Type extension ...");
    975         fflush(stdout);
    976 
    977         ret = mbedtls_x509write_crt_set_ns_cert_type(&crt, opt.ns_cert_type);
    978         if (ret != 0) {
    979             mbedtls_strerror(ret, buf, sizeof(buf));
    980             mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_ns_cert_type "
    981                            "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
    982             goto exit;
    983         }
    984 
    985         mbedtls_printf(" ok\n");
    986     }
    987 
    988     /*
    989      * 1.2. Writing the certificate
    990      */
    991     mbedtls_printf("  . Writing the certificate...");
    992     fflush(stdout);
    993 
    994     if ((ret = write_certificate(&crt, opt.output_file,
    995                                  mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
    996         mbedtls_strerror(ret, buf, sizeof(buf));
    997         mbedtls_printf(" failed\n  !  write_certificate -0x%04x - %s\n\n",
    998                        (unsigned int) -ret, buf);
    999         goto exit;
   1000     }
   1001 
   1002     mbedtls_printf(" ok\n");
   1003 
   1004     exit_code = MBEDTLS_EXIT_SUCCESS;
   1005 
   1006 exit:
   1007     cur = opt.san_list;
   1008     while (cur != NULL) {
   1009         mbedtls_x509_san_list *next = cur->next;
   1010         /* Note: mbedtls_x509_free_subject_alt_name() is not what we want here.
   1011          * It's the right thing for entries that were parsed from a certificate,
   1012          * where pointers are to the raw certificate, but here all the
   1013          * pointers were allocated while parsing from a user-provided string. */
   1014         if (cur->node.type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
   1015             mbedtls_x509_name *dn = &cur->node.san.directory_name;
   1016             mbedtls_free(dn->oid.p);
   1017             mbedtls_free(dn->val.p);
   1018             mbedtls_asn1_free_named_data_list(&dn->next);
   1019         }
   1020         mbedtls_free(cur);
   1021         cur = next;
   1022     }
   1023 
   1024 #if defined(MBEDTLS_X509_CSR_PARSE_C)
   1025     mbedtls_x509_csr_free(&csr);
   1026 #endif /* MBEDTLS_X509_CSR_PARSE_C */
   1027     mbedtls_x509_crt_free(&issuer_crt);
   1028     mbedtls_x509write_crt_free(&crt);
   1029     mbedtls_pk_free(&loaded_subject_key);
   1030     mbedtls_pk_free(&loaded_issuer_key);
   1031     mbedtls_ctr_drbg_free(&ctr_drbg);
   1032     mbedtls_entropy_free(&entropy);
   1033 #if defined(MBEDTLS_USE_PSA_CRYPTO)
   1034     mbedtls_psa_crypto_free();
   1035 #endif /* MBEDTLS_USE_PSA_CRYPTO */
   1036 
   1037     mbedtls_exit(exit_code);
   1038 }
   1039 #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
   1040           MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
   1041           MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */