quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

x509_crl.c (20976B)


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