Path: blob/master/thirdparty/mbedtls/library/asn1parse.c
9898 views
/*1* Generic ASN.1 parsing2*3* Copyright The Mbed TLS Contributors4* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later5*/67#include "common.h"89#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \10defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)1112#include "mbedtls/asn1.h"13#include "mbedtls/platform_util.h"14#include "mbedtls/error.h"1516#include <string.h>1718#if defined(MBEDTLS_BIGNUM_C)19#include "mbedtls/bignum.h"20#endif2122#include "mbedtls/platform.h"2324/*25* ASN.1 DER decoding routines26*/27int mbedtls_asn1_get_len(unsigned char **p,28const unsigned char *end,29size_t *len)30{31if ((end - *p) < 1) {32return MBEDTLS_ERR_ASN1_OUT_OF_DATA;33}3435if ((**p & 0x80) == 0) {36*len = *(*p)++;37} else {38int n = (**p) & 0x7F;39if (n == 0 || n > 4) {40return MBEDTLS_ERR_ASN1_INVALID_LENGTH;41}42if ((end - *p) <= n) {43return MBEDTLS_ERR_ASN1_OUT_OF_DATA;44}45*len = 0;46(*p)++;47while (n--) {48*len = (*len << 8) | **p;49(*p)++;50}51}5253if (*len > (size_t) (end - *p)) {54return MBEDTLS_ERR_ASN1_OUT_OF_DATA;55}5657return 0;58}5960int mbedtls_asn1_get_tag(unsigned char **p,61const unsigned char *end,62size_t *len, int tag)63{64if ((end - *p) < 1) {65return MBEDTLS_ERR_ASN1_OUT_OF_DATA;66}6768if (**p != tag) {69return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;70}7172(*p)++;7374return mbedtls_asn1_get_len(p, end, len);75}76#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */7778#if defined(MBEDTLS_ASN1_PARSE_C)79int mbedtls_asn1_get_bool(unsigned char **p,80const unsigned char *end,81int *val)82{83int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;84size_t len;8586if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {87return ret;88}8990if (len != 1) {91return MBEDTLS_ERR_ASN1_INVALID_LENGTH;92}9394*val = (**p != 0) ? 1 : 0;95(*p)++;9697return 0;98}99100static int asn1_get_tagged_int(unsigned char **p,101const unsigned char *end,102int tag, int *val)103{104int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;105size_t len;106107if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {108return ret;109}110111/*112* len==0 is malformed (0 must be represented as 020100 for INTEGER,113* or 0A0100 for ENUMERATED tags114*/115if (len == 0) {116return MBEDTLS_ERR_ASN1_INVALID_LENGTH;117}118/* This is a cryptography library. Reject negative integers. */119if ((**p & 0x80) != 0) {120return MBEDTLS_ERR_ASN1_INVALID_LENGTH;121}122123/* Skip leading zeros. */124while (len > 0 && **p == 0) {125++(*p);126--len;127}128129/* Reject integers that don't fit in an int. This code assumes that130* the int type has no padding bit. */131if (len > sizeof(int)) {132return MBEDTLS_ERR_ASN1_INVALID_LENGTH;133}134if (len == sizeof(int) && (**p & 0x80) != 0) {135return MBEDTLS_ERR_ASN1_INVALID_LENGTH;136}137138*val = 0;139while (len-- > 0) {140*val = (*val << 8) | **p;141(*p)++;142}143144return 0;145}146147int mbedtls_asn1_get_int(unsigned char **p,148const unsigned char *end,149int *val)150{151return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);152}153154int mbedtls_asn1_get_enum(unsigned char **p,155const unsigned char *end,156int *val)157{158return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);159}160161#if defined(MBEDTLS_BIGNUM_C)162int mbedtls_asn1_get_mpi(unsigned char **p,163const unsigned char *end,164mbedtls_mpi *X)165{166int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;167size_t len;168169if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {170return ret;171}172173ret = mbedtls_mpi_read_binary(X, *p, len);174175*p += len;176177return ret;178}179#endif /* MBEDTLS_BIGNUM_C */180181int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,182mbedtls_asn1_bitstring *bs)183{184int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;185186/* Certificate type is a single byte bitstring */187if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {188return ret;189}190191/* Check length, subtract one for actual bit string length */192if (bs->len < 1) {193return MBEDTLS_ERR_ASN1_OUT_OF_DATA;194}195bs->len -= 1;196197/* Get number of unused bits, ensure unused bits <= 7 */198bs->unused_bits = **p;199if (bs->unused_bits > 7) {200return MBEDTLS_ERR_ASN1_INVALID_LENGTH;201}202(*p)++;203204/* Get actual bitstring */205bs->p = *p;206*p += bs->len;207208if (*p != end) {209return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;210}211212return 0;213}214215/*216* Traverse an ASN.1 "SEQUENCE OF <tag>"217* and call a callback for each entry found.218*/219int mbedtls_asn1_traverse_sequence_of(220unsigned char **p,221const unsigned char *end,222unsigned char tag_must_mask, unsigned char tag_must_val,223unsigned char tag_may_mask, unsigned char tag_may_val,224int (*cb)(void *ctx, int tag,225unsigned char *start, size_t len),226void *ctx)227{228int ret;229size_t len;230231/* Get main sequence tag */232if ((ret = mbedtls_asn1_get_tag(p, end, &len,233MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {234return ret;235}236237if (*p + len != end) {238return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;239}240241while (*p < end) {242unsigned char const tag = *(*p)++;243244if ((tag & tag_must_mask) != tag_must_val) {245return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;246}247248if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {249return ret;250}251252if ((tag & tag_may_mask) == tag_may_val) {253if (cb != NULL) {254ret = cb(ctx, tag, *p, len);255if (ret != 0) {256return ret;257}258}259}260261*p += len;262}263264return 0;265}266267/*268* Get a bit string without unused bits269*/270int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,271size_t *len)272{273int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;274275if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {276return ret;277}278279if (*len == 0) {280return MBEDTLS_ERR_ASN1_INVALID_DATA;281}282--(*len);283284if (**p != 0) {285return MBEDTLS_ERR_ASN1_INVALID_DATA;286}287++(*p);288289return 0;290}291292void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)293{294while (seq != NULL) {295mbedtls_asn1_sequence *next = seq->next;296mbedtls_free(seq);297seq = next;298}299}300301typedef struct {302int tag;303mbedtls_asn1_sequence *cur;304} asn1_get_sequence_of_cb_ctx_t;305306static int asn1_get_sequence_of_cb(void *ctx,307int tag,308unsigned char *start,309size_t len)310{311asn1_get_sequence_of_cb_ctx_t *cb_ctx =312(asn1_get_sequence_of_cb_ctx_t *) ctx;313mbedtls_asn1_sequence *cur =314cb_ctx->cur;315316if (cur->buf.p != NULL) {317cur->next =318mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));319320if (cur->next == NULL) {321return MBEDTLS_ERR_ASN1_ALLOC_FAILED;322}323324cur = cur->next;325}326327cur->buf.p = start;328cur->buf.len = len;329cur->buf.tag = tag;330331cb_ctx->cur = cur;332return 0;333}334335/*336* Parses and splits an ASN.1 "SEQUENCE OF <tag>"337*/338int mbedtls_asn1_get_sequence_of(unsigned char **p,339const unsigned char *end,340mbedtls_asn1_sequence *cur,341int tag)342{343asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };344memset(cur, 0, sizeof(mbedtls_asn1_sequence));345return mbedtls_asn1_traverse_sequence_of(346p, end, 0xFF, tag, 0, 0,347asn1_get_sequence_of_cb, &cb_ctx);348}349350int mbedtls_asn1_get_alg(unsigned char **p,351const unsigned char *end,352mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)353{354int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;355size_t len;356357if ((ret = mbedtls_asn1_get_tag(p, end, &len,358MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {359return ret;360}361362if ((end - *p) < 1) {363return MBEDTLS_ERR_ASN1_OUT_OF_DATA;364}365366alg->tag = **p;367end = *p + len;368369if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {370return ret;371}372373alg->p = *p;374*p += alg->len;375376if (*p == end) {377mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));378return 0;379}380381params->tag = **p;382(*p)++;383384if ((ret = mbedtls_asn1_get_len(p, end, ¶ms->len)) != 0) {385return ret;386}387388params->p = *p;389*p += params->len;390391if (*p != end) {392return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;393}394395return 0;396}397398int mbedtls_asn1_get_alg_null(unsigned char **p,399const unsigned char *end,400mbedtls_asn1_buf *alg)401{402int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;403mbedtls_asn1_buf params;404405memset(¶ms, 0, sizeof(mbedtls_asn1_buf));406407if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 0) {408return ret;409}410411if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {412return MBEDTLS_ERR_ASN1_INVALID_DATA;413}414415return 0;416}417418#if !defined(MBEDTLS_DEPRECATED_REMOVED)419void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)420{421if (cur == NULL) {422return;423}424425mbedtls_free(cur->oid.p);426mbedtls_free(cur->val.p);427428mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));429}430#endif /* MBEDTLS_DEPRECATED_REMOVED */431432void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)433{434mbedtls_asn1_named_data *cur;435436while ((cur = *head) != NULL) {437*head = cur->next;438mbedtls_free(cur->oid.p);439mbedtls_free(cur->val.p);440mbedtls_free(cur);441}442}443444void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)445{446for (mbedtls_asn1_named_data *next; name != NULL; name = next) {447next = name->next;448mbedtls_free(name);449}450}451452const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,453const char *oid, size_t len)454{455while (list != NULL) {456if (list->oid.len == len &&457memcmp(list->oid.p, oid, len) == 0) {458break;459}460461list = list->next;462}463464return list;465}466467#endif /* MBEDTLS_ASN1_PARSE_C */468469470