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