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