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