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