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