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  */
x509_crl_get_version(unsigned char ** p,const unsigned char * end,int * ver)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  */
x509_get_crl_ext(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * ext)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  */
x509_get_crl_entry_ext(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * ext)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  */
x509_get_entries(unsigned char ** p,const unsigned char * end,mbedtls_x509_crl_entry * entry)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  */
mbedtls_x509_crl_parse_der(mbedtls_x509_crl * chain,const unsigned char * buf,size_t buflen)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  */
mbedtls_x509_crl_parse(mbedtls_x509_crl * chain,const unsigned char * buf,size_t buflen)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  */
mbedtls_x509_crl_parse_file(mbedtls_x509_crl * chain,const char * path)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  */
mbedtls_x509_crl_info(char * buf,size_t size,const char * prefix,const mbedtls_x509_crl * crl)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  */
mbedtls_x509_crl_init(mbedtls_x509_crl * crl)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  */
mbedtls_x509_crl_free(mbedtls_x509_crl * crl)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 */
714