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