LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - asn1parse.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.9 % 191 145
Test Date: 2025-06-29 08:09:00 Functions: 84.2 % 19 16

            Line data    Source code
       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       777366 : int mbedtls_asn1_get_len(unsigned char **p,
      29              :                          const unsigned char *end,
      30              :                          size_t *len)
      31              : {
      32       777366 :     if ((end - *p) < 1) {
      33            0 :         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
      34              :     }
      35              : 
      36       777366 :     if ((**p & 0x80) == 0) {
      37       716041 :         *len = *(*p)++;
      38              :     } else {
      39        61325 :         int n = (**p) & 0x7F;
      40        61325 :         if (n == 0 || n > 4) {
      41            0 :             return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
      42              :         }
      43        61325 :         if ((end - *p) <= n) {
      44            0 :             return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
      45              :         }
      46        61325 :         *len = 0;
      47        61325 :         (*p)++;
      48       164028 :         while (n--) {
      49       102703 :             *len = (*len << 8) | **p;
      50       102703 :             (*p)++;
      51              :         }
      52              :     }
      53              : 
      54       777366 :     if (*len > (size_t) (end - *p)) {
      55            0 :         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
      56              :     }
      57              : 
      58       777366 :     return 0;
      59              : }
      60              : 
      61       730717 : int mbedtls_asn1_get_tag(unsigned char **p,
      62              :                          const unsigned char *end,
      63              :                          size_t *len, int tag)
      64              : {
      65       730717 :     if ((end - *p) < 1) {
      66         1778 :         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
      67              :     }
      68              : 
      69       728939 :     if (**p != tag) {
      70        71358 :         return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
      71              :     }
      72              : 
      73       657581 :     (*p)++;
      74              : 
      75       657581 :     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        70465 : int mbedtls_asn1_get_bool(unsigned char **p,
      81              :                           const unsigned char *end,
      82              :                           int *val)
      83              : {
      84        70465 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
      85              :     size_t len;
      86              : 
      87        70465 :     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
      88        44811 :         return ret;
      89              :     }
      90              : 
      91        25654 :     if (len != 1) {
      92            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
      93              :     }
      94              : 
      95        25654 :     *val = (**p != 0) ? 1 : 0;
      96        25654 :     (*p)++;
      97              : 
      98        25654 :     return 0;
      99              : }
     100              : 
     101        13172 : static int asn1_get_tagged_int(unsigned char **p,
     102              :                                const unsigned char *end,
     103              :                                int tag, int *val)
     104              : {
     105        13172 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     106              :     size_t len;
     107              : 
     108        13172 :     if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
     109            0 :         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        13172 :     if (len == 0) {
     117            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     118              :     }
     119              :     /* This is a cryptography library. Reject negative integers. */
     120        13172 :     if ((**p & 0x80) != 0) {
     121            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     122              :     }
     123              : 
     124              :     /* Skip leading zeros. */
     125        13389 :     while (len > 0 && **p == 0) {
     126          217 :         ++(*p);
     127          217 :         --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        13172 :     if (len > sizeof(int)) {
     133            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     134              :     }
     135        13172 :     if (len == sizeof(int) && (**p & 0x80) != 0) {
     136            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     137              :     }
     138              : 
     139        13172 :     *val = 0;
     140        26127 :     while (len-- > 0) {
     141        12955 :         *val = (*val << 8) | **p;
     142        12955 :         (*p)++;
     143              :     }
     144              : 
     145        13172 :     return 0;
     146              : }
     147              : 
     148        13172 : int mbedtls_asn1_get_int(unsigned char **p,
     149              :                          const unsigned char *end,
     150              :                          int *val)
     151              : {
     152        13172 :     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
     153              : }
     154              : 
     155            0 : int mbedtls_asn1_get_enum(unsigned char **p,
     156              :                           const unsigned char *end,
     157              :                           int *val)
     158              : {
     159            0 :     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
     160              : }
     161              : 
     162              : #if defined(MBEDTLS_BIGNUM_C)
     163         3070 : int mbedtls_asn1_get_mpi(unsigned char **p,
     164              :                          const unsigned char *end,
     165              :                          mbedtls_mpi *X)
     166              : {
     167         3070 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     168              :     size_t len;
     169              : 
     170         3070 :     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
     171            0 :         return ret;
     172              :     }
     173              : 
     174         3070 :     ret = mbedtls_mpi_read_binary(X, *p, len);
     175              : 
     176         3070 :     *p += len;
     177              : 
     178         3070 :     return ret;
     179              : }
     180              : #endif /* MBEDTLS_BIGNUM_C */
     181              : 
     182        10540 : int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
     183              :                                mbedtls_asn1_bitstring *bs)
     184              : {
     185        10540 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     186              : 
     187              :     /* Certificate type is a single byte bitstring */
     188        10540 :     if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
     189            0 :         return ret;
     190              :     }
     191              : 
     192              :     /* Check length, subtract one for actual bit string length */
     193        10540 :     if (bs->len < 1) {
     194            0 :         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     195              :     }
     196        10540 :     bs->len -= 1;
     197              : 
     198              :     /* Get number of unused bits, ensure unused bits <= 7 */
     199        10540 :     bs->unused_bits = **p;
     200        10540 :     if (bs->unused_bits > 7) {
     201            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     202              :     }
     203        10540 :     (*p)++;
     204              : 
     205              :     /* Get actual bitstring */
     206        10540 :     bs->p = *p;
     207        10540 :     *p += bs->len;
     208              : 
     209        10540 :     if (*p != end) {
     210            0 :         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
     211              :     }
     212              : 
     213        10540 :     return 0;
     214              : }
     215              : 
     216              : /*
     217              :  * Traverse an ASN.1 "SEQUENCE OF <tag>"
     218              :  * and call a callback for each entry found.
     219              :  */
     220        10546 : 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        10546 :     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
     234              :                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
     235            0 :         return ret;
     236              :     }
     237              : 
     238        10546 :     if (*p + len != end) {
     239            0 :         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
     240              :     }
     241              : 
     242        40382 :     while (*p < end) {
     243        29836 :         unsigned char const tag = *(*p)++;
     244              : 
     245        29836 :         if ((tag & tag_must_mask) != tag_must_val) {
     246            0 :             return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
     247              :         }
     248              : 
     249        29836 :         if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
     250            0 :             return ret;
     251              :         }
     252              : 
     253        29836 :         if ((tag & tag_may_mask) == tag_may_val) {
     254        29836 :             if (cb != NULL) {
     255        29836 :                 ret = cb(ctx, tag, *p, len);
     256        29836 :                 if (ret != 0) {
     257            0 :                     return ret;
     258              :                 }
     259              :             }
     260              :         }
     261              : 
     262        29836 :         *p += len;
     263              :     }
     264              : 
     265        10546 :     return 0;
     266              : }
     267              : 
     268              : /*
     269              :  * Get a bit string without unused bits
     270              :  */
     271        25775 : int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
     272              :                                     size_t *len)
     273              : {
     274        25775 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     275              : 
     276        25775 :     if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
     277            0 :         return ret;
     278              :     }
     279              : 
     280        25775 :     if (*len == 0) {
     281            0 :         return MBEDTLS_ERR_ASN1_INVALID_DATA;
     282              :     }
     283        25775 :     --(*len);
     284              : 
     285        25775 :     if (**p != 0) {
     286            0 :         return MBEDTLS_ERR_ASN1_INVALID_DATA;
     287              :     }
     288        25775 :     ++(*p);
     289              : 
     290        25775 :     return 0;
     291              : }
     292              : 
     293        51216 : void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
     294              : {
     295        71984 :     while (seq != NULL) {
     296        20768 :         mbedtls_asn1_sequence *next = seq->next;
     297        20768 :         mbedtls_free(seq);
     298        20768 :         seq = next;
     299              :     }
     300        51216 : }
     301              : 
     302              : typedef struct {
     303              :     int tag;
     304              :     mbedtls_asn1_sequence *cur;
     305              : } asn1_get_sequence_of_cb_ctx_t;
     306              : 
     307        29836 : static int asn1_get_sequence_of_cb(void *ctx,
     308              :                                    int tag,
     309              :                                    unsigned char *start,
     310              :                                    size_t len)
     311              : {
     312        29836 :     asn1_get_sequence_of_cb_ctx_t *cb_ctx =
     313              :         (asn1_get_sequence_of_cb_ctx_t *) ctx;
     314        29836 :     mbedtls_asn1_sequence *cur =
     315              :         cb_ctx->cur;
     316              : 
     317        29836 :     if (cur->buf.p != NULL) {
     318        19290 :         cur->next =
     319        19290 :             mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
     320              : 
     321        19290 :         if (cur->next == NULL) {
     322            0 :             return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
     323              :         }
     324              : 
     325        19290 :         cur = cur->next;
     326              :     }
     327              : 
     328        29836 :     cur->buf.p = start;
     329        29836 :     cur->buf.len = len;
     330        29836 :     cur->buf.tag = tag;
     331              : 
     332        29836 :     cb_ctx->cur = cur;
     333        29836 :     return 0;
     334              : }
     335              : 
     336              : /*
     337              :  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
     338              :  */
     339        10546 : int mbedtls_asn1_get_sequence_of(unsigned char **p,
     340              :                                  const unsigned char *end,
     341              :                                  mbedtls_asn1_sequence *cur,
     342              :                                  int tag)
     343              : {
     344        10546 :     asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
     345        10546 :     memset(cur, 0, sizeof(mbedtls_asn1_sequence));
     346        10546 :     return mbedtls_asn1_traverse_sequence_of(
     347              :         p, end, 0xFF, tag, 0, 0,
     348              :         asn1_get_sequence_of_cb, &cb_ctx);
     349              : }
     350              : 
     351        38621 : int mbedtls_asn1_get_alg(unsigned char **p,
     352              :                          const unsigned char *end,
     353              :                          mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
     354              : {
     355        38621 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     356              :     size_t len;
     357              : 
     358        38621 :     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
     359              :                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
     360            0 :         return ret;
     361              :     }
     362              : 
     363        38621 :     if ((end - *p) < 1) {
     364            0 :         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
     365              :     }
     366              : 
     367        38621 :     alg->tag = **p;
     368        38621 :     end = *p + len;
     369              : 
     370        38621 :     if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
     371            0 :         return ret;
     372              :     }
     373              : 
     374        38621 :     alg->p = *p;
     375        38621 :     *p += alg->len;
     376              : 
     377        38621 :     if (*p == end) {
     378        22980 :         mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
     379        22980 :         return 0;
     380              :     }
     381              : 
     382        15641 :     params->tag = **p;
     383        15641 :     (*p)++;
     384              : 
     385        15641 :     if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
     386            0 :         return ret;
     387              :     }
     388              : 
     389        15641 :     params->p = *p;
     390        15641 :     *p += params->len;
     391              : 
     392        15641 :     if (*p != end) {
     393            0 :         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
     394              :     }
     395              : 
     396        15641 :     return 0;
     397              : }
     398              : 
     399            0 : int mbedtls_asn1_get_alg_null(unsigned char **p,
     400              :                               const unsigned char *end,
     401              :                               mbedtls_asn1_buf *alg)
     402              : {
     403            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     404              :     mbedtls_asn1_buf params;
     405              : 
     406            0 :     memset(&params, 0, sizeof(mbedtls_asn1_buf));
     407              : 
     408            0 :     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
     409            0 :         return ret;
     410              :     }
     411              : 
     412            0 :     if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
     413            0 :         return MBEDTLS_ERR_ASN1_INVALID_DATA;
     414              :     }
     415              : 
     416            0 :     return 0;
     417              : }
     418              : 
     419              : #if !defined(MBEDTLS_DEPRECATED_REMOVED)
     420            0 : void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
     421              : {
     422            0 :     if (cur == NULL) {
     423            0 :         return;
     424              :     }
     425              : 
     426            0 :     mbedtls_free(cur->oid.p);
     427            0 :     mbedtls_free(cur->val.p);
     428              : 
     429            0 :     mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
     430              : }
     431              : #endif /* MBEDTLS_DEPRECATED_REMOVED */
     432              : 
     433           20 : void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
     434              : {
     435              :     mbedtls_asn1_named_data *cur;
     436              : 
     437           82 :     while ((cur = *head) != NULL) {
     438           62 :         *head = cur->next;
     439           62 :         mbedtls_free(cur->oid.p);
     440           62 :         mbedtls_free(cur->val.p);
     441           62 :         mbedtls_free(cur);
     442              :     }
     443           20 : }
     444              : 
     445        25608 : void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
     446              : {
     447        25728 :     for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
     448          120 :         next = name->next;
     449          120 :         mbedtls_free(name);
     450              :     }
     451        25608 : }
     452              : 
     453           62 : 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          188 :     while (list != NULL) {
     457          126 :         if (list->oid.len == len &&
     458           84 :             memcmp(list->oid.p, oid, len) == 0) {
     459            0 :             break;
     460              :         }
     461              : 
     462          126 :         list = list->next;
     463              :     }
     464              : 
     465           62 :     return list;
     466              : }
     467              : 
     468              : #endif /* MBEDTLS_ASN1_PARSE_C */
        

Generated by: LCOV version 2.0-1