2 * X.509 Certidicate Revocation List (CRL) parsing
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 * The ITU-T X.509 standard defines a certificate format for PKI.
26 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
27 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
28 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
31 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
34 #if !defined(MBEDTLS_CONFIG_FILE)
35 #include "mbedtls/config.h"
37 #include MBEDTLS_CONFIG_FILE
40 #if defined(MBEDTLS_X509_CRL_PARSE_C)
42 #include "mbedtls/x509_crl.h"
43 #include "mbedtls/oid.h"
44 #include "mbedtls/platform_util.h"
48 #if defined(MBEDTLS_PEM_PARSE_C)
49 #include "mbedtls/pem.h"
52 #if defined(MBEDTLS_PLATFORM_C)
53 #include "mbedtls/platform.h"
57 #define mbedtls_free free
58 #define mbedtls_calloc calloc
59 #define mbedtls_snprintf snprintf
62 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
68 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
73 * Version ::= INTEGER { v1(0), v2(1) }
75 static int x509_crl_get_version( unsigned char **p
,
76 const unsigned char *end
,
81 if( ( ret
= mbedtls_asn1_get_int( p
, end
, ver
) ) != 0 )
83 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
89 return( MBEDTLS_ERR_X509_INVALID_VERSION
+ ret
);
96 * X.509 CRL v2 extensions
98 * We currently don't parse any extension's content, but we do check that the
99 * list of extensions is well-formed and abort on critical extensions (that
100 * are unsupported as we don't support any extension so far)
102 static int x509_get_crl_ext( unsigned char **p
,
103 const unsigned char *end
,
104 mbedtls_x509_buf
*ext
)
109 * crlExtensions [0] EXPLICIT Extensions OPTIONAL
110 * -- if present, version MUST be v2
112 if( ( ret
= mbedtls_x509_get_ext( p
, end
, ext
, 0 ) ) != 0 )
114 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
123 * Extension ::= SEQUENCE {
124 * extnID OBJECT IDENTIFIER,
125 * critical BOOLEAN DEFAULT FALSE,
126 * extnValue OCTET STRING }
129 const unsigned char *end_ext_data
;
132 /* Get enclosing sequence tag */
133 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
134 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
135 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
137 end_ext_data
= *p
+ len
;
139 /* Get OID (currently ignored) */
140 if( ( ret
= mbedtls_asn1_get_tag( p
, end_ext_data
, &len
,
141 MBEDTLS_ASN1_OID
) ) != 0 )
143 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
147 /* Get optional critical */
148 if( ( ret
= mbedtls_asn1_get_bool( p
, end_ext_data
,
149 &is_critical
) ) != 0 &&
150 ( ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) )
152 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
155 /* Data should be octet string type */
156 if( ( ret
= mbedtls_asn1_get_tag( p
, end_ext_data
, &len
,
157 MBEDTLS_ASN1_OCTET_STRING
) ) != 0 )
158 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
160 /* Ignore data so far and just check its length */
162 if( *p
!= end_ext_data
)
163 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
164 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
166 /* Abort on (unsupported) critical extensions */
168 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
169 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
173 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
174 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
180 * X.509 CRL v2 entry extensions (no extensions parsed yet.)
182 static int x509_get_crl_entry_ext( unsigned char **p
,
183 const unsigned char *end
,
184 mbedtls_x509_buf
*ext
)
197 * Get CRL-entry extension sequence header
198 * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
200 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &ext
->len
,
201 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
203 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
208 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
213 if( end
!= *p
+ ext
->len
)
214 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
215 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
219 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
220 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
221 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
227 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
228 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
236 static int x509_get_entries( unsigned char **p
,
237 const unsigned char *end
,
238 mbedtls_x509_crl_entry
*entry
)
242 mbedtls_x509_crl_entry
*cur_entry
= entry
;
247 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &entry_len
,
248 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
) ) != 0 )
250 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
256 end
= *p
+ entry_len
;
261 const unsigned char *end2
;
263 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len2
,
264 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
) ) != 0 )
269 cur_entry
->raw
.tag
= **p
;
270 cur_entry
->raw
.p
= *p
;
271 cur_entry
->raw
.len
= len2
;
274 if( ( ret
= mbedtls_x509_get_serial( p
, end2
, &cur_entry
->serial
) ) != 0 )
277 if( ( ret
= mbedtls_x509_get_time( p
, end2
,
278 &cur_entry
->revocation_date
) ) != 0 )
281 if( ( ret
= x509_get_crl_entry_ext( p
, end2
,
282 &cur_entry
->entry_ext
) ) != 0 )
287 cur_entry
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry
) );
289 if( cur_entry
->next
== NULL
)
290 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
292 cur_entry
= cur_entry
->next
;
300 * Parse one CRLs in DER format and append it to the chained list
302 int mbedtls_x509_crl_parse_der( mbedtls_x509_crl
*chain
,
303 const unsigned char *buf
, size_t buflen
)
307 unsigned char *p
= NULL
, *end
= NULL
;
308 mbedtls_x509_buf sig_params1
, sig_params2
, sig_oid2
;
309 mbedtls_x509_crl
*crl
= chain
;
312 * Check for valid input
314 if( crl
== NULL
|| buf
== NULL
)
315 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
317 memset( &sig_params1
, 0, sizeof( mbedtls_x509_buf
) );
318 memset( &sig_params2
, 0, sizeof( mbedtls_x509_buf
) );
319 memset( &sig_oid2
, 0, sizeof( mbedtls_x509_buf
) );
322 * Add new CRL on the end of the chain if needed.
324 while( crl
->version
!= 0 && crl
->next
!= NULL
)
327 if( crl
->version
!= 0 && crl
->next
== NULL
)
329 crl
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_crl
) );
331 if( crl
->next
== NULL
)
333 mbedtls_x509_crl_free( crl
);
334 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
337 mbedtls_x509_crl_init( crl
->next
);
342 * Copy raw DER-encoded CRL
345 return( MBEDTLS_ERR_X509_INVALID_FORMAT
);
347 p
= mbedtls_calloc( 1, buflen
);
349 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
351 memcpy( p
, buf
, buflen
);
354 crl
->raw
.len
= buflen
;
359 * CertificateList ::= SEQUENCE {
360 * tbsCertList TBSCertList,
361 * signatureAlgorithm AlgorithmIdentifier,
362 * signatureValue BIT STRING }
364 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
365 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
367 mbedtls_x509_crl_free( crl
);
368 return( MBEDTLS_ERR_X509_INVALID_FORMAT
);
371 if( len
!= (size_t) ( end
- p
) )
373 mbedtls_x509_crl_free( crl
);
374 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
375 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
379 * TBSCertList ::= SEQUENCE {
383 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
384 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
386 mbedtls_x509_crl_free( crl
);
387 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
391 crl
->tbs
.len
= end
- crl
->tbs
.p
;
394 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
395 * -- if present, MUST be v2
397 * signature AlgorithmIdentifier
399 if( ( ret
= x509_crl_get_version( &p
, end
, &crl
->version
) ) != 0 ||
400 ( ret
= mbedtls_x509_get_alg( &p
, end
, &crl
->sig_oid
, &sig_params1
) ) != 0 )
402 mbedtls_x509_crl_free( crl
);
406 if( crl
->version
< 0 || crl
->version
> 1 )
408 mbedtls_x509_crl_free( crl
);
409 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION
);
414 if( ( ret
= mbedtls_x509_get_sig_alg( &crl
->sig_oid
, &sig_params1
,
415 &crl
->sig_md
, &crl
->sig_pk
,
416 &crl
->sig_opts
) ) != 0 )
418 mbedtls_x509_crl_free( crl
);
419 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG
);
425 crl
->issuer_raw
.p
= p
;
427 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
428 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
430 mbedtls_x509_crl_free( crl
);
431 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
434 if( ( ret
= mbedtls_x509_get_name( &p
, p
+ len
, &crl
->issuer
) ) != 0 )
436 mbedtls_x509_crl_free( crl
);
440 crl
->issuer_raw
.len
= p
- crl
->issuer_raw
.p
;
444 * nextUpdate Time OPTIONAL
446 if( ( ret
= mbedtls_x509_get_time( &p
, end
, &crl
->this_update
) ) != 0 )
448 mbedtls_x509_crl_free( crl
);
452 if( ( ret
= mbedtls_x509_get_time( &p
, end
, &crl
->next_update
) ) != 0 )
454 if( ret
!= ( MBEDTLS_ERR_X509_INVALID_DATE
+
455 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) &&
456 ret
!= ( MBEDTLS_ERR_X509_INVALID_DATE
+
457 MBEDTLS_ERR_ASN1_OUT_OF_DATA
) )
459 mbedtls_x509_crl_free( crl
);
465 * revokedCertificates SEQUENCE OF SEQUENCE {
466 * userCertificate CertificateSerialNumber,
467 * revocationDate Time,
468 * crlEntryExtensions Extensions OPTIONAL
469 * -- if present, MUST be v2
472 if( ( ret
= x509_get_entries( &p
, end
, &crl
->entry
) ) != 0 )
474 mbedtls_x509_crl_free( crl
);
479 * crlExtensions EXPLICIT Extensions OPTIONAL
480 * -- if present, MUST be v2
482 if( crl
->version
== 2 )
484 ret
= x509_get_crl_ext( &p
, end
, &crl
->crl_ext
);
488 mbedtls_x509_crl_free( crl
);
495 mbedtls_x509_crl_free( crl
);
496 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
497 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
500 end
= crl
->raw
.p
+ crl
->raw
.len
;
503 * signatureAlgorithm AlgorithmIdentifier,
504 * signatureValue BIT STRING
506 if( ( ret
= mbedtls_x509_get_alg( &p
, end
, &sig_oid2
, &sig_params2
) ) != 0 )
508 mbedtls_x509_crl_free( crl
);
512 if( crl
->sig_oid
.len
!= sig_oid2
.len
||
513 memcmp( crl
->sig_oid
.p
, sig_oid2
.p
, crl
->sig_oid
.len
) != 0 ||
514 sig_params1
.len
!= sig_params2
.len
||
515 ( sig_params1
.len
!= 0 &&
516 memcmp( sig_params1
.p
, sig_params2
.p
, sig_params1
.len
) != 0 ) )
518 mbedtls_x509_crl_free( crl
);
519 return( MBEDTLS_ERR_X509_SIG_MISMATCH
);
522 if( ( ret
= mbedtls_x509_get_sig( &p
, end
, &crl
->sig
) ) != 0 )
524 mbedtls_x509_crl_free( crl
);
530 mbedtls_x509_crl_free( crl
);
531 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
532 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
539 * Parse one or more CRLs and add them to the chained list
541 int mbedtls_x509_crl_parse( mbedtls_x509_crl
*chain
, const unsigned char *buf
, size_t buflen
)
543 #if defined(MBEDTLS_PEM_PARSE_C)
546 mbedtls_pem_context pem
;
549 if( chain
== NULL
|| buf
== NULL
)
550 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
554 mbedtls_pem_init( &pem
);
556 // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
558 if( buflen
== 0 || buf
[buflen
- 1] != '\0' )
559 ret
= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
;
561 ret
= mbedtls_pem_read_buffer( &pem
,
562 "-----BEGIN X509 CRL-----",
563 "-----END X509 CRL-----",
564 buf
, NULL
, 0, &use_len
);
576 if( ( ret
= mbedtls_x509_crl_parse_der( chain
,
577 pem
.buf
, pem
.buflen
) ) != 0 )
579 mbedtls_pem_free( &pem
);
585 mbedtls_pem_free( &pem
);
589 mbedtls_pem_free( &pem
);
591 /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
592 * And a valid CRL cannot be less than 1 byte anyway. */
593 while( is_pem
&& buflen
> 1 );
598 #endif /* MBEDTLS_PEM_PARSE_C */
599 return( mbedtls_x509_crl_parse_der( chain
, buf
, buflen
) );
602 #if defined(MBEDTLS_FS_IO)
604 * Load one or more CRLs and add them to the chained list
606 int mbedtls_x509_crl_parse_file( mbedtls_x509_crl
*chain
, const char *path
)
612 if( ( ret
= mbedtls_pk_load_file( path
, &buf
, &n
) ) != 0 )
615 ret
= mbedtls_x509_crl_parse( chain
, buf
, n
);
617 mbedtls_platform_zeroize( buf
, n
);
622 #endif /* MBEDTLS_FS_IO */
625 * Return an informational string about the certificate.
627 #define BEFORE_COLON 14
630 * Return an informational string about the CRL.
632 int mbedtls_x509_crl_info( char *buf
, size_t size
, const char *prefix
,
633 const mbedtls_x509_crl
*crl
)
638 const mbedtls_x509_crl_entry
*entry
;
643 ret
= mbedtls_snprintf( p
, n
, "%sCRL version : %d",
644 prefix
, crl
->version
);
645 MBEDTLS_X509_SAFE_SNPRINTF
;
647 ret
= mbedtls_snprintf( p
, n
, "\n%sissuer name : ", prefix
);
648 MBEDTLS_X509_SAFE_SNPRINTF
;
649 ret
= mbedtls_x509_dn_gets( p
, n
, &crl
->issuer
);
650 MBEDTLS_X509_SAFE_SNPRINTF
;
652 ret
= mbedtls_snprintf( p
, n
, "\n%sthis update : " \
653 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
654 crl
->this_update
.year
, crl
->this_update
.mon
,
655 crl
->this_update
.day
, crl
->this_update
.hour
,
656 crl
->this_update
.min
, crl
->this_update
.sec
);
657 MBEDTLS_X509_SAFE_SNPRINTF
;
659 ret
= mbedtls_snprintf( p
, n
, "\n%snext update : " \
660 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
661 crl
->next_update
.year
, crl
->next_update
.mon
,
662 crl
->next_update
.day
, crl
->next_update
.hour
,
663 crl
->next_update
.min
, crl
->next_update
.sec
);
664 MBEDTLS_X509_SAFE_SNPRINTF
;
668 ret
= mbedtls_snprintf( p
, n
, "\n%sRevoked certificates:",
670 MBEDTLS_X509_SAFE_SNPRINTF
;
672 while( entry
!= NULL
&& entry
->raw
.len
!= 0 )
674 ret
= mbedtls_snprintf( p
, n
, "\n%sserial number: ",
676 MBEDTLS_X509_SAFE_SNPRINTF
;
678 ret
= mbedtls_x509_serial_gets( p
, n
, &entry
->serial
);
679 MBEDTLS_X509_SAFE_SNPRINTF
;
681 ret
= mbedtls_snprintf( p
, n
, " revocation date: " \
682 "%04d-%02d-%02d %02d:%02d:%02d",
683 entry
->revocation_date
.year
, entry
->revocation_date
.mon
,
684 entry
->revocation_date
.day
, entry
->revocation_date
.hour
,
685 entry
->revocation_date
.min
, entry
->revocation_date
.sec
);
686 MBEDTLS_X509_SAFE_SNPRINTF
;
691 ret
= mbedtls_snprintf( p
, n
, "\n%ssigned using : ", prefix
);
692 MBEDTLS_X509_SAFE_SNPRINTF
;
694 ret
= mbedtls_x509_sig_alg_gets( p
, n
, &crl
->sig_oid
, crl
->sig_pk
, crl
->sig_md
,
696 MBEDTLS_X509_SAFE_SNPRINTF
;
698 ret
= mbedtls_snprintf( p
, n
, "\n" );
699 MBEDTLS_X509_SAFE_SNPRINTF
;
701 return( (int) ( size
- n
) );
705 * Initialize a CRL chain
707 void mbedtls_x509_crl_init( mbedtls_x509_crl
*crl
)
709 memset( crl
, 0, sizeof(mbedtls_x509_crl
) );
713 * Unallocate all CRL data
715 void mbedtls_x509_crl_free( mbedtls_x509_crl
*crl
)
717 mbedtls_x509_crl
*crl_cur
= crl
;
718 mbedtls_x509_crl
*crl_prv
;
719 mbedtls_x509_name
*name_cur
;
720 mbedtls_x509_name
*name_prv
;
721 mbedtls_x509_crl_entry
*entry_cur
;
722 mbedtls_x509_crl_entry
*entry_prv
;
729 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
730 mbedtls_free( crl_cur
->sig_opts
);
733 name_cur
= crl_cur
->issuer
.next
;
734 while( name_cur
!= NULL
)
737 name_cur
= name_cur
->next
;
738 mbedtls_platform_zeroize( name_prv
, sizeof( mbedtls_x509_name
) );
739 mbedtls_free( name_prv
);
742 entry_cur
= crl_cur
->entry
.next
;
743 while( entry_cur
!= NULL
)
745 entry_prv
= entry_cur
;
746 entry_cur
= entry_cur
->next
;
747 mbedtls_platform_zeroize( entry_prv
,
748 sizeof( mbedtls_x509_crl_entry
) );
749 mbedtls_free( entry_prv
);
752 if( crl_cur
->raw
.p
!= NULL
)
754 mbedtls_platform_zeroize( crl_cur
->raw
.p
, crl_cur
->raw
.len
);
755 mbedtls_free( crl_cur
->raw
.p
);
758 crl_cur
= crl_cur
->next
;
760 while( crl_cur
!= NULL
);
766 crl_cur
= crl_cur
->next
;
768 mbedtls_platform_zeroize( crl_prv
, sizeof( mbedtls_x509_crl
) );
770 mbedtls_free( crl_prv
);
772 while( crl_cur
!= NULL
);
775 #endif /* MBEDTLS_X509_CRL_PARSE_C */