quickjs-tart

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

x509write_csr.c (11023B)


      1 /*
      2  *  X.509 Certificate Signing Request writing
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 /*
      8  * References:
      9  * - CSRs: PKCS#10 v1.7 aka RFC 2986
     10  * - attributes: PKCS#9 v2.0 aka RFC 2985
     11  */
     12 
     13 #include "common.h"
     14 
     15 #if defined(MBEDTLS_X509_CSR_WRITE_C)
     16 
     17 #include "x509_internal.h"
     18 #include "mbedtls/x509_csr.h"
     19 #include "mbedtls/asn1write.h"
     20 #include "mbedtls/error.h"
     21 #include "mbedtls/oid.h"
     22 #include "mbedtls/platform_util.h"
     23 
     24 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     25 #include "psa/crypto.h"
     26 #include "psa_util_internal.h"
     27 #include "mbedtls/psa_util.h"
     28 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     29 
     30 #include <string.h>
     31 #include <stdlib.h>
     32 
     33 #if defined(MBEDTLS_PEM_WRITE_C)
     34 #include "mbedtls/pem.h"
     35 #endif
     36 
     37 #include "mbedtls/platform.h"
     38 
     39 void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
     40 {
     41     memset(ctx, 0, sizeof(mbedtls_x509write_csr));
     42 }
     43 
     44 void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
     45 {
     46     if (ctx == NULL) {
     47         return;
     48     }
     49 
     50     mbedtls_asn1_free_named_data_list(&ctx->subject);
     51     mbedtls_asn1_free_named_data_list(&ctx->extensions);
     52 
     53     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr));
     54 }
     55 
     56 void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg)
     57 {
     58     ctx->md_alg = md_alg;
     59 }
     60 
     61 void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key)
     62 {
     63     ctx->key = key;
     64 }
     65 
     66 int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,
     67                                            const char *subject_name)
     68 {
     69     mbedtls_asn1_free_named_data_list(&ctx->subject);
     70     return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
     71 }
     72 
     73 int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
     74                                         const char *oid, size_t oid_len,
     75                                         int critical,
     76                                         const unsigned char *val, size_t val_len)
     77 {
     78     return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
     79                                       critical, val, val_len);
     80 }
     81 
     82 int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
     83                                                        const mbedtls_x509_san_list *san_list)
     84 {
     85     return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);
     86 }
     87 
     88 int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
     89 {
     90     unsigned char buf[4] = { 0 };
     91     unsigned char *c;
     92     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     93 
     94     c = buf + 4;
     95 
     96     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8);
     97     if (ret < 3 || ret > 4) {
     98         return ret;
     99     }
    100 
    101     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
    102                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
    103                                               0, c, (size_t) ret);
    104     if (ret != 0) {
    105         return ret;
    106     }
    107 
    108     return 0;
    109 }
    110 
    111 int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,
    112                                            unsigned char ns_cert_type)
    113 {
    114     unsigned char buf[4] = { 0 };
    115     unsigned char *c;
    116     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    117 
    118     c = buf + 4;
    119 
    120     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
    121     if (ret < 3 || ret > 4) {
    122         return ret;
    123     }
    124 
    125     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
    126                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
    127                                               0, c, (size_t) ret);
    128     if (ret != 0) {
    129         return ret;
    130     }
    131 
    132     return 0;
    133 }
    134 
    135 static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
    136                                       unsigned char *buf,
    137                                       size_t size,
    138                                       unsigned char *sig, size_t sig_size,
    139                                       int (*f_rng)(void *, unsigned char *, size_t),
    140                                       void *p_rng)
    141 {
    142     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    143     const char *sig_oid;
    144     size_t sig_oid_len = 0;
    145     unsigned char *c, *c2;
    146     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
    147     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
    148     size_t len = 0;
    149     mbedtls_pk_type_t pk_alg;
    150 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    151     size_t hash_len;
    152     psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg);
    153 #endif /* MBEDTLS_USE_PSA_CRYPTO */
    154 
    155     /* Write the CSR backwards starting from the end of buf */
    156     c = buf + size;
    157 
    158     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
    159                                                             ctx->extensions));
    160 
    161     if (len) {
    162         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
    163         MBEDTLS_ASN1_CHK_ADD(len,
    164                              mbedtls_asn1_write_tag(
    165                                  &c, buf,
    166                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
    167 
    168         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
    169         MBEDTLS_ASN1_CHK_ADD(len,
    170                              mbedtls_asn1_write_tag(
    171                                  &c, buf,
    172                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
    173 
    174         MBEDTLS_ASN1_CHK_ADD(len,
    175                              mbedtls_asn1_write_oid(
    176                                  &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
    177                                  MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));
    178 
    179         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
    180         MBEDTLS_ASN1_CHK_ADD(len,
    181                              mbedtls_asn1_write_tag(
    182                                  &c, buf,
    183                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
    184     }
    185 
    186     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
    187     MBEDTLS_ASN1_CHK_ADD(len,
    188                          mbedtls_asn1_write_tag(
    189                              &c, buf,
    190                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
    191 
    192     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,
    193                                                               buf, (size_t) (c - buf)));
    194     c -= pub_len;
    195     len += pub_len;
    196 
    197     /*
    198      *  Subject  ::=  Name
    199      */
    200     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
    201                                                        ctx->subject));
    202 
    203     /*
    204      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
    205      */
    206     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
    207 
    208     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
    209     MBEDTLS_ASN1_CHK_ADD(len,
    210                          mbedtls_asn1_write_tag(
    211                              &c, buf,
    212                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
    213 
    214     /*
    215      * Sign the written CSR data into the sig buffer
    216      * Note: hash errors can happen only after an internal error
    217      */
    218 #if defined(MBEDTLS_USE_PSA_CRYPTO)
    219     if (psa_hash_compute(hash_alg,
    220                          c,
    221                          len,
    222                          hash,
    223                          sizeof(hash),
    224                          &hash_len) != PSA_SUCCESS) {
    225         return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
    226     }
    227 #else /* MBEDTLS_USE_PSA_CRYPTO */
    228     ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash);
    229     if (ret != 0) {
    230         return ret;
    231     }
    232 #endif
    233     if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0,
    234                                sig, sig_size, &sig_len,
    235                                f_rng, p_rng)) != 0) {
    236         return ret;
    237     }
    238 
    239     if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) {
    240         pk_alg = MBEDTLS_PK_RSA;
    241     } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) {
    242         pk_alg = MBEDTLS_PK_ECDSA;
    243     } else {
    244         return MBEDTLS_ERR_X509_INVALID_ALG;
    245     }
    246 
    247     if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
    248                                               &sig_oid, &sig_oid_len)) != 0) {
    249         return ret;
    250     }
    251 
    252     /*
    253      * Move the written CSR data to the start of buf to create space for
    254      * writing the signature into buf.
    255      */
    256     memmove(buf, c, len);
    257 
    258     /*
    259      * Write sig and its OID into buf backwards from the end of buf.
    260      * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len
    261      * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.
    262      */
    263     c2 = buf + size;
    264     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,
    265                          mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,
    266                                                 sig, sig_len, pk_alg));
    267 
    268     /*
    269      * Compact the space between the CSR data and signature by moving the
    270      * CSR data to the start of the signature.
    271      */
    272     c2 -= len;
    273     memmove(c2, buf, len);
    274 
    275     /* ASN encode the total size and tag the CSR data with it. */
    276     len += sig_and_oid_len;
    277     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len));
    278     MBEDTLS_ASN1_CHK_ADD(len,
    279                          mbedtls_asn1_write_tag(
    280                              &c2, buf,
    281                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
    282 
    283     /* Zero the unused bytes at the start of buf */
    284     memset(buf, 0, (size_t) (c2 - buf));
    285 
    286     return (int) len;
    287 }
    288 
    289 int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf,
    290                               size_t size,
    291                               int (*f_rng)(void *, unsigned char *, size_t),
    292                               void *p_rng)
    293 {
    294     int ret;
    295     unsigned char *sig;
    296 
    297     if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) {
    298         return MBEDTLS_ERR_X509_ALLOC_FAILED;
    299     }
    300 
    301     ret = x509write_csr_der_internal(ctx, buf, size,
    302                                      sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE,
    303                                      f_rng, p_rng);
    304 
    305     mbedtls_free(sig);
    306 
    307     return ret;
    308 }
    309 
    310 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
    311 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
    312 
    313 #if defined(MBEDTLS_PEM_WRITE_C)
    314 int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
    315                               int (*f_rng)(void *, unsigned char *, size_t),
    316                               void *p_rng)
    317 {
    318     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    319     size_t olen = 0;
    320 
    321     if ((ret = mbedtls_x509write_csr_der(ctx, buf, size,
    322                                          f_rng, p_rng)) < 0) {
    323         return ret;
    324     }
    325 
    326     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR,
    327                                         buf + size - ret,
    328                                         ret, buf, size, &olen)) != 0) {
    329         return ret;
    330     }
    331 
    332     return 0;
    333 }
    334 #endif /* MBEDTLS_PEM_WRITE_C */
    335 
    336 #endif /* MBEDTLS_X509_CSR_WRITE_C */