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