quickjs-tart

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

asn1parse.c (11242B)


      1 /*
      2  *  Generic ASN.1 parsing
      3  *
      4  *  Copyright The Mbed TLS Contributors
      5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6  */
      7 
      8 #include "common.h"
      9 
     10 #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
     11     defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
     12 
     13 #include "mbedtls/asn1.h"
     14 #include "mbedtls/platform_util.h"
     15 #include "mbedtls/error.h"
     16 
     17 #include <string.h>
     18 
     19 #if defined(MBEDTLS_BIGNUM_C)
     20 #include "mbedtls/bignum.h"
     21 #endif
     22 
     23 #include "mbedtls/platform.h"
     24 
     25 /*
     26  * ASN.1 DER decoding routines
     27  */
     28 int mbedtls_asn1_get_len(unsigned char **p,
     29                          const unsigned char *end,
     30                          size_t *len)
     31 {
     32     if ((end - *p) < 1) {
     33         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     34     }
     35 
     36     if ((**p & 0x80) == 0) {
     37         *len = *(*p)++;
     38     } else {
     39         int n = (**p) & 0x7F;
     40         if (n == 0 || n > 4) {
     41             return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     42         }
     43         if ((end - *p) <= n) {
     44             return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     45         }
     46         *len = 0;
     47         (*p)++;
     48         while (n--) {
     49             *len = (*len << 8) | **p;
     50             (*p)++;
     51         }
     52     }
     53 
     54     if (*len > (size_t) (end - *p)) {
     55         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     56     }
     57 
     58     return 0;
     59 }
     60 
     61 int mbedtls_asn1_get_tag(unsigned char **p,
     62                          const unsigned char *end,
     63                          size_t *len, int tag)
     64 {
     65     if ((end - *p) < 1) {
     66         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     67     }
     68 
     69     if (**p != tag) {
     70         return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
     71     }
     72 
     73     (*p)++;
     74 
     75     return mbedtls_asn1_get_len(p, end, len);
     76 }
     77 #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
     78 
     79 #if defined(MBEDTLS_ASN1_PARSE_C)
     80 int mbedtls_asn1_get_bool(unsigned char **p,
     81                           const unsigned char *end,
     82                           int *val)
     83 {
     84     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     85     size_t len;
     86 
     87     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
     88         return ret;
     89     }
     90 
     91     if (len != 1) {
     92         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     93     }
     94 
     95     *val = (**p != 0) ? 1 : 0;
     96     (*p)++;
     97 
     98     return 0;
     99 }
    100 
    101 static int asn1_get_tagged_int(unsigned char **p,
    102                                const unsigned char *end,
    103                                int tag, int *val)
    104 {
    105     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    106     size_t len;
    107 
    108     if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
    109         return ret;
    110     }
    111 
    112     /*
    113      * len==0 is malformed (0 must be represented as 020100 for INTEGER,
    114      * or 0A0100 for ENUMERATED tags
    115      */
    116     if (len == 0) {
    117         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
    118     }
    119     /* This is a cryptography library. Reject negative integers. */
    120     if ((**p & 0x80) != 0) {
    121         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
    122     }
    123 
    124     /* Skip leading zeros. */
    125     while (len > 0 && **p == 0) {
    126         ++(*p);
    127         --len;
    128     }
    129 
    130     /* Reject integers that don't fit in an int. This code assumes that
    131      * the int type has no padding bit. */
    132     if (len > sizeof(int)) {
    133         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
    134     }
    135     if (len == sizeof(int) && (**p & 0x80) != 0) {
    136         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
    137     }
    138 
    139     *val = 0;
    140     while (len-- > 0) {
    141         *val = (*val << 8) | **p;
    142         (*p)++;
    143     }
    144 
    145     return 0;
    146 }
    147 
    148 int mbedtls_asn1_get_int(unsigned char **p,
    149                          const unsigned char *end,
    150                          int *val)
    151 {
    152     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
    153 }
    154 
    155 int mbedtls_asn1_get_enum(unsigned char **p,
    156                           const unsigned char *end,
    157                           int *val)
    158 {
    159     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
    160 }
    161 
    162 #if defined(MBEDTLS_BIGNUM_C)
    163 int mbedtls_asn1_get_mpi(unsigned char **p,
    164                          const unsigned char *end,
    165                          mbedtls_mpi *X)
    166 {
    167     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    168     size_t len;
    169 
    170     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
    171         return ret;
    172     }
    173 
    174     ret = mbedtls_mpi_read_binary(X, *p, len);
    175 
    176     *p += len;
    177 
    178     return ret;
    179 }
    180 #endif /* MBEDTLS_BIGNUM_C */
    181 
    182 int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
    183                                mbedtls_asn1_bitstring *bs)
    184 {
    185     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    186 
    187     /* Certificate type is a single byte bitstring */
    188     if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
    189         return ret;
    190     }
    191 
    192     /* Check length, subtract one for actual bit string length */
    193     if (bs->len < 1) {
    194         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
    195     }
    196     bs->len -= 1;
    197 
    198     /* Get number of unused bits, ensure unused bits <= 7 */
    199     bs->unused_bits = **p;
    200     if (bs->unused_bits > 7) {
    201         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
    202     }
    203     (*p)++;
    204 
    205     /* Get actual bitstring */
    206     bs->p = *p;
    207     *p += bs->len;
    208 
    209     if (*p != end) {
    210         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
    211     }
    212 
    213     return 0;
    214 }
    215 
    216 /*
    217  * Traverse an ASN.1 "SEQUENCE OF <tag>"
    218  * and call a callback for each entry found.
    219  */
    220 int mbedtls_asn1_traverse_sequence_of(
    221     unsigned char **p,
    222     const unsigned char *end,
    223     unsigned char tag_must_mask, unsigned char tag_must_val,
    224     unsigned char tag_may_mask, unsigned char tag_may_val,
    225     int (*cb)(void *ctx, int tag,
    226               unsigned char *start, size_t len),
    227     void *ctx)
    228 {
    229     int ret;
    230     size_t len;
    231 
    232     /* Get main sequence tag */
    233     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
    234                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
    235         return ret;
    236     }
    237 
    238     if (*p + len != end) {
    239         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
    240     }
    241 
    242     while (*p < end) {
    243         unsigned char const tag = *(*p)++;
    244 
    245         if ((tag & tag_must_mask) != tag_must_val) {
    246             return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
    247         }
    248 
    249         if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
    250             return ret;
    251         }
    252 
    253         if ((tag & tag_may_mask) == tag_may_val) {
    254             if (cb != NULL) {
    255                 ret = cb(ctx, tag, *p, len);
    256                 if (ret != 0) {
    257                     return ret;
    258                 }
    259             }
    260         }
    261 
    262         *p += len;
    263     }
    264 
    265     return 0;
    266 }
    267 
    268 /*
    269  * Get a bit string without unused bits
    270  */
    271 int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
    272                                     size_t *len)
    273 {
    274     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    275 
    276     if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
    277         return ret;
    278     }
    279 
    280     if (*len == 0) {
    281         return MBEDTLS_ERR_ASN1_INVALID_DATA;
    282     }
    283     --(*len);
    284 
    285     if (**p != 0) {
    286         return MBEDTLS_ERR_ASN1_INVALID_DATA;
    287     }
    288     ++(*p);
    289 
    290     return 0;
    291 }
    292 
    293 void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
    294 {
    295     while (seq != NULL) {
    296         mbedtls_asn1_sequence *next = seq->next;
    297         mbedtls_free(seq);
    298         seq = next;
    299     }
    300 }
    301 
    302 typedef struct {
    303     int tag;
    304     mbedtls_asn1_sequence *cur;
    305 } asn1_get_sequence_of_cb_ctx_t;
    306 
    307 static int asn1_get_sequence_of_cb(void *ctx,
    308                                    int tag,
    309                                    unsigned char *start,
    310                                    size_t len)
    311 {
    312     asn1_get_sequence_of_cb_ctx_t *cb_ctx =
    313         (asn1_get_sequence_of_cb_ctx_t *) ctx;
    314     mbedtls_asn1_sequence *cur =
    315         cb_ctx->cur;
    316 
    317     if (cur->buf.p != NULL) {
    318         cur->next =
    319             mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
    320 
    321         if (cur->next == NULL) {
    322             return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
    323         }
    324 
    325         cur = cur->next;
    326     }
    327 
    328     cur->buf.p = start;
    329     cur->buf.len = len;
    330     cur->buf.tag = tag;
    331 
    332     cb_ctx->cur = cur;
    333     return 0;
    334 }
    335 
    336 /*
    337  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
    338  */
    339 int mbedtls_asn1_get_sequence_of(unsigned char **p,
    340                                  const unsigned char *end,
    341                                  mbedtls_asn1_sequence *cur,
    342                                  int tag)
    343 {
    344     asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
    345     memset(cur, 0, sizeof(mbedtls_asn1_sequence));
    346     return mbedtls_asn1_traverse_sequence_of(
    347         p, end, 0xFF, tag, 0, 0,
    348         asn1_get_sequence_of_cb, &cb_ctx);
    349 }
    350 
    351 int mbedtls_asn1_get_alg(unsigned char **p,
    352                          const unsigned char *end,
    353                          mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
    354 {
    355     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    356     size_t len;
    357 
    358     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
    359                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
    360         return ret;
    361     }
    362 
    363     if ((end - *p) < 1) {
    364         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
    365     }
    366 
    367     alg->tag = **p;
    368     end = *p + len;
    369 
    370     if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
    371         return ret;
    372     }
    373 
    374     alg->p = *p;
    375     *p += alg->len;
    376 
    377     if (*p == end) {
    378         mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
    379         return 0;
    380     }
    381 
    382     params->tag = **p;
    383     (*p)++;
    384 
    385     if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
    386         return ret;
    387     }
    388 
    389     params->p = *p;
    390     *p += params->len;
    391 
    392     if (*p != end) {
    393         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
    394     }
    395 
    396     return 0;
    397 }
    398 
    399 int mbedtls_asn1_get_alg_null(unsigned char **p,
    400                               const unsigned char *end,
    401                               mbedtls_asn1_buf *alg)
    402 {
    403     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    404     mbedtls_asn1_buf params;
    405 
    406     memset(&params, 0, sizeof(mbedtls_asn1_buf));
    407 
    408     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
    409         return ret;
    410     }
    411 
    412     if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
    413         return MBEDTLS_ERR_ASN1_INVALID_DATA;
    414     }
    415 
    416     return 0;
    417 }
    418 
    419 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
    420 void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
    421 {
    422     if (cur == NULL) {
    423         return;
    424     }
    425 
    426     mbedtls_free(cur->oid.p);
    427     mbedtls_free(cur->val.p);
    428 
    429     mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
    430 }
    431 #endif /* MBEDTLS_DEPRECATED_REMOVED */
    432 
    433 void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
    434 {
    435     mbedtls_asn1_named_data *cur;
    436 
    437     while ((cur = *head) != NULL) {
    438         *head = cur->next;
    439         mbedtls_free(cur->oid.p);
    440         mbedtls_free(cur->val.p);
    441         mbedtls_free(cur);
    442     }
    443 }
    444 
    445 void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
    446 {
    447     for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
    448         next = name->next;
    449         mbedtls_free(name);
    450     }
    451 }
    452 
    453 const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
    454                                                             const char *oid, size_t len)
    455 {
    456     while (list != NULL) {
    457         if (list->oid.len == len &&
    458             memcmp(list->oid.p, oid, len) == 0) {
    459             break;
    460         }
    461 
    462         list = list->next;
    463     }
    464 
    465     return list;
    466 }
    467 
    468 #endif /* MBEDTLS_ASN1_PARSE_C */