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