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 */ 28int 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 61int 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) 80int 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 101static 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 148int 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 155int 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) 163int 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 182int 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 */ 220int 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 */ 271int 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 293void 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 302typedef struct { 303 int tag; 304 mbedtls_asn1_sequence *cur; 305} asn1_get_sequence_of_cb_ctx_t; 306 307static 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 */ 339int 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 351int 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, ¶ms->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 399int 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(¶ms, 0, sizeof(mbedtls_asn1_buf)); 407 408 if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 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) 420void 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 433void 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 445void 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 453const 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 */ 469