2 * X.509 Certidicate Revocation List (CRL) parsing
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This file is part of mbed TLS (https://tls.mbed.org)
22 * The ITU-T X.509 standard defines a certificate format for PKI.
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)
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
32 #if !defined(MBEDTLS_CONFIG_FILE)
33 #include "mbedtls/config.h"
35 #include MBEDTLS_CONFIG_FILE
38 #if defined(MBEDTLS_X509_CRL_PARSE_C)
40 #include "mbedtls/x509_crl.h"
41 #include "mbedtls/oid.h"
45 #if defined(MBEDTLS_PEM_PARSE_C)
46 #include "mbedtls/pem.h"
49 #if defined(MBEDTLS_PLATFORM_C)
50 #include "mbedtls/platform.h"
54 #define mbedtls_free free
55 #define mbedtls_calloc calloc
56 #define mbedtls_snprintf snprintf
59 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
65 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
69 /* Implementation that should never be optimized out by the compiler */
70 static void mbedtls_zeroize( void *v
, size_t n
) {
71 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
75 * Version ::= INTEGER { v1(0), v2(1) }
77 static int x509_crl_get_version( unsigned char **p
,
78 const unsigned char *end
,
83 if( ( ret
= mbedtls_asn1_get_int( p
, end
, ver
) ) != 0 )
85 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
91 return( MBEDTLS_ERR_X509_INVALID_VERSION
+ ret
);
98 * X.509 CRL v2 extensions (no extensions parsed yet.)
100 static int x509_get_crl_ext( unsigned char **p
,
101 const unsigned char *end
,
102 mbedtls_x509_buf
*ext
)
107 /* Get explicit tag */
108 if( ( ret
= mbedtls_x509_get_ext( p
, end
, ext
, 0) ) != 0 )
110 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
118 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
119 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
120 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
126 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
127 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
133 * X.509 CRL v2 entry extensions (no extensions parsed yet.)
135 static int x509_get_crl_entry_ext( unsigned char **p
,
136 const unsigned char *end
,
137 mbedtls_x509_buf
*ext
)
150 * Get CRL-entry extension sequence header
151 * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
153 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &ext
->len
,
154 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
156 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
161 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
166 if( end
!= *p
+ ext
->len
)
167 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
168 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
172 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
173 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
174 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
180 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
181 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
189 static int x509_get_entries( unsigned char **p
,
190 const unsigned char *end
,
191 mbedtls_x509_crl_entry
*entry
)
195 mbedtls_x509_crl_entry
*cur_entry
= entry
;
200 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &entry_len
,
201 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
) ) != 0 )
203 if( ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
209 end
= *p
+ entry_len
;
214 const unsigned char *end2
;
216 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len2
,
217 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
) ) != 0 )
222 cur_entry
->raw
.tag
= **p
;
223 cur_entry
->raw
.p
= *p
;
224 cur_entry
->raw
.len
= len2
;
227 if( ( ret
= mbedtls_x509_get_serial( p
, end2
, &cur_entry
->serial
) ) != 0 )
230 if( ( ret
= mbedtls_x509_get_time( p
, end2
,
231 &cur_entry
->revocation_date
) ) != 0 )
234 if( ( ret
= x509_get_crl_entry_ext( p
, end2
,
235 &cur_entry
->entry_ext
) ) != 0 )
240 cur_entry
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry
) );
242 if( cur_entry
->next
== NULL
)
243 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
245 cur_entry
= cur_entry
->next
;
253 * Parse one CRLs in DER format and append it to the chained list
255 int mbedtls_x509_crl_parse_der( mbedtls_x509_crl
*chain
,
256 const unsigned char *buf
, size_t buflen
)
260 unsigned char *p
, *end
;
261 mbedtls_x509_buf sig_params1
, sig_params2
, sig_oid2
;
262 mbedtls_x509_crl
*crl
= chain
;
265 * Check for valid input
267 if( crl
== NULL
|| buf
== NULL
)
268 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
270 memset( &sig_params1
, 0, sizeof( mbedtls_x509_buf
) );
271 memset( &sig_params2
, 0, sizeof( mbedtls_x509_buf
) );
272 memset( &sig_oid2
, 0, sizeof( mbedtls_x509_buf
) );
275 * Add new CRL on the end of the chain if needed.
277 while( crl
->version
!= 0 && crl
->next
!= NULL
)
280 if( crl
->version
!= 0 && crl
->next
== NULL
)
282 crl
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_crl
) );
284 if( crl
->next
== NULL
)
286 mbedtls_x509_crl_free( crl
);
287 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
290 mbedtls_x509_crl_init( crl
->next
);
295 * Copy raw DER-encoded CRL
297 if( ( p
= mbedtls_calloc( 1, buflen
) ) == NULL
)
298 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
300 memcpy( p
, buf
, buflen
);
303 crl
->raw
.len
= buflen
;
308 * CertificateList ::= SEQUENCE {
309 * tbsCertList TBSCertList,
310 * signatureAlgorithm AlgorithmIdentifier,
311 * signatureValue BIT STRING }
313 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
314 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
316 mbedtls_x509_crl_free( crl
);
317 return( MBEDTLS_ERR_X509_INVALID_FORMAT
);
320 if( len
!= (size_t) ( end
- p
) )
322 mbedtls_x509_crl_free( crl
);
323 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
324 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
328 * TBSCertList ::= SEQUENCE {
332 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
333 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
335 mbedtls_x509_crl_free( crl
);
336 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
340 crl
->tbs
.len
= end
- crl
->tbs
.p
;
343 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
344 * -- if present, MUST be v2
346 * signature AlgorithmIdentifier
348 if( ( ret
= x509_crl_get_version( &p
, end
, &crl
->version
) ) != 0 ||
349 ( ret
= mbedtls_x509_get_alg( &p
, end
, &crl
->sig_oid
, &sig_params1
) ) != 0 )
351 mbedtls_x509_crl_free( crl
);
357 if( crl
->version
> 2 )
359 mbedtls_x509_crl_free( crl
);
360 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION
);
363 if( ( ret
= mbedtls_x509_get_sig_alg( &crl
->sig_oid
, &sig_params1
,
364 &crl
->sig_md
, &crl
->sig_pk
,
365 &crl
->sig_opts
) ) != 0 )
367 mbedtls_x509_crl_free( crl
);
368 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG
);
374 crl
->issuer_raw
.p
= p
;
376 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
377 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
379 mbedtls_x509_crl_free( crl
);
380 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
383 if( ( ret
= mbedtls_x509_get_name( &p
, p
+ len
, &crl
->issuer
) ) != 0 )
385 mbedtls_x509_crl_free( crl
);
389 crl
->issuer_raw
.len
= p
- crl
->issuer_raw
.p
;
393 * nextUpdate Time OPTIONAL
395 if( ( ret
= mbedtls_x509_get_time( &p
, end
, &crl
->this_update
) ) != 0 )
397 mbedtls_x509_crl_free( crl
);
401 if( ( ret
= mbedtls_x509_get_time( &p
, end
, &crl
->next_update
) ) != 0 )
403 if( ret
!= ( MBEDTLS_ERR_X509_INVALID_DATE
+
404 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) &&
405 ret
!= ( MBEDTLS_ERR_X509_INVALID_DATE
+
406 MBEDTLS_ERR_ASN1_OUT_OF_DATA
) )
408 mbedtls_x509_crl_free( crl
);
414 * revokedCertificates SEQUENCE OF SEQUENCE {
415 * userCertificate CertificateSerialNumber,
416 * revocationDate Time,
417 * crlEntryExtensions Extensions OPTIONAL
418 * -- if present, MUST be v2
421 if( ( ret
= x509_get_entries( &p
, end
, &crl
->entry
) ) != 0 )
423 mbedtls_x509_crl_free( crl
);
428 * crlExtensions EXPLICIT Extensions OPTIONAL
429 * -- if present, MUST be v2
431 if( crl
->version
== 2 )
433 ret
= x509_get_crl_ext( &p
, end
, &crl
->crl_ext
);
437 mbedtls_x509_crl_free( crl
);
444 mbedtls_x509_crl_free( crl
);
445 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
446 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
449 end
= crl
->raw
.p
+ crl
->raw
.len
;
452 * signatureAlgorithm AlgorithmIdentifier,
453 * signatureValue BIT STRING
455 if( ( ret
= mbedtls_x509_get_alg( &p
, end
, &sig_oid2
, &sig_params2
) ) != 0 )
457 mbedtls_x509_crl_free( crl
);
461 if( crl
->sig_oid
.len
!= sig_oid2
.len
||
462 memcmp( crl
->sig_oid
.p
, sig_oid2
.p
, crl
->sig_oid
.len
) != 0 ||
463 sig_params1
.len
!= sig_params2
.len
||
464 ( sig_params1
.len
!= 0 &&
465 memcmp( sig_params1
.p
, sig_params2
.p
, sig_params1
.len
) != 0 ) )
467 mbedtls_x509_crl_free( crl
);
468 return( MBEDTLS_ERR_X509_SIG_MISMATCH
);
471 if( ( ret
= mbedtls_x509_get_sig( &p
, end
, &crl
->sig
) ) != 0 )
473 mbedtls_x509_crl_free( crl
);
479 mbedtls_x509_crl_free( crl
);
480 return( MBEDTLS_ERR_X509_INVALID_FORMAT
+
481 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
488 * Parse one or more CRLs and add them to the chained list
490 int mbedtls_x509_crl_parse( mbedtls_x509_crl
*chain
, const unsigned char *buf
, size_t buflen
)
492 #if defined(MBEDTLS_PEM_PARSE_C)
495 mbedtls_pem_context pem
;
498 if( chain
== NULL
|| buf
== NULL
)
499 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
503 mbedtls_pem_init( &pem
);
505 // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
507 if( buflen
== 0 || buf
[buflen
- 1] != '\0' )
508 ret
= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
;
510 ret
= mbedtls_pem_read_buffer( &pem
,
511 "-----BEGIN X509 CRL-----",
512 "-----END X509 CRL-----",
513 buf
, NULL
, 0, &use_len
);
525 if( ( ret
= mbedtls_x509_crl_parse_der( chain
,
526 pem
.buf
, pem
.buflen
) ) != 0 )
531 mbedtls_pem_free( &pem
);
533 else if( ret
!= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
)
535 mbedtls_pem_free( &pem
);
539 /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
540 * And a valid CRL cannot be less than 1 byte anyway. */
541 while( is_pem
&& buflen
> 1 );
546 #endif /* MBEDTLS_PEM_PARSE_C */
547 return( mbedtls_x509_crl_parse_der( chain
, buf
, buflen
) );
550 #if defined(MBEDTLS_FS_IO)
552 * Load one or more CRLs and add them to the chained list
554 int mbedtls_x509_crl_parse_file( mbedtls_x509_crl
*chain
, const char *path
)
560 if( ( ret
= mbedtls_pk_load_file( path
, &buf
, &n
) ) != 0 )
563 ret
= mbedtls_x509_crl_parse( chain
, buf
, n
);
565 mbedtls_zeroize( buf
, n
);
570 #endif /* MBEDTLS_FS_IO */
573 * Return an informational string about the certificate.
575 #define BEFORE_COLON 14
578 * Return an informational string about the CRL.
580 int mbedtls_x509_crl_info( char *buf
, size_t size
, const char *prefix
,
581 const mbedtls_x509_crl
*crl
)
586 const mbedtls_x509_crl_entry
*entry
;
591 ret
= mbedtls_snprintf( p
, n
, "%sCRL version : %d",
592 prefix
, crl
->version
);
593 MBEDTLS_X509_SAFE_SNPRINTF
;
595 ret
= mbedtls_snprintf( p
, n
, "\n%sissuer name : ", prefix
);
596 MBEDTLS_X509_SAFE_SNPRINTF
;
597 ret
= mbedtls_x509_dn_gets( p
, n
, &crl
->issuer
);
598 MBEDTLS_X509_SAFE_SNPRINTF
;
600 ret
= mbedtls_snprintf( p
, n
, "\n%sthis update : " \
601 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
602 crl
->this_update
.year
, crl
->this_update
.mon
,
603 crl
->this_update
.day
, crl
->this_update
.hour
,
604 crl
->this_update
.min
, crl
->this_update
.sec
);
605 MBEDTLS_X509_SAFE_SNPRINTF
;
607 ret
= mbedtls_snprintf( p
, n
, "\n%snext update : " \
608 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
609 crl
->next_update
.year
, crl
->next_update
.mon
,
610 crl
->next_update
.day
, crl
->next_update
.hour
,
611 crl
->next_update
.min
, crl
->next_update
.sec
);
612 MBEDTLS_X509_SAFE_SNPRINTF
;
616 ret
= mbedtls_snprintf( p
, n
, "\n%sRevoked certificates:",
618 MBEDTLS_X509_SAFE_SNPRINTF
;
620 while( entry
!= NULL
&& entry
->raw
.len
!= 0 )
622 ret
= mbedtls_snprintf( p
, n
, "\n%sserial number: ",
624 MBEDTLS_X509_SAFE_SNPRINTF
;
626 ret
= mbedtls_x509_serial_gets( p
, n
, &entry
->serial
);
627 MBEDTLS_X509_SAFE_SNPRINTF
;
629 ret
= mbedtls_snprintf( p
, n
, " revocation date: " \
630 "%04d-%02d-%02d %02d:%02d:%02d",
631 entry
->revocation_date
.year
, entry
->revocation_date
.mon
,
632 entry
->revocation_date
.day
, entry
->revocation_date
.hour
,
633 entry
->revocation_date
.min
, entry
->revocation_date
.sec
);
634 MBEDTLS_X509_SAFE_SNPRINTF
;
639 ret
= mbedtls_snprintf( p
, n
, "\n%ssigned using : ", prefix
);
640 MBEDTLS_X509_SAFE_SNPRINTF
;
642 ret
= mbedtls_x509_sig_alg_gets( p
, n
, &crl
->sig_oid
, crl
->sig_pk
, crl
->sig_md
,
644 MBEDTLS_X509_SAFE_SNPRINTF
;
646 ret
= mbedtls_snprintf( p
, n
, "\n" );
647 MBEDTLS_X509_SAFE_SNPRINTF
;
649 return( (int) ( size
- n
) );
653 * Initialize a CRL chain
655 void mbedtls_x509_crl_init( mbedtls_x509_crl
*crl
)
657 memset( crl
, 0, sizeof(mbedtls_x509_crl
) );
661 * Unallocate all CRL data
663 void mbedtls_x509_crl_free( mbedtls_x509_crl
*crl
)
665 mbedtls_x509_crl
*crl_cur
= crl
;
666 mbedtls_x509_crl
*crl_prv
;
667 mbedtls_x509_name
*name_cur
;
668 mbedtls_x509_name
*name_prv
;
669 mbedtls_x509_crl_entry
*entry_cur
;
670 mbedtls_x509_crl_entry
*entry_prv
;
677 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
678 mbedtls_free( crl_cur
->sig_opts
);
681 name_cur
= crl_cur
->issuer
.next
;
682 while( name_cur
!= NULL
)
685 name_cur
= name_cur
->next
;
686 mbedtls_zeroize( name_prv
, sizeof( mbedtls_x509_name
) );
687 mbedtls_free( name_prv
);
690 entry_cur
= crl_cur
->entry
.next
;
691 while( entry_cur
!= NULL
)
693 entry_prv
= entry_cur
;
694 entry_cur
= entry_cur
->next
;
695 mbedtls_zeroize( entry_prv
, sizeof( mbedtls_x509_crl_entry
) );
696 mbedtls_free( entry_prv
);
699 if( crl_cur
->raw
.p
!= NULL
)
701 mbedtls_zeroize( crl_cur
->raw
.p
, crl_cur
->raw
.len
);
702 mbedtls_free( crl_cur
->raw
.p
);
705 crl_cur
= crl_cur
->next
;
707 while( crl_cur
!= NULL
);
713 crl_cur
= crl_cur
->next
;
715 mbedtls_zeroize( crl_prv
, sizeof( mbedtls_x509_crl
) );
717 mbedtls_free( crl_prv
);
719 while( crl_cur
!= NULL
);
722 #endif /* MBEDTLS_X509_CRL_PARSE_C */