1 /* 2 * X.509 common functions for parsing and verification 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 /* 8 * The ITU-T X.509 standard defines a certificate format for PKI. 9 * 10 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) 11 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) 12 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) 13 * 14 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf 15 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf 16 */ 17 18 #include "common.h" 19 20 #if defined(MBEDTLS_X509_USE_C) 21 22 #include "x509_internal.h" 23 #include "mbedtls/asn1.h" 24 #include "mbedtls/error.h" 25 #include "mbedtls/oid.h" 26 27 #include <stdio.h> 28 #include <string.h> 29 30 #if defined(MBEDTLS_PEM_PARSE_C) 31 #include "mbedtls/pem.h" 32 #endif 33 34 #include "mbedtls/asn1write.h" 35 36 #include "mbedtls/platform.h" 37 38 #if defined(MBEDTLS_HAVE_TIME) 39 #include "mbedtls/platform_time.h" 40 #endif 41 #if defined(MBEDTLS_HAVE_TIME_DATE) 42 #include "mbedtls/platform_util.h" 43 #include <time.h> 44 #endif 45 46 #define CHECK(code) \ 47 do { \ 48 if ((ret = (code)) != 0) { \ 49 return ret; \ 50 } \ 51 } while (0) 52 53 #define CHECK_RANGE(min, max, val) \ 54 do { \ 55 if ((val) < (min) || (val) > (max)) { \ 56 return ret; \ 57 } \ 58 } while (0) 59 60 /* 61 * CertificateSerialNumber ::= INTEGER 62 */ 63 int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, 64 mbedtls_x509_buf *serial) 65 { 66 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 67 68 if ((end - *p) < 1) { 69 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, 70 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 71 } 72 73 if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) && 74 **p != MBEDTLS_ASN1_INTEGER) { 75 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, 76 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 77 } 78 79 serial->tag = *(*p)++; 80 81 if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) { 82 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret); 83 } 84 85 serial->p = *p; 86 *p += serial->len; 87 88 return 0; 89 } 90 91 /* Get an algorithm identifier without parameters (eg for signatures) 92 * 93 * AlgorithmIdentifier ::= SEQUENCE { 94 * algorithm OBJECT IDENTIFIER, 95 * parameters ANY DEFINED BY algorithm OPTIONAL } 96 */ 97 int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, 98 mbedtls_x509_buf *alg) 99 { 100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 101 102 if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { 103 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 104 } 105 106 return 0; 107 } 108 109 /* 110 * Parse an algorithm identifier with (optional) parameters 111 */ 112 int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, 113 mbedtls_x509_buf *alg, mbedtls_x509_buf *params) 114 { 115 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 116 117 if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) { 118 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 119 } 120 121 return 0; 122 } 123 124 /* 125 * Convert md type to string 126 */ 127 #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 128 129 static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) 130 { 131 switch (md_alg) { 132 #if defined(MBEDTLS_MD_CAN_MD5) 133 case MBEDTLS_MD_MD5: 134 return "MD5"; 135 #endif 136 #if defined(MBEDTLS_MD_CAN_SHA1) 137 case MBEDTLS_MD_SHA1: 138 return "SHA1"; 139 #endif 140 #if defined(MBEDTLS_MD_CAN_SHA224) 141 case MBEDTLS_MD_SHA224: 142 return "SHA224"; 143 #endif 144 #if defined(MBEDTLS_MD_CAN_SHA256) 145 case MBEDTLS_MD_SHA256: 146 return "SHA256"; 147 #endif 148 #if defined(MBEDTLS_MD_CAN_SHA384) 149 case MBEDTLS_MD_SHA384: 150 return "SHA384"; 151 #endif 152 #if defined(MBEDTLS_MD_CAN_SHA512) 153 case MBEDTLS_MD_SHA512: 154 return "SHA512"; 155 #endif 156 #if defined(MBEDTLS_MD_CAN_RIPEMD160) 157 case MBEDTLS_MD_RIPEMD160: 158 return "RIPEMD160"; 159 #endif 160 case MBEDTLS_MD_NONE: 161 return NULL; 162 default: 163 return NULL; 164 } 165 } 166 167 #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ 168 169 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 170 /* 171 * HashAlgorithm ::= AlgorithmIdentifier 172 * 173 * AlgorithmIdentifier ::= SEQUENCE { 174 * algorithm OBJECT IDENTIFIER, 175 * parameters ANY DEFINED BY algorithm OPTIONAL } 176 * 177 * For HashAlgorithm, parameters MUST be NULL or absent. 178 */ 179 static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) 180 { 181 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 182 unsigned char *p; 183 const unsigned char *end; 184 mbedtls_x509_buf md_oid; 185 size_t len; 186 187 /* Make sure we got a SEQUENCE and setup bounds */ 188 if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 189 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 190 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 191 } 192 193 p = alg->p; 194 end = p + alg->len; 195 196 if (p >= end) { 197 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 198 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 199 } 200 201 /* Parse md_oid */ 202 md_oid.tag = *p; 203 204 if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) { 205 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 206 } 207 208 md_oid.p = p; 209 p += md_oid.len; 210 211 /* Get md_alg from md_oid */ 212 if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) { 213 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 214 } 215 216 /* Make sure params is absent of NULL */ 217 if (p == end) { 218 return 0; 219 } 220 221 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) { 222 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 223 } 224 225 if (p != end) { 226 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 227 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 228 } 229 230 return 0; 231 } 232 233 /* 234 * RSASSA-PSS-params ::= SEQUENCE { 235 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, 236 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, 237 * saltLength [2] INTEGER DEFAULT 20, 238 * trailerField [3] INTEGER DEFAULT 1 } 239 * -- Note that the tags in this Sequence are explicit. 240 * 241 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value 242 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other 243 * option. Enforce this at parsing time. 244 */ 245 int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, 246 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, 247 int *salt_len) 248 { 249 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 250 unsigned char *p; 251 const unsigned char *end, *end2; 252 size_t len; 253 mbedtls_x509_buf alg_id, alg_params; 254 255 /* First set everything to defaults */ 256 *md_alg = MBEDTLS_MD_SHA1; 257 *mgf_md = MBEDTLS_MD_SHA1; 258 *salt_len = 20; 259 260 /* Make sure params is a SEQUENCE and setup bounds */ 261 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 262 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 263 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 264 } 265 266 p = (unsigned char *) params->p; 267 end = p + params->len; 268 269 if (p == end) { 270 return 0; 271 } 272 273 /* 274 * HashAlgorithm 275 */ 276 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 277 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 278 0)) == 0) { 279 end2 = p + len; 280 281 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ 282 if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) { 283 return ret; 284 } 285 286 if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) { 287 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 288 } 289 290 if (p != end2) { 291 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 292 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 293 } 294 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 295 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 296 } 297 298 if (p == end) { 299 return 0; 300 } 301 302 /* 303 * MaskGenAlgorithm 304 */ 305 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 306 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 307 1)) == 0) { 308 end2 = p + len; 309 310 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ 311 if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) { 312 return ret; 313 } 314 315 /* Only MFG1 is recognised for now */ 316 if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) { 317 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, 318 MBEDTLS_ERR_OID_NOT_FOUND); 319 } 320 321 /* Parse HashAlgorithm */ 322 if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) { 323 return ret; 324 } 325 326 if (p != end2) { 327 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 328 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 329 } 330 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 331 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 332 } 333 334 if (p == end) { 335 return 0; 336 } 337 338 /* 339 * salt_len 340 */ 341 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 342 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 343 2)) == 0) { 344 end2 = p + len; 345 346 if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) { 347 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 348 } 349 350 if (p != end2) { 351 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 352 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 353 } 354 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 355 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 356 } 357 358 if (p == end) { 359 return 0; 360 } 361 362 /* 363 * trailer_field (if present, must be 1) 364 */ 365 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 366 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 367 3)) == 0) { 368 int trailer_field; 369 370 end2 = p + len; 371 372 if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) { 373 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 374 } 375 376 if (p != end2) { 377 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 378 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 379 } 380 381 if (trailer_field != 1) { 382 return MBEDTLS_ERR_X509_INVALID_ALG; 383 } 384 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 385 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 386 } 387 388 if (p != end) { 389 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 390 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 391 } 392 393 return 0; 394 } 395 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 396 397 /* 398 * AttributeTypeAndValue ::= SEQUENCE { 399 * type AttributeType, 400 * value AttributeValue } 401 * 402 * AttributeType ::= OBJECT IDENTIFIER 403 * 404 * AttributeValue ::= ANY DEFINED BY AttributeType 405 */ 406 static int x509_get_attr_type_value(unsigned char **p, 407 const unsigned char *end, 408 mbedtls_x509_name *cur) 409 { 410 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 411 size_t len; 412 mbedtls_x509_buf *oid; 413 mbedtls_x509_buf *val; 414 415 if ((ret = mbedtls_asn1_get_tag(p, end, &len, 416 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 417 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 418 } 419 420 end = *p + len; 421 422 if ((end - *p) < 1) { 423 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 424 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 425 } 426 427 oid = &cur->oid; 428 oid->tag = **p; 429 430 if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) { 431 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 432 } 433 434 oid->p = *p; 435 *p += oid->len; 436 437 if ((end - *p) < 1) { 438 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 439 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 440 } 441 442 if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && 443 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && 444 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && 445 **p != MBEDTLS_ASN1_BIT_STRING) { 446 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 447 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 448 } 449 450 val = &cur->val; 451 val->tag = *(*p)++; 452 453 if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) { 454 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 455 } 456 457 val->p = *p; 458 *p += val->len; 459 460 if (*p != end) { 461 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 462 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 463 } 464 465 cur->next = NULL; 466 467 return 0; 468 } 469 470 /* 471 * Name ::= CHOICE { -- only one possibility for now -- 472 * rdnSequence RDNSequence } 473 * 474 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 475 * 476 * RelativeDistinguishedName ::= 477 * SET OF AttributeTypeAndValue 478 * 479 * AttributeTypeAndValue ::= SEQUENCE { 480 * type AttributeType, 481 * value AttributeValue } 482 * 483 * AttributeType ::= OBJECT IDENTIFIER 484 * 485 * AttributeValue ::= ANY DEFINED BY AttributeType 486 * 487 * The data structure is optimized for the common case where each RDN has only 488 * one element, which is represented as a list of AttributeTypeAndValue. 489 * For the general case we still use a flat list, but we mark elements of the 490 * same set so that they are "merged" together in the functions that consume 491 * this list, eg mbedtls_x509_dn_gets(). 492 * 493 * On success, this function may allocate a linked list starting at cur->next 494 * that must later be free'd by the caller using mbedtls_free(). In error 495 * cases, this function frees all allocated memory internally and the caller 496 * has no freeing responsibilities. 497 */ 498 int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, 499 mbedtls_x509_name *cur) 500 { 501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 502 size_t set_len; 503 const unsigned char *end_set; 504 mbedtls_x509_name *head = cur; 505 506 /* don't use recursion, we'd risk stack overflow if not optimized */ 507 while (1) { 508 /* 509 * parse SET 510 */ 511 if ((ret = mbedtls_asn1_get_tag(p, end, &set_len, 512 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { 513 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 514 goto error; 515 } 516 517 end_set = *p + set_len; 518 519 while (1) { 520 if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { 521 goto error; 522 } 523 524 if (*p == end_set) { 525 break; 526 } 527 528 /* Mark this item as being no the only one in a set */ 529 cur->next_merged = 1; 530 531 cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); 532 533 if (cur->next == NULL) { 534 ret = MBEDTLS_ERR_X509_ALLOC_FAILED; 535 goto error; 536 } 537 538 cur = cur->next; 539 } 540 541 /* 542 * continue until end of SEQUENCE is reached 543 */ 544 if (*p == end) { 545 return 0; 546 } 547 548 cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); 549 550 if (cur->next == NULL) { 551 ret = MBEDTLS_ERR_X509_ALLOC_FAILED; 552 goto error; 553 } 554 555 cur = cur->next; 556 } 557 558 error: 559 /* Skip the first element as we did not allocate it */ 560 mbedtls_asn1_free_named_data_list_shallow(head->next); 561 head->next = NULL; 562 563 return ret; 564 } 565 566 static int x509_date_is_valid(const mbedtls_x509_time *t) 567 { 568 unsigned int month_days; 569 unsigned int year; 570 switch (t->mon) { 571 case 1: case 3: case 5: case 7: case 8: case 10: case 12: 572 month_days = 31; 573 break; 574 case 4: case 6: case 9: case 11: 575 month_days = 30; 576 break; 577 case 2: 578 year = (unsigned int) t->year; 579 month_days = ((year & 3) || (!(year % 100) 580 && (year % 400))) 581 ? 28 : 29; 582 break; 583 default: 584 return MBEDTLS_ERR_X509_INVALID_DATE; 585 } 586 587 if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */ 588 /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */ 589 (unsigned int) t->year > 9999 || /* (0 - 9999) */ 590 (unsigned int) t->hour > 23 || /* (0 - 23) */ 591 (unsigned int) t->min > 59 || /* (0 - 59) */ 592 (unsigned int) t->sec > 59) { /* (0 - 59) */ 593 return MBEDTLS_ERR_X509_INVALID_DATE; 594 } 595 596 return 0; 597 } 598 599 static int x509_parse2_int(const unsigned char *p) 600 { 601 uint32_t d1 = p[0] - '0'; 602 uint32_t d2 = p[1] - '0'; 603 return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1; 604 } 605 606 /* 607 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) 608 * field. 609 */ 610 static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, 611 size_t yearlen) 612 { 613 int x; 614 615 /* 616 * Parse year, month, day, hour, minute, second 617 */ 618 tm->year = x509_parse2_int(p); 619 if (tm->year < 0) { 620 return MBEDTLS_ERR_X509_INVALID_DATE; 621 } 622 623 if (4 == yearlen) { 624 x = tm->year * 100; 625 p += 2; 626 tm->year = x509_parse2_int(p); 627 if (tm->year < 0) { 628 return MBEDTLS_ERR_X509_INVALID_DATE; 629 } 630 } else { 631 x = (tm->year < 50) ? 2000 : 1900; 632 } 633 tm->year += x; 634 635 tm->mon = x509_parse2_int(p + 2); 636 tm->day = x509_parse2_int(p + 4); 637 tm->hour = x509_parse2_int(p + 6); 638 tm->min = x509_parse2_int(p + 8); 639 tm->sec = x509_parse2_int(p + 10); 640 641 return x509_date_is_valid(tm); 642 } 643 644 /* 645 * Time ::= CHOICE { 646 * utcTime UTCTime, 647 * generalTime GeneralizedTime } 648 */ 649 int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, 650 mbedtls_x509_time *tm) 651 { 652 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 653 size_t len, year_len; 654 unsigned char tag; 655 656 if ((end - *p) < 1) { 657 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 658 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 659 } 660 661 tag = **p; 662 663 if (tag == MBEDTLS_ASN1_UTC_TIME) { 664 year_len = 2; 665 } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) { 666 year_len = 4; 667 } else { 668 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 669 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 670 } 671 672 (*p)++; 673 ret = mbedtls_asn1_get_len(p, end, &len); 674 675 if (ret != 0) { 676 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); 677 } 678 679 /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */ 680 if (len != year_len + 10 && 681 !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) { 682 return MBEDTLS_ERR_X509_INVALID_DATE; 683 } 684 685 (*p) += len; 686 return x509_parse_time(*p - len, tm, year_len); 687 } 688 689 int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) 690 { 691 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 692 size_t len; 693 int tag_type; 694 695 if ((end - *p) < 1) { 696 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, 697 MBEDTLS_ERR_ASN1_OUT_OF_DATA); 698 } 699 700 tag_type = **p; 701 702 if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { 703 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret); 704 } 705 706 sig->tag = tag_type; 707 sig->len = len; 708 sig->p = *p; 709 710 *p += len; 711 712 return 0; 713 } 714 715 /* 716 * Get signature algorithm from alg OID and optional parameters 717 */ 718 int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, 719 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, 720 void **sig_opts) 721 { 722 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 723 724 if (*sig_opts != NULL) { 725 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 726 } 727 728 if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) { 729 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret); 730 } 731 732 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 733 if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) { 734 mbedtls_pk_rsassa_pss_options *pss_opts; 735 736 pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options)); 737 if (pss_opts == NULL) { 738 return MBEDTLS_ERR_X509_ALLOC_FAILED; 739 } 740 741 ret = mbedtls_x509_get_rsassa_pss_params(sig_params, 742 md_alg, 743 &pss_opts->mgf1_hash_id, 744 &pss_opts->expected_salt_len); 745 if (ret != 0) { 746 mbedtls_free(pss_opts); 747 return ret; 748 } 749 750 *sig_opts = (void *) pss_opts; 751 } else 752 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 753 { 754 /* Make sure parameters are absent or NULL */ 755 if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) || 756 sig_params->len != 0) { 757 return MBEDTLS_ERR_X509_INVALID_ALG; 758 } 759 } 760 761 return 0; 762 } 763 764 /* 765 * X.509 Extensions (No parsing of extensions, pointer should 766 * be either manually updated or extensions should be parsed!) 767 */ 768 int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, 769 mbedtls_x509_buf *ext, int tag) 770 { 771 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 772 size_t len; 773 774 /* Extension structure use EXPLICIT tagging. That is, the actual 775 * `Extensions` structure is wrapped by a tag-length pair using 776 * the respective context-specific tag. */ 777 ret = mbedtls_asn1_get_tag(p, end, &ext->len, 778 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag); 779 if (ret != 0) { 780 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 781 } 782 783 ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; 784 ext->p = *p; 785 end = *p + ext->len; 786 787 /* 788 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 789 */ 790 if ((ret = mbedtls_asn1_get_tag(p, end, &len, 791 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 792 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 793 } 794 795 if (end != *p + len) { 796 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 797 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 798 } 799 800 return 0; 801 } 802 803 static char nibble_to_hex_digit(int i) 804 { 805 return (i < 10) ? (i + '0') : (i - 10 + 'A'); 806 } 807 808 /* 809 * Store the name in printable form into buf; no more 810 * than size characters will be written 811 */ 812 int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) 813 { 814 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 815 size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start; 816 /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/ 817 unsigned char asn1_tag_len_buf[6]; 818 unsigned char *asn1_len_p; 819 unsigned char c, merge = 0; 820 const mbedtls_x509_name *name; 821 const char *short_name = NULL; 822 char lowbits, highbits; 823 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; 824 int print_hexstring; 825 826 memset(s, 0, sizeof(s)); 827 828 name = dn; 829 p = buf; 830 n = size; 831 832 while (name != NULL) { 833 if (!name->oid.p) { 834 name = name->next; 835 continue; 836 } 837 838 if (name != dn) { 839 ret = mbedtls_snprintf(p, n, merge ? " + " : ", "); 840 MBEDTLS_X509_SAFE_SNPRINTF; 841 } 842 843 print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) && 844 (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) && 845 (name->val.tag != MBEDTLS_ASN1_IA5_STRING); 846 847 if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) { 848 ret = mbedtls_snprintf(p, n, "%s=", short_name); 849 } else { 850 if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) { 851 n -= ret; 852 p += ret; 853 ret = mbedtls_snprintf(p, n, "="); 854 print_hexstring = 1; 855 } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { 856 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 857 } else { 858 ret = mbedtls_snprintf(p, n, "\?\?="); 859 } 860 } 861 MBEDTLS_X509_SAFE_SNPRINTF; 862 863 if (print_hexstring) { 864 s[0] = '#'; 865 866 asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf); 867 if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) { 868 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 869 } 870 asn1_len_size = ret; 871 if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) { 872 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 873 } 874 asn1_tag_size = ret; 875 asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size; 876 for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) { 877 if (j + 1 >= sizeof(s) - 1) { 878 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 879 } 880 c = asn1_tag_len_buf[asn1_tag_len_buf_start+i]; 881 lowbits = (c & 0x0F); 882 highbits = c >> 4; 883 s[j++] = nibble_to_hex_digit(highbits); 884 s[j++] = nibble_to_hex_digit(lowbits); 885 } 886 for (i = 0; i < name->val.len; i++) { 887 if (j + 1 >= sizeof(s) - 1) { 888 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 889 } 890 c = name->val.p[i]; 891 lowbits = (c & 0x0F); 892 highbits = c >> 4; 893 s[j++] = nibble_to_hex_digit(highbits); 894 s[j++] = nibble_to_hex_digit(lowbits); 895 } 896 } else { 897 for (i = 0, j = 0; i < name->val.len; i++, j++) { 898 if (j >= sizeof(s) - 1) { 899 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 900 } 901 902 c = name->val.p[i]; 903 // Special characters requiring escaping, RFC 4514 Section 2.4 904 if (c == '\0') { 905 return MBEDTLS_ERR_X509_INVALID_NAME; 906 } else { 907 if (strchr(",=+<>;\"\\", c) || 908 ((i == 0) && strchr("# ", c)) || 909 ((i == name->val.len-1) && (c == ' '))) { 910 if (j + 1 >= sizeof(s) - 1) { 911 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 912 } 913 s[j++] = '\\'; 914 } 915 } 916 if (c < 32 || c >= 127) { 917 if (j + 3 >= sizeof(s) - 1) { 918 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 919 } 920 s[j++] = '\\'; 921 lowbits = (c & 0x0F); 922 highbits = c >> 4; 923 s[j++] = nibble_to_hex_digit(highbits); 924 s[j] = nibble_to_hex_digit(lowbits); 925 } else { 926 s[j] = c; 927 } 928 } 929 } 930 s[j] = '\0'; 931 ret = mbedtls_snprintf(p, n, "%s", s); 932 MBEDTLS_X509_SAFE_SNPRINTF; 933 934 merge = name->next_merged; 935 name = name->next; 936 } 937 938 return (int) (size - n); 939 } 940 941 /* 942 * Store the serial in printable form into buf; no more 943 * than size characters will be written 944 */ 945 int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) 946 { 947 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 948 size_t i, n, nr; 949 char *p; 950 951 p = buf; 952 n = size; 953 954 nr = (serial->len <= 32) 955 ? serial->len : 28; 956 957 for (i = 0; i < nr; i++) { 958 if (i == 0 && nr > 1 && serial->p[i] == 0x0) { 959 continue; 960 } 961 962 ret = mbedtls_snprintf(p, n, "%02X%s", 963 serial->p[i], (i < nr - 1) ? ":" : ""); 964 MBEDTLS_X509_SAFE_SNPRINTF; 965 } 966 967 if (nr != serial->len) { 968 ret = mbedtls_snprintf(p, n, "...."); 969 MBEDTLS_X509_SAFE_SNPRINTF; 970 } 971 972 return (int) (size - n); 973 } 974 975 #if !defined(MBEDTLS_X509_REMOVE_INFO) 976 /* 977 * Helper for writing signature algorithms 978 */ 979 int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, 980 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, 981 const void *sig_opts) 982 { 983 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 984 char *p = buf; 985 size_t n = size; 986 const char *desc = NULL; 987 988 ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc); 989 if (ret != 0) { 990 ret = mbedtls_snprintf(p, n, "???"); 991 } else { 992 ret = mbedtls_snprintf(p, n, "%s", desc); 993 } 994 MBEDTLS_X509_SAFE_SNPRINTF; 995 996 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 997 if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { 998 const mbedtls_pk_rsassa_pss_options *pss_opts; 999 1000 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; 1001 1002 const char *name = md_type_to_string(md_alg); 1003 const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); 1004 1005 ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", 1006 name ? name : "???", 1007 mgf_name ? mgf_name : "???", 1008 (unsigned int) pss_opts->expected_salt_len); 1009 MBEDTLS_X509_SAFE_SNPRINTF; 1010 } 1011 #else 1012 ((void) pk_alg); 1013 ((void) md_alg); 1014 ((void) sig_opts); 1015 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 1016 1017 return (int) (size - n); 1018 } 1019 #endif /* MBEDTLS_X509_REMOVE_INFO */ 1020 1021 /* 1022 * Helper for writing "RSA key size", "EC key size", etc 1023 */ 1024 int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) 1025 { 1026 char *p = buf; 1027 size_t n = buf_size; 1028 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1029 1030 ret = mbedtls_snprintf(p, n, "%s key size", name); 1031 MBEDTLS_X509_SAFE_SNPRINTF; 1032 1033 return 0; 1034 } 1035 1036 int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, 1037 const mbedtls_x509_time *t2) 1038 { 1039 int x; 1040 1041 x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) - 1042 ((t2->year << 9) | (t2->mon << 5) | (t2->day))); 1043 if (x != 0) { 1044 return x; 1045 } 1046 1047 x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) - 1048 ((t2->hour << 12) | (t2->min << 6) | (t2->sec))); 1049 return x; 1050 } 1051 1052 #if defined(MBEDTLS_HAVE_TIME_DATE) 1053 int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) 1054 { 1055 struct tm tm; 1056 1057 if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) { 1058 return -1; 1059 } 1060 1061 now->year = tm.tm_year + 1900; 1062 now->mon = tm.tm_mon + 1; 1063 now->day = tm.tm_mday; 1064 now->hour = tm.tm_hour; 1065 now->min = tm.tm_min; 1066 now->sec = tm.tm_sec; 1067 return 0; 1068 } 1069 1070 static int x509_get_current_time(mbedtls_x509_time *now) 1071 { 1072 return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now); 1073 } 1074 1075 int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) 1076 { 1077 mbedtls_x509_time now; 1078 1079 if (x509_get_current_time(&now) != 0) { 1080 return 1; 1081 } 1082 1083 return mbedtls_x509_time_cmp(to, &now) < 0; 1084 } 1085 1086 int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) 1087 { 1088 mbedtls_x509_time now; 1089 1090 if (x509_get_current_time(&now) != 0) { 1091 return 1; 1092 } 1093 1094 return mbedtls_x509_time_cmp(from, &now) > 0; 1095 } 1096 1097 #else /* MBEDTLS_HAVE_TIME_DATE */ 1098 1099 int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) 1100 { 1101 ((void) to); 1102 return 0; 1103 } 1104 1105 int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) 1106 { 1107 ((void) from); 1108 return 0; 1109 } 1110 #endif /* MBEDTLS_HAVE_TIME_DATE */ 1111 1112 /* Common functions for parsing CRT and CSR. */ 1113 #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) 1114 /* 1115 * OtherName ::= SEQUENCE { 1116 * type-id OBJECT IDENTIFIER, 1117 * value [0] EXPLICIT ANY DEFINED BY type-id } 1118 * 1119 * HardwareModuleName ::= SEQUENCE { 1120 * hwType OBJECT IDENTIFIER, 1121 * hwSerialNum OCTET STRING } 1122 * 1123 * NOTE: we currently only parse and use otherName of type HwModuleName, 1124 * as defined in RFC 4108. 1125 */ 1126 static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, 1127 mbedtls_x509_san_other_name *other_name) 1128 { 1129 int ret = 0; 1130 size_t len; 1131 unsigned char *p = subject_alt_name->p; 1132 const unsigned char *end = p + subject_alt_name->len; 1133 mbedtls_x509_buf cur_oid; 1134 1135 if ((subject_alt_name->tag & 1136 (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != 1137 (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { 1138 /* 1139 * The given subject alternative name is not of type "othername". 1140 */ 1141 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1142 } 1143 1144 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1145 MBEDTLS_ASN1_OID)) != 0) { 1146 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1147 } 1148 1149 cur_oid.tag = MBEDTLS_ASN1_OID; 1150 cur_oid.p = p; 1151 cur_oid.len = len; 1152 1153 /* 1154 * Only HwModuleName is currently supported. 1155 */ 1156 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { 1157 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 1158 } 1159 other_name->type_id = cur_oid; 1160 1161 p += len; 1162 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1163 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 1164 0) { 1165 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1166 } 1167 1168 if (end != p + len) { 1169 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1170 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1171 } 1172 1173 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1174 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1175 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1176 } 1177 1178 if (end != p + len) { 1179 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1180 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1181 } 1182 1183 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { 1184 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1185 } 1186 1187 other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; 1188 other_name->value.hardware_module_name.oid.p = p; 1189 other_name->value.hardware_module_name.oid.len = len; 1190 1191 p += len; 1192 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1193 MBEDTLS_ASN1_OCTET_STRING)) != 0) { 1194 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1195 } 1196 1197 other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; 1198 other_name->value.hardware_module_name.val.p = p; 1199 other_name->value.hardware_module_name.val.len = len; 1200 p += len; 1201 if (p != end) { 1202 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1203 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1204 } 1205 return 0; 1206 } 1207 1208 /* Check mbedtls_x509_get_subject_alt_name for detailed description. 1209 * 1210 * In some cases while parsing subject alternative names the sequence tag is optional 1211 * (e.g. CertSerialNumber). This function is designed to handle such case. 1212 */ 1213 int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, 1214 const unsigned char *end, 1215 mbedtls_x509_sequence *subject_alt_name) 1216 { 1217 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1218 size_t tag_len; 1219 mbedtls_asn1_sequence *cur = subject_alt_name; 1220 1221 while (*p < end) { 1222 mbedtls_x509_subject_alternative_name tmp_san_name; 1223 mbedtls_x509_buf tmp_san_buf; 1224 memset(&tmp_san_name, 0, sizeof(tmp_san_name)); 1225 1226 tmp_san_buf.tag = **p; 1227 (*p)++; 1228 1229 if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { 1230 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1231 } 1232 1233 tmp_san_buf.p = *p; 1234 tmp_san_buf.len = tag_len; 1235 1236 if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != 1237 MBEDTLS_ASN1_CONTEXT_SPECIFIC) { 1238 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1239 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 1240 } 1241 1242 /* 1243 * Check that the SAN is structured correctly by parsing it. 1244 * The SAN structure is discarded afterwards. 1245 */ 1246 ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name); 1247 /* 1248 * In case the extension is malformed, return an error, 1249 * and clear the allocated sequences. 1250 */ 1251 if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { 1252 mbedtls_asn1_sequence_free(subject_alt_name->next); 1253 subject_alt_name->next = NULL; 1254 return ret; 1255 } 1256 1257 mbedtls_x509_free_subject_alt_name(&tmp_san_name); 1258 /* Allocate and assign next pointer */ 1259 if (cur->buf.p != NULL) { 1260 if (cur->next != NULL) { 1261 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; 1262 } 1263 1264 cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); 1265 1266 if (cur->next == NULL) { 1267 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1268 MBEDTLS_ERR_ASN1_ALLOC_FAILED); 1269 } 1270 1271 cur = cur->next; 1272 } 1273 1274 cur->buf = tmp_san_buf; 1275 *p += tmp_san_buf.len; 1276 } 1277 1278 /* Set final sequence entry's next pointer to NULL */ 1279 cur->next = NULL; 1280 1281 if (*p != end) { 1282 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1283 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1284 } 1285 1286 return 0; 1287 } 1288 1289 /* 1290 * SubjectAltName ::= GeneralNames 1291 * 1292 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 1293 * 1294 * GeneralName ::= CHOICE { 1295 * otherName [0] OtherName, 1296 * rfc822Name [1] IA5String, 1297 * dNSName [2] IA5String, 1298 * x400Address [3] ORAddress, 1299 * directoryName [4] Name, 1300 * ediPartyName [5] EDIPartyName, 1301 * uniformResourceIdentifier [6] IA5String, 1302 * iPAddress [7] OCTET STRING, 1303 * registeredID [8] OBJECT IDENTIFIER } 1304 * 1305 * OtherName ::= SEQUENCE { 1306 * type-id OBJECT IDENTIFIER, 1307 * value [0] EXPLICIT ANY DEFINED BY type-id } 1308 * 1309 * EDIPartyName ::= SEQUENCE { 1310 * nameAssigner [0] DirectoryString OPTIONAL, 1311 * partyName [1] DirectoryString } 1312 * 1313 * We list all types, but use the following GeneralName types from RFC 5280: 1314 * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" 1315 * of type "otherName", as defined in RFC 4108. 1316 */ 1317 int mbedtls_x509_get_subject_alt_name(unsigned char **p, 1318 const unsigned char *end, 1319 mbedtls_x509_sequence *subject_alt_name) 1320 { 1321 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1322 size_t len; 1323 1324 /* Get main sequence tag */ 1325 if ((ret = mbedtls_asn1_get_tag(p, end, &len, 1326 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1327 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1328 } 1329 1330 if (*p + len != end) { 1331 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1332 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1333 } 1334 1335 return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name); 1336 } 1337 1338 int mbedtls_x509_get_ns_cert_type(unsigned char **p, 1339 const unsigned char *end, 1340 unsigned char *ns_cert_type) 1341 { 1342 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1343 mbedtls_x509_bitstring bs = { 0, 0, NULL }; 1344 1345 if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { 1346 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1347 } 1348 1349 /* A bitstring with no flags set is still technically valid, as it will mean 1350 that the certificate has no designated purpose at the time of creation. */ 1351 if (bs.len == 0) { 1352 *ns_cert_type = 0; 1353 return 0; 1354 } 1355 1356 if (bs.len != 1) { 1357 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1358 MBEDTLS_ERR_ASN1_INVALID_LENGTH); 1359 } 1360 1361 /* Get actual bitstring */ 1362 *ns_cert_type = *bs.p; 1363 return 0; 1364 } 1365 1366 int mbedtls_x509_get_key_usage(unsigned char **p, 1367 const unsigned char *end, 1368 unsigned int *key_usage) 1369 { 1370 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1371 size_t i; 1372 mbedtls_x509_bitstring bs = { 0, 0, NULL }; 1373 1374 if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { 1375 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1376 } 1377 1378 /* A bitstring with no flags set is still technically valid, as it will mean 1379 that the certificate has no designated purpose at the time of creation. */ 1380 if (bs.len == 0) { 1381 *key_usage = 0; 1382 return 0; 1383 } 1384 1385 /* Get actual bitstring */ 1386 *key_usage = 0; 1387 for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { 1388 *key_usage |= (unsigned int) bs.p[i] << (8*i); 1389 } 1390 1391 return 0; 1392 } 1393 1394 int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, 1395 mbedtls_x509_subject_alternative_name *san) 1396 { 1397 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1398 switch (san_buf->tag & 1399 (MBEDTLS_ASN1_TAG_CLASS_MASK | 1400 MBEDTLS_ASN1_TAG_VALUE_MASK)) { 1401 /* 1402 * otherName 1403 */ 1404 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): 1405 { 1406 mbedtls_x509_san_other_name other_name; 1407 1408 ret = x509_get_other_name(san_buf, &other_name); 1409 if (ret != 0) { 1410 return ret; 1411 } 1412 1413 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1414 san->type = MBEDTLS_X509_SAN_OTHER_NAME; 1415 memcpy(&san->san.other_name, 1416 &other_name, sizeof(other_name)); 1417 1418 } 1419 break; 1420 /* 1421 * uniformResourceIdentifier 1422 */ 1423 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): 1424 { 1425 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1426 san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; 1427 1428 memcpy(&san->san.unstructured_name, 1429 san_buf, sizeof(*san_buf)); 1430 1431 } 1432 break; 1433 /* 1434 * dNSName 1435 */ 1436 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): 1437 { 1438 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1439 san->type = MBEDTLS_X509_SAN_DNS_NAME; 1440 1441 memcpy(&san->san.unstructured_name, 1442 san_buf, sizeof(*san_buf)); 1443 } 1444 break; 1445 /* 1446 * IP address 1447 */ 1448 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS): 1449 { 1450 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1451 san->type = MBEDTLS_X509_SAN_IP_ADDRESS; 1452 // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported 1453 if (san_buf->len == 4 || san_buf->len == 16) { 1454 memcpy(&san->san.unstructured_name, 1455 san_buf, sizeof(*san_buf)); 1456 } else { 1457 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1458 } 1459 } 1460 break; 1461 /* 1462 * rfc822Name 1463 */ 1464 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): 1465 { 1466 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1467 san->type = MBEDTLS_X509_SAN_RFC822_NAME; 1468 memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); 1469 } 1470 break; 1471 /* 1472 * directoryName 1473 */ 1474 case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME): 1475 { 1476 size_t name_len; 1477 unsigned char *p = san_buf->p; 1478 memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1479 san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME; 1480 1481 ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len, 1482 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); 1483 1484 if (ret != 0) { 1485 return ret; 1486 } 1487 1488 if ((ret = mbedtls_x509_get_name(&p, p + name_len, 1489 &san->san.directory_name)) != 0) { 1490 return ret; 1491 } 1492 } 1493 break; 1494 /* 1495 * Type not supported 1496 */ 1497 default: 1498 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 1499 } 1500 return 0; 1501 } 1502 1503 void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) 1504 { 1505 if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { 1506 mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next); 1507 } 1508 } 1509 1510 #if !defined(MBEDTLS_X509_REMOVE_INFO) 1511 int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, 1512 const mbedtls_x509_sequence 1513 *subject_alt_name, 1514 const char *prefix) 1515 { 1516 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1517 size_t i; 1518 size_t n = *size; 1519 char *p = *buf; 1520 const mbedtls_x509_sequence *cur = subject_alt_name; 1521 mbedtls_x509_subject_alternative_name san; 1522 int parse_ret; 1523 1524 while (cur != NULL) { 1525 memset(&san, 0, sizeof(san)); 1526 parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); 1527 if (parse_ret != 0) { 1528 if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { 1529 ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix); 1530 MBEDTLS_X509_SAFE_SNPRINTF; 1531 } else { 1532 ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix); 1533 MBEDTLS_X509_SAFE_SNPRINTF; 1534 } 1535 cur = cur->next; 1536 continue; 1537 } 1538 1539 switch (san.type) { 1540 /* 1541 * otherName 1542 */ 1543 case MBEDTLS_X509_SAN_OTHER_NAME: 1544 { 1545 mbedtls_x509_san_other_name *other_name = &san.san.other_name; 1546 1547 ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); 1548 MBEDTLS_X509_SAFE_SNPRINTF; 1549 1550 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, 1551 &other_name->type_id) == 0) { 1552 ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); 1553 MBEDTLS_X509_SAFE_SNPRINTF; 1554 ret = 1555 mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); 1556 MBEDTLS_X509_SAFE_SNPRINTF; 1557 1558 ret = mbedtls_oid_get_numeric_string(p, 1559 n, 1560 &other_name->value.hardware_module_name.oid); 1561 MBEDTLS_X509_SAFE_SNPRINTF; 1562 1563 ret = 1564 mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); 1565 MBEDTLS_X509_SAFE_SNPRINTF; 1566 1567 for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { 1568 ret = mbedtls_snprintf(p, 1569 n, 1570 "%02X", 1571 other_name->value.hardware_module_name.val.p[i]); 1572 MBEDTLS_X509_SAFE_SNPRINTF; 1573 } 1574 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ 1575 } 1576 break; 1577 /* 1578 * uniformResourceIdentifier 1579 */ 1580 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 1581 { 1582 ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix); 1583 MBEDTLS_X509_SAFE_SNPRINTF; 1584 if (san.san.unstructured_name.len >= n) { 1585 if (n > 0) { 1586 *p = '\0'; 1587 } 1588 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1589 } 1590 1591 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); 1592 p += san.san.unstructured_name.len; 1593 n -= san.san.unstructured_name.len; 1594 } 1595 break; 1596 /* 1597 * dNSName 1598 * RFC822 Name 1599 */ 1600 case MBEDTLS_X509_SAN_DNS_NAME: 1601 case MBEDTLS_X509_SAN_RFC822_NAME: 1602 { 1603 const char *dns_name = "dNSName"; 1604 const char *rfc822_name = "rfc822Name"; 1605 1606 ret = mbedtls_snprintf(p, n, 1607 "\n%s %s : ", 1608 prefix, 1609 san.type == 1610 MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); 1611 MBEDTLS_X509_SAFE_SNPRINTF; 1612 if (san.san.unstructured_name.len >= n) { 1613 if (n > 0) { 1614 *p = '\0'; 1615 } 1616 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1617 } 1618 1619 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); 1620 p += san.san.unstructured_name.len; 1621 n -= san.san.unstructured_name.len; 1622 } 1623 break; 1624 /* 1625 * iPAddress 1626 */ 1627 case MBEDTLS_X509_SAN_IP_ADDRESS: 1628 { 1629 ret = mbedtls_snprintf(p, n, "\n%s %s : ", 1630 prefix, "iPAddress"); 1631 MBEDTLS_X509_SAFE_SNPRINTF; 1632 if (san.san.unstructured_name.len >= n) { 1633 if (n > 0) { 1634 *p = '\0'; 1635 } 1636 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1637 } 1638 1639 unsigned char *ip = san.san.unstructured_name.p; 1640 // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported 1641 if (san.san.unstructured_name.len == 4) { 1642 ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); 1643 MBEDTLS_X509_SAFE_SNPRINTF; 1644 } else if (san.san.unstructured_name.len == 16) { 1645 ret = mbedtls_snprintf(p, n, 1646 "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X", 1647 ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], 1648 ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], 1649 ip[14], ip[15]); 1650 MBEDTLS_X509_SAFE_SNPRINTF; 1651 } else { 1652 if (n > 0) { 1653 *p = '\0'; 1654 } 1655 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1656 } 1657 } 1658 break; 1659 /* 1660 * directoryName 1661 */ 1662 case MBEDTLS_X509_SAN_DIRECTORY_NAME: 1663 { 1664 ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix); 1665 if (ret < 0 || (size_t) ret >= n) { 1666 mbedtls_x509_free_subject_alt_name(&san); 1667 } 1668 1669 MBEDTLS_X509_SAFE_SNPRINTF; 1670 ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name); 1671 1672 if (ret < 0) { 1673 mbedtls_x509_free_subject_alt_name(&san); 1674 if (n > 0) { 1675 *p = '\0'; 1676 } 1677 return ret; 1678 } 1679 1680 p += ret; 1681 n -= ret; 1682 } 1683 break; 1684 /* 1685 * Type not supported, skip item. 1686 */ 1687 default: 1688 ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix); 1689 MBEDTLS_X509_SAFE_SNPRINTF; 1690 break; 1691 } 1692 1693 /* So far memory is freed only in the case of directoryName 1694 * parsing succeeding, as mbedtls_x509_get_name allocates memory. */ 1695 mbedtls_x509_free_subject_alt_name(&san); 1696 cur = cur->next; 1697 } 1698 1699 *p = '\0'; 1700 1701 *size = n; 1702 *buf = p; 1703 1704 return 0; 1705 } 1706 1707 #define PRINT_ITEM(i) \ 1708 do { \ 1709 ret = mbedtls_snprintf(p, n, "%s" i, sep); \ 1710 MBEDTLS_X509_SAFE_SNPRINTF; \ 1711 sep = ", "; \ 1712 } while (0) 1713 1714 #define CERT_TYPE(type, name) \ 1715 do { \ 1716 if (ns_cert_type & (type)) { \ 1717 PRINT_ITEM(name); \ 1718 } \ 1719 } while (0) 1720 1721 int mbedtls_x509_info_cert_type(char **buf, size_t *size, 1722 unsigned char ns_cert_type) 1723 { 1724 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1725 size_t n = *size; 1726 char *p = *buf; 1727 const char *sep = ""; 1728 1729 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); 1730 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); 1731 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); 1732 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); 1733 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); 1734 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); 1735 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); 1736 CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); 1737 1738 *size = n; 1739 *buf = p; 1740 1741 return 0; 1742 } 1743 1744 #define KEY_USAGE(code, name) \ 1745 do { \ 1746 if ((key_usage) & (code)) { \ 1747 PRINT_ITEM(name); \ 1748 } \ 1749 } while (0) 1750 1751 int mbedtls_x509_info_key_usage(char **buf, size_t *size, 1752 unsigned int key_usage) 1753 { 1754 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1755 size_t n = *size; 1756 char *p = *buf; 1757 const char *sep = ""; 1758 1759 KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); 1760 KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); 1761 KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); 1762 KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); 1763 KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); 1764 KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); 1765 KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); 1766 KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); 1767 KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); 1768 1769 *size = n; 1770 *buf = p; 1771 1772 return 0; 1773 } 1774 #endif /* MBEDTLS_X509_REMOVE_INFO */ 1775 #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ 1776 #endif /* MBEDTLS_X509_USE_C */ 1777