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