1/* 2 * X.509 Certificate Revocation List (CRL) parsing 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_CRL_PARSE_C) 21 22#include "mbedtls/x509_crl.h" 23#include "x509_internal.h" 24#include "mbedtls/error.h" 25#include "mbedtls/oid.h" 26#include "mbedtls/platform_util.h" 27 28#include <string.h> 29 30#if defined(MBEDTLS_PEM_PARSE_C) 31#include "mbedtls/pem.h" 32#endif 33 34#include "mbedtls/platform.h" 35 36#if defined(MBEDTLS_HAVE_TIME) 37#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 38#include <windows.h> 39#else 40#include <time.h> 41#endif 42#endif 43 44#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) 45#include <stdio.h> 46#endif 47 48/* 49 * Version ::= INTEGER { v1(0), v2(1) } 50 */ 51static int x509_crl_get_version(unsigned char **p, 52 const unsigned char *end, 53 int *ver) 54{ 55 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 56 57 if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { 58 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 59 *ver = 0; 60 return 0; 61 } 62 63 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); 64 } 65 66 return 0; 67} 68 69/* 70 * X.509 CRL v2 extensions 71 * 72 * We currently don't parse any extension's content, but we do check that the 73 * list of extensions is well-formed and abort on critical extensions (that 74 * are unsupported as we don't support any extension so far) 75 */ 76static int x509_get_crl_ext(unsigned char **p, 77 const unsigned char *end, 78 mbedtls_x509_buf *ext) 79{ 80 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 81 82 if (*p == end) { 83 return 0; 84 } 85 86 /* 87 * crlExtensions [0] EXPLICIT Extensions OPTIONAL 88 * -- if present, version MUST be v2 89 */ 90 if ((ret = mbedtls_x509_get_ext(p, end, ext, 0)) != 0) { 91 return ret; 92 } 93 94 end = ext->p + ext->len; 95 96 while (*p < end) { 97 /* 98 * Extension ::= SEQUENCE { 99 * extnID OBJECT IDENTIFIER, 100 * critical BOOLEAN DEFAULT FALSE, 101 * extnValue OCTET STRING } 102 */ 103 int is_critical = 0; 104 const unsigned char *end_ext_data; 105 size_t len; 106 107 /* Get enclosing sequence tag */ 108 if ((ret = mbedtls_asn1_get_tag(p, end, &len, 109 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 110 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 111 } 112 113 end_ext_data = *p + len; 114 115 /* Get OID (currently ignored) */ 116 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, 117 MBEDTLS_ASN1_OID)) != 0) { 118 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 119 } 120 *p += len; 121 122 /* Get optional critical */ 123 if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, 124 &is_critical)) != 0 && 125 (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { 126 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 127 } 128 129 /* Data should be octet string type */ 130 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, 131 MBEDTLS_ASN1_OCTET_STRING)) != 0) { 132 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 133 } 134 135 /* Ignore data so far and just check its length */ 136 *p += len; 137 if (*p != end_ext_data) { 138 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 139 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 140 } 141 142 /* Abort on (unsupported) critical extensions */ 143 if (is_critical) { 144 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 145 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 146 } 147 } 148 149 if (*p != end) { 150 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 151 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 152 } 153 154 return 0; 155} 156 157/* 158 * X.509 CRL v2 entry extensions (no extensions parsed yet.) 159 */ 160static int x509_get_crl_entry_ext(unsigned char **p, 161 const unsigned char *end, 162 mbedtls_x509_buf *ext) 163{ 164 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 165 size_t len = 0; 166 167 /* OPTIONAL */ 168 if (end <= *p) { 169 return 0; 170 } 171 172 ext->tag = **p; 173 ext->p = *p; 174 175 /* 176 * Get CRL-entry extension sequence header 177 * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 178 */ 179 if ((ret = mbedtls_asn1_get_tag(p, end, &ext->len, 180 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 181 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 182 ext->p = NULL; 183 return 0; 184 } 185 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 186 } 187 188 end = *p + ext->len; 189 190 if (end != *p + ext->len) { 191 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 192 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 193 } 194 195 while (*p < end) { 196 if ((ret = mbedtls_asn1_get_tag(p, end, &len, 197 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 198 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 199 } 200 201 *p += len; 202 } 203 204 if (*p != end) { 205 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 206 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 207 } 208 209 return 0; 210} 211 212/* 213 * X.509 CRL Entries 214 */ 215static int x509_get_entries(unsigned char **p, 216 const unsigned char *end, 217 mbedtls_x509_crl_entry *entry) 218{ 219 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 220 size_t entry_len; 221 mbedtls_x509_crl_entry *cur_entry = entry; 222 223 if (*p == end) { 224 return 0; 225 } 226 227 if ((ret = mbedtls_asn1_get_tag(p, end, &entry_len, 228 MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { 229 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 230 return 0; 231 } 232 233 return ret; 234 } 235 236 end = *p + entry_len; 237 238 while (*p < end) { 239 size_t len2; 240 const unsigned char *end2; 241 242 cur_entry->raw.tag = **p; 243 if ((ret = mbedtls_asn1_get_tag(p, end, &len2, 244 MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { 245 return ret; 246 } 247 248 cur_entry->raw.p = *p; 249 cur_entry->raw.len = len2; 250 end2 = *p + len2; 251 252 if ((ret = mbedtls_x509_get_serial(p, end2, &cur_entry->serial)) != 0) { 253 return ret; 254 } 255 256 if ((ret = mbedtls_x509_get_time(p, end2, 257 &cur_entry->revocation_date)) != 0) { 258 return ret; 259 } 260 261 if ((ret = x509_get_crl_entry_ext(p, end2, 262 &cur_entry->entry_ext)) != 0) { 263 return ret; 264 } 265 266 if (*p < end) { 267 cur_entry->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry)); 268 269 if (cur_entry->next == NULL) { 270 return MBEDTLS_ERR_X509_ALLOC_FAILED; 271 } 272 273 cur_entry = cur_entry->next; 274 } 275 } 276 277 return 0; 278} 279 280/* 281 * Parse one CRLs in DER format and append it to the chained list 282 */ 283int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, 284 const unsigned char *buf, size_t buflen) 285{ 286 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 287 size_t len; 288 unsigned char *p = NULL, *end = NULL; 289 mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; 290 mbedtls_x509_crl *crl = chain; 291 292 /* 293 * Check for valid input 294 */ 295 if (crl == NULL || buf == NULL) { 296 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 297 } 298 299 memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); 300 memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); 301 memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); 302 303 /* 304 * Add new CRL on the end of the chain if needed. 305 */ 306 while (crl->version != 0 && crl->next != NULL) { 307 crl = crl->next; 308 } 309 310 if (crl->version != 0 && crl->next == NULL) { 311 crl->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl)); 312 313 if (crl->next == NULL) { 314 mbedtls_x509_crl_free(crl); 315 return MBEDTLS_ERR_X509_ALLOC_FAILED; 316 } 317 318 mbedtls_x509_crl_init(crl->next); 319 crl = crl->next; 320 } 321 322 /* 323 * Copy raw DER-encoded CRL 324 */ 325 if (buflen == 0) { 326 return MBEDTLS_ERR_X509_INVALID_FORMAT; 327 } 328 329 p = mbedtls_calloc(1, buflen); 330 if (p == NULL) { 331 return MBEDTLS_ERR_X509_ALLOC_FAILED; 332 } 333 334 memcpy(p, buf, buflen); 335 336 crl->raw.p = p; 337 crl->raw.len = buflen; 338 339 end = p + buflen; 340 341 /* 342 * CertificateList ::= SEQUENCE { 343 * tbsCertList TBSCertList, 344 * signatureAlgorithm AlgorithmIdentifier, 345 * signatureValue BIT STRING } 346 */ 347 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 348 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 349 mbedtls_x509_crl_free(crl); 350 return MBEDTLS_ERR_X509_INVALID_FORMAT; 351 } 352 353 if (len != (size_t) (end - p)) { 354 mbedtls_x509_crl_free(crl); 355 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, 356 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 357 } 358 359 /* 360 * TBSCertList ::= SEQUENCE { 361 */ 362 crl->tbs.p = p; 363 364 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 365 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 366 mbedtls_x509_crl_free(crl); 367 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); 368 } 369 370 end = p + len; 371 crl->tbs.len = (size_t) (end - crl->tbs.p); 372 373 /* 374 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } 375 * -- if present, MUST be v2 376 * 377 * signature AlgorithmIdentifier 378 */ 379 if ((ret = x509_crl_get_version(&p, end, &crl->version)) != 0 || 380 (ret = mbedtls_x509_get_alg(&p, end, &crl->sig_oid, &sig_params1)) != 0) { 381 mbedtls_x509_crl_free(crl); 382 return ret; 383 } 384 385 if (crl->version < 0 || crl->version > 1) { 386 mbedtls_x509_crl_free(crl); 387 return MBEDTLS_ERR_X509_UNKNOWN_VERSION; 388 } 389 390 crl->version++; 391 392 if ((ret = mbedtls_x509_get_sig_alg(&crl->sig_oid, &sig_params1, 393 &crl->sig_md, &crl->sig_pk, 394 &crl->sig_opts)) != 0) { 395 mbedtls_x509_crl_free(crl); 396 return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG; 397 } 398 399 /* 400 * issuer Name 401 */ 402 crl->issuer_raw.p = p; 403 404 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 405 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 406 mbedtls_x509_crl_free(crl); 407 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); 408 } 409 410 if ((ret = mbedtls_x509_get_name(&p, p + len, &crl->issuer)) != 0) { 411 mbedtls_x509_crl_free(crl); 412 return ret; 413 } 414 415 crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p); 416 417 /* 418 * thisUpdate Time 419 * nextUpdate Time OPTIONAL 420 */ 421 if ((ret = mbedtls_x509_get_time(&p, end, &crl->this_update)) != 0) { 422 mbedtls_x509_crl_free(crl); 423 return ret; 424 } 425 426 if ((ret = mbedtls_x509_get_time(&p, end, &crl->next_update)) != 0) { 427 if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 428 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) && 429 ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 430 MBEDTLS_ERR_ASN1_OUT_OF_DATA))) { 431 mbedtls_x509_crl_free(crl); 432 return ret; 433 } 434 } 435 436 /* 437 * revokedCertificates SEQUENCE OF SEQUENCE { 438 * userCertificate CertificateSerialNumber, 439 * revocationDate Time, 440 * crlEntryExtensions Extensions OPTIONAL 441 * -- if present, MUST be v2 442 * } OPTIONAL 443 */ 444 if ((ret = x509_get_entries(&p, end, &crl->entry)) != 0) { 445 mbedtls_x509_crl_free(crl); 446 return ret; 447 } 448 449 /* 450 * crlExtensions EXPLICIT Extensions OPTIONAL 451 * -- if present, MUST be v2 452 */ 453 if (crl->version == 2) { 454 ret = x509_get_crl_ext(&p, end, &crl->crl_ext); 455 456 if (ret != 0) { 457 mbedtls_x509_crl_free(crl); 458 return ret; 459 } 460 } 461 462 if (p != end) { 463 mbedtls_x509_crl_free(crl); 464 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, 465 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 466 } 467 468 end = crl->raw.p + crl->raw.len; 469 470 /* 471 * signatureAlgorithm AlgorithmIdentifier, 472 * signatureValue BIT STRING 473 */ 474 if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { 475 mbedtls_x509_crl_free(crl); 476 return ret; 477 } 478 479 if (crl->sig_oid.len != sig_oid2.len || 480 memcmp(crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len) != 0 || 481 sig_params1.len != sig_params2.len || 482 (sig_params1.len != 0 && 483 memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { 484 mbedtls_x509_crl_free(crl); 485 return MBEDTLS_ERR_X509_SIG_MISMATCH; 486 } 487 488 if ((ret = mbedtls_x509_get_sig(&p, end, &crl->sig)) != 0) { 489 mbedtls_x509_crl_free(crl); 490 return ret; 491 } 492 493 if (p != end) { 494 mbedtls_x509_crl_free(crl); 495 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, 496 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 497 } 498 499 return 0; 500} 501 502/* 503 * Parse one or more CRLs and add them to the chained list 504 */ 505int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen) 506{ 507#if defined(MBEDTLS_PEM_PARSE_C) 508 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 509 size_t use_len = 0; 510 mbedtls_pem_context pem; 511 int is_pem = 0; 512 513 if (chain == NULL || buf == NULL) { 514 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 515 } 516 517 do { 518 mbedtls_pem_init(&pem); 519 520 // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated 521 // string 522 if (buflen == 0 || buf[buflen - 1] != '\0') { 523 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 524 } else { 525 ret = mbedtls_pem_read_buffer(&pem, 526 "-----BEGIN X509 CRL-----", 527 "-----END X509 CRL-----", 528 buf, NULL, 0, &use_len); 529 } 530 531 if (ret == 0) { 532 /* 533 * Was PEM encoded 534 */ 535 is_pem = 1; 536 537 buflen -= use_len; 538 buf += use_len; 539 540 if ((ret = mbedtls_x509_crl_parse_der(chain, 541 pem.buf, pem.buflen)) != 0) { 542 mbedtls_pem_free(&pem); 543 return ret; 544 } 545 } else if (is_pem) { 546 mbedtls_pem_free(&pem); 547 return ret; 548 } 549 550 mbedtls_pem_free(&pem); 551 } 552 /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. 553 * And a valid CRL cannot be less than 1 byte anyway. */ 554 while (is_pem && buflen > 1); 555 556 if (is_pem) { 557 return 0; 558 } else 559#endif /* MBEDTLS_PEM_PARSE_C */ 560 return mbedtls_x509_crl_parse_der(chain, buf, buflen); 561} 562 563#if defined(MBEDTLS_FS_IO) 564/* 565 * Load one or more CRLs and add them to the chained list 566 */ 567int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path) 568{ 569 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 570 size_t n; 571 unsigned char *buf; 572 573 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { 574 return ret; 575 } 576 577 ret = mbedtls_x509_crl_parse(chain, buf, n); 578 579 mbedtls_zeroize_and_free(buf, n); 580 581 return ret; 582} 583#endif /* MBEDTLS_FS_IO */ 584 585#if !defined(MBEDTLS_X509_REMOVE_INFO) 586/* 587 * Return an informational string about the certificate. 588 */ 589#define BEFORE_COLON 14 590#define BC "14" 591/* 592 * Return an informational string about the CRL. 593 */ 594int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, 595 const mbedtls_x509_crl *crl) 596{ 597 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 598 size_t n; 599 char *p; 600 const mbedtls_x509_crl_entry *entry; 601 602 p = buf; 603 n = size; 604 605 ret = mbedtls_snprintf(p, n, "%sCRL version : %d", 606 prefix, crl->version); 607 MBEDTLS_X509_SAFE_SNPRINTF; 608 609 ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); 610 MBEDTLS_X509_SAFE_SNPRINTF; 611 ret = mbedtls_x509_dn_gets(p, n, &crl->issuer); 612 MBEDTLS_X509_SAFE_SNPRINTF; 613 614 ret = mbedtls_snprintf(p, n, "\n%sthis update : " \ 615 "%04d-%02d-%02d %02d:%02d:%02d", prefix, 616 crl->this_update.year, crl->this_update.mon, 617 crl->this_update.day, crl->this_update.hour, 618 crl->this_update.min, crl->this_update.sec); 619 MBEDTLS_X509_SAFE_SNPRINTF; 620 621 ret = mbedtls_snprintf(p, n, "\n%snext update : " \ 622 "%04d-%02d-%02d %02d:%02d:%02d", prefix, 623 crl->next_update.year, crl->next_update.mon, 624 crl->next_update.day, crl->next_update.hour, 625 crl->next_update.min, crl->next_update.sec); 626 MBEDTLS_X509_SAFE_SNPRINTF; 627 628 entry = &crl->entry; 629 630 ret = mbedtls_snprintf(p, n, "\n%sRevoked certificates:", 631 prefix); 632 MBEDTLS_X509_SAFE_SNPRINTF; 633 634 while (entry != NULL && entry->raw.len != 0) { 635 ret = mbedtls_snprintf(p, n, "\n%sserial number: ", 636 prefix); 637 MBEDTLS_X509_SAFE_SNPRINTF; 638 639 ret = mbedtls_x509_serial_gets(p, n, &entry->serial); 640 MBEDTLS_X509_SAFE_SNPRINTF; 641 642 ret = mbedtls_snprintf(p, n, " revocation date: " \ 643 "%04d-%02d-%02d %02d:%02d:%02d", 644 entry->revocation_date.year, entry->revocation_date.mon, 645 entry->revocation_date.day, entry->revocation_date.hour, 646 entry->revocation_date.min, entry->revocation_date.sec); 647 MBEDTLS_X509_SAFE_SNPRINTF; 648 649 entry = entry->next; 650 } 651 652 ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); 653 MBEDTLS_X509_SAFE_SNPRINTF; 654 655 ret = mbedtls_x509_sig_alg_gets(p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, 656 crl->sig_opts); 657 MBEDTLS_X509_SAFE_SNPRINTF; 658 659 ret = mbedtls_snprintf(p, n, "\n"); 660 MBEDTLS_X509_SAFE_SNPRINTF; 661 662 return (int) (size - n); 663} 664#endif /* MBEDTLS_X509_REMOVE_INFO */ 665 666/* 667 * Initialize a CRL chain 668 */ 669void mbedtls_x509_crl_init(mbedtls_x509_crl *crl) 670{ 671 memset(crl, 0, sizeof(mbedtls_x509_crl)); 672} 673 674/* 675 * Unallocate all CRL data 676 */ 677void mbedtls_x509_crl_free(mbedtls_x509_crl *crl) 678{ 679 mbedtls_x509_crl *crl_cur = crl; 680 mbedtls_x509_crl *crl_prv; 681 mbedtls_x509_crl_entry *entry_cur; 682 mbedtls_x509_crl_entry *entry_prv; 683 684 while (crl_cur != NULL) { 685#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 686 mbedtls_free(crl_cur->sig_opts); 687#endif 688 689 mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next); 690 691 entry_cur = crl_cur->entry.next; 692 while (entry_cur != NULL) { 693 entry_prv = entry_cur; 694 entry_cur = entry_cur->next; 695 mbedtls_zeroize_and_free(entry_prv, 696 sizeof(mbedtls_x509_crl_entry)); 697 } 698 699 if (crl_cur->raw.p != NULL) { 700 mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len); 701 } 702 703 crl_prv = crl_cur; 704 crl_cur = crl_cur->next; 705 706 mbedtls_platform_zeroize(crl_prv, sizeof(mbedtls_x509_crl)); 707 if (crl_prv != crl) { 708 mbedtls_free(crl_prv); 709 } 710 } 711} 712 713#endif /* MBEDTLS_X509_CRL_PARSE_C */ 714