2 * X.509 Certidicate Revocation List (CRL) parsing
4 * Copyright The Mbed TLS Contributors
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.
20 * The ITU-T X.509 standard defines a certificate format for PKI.
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)
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
32 #if defined(MBEDTLS_X509_CRL_PARSE_C)
34 #include "mbedtls/x509_crl.h"
35 #include "mbedtls/error.h"
36 #include "mbedtls/oid.h"
37 #include "mbedtls/platform_util.h"
41 #if defined(MBEDTLS_PEM_PARSE_C)
42 #include "mbedtls/pem.h"
45 #if defined(MBEDTLS_PLATFORM_C)
46 #include "mbedtls/platform.h"
50 #define mbedtls_free free
51 #define mbedtls_calloc calloc
52 #define mbedtls_snprintf snprintf
55 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
61 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
66 * Version ::= INTEGER { v1(0), v2(1) }
68 static int x509_crl_get_version(unsigned char **p
,
69 const unsigned char *end
,
71 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
73 if ((ret
= mbedtls_asn1_get_int(p
, end
, ver
)) != 0) {
74 if (ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) {
79 return (MBEDTLS_ERR_X509_INVALID_VERSION
+ ret
);
86 * X.509 CRL v2 extensions
88 * We currently don't parse any extension's content, but we do check that the
89 * list of extensions is well-formed and abort on critical extensions (that
90 * are unsupported as we don't support any extension so far)
92 static int x509_get_crl_ext(unsigned char **p
,
93 const unsigned char *end
,
94 mbedtls_x509_buf
*ext
) {
95 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
101 * crlExtensions [0] EXPLICIT Extensions OPTIONAL
102 * -- if present, version MUST be v2
104 if ((ret
= mbedtls_x509_get_ext(p
, end
, ext
, 0)) != 0)
107 end
= ext
->p
+ ext
->len
;
111 * Extension ::= SEQUENCE {
112 * extnID OBJECT IDENTIFIER,
113 * critical BOOLEAN DEFAULT FALSE,
114 * extnValue OCTET STRING }
117 const unsigned char *end_ext_data
;
120 /* Get enclosing sequence tag */
121 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
,
122 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0)
123 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
125 end_ext_data
= *p
+ len
;
127 /* Get OID (currently ignored) */
128 if ((ret
= mbedtls_asn1_get_tag(p
, end_ext_data
, &len
,
129 MBEDTLS_ASN1_OID
)) != 0) {
130 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
134 /* Get optional critical */
135 if ((ret
= mbedtls_asn1_get_bool(p
, end_ext_data
,
136 &is_critical
)) != 0 &&
137 (ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)) {
138 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
141 /* Data should be octet string type */
142 if ((ret
= mbedtls_asn1_get_tag(p
, end_ext_data
, &len
,
143 MBEDTLS_ASN1_OCTET_STRING
)) != 0)
144 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
146 /* Ignore data so far and just check its length */
148 if (*p
!= end_ext_data
)
149 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
150 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
152 /* Abort on (unsupported) critical extensions */
154 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
155 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
159 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
160 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
166 * X.509 CRL v2 entry extensions (no extensions parsed yet.)
168 static int x509_get_crl_entry_ext(unsigned char **p
,
169 const unsigned char *end
,
170 mbedtls_x509_buf
*ext
) {
171 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
182 * Get CRL-entry extension sequence header
183 * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2
185 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &ext
->len
,
186 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
187 if (ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) {
191 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
196 if (end
!= *p
+ ext
->len
)
197 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
198 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
201 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
,
202 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0)
203 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
209 return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
210 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
218 static int x509_get_entries(unsigned char **p
,
219 const unsigned char *end
,
220 mbedtls_x509_crl_entry
*entry
) {
221 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
223 mbedtls_x509_crl_entry
*cur_entry
= entry
;
228 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &entry_len
,
229 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
)) != 0) {
230 if (ret
== MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
236 end
= *p
+ entry_len
;
240 const unsigned char *end2
;
242 cur_entry
->raw
.tag
= **p
;
243 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len2
,
244 MBEDTLS_ASN1_SEQUENCE
| MBEDTLS_ASN1_CONSTRUCTED
)) != 0) {
248 cur_entry
->raw
.p
= *p
;
249 cur_entry
->raw
.len
= len2
;
252 if ((ret
= mbedtls_x509_get_serial(p
, end2
, &cur_entry
->serial
)) != 0)
255 if ((ret
= mbedtls_x509_get_time(p
, end2
,
256 &cur_entry
->revocation_date
)) != 0)
259 if ((ret
= x509_get_crl_entry_ext(p
, end2
,
260 &cur_entry
->entry_ext
)) != 0)
264 cur_entry
->next
= mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry
));
266 if (cur_entry
->next
== NULL
)
267 return (MBEDTLS_ERR_X509_ALLOC_FAILED
);
269 cur_entry
= cur_entry
->next
;
277 * Parse one CRLs in DER format and append it to the chained list
279 int mbedtls_x509_crl_parse_der(mbedtls_x509_crl
*chain
,
280 const unsigned char *buf
, size_t buflen
) {
281 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
283 unsigned char *p
= NULL
, *end
= NULL
;
284 mbedtls_x509_buf sig_params1
, sig_params2
, sig_oid2
;
285 mbedtls_x509_crl
*crl
= chain
;
288 * Check for valid input
290 if (crl
== NULL
|| buf
== NULL
)
291 return (MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
293 memset(&sig_params1
, 0, sizeof(mbedtls_x509_buf
));
294 memset(&sig_params2
, 0, sizeof(mbedtls_x509_buf
));
295 memset(&sig_oid2
, 0, sizeof(mbedtls_x509_buf
));
298 * Add new CRL on the end of the chain if needed.
300 while (crl
->version
!= 0 && crl
->next
!= NULL
)
303 if (crl
->version
!= 0 && crl
->next
== NULL
) {
304 crl
->next
= mbedtls_calloc(1, sizeof(mbedtls_x509_crl
));
306 if (crl
->next
== NULL
) {
307 mbedtls_x509_crl_free(crl
);
308 return (MBEDTLS_ERR_X509_ALLOC_FAILED
);
311 mbedtls_x509_crl_init(crl
->next
);
316 * Copy raw DER-encoded CRL
319 return (MBEDTLS_ERR_X509_INVALID_FORMAT
);
321 p
= mbedtls_calloc(1, buflen
);
323 return (MBEDTLS_ERR_X509_ALLOC_FAILED
);
325 memcpy(p
, buf
, buflen
);
328 crl
->raw
.len
= buflen
;
333 * CertificateList ::= SEQUENCE {
334 * tbsCertList TBSCertList,
335 * signatureAlgorithm AlgorithmIdentifier,
336 * signatureValue BIT STRING }
338 if ((ret
= mbedtls_asn1_get_tag(&p
, end
, &len
,
339 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
340 mbedtls_x509_crl_free(crl
);
341 return (MBEDTLS_ERR_X509_INVALID_FORMAT
);
344 if (len
!= (size_t)(end
- p
)) {
345 mbedtls_x509_crl_free(crl
);
346 return (MBEDTLS_ERR_X509_INVALID_FORMAT
+
347 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
351 * TBSCertList ::= SEQUENCE {
355 if ((ret
= mbedtls_asn1_get_tag(&p
, end
, &len
,
356 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
357 mbedtls_x509_crl_free(crl
);
358 return (MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
362 crl
->tbs
.len
= end
- crl
->tbs
.p
;
365 * Version ::= INTEGER OPTIONAL { v1(0), v2(1) }
366 * -- if present, MUST be v2
368 * signature AlgorithmIdentifier
370 if ((ret
= x509_crl_get_version(&p
, end
, &crl
->version
)) != 0 ||
371 (ret
= mbedtls_x509_get_alg(&p
, end
, &crl
->sig_oid
, &sig_params1
)) != 0) {
372 mbedtls_x509_crl_free(crl
);
376 if (crl
->version
< 0 || crl
->version
> 1) {
377 mbedtls_x509_crl_free(crl
);
378 return (MBEDTLS_ERR_X509_UNKNOWN_VERSION
);
383 if ((ret
= mbedtls_x509_get_sig_alg(&crl
->sig_oid
, &sig_params1
,
384 &crl
->sig_md
, &crl
->sig_pk
,
385 &crl
->sig_opts
)) != 0) {
386 mbedtls_x509_crl_free(crl
);
387 return (MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG
);
393 crl
->issuer_raw
.p
= p
;
395 if ((ret
= mbedtls_asn1_get_tag(&p
, end
, &len
,
396 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
397 mbedtls_x509_crl_free(crl
);
398 return (MBEDTLS_ERR_X509_INVALID_FORMAT
+ ret
);
401 if ((ret
= mbedtls_x509_get_name(&p
, p
+ len
, &crl
->issuer
)) != 0) {
402 mbedtls_x509_crl_free(crl
);
406 crl
->issuer_raw
.len
= p
- crl
->issuer_raw
.p
;
410 * nextUpdate Time OPTIONAL
412 if ((ret
= mbedtls_x509_get_time(&p
, end
, &crl
->this_update
)) != 0) {
413 mbedtls_x509_crl_free(crl
);
417 if ((ret
= mbedtls_x509_get_time(&p
, end
, &crl
->next_update
)) != 0) {
418 if (ret
!= (MBEDTLS_ERR_X509_INVALID_DATE
+
419 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
) &&
420 ret
!= (MBEDTLS_ERR_X509_INVALID_DATE
+
421 MBEDTLS_ERR_ASN1_OUT_OF_DATA
)) {
422 mbedtls_x509_crl_free(crl
);
428 * revokedCertificates SEQUENCE OF SEQUENCE {
429 * userCertificate CertificateSerialNumber,
430 * revocationDate Time,
431 * crlEntryExtensions Extensions OPTIONAL
432 * -- if present, MUST be v2
435 if ((ret
= x509_get_entries(&p
, end
, &crl
->entry
)) != 0) {
436 mbedtls_x509_crl_free(crl
);
441 * crlExtensions EXPLICIT Extensions OPTIONAL
442 * -- if present, MUST be v2
444 if (crl
->version
== 2) {
445 ret
= x509_get_crl_ext(&p
, end
, &crl
->crl_ext
);
448 mbedtls_x509_crl_free(crl
);
454 mbedtls_x509_crl_free(crl
);
455 return (MBEDTLS_ERR_X509_INVALID_FORMAT
+
456 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
459 end
= crl
->raw
.p
+ crl
->raw
.len
;
462 * signatureAlgorithm AlgorithmIdentifier,
463 * signatureValue BIT STRING
465 if ((ret
= mbedtls_x509_get_alg(&p
, end
, &sig_oid2
, &sig_params2
)) != 0) {
466 mbedtls_x509_crl_free(crl
);
470 if (crl
->sig_oid
.len
!= sig_oid2
.len
||
471 memcmp(crl
->sig_oid
.p
, sig_oid2
.p
, crl
->sig_oid
.len
) != 0 ||
472 sig_params1
.len
!= sig_params2
.len
||
473 (sig_params1
.len
!= 0 &&
474 memcmp(sig_params1
.p
, sig_params2
.p
, sig_params1
.len
) != 0)) {
475 mbedtls_x509_crl_free(crl
);
476 return (MBEDTLS_ERR_X509_SIG_MISMATCH
);
479 if ((ret
= mbedtls_x509_get_sig(&p
, end
, &crl
->sig
)) != 0) {
480 mbedtls_x509_crl_free(crl
);
485 mbedtls_x509_crl_free(crl
);
486 return (MBEDTLS_ERR_X509_INVALID_FORMAT
+
487 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
494 * Parse one or more CRLs and add them to the chained list
496 int mbedtls_x509_crl_parse(mbedtls_x509_crl
*chain
, const unsigned char *buf
, size_t buflen
) {
497 #if defined(MBEDTLS_PEM_PARSE_C)
498 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
500 mbedtls_pem_context pem
;
503 if (chain
== NULL
|| buf
== NULL
)
504 return (MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
507 mbedtls_pem_init(&pem
);
509 // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
511 if (buflen
== 0 || buf
[buflen
- 1] != '\0')
512 ret
= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
;
514 ret
= mbedtls_pem_read_buffer(&pem
,
515 "-----BEGIN X509 CRL-----",
516 "-----END X509 CRL-----",
517 buf
, NULL
, 0, &use_len
);
528 if ((ret
= mbedtls_x509_crl_parse_der(chain
,
529 pem
.buf
, pem
.buflen
)) != 0) {
530 mbedtls_pem_free(&pem
);
534 mbedtls_pem_free(&pem
);
538 mbedtls_pem_free(&pem
);
540 /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
541 * And a valid CRL cannot be less than 1 byte anyway. */
542 while (is_pem
&& buflen
> 1);
547 #endif /* MBEDTLS_PEM_PARSE_C */
548 return (mbedtls_x509_crl_parse_der(chain
, buf
, buflen
));
551 #if defined(MBEDTLS_FS_IO)
553 * Load one or more CRLs and add them to the chained list
555 int mbedtls_x509_crl_parse_file(mbedtls_x509_crl
*chain
, const char *path
) {
556 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
560 if ((ret
= mbedtls_pk_load_file(path
, &buf
, &n
)) != 0)
563 ret
= mbedtls_x509_crl_parse(chain
, buf
, n
);
565 mbedtls_platform_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
) {
582 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
585 const mbedtls_x509_crl_entry
*entry
;
590 ret
= mbedtls_snprintf(p
, n
, "%sCRL version : %d",
591 prefix
, crl
->version
);
592 MBEDTLS_X509_SAFE_SNPRINTF
;
594 ret
= mbedtls_snprintf(p
, n
, "\n%sissuer name : ", prefix
);
595 MBEDTLS_X509_SAFE_SNPRINTF
;
596 ret
= mbedtls_x509_dn_gets(p
, n
, &crl
->issuer
);
597 MBEDTLS_X509_SAFE_SNPRINTF
;
599 ret
= mbedtls_snprintf(p
, n
, "\n%sthis update : " \
600 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
601 crl
->this_update
.year
, crl
->this_update
.mon
,
602 crl
->this_update
.day
, crl
->this_update
.hour
,
603 crl
->this_update
.min
, crl
->this_update
.sec
);
604 MBEDTLS_X509_SAFE_SNPRINTF
;
606 ret
= mbedtls_snprintf(p
, n
, "\n%snext update : " \
607 "%04d-%02d-%02d %02d:%02d:%02d", prefix
,
608 crl
->next_update
.year
, crl
->next_update
.mon
,
609 crl
->next_update
.day
, crl
->next_update
.hour
,
610 crl
->next_update
.min
, crl
->next_update
.sec
);
611 MBEDTLS_X509_SAFE_SNPRINTF
;
615 ret
= mbedtls_snprintf(p
, n
, "\n%sRevoked certificates:",
617 MBEDTLS_X509_SAFE_SNPRINTF
;
619 while (entry
!= NULL
&& entry
->raw
.len
!= 0) {
620 ret
= mbedtls_snprintf(p
, n
, "\n%sserial number: ",
622 MBEDTLS_X509_SAFE_SNPRINTF
;
624 ret
= mbedtls_x509_serial_gets(p
, n
, &entry
->serial
);
625 MBEDTLS_X509_SAFE_SNPRINTF
;
627 ret
= mbedtls_snprintf(p
, n
, " revocation date: " \
628 "%04d-%02d-%02d %02d:%02d:%02d",
629 entry
->revocation_date
.year
, entry
->revocation_date
.mon
,
630 entry
->revocation_date
.day
, entry
->revocation_date
.hour
,
631 entry
->revocation_date
.min
, entry
->revocation_date
.sec
);
632 MBEDTLS_X509_SAFE_SNPRINTF
;
637 ret
= mbedtls_snprintf(p
, n
, "\n%ssigned using : ", prefix
);
638 MBEDTLS_X509_SAFE_SNPRINTF
;
640 ret
= mbedtls_x509_sig_alg_gets(p
, n
, &crl
->sig_oid
, crl
->sig_pk
, crl
->sig_md
,
642 MBEDTLS_X509_SAFE_SNPRINTF
;
644 ret
= mbedtls_snprintf(p
, n
, "\n");
645 MBEDTLS_X509_SAFE_SNPRINTF
;
647 return ((int)(size
- n
));
651 * Initialize a CRL chain
653 void mbedtls_x509_crl_init(mbedtls_x509_crl
*crl
) {
654 memset(crl
, 0, sizeof(mbedtls_x509_crl
));
658 * Unallocate all CRL data
660 void mbedtls_x509_crl_free(mbedtls_x509_crl
*crl
) {
661 mbedtls_x509_crl
*crl_cur
= crl
;
662 mbedtls_x509_crl
*crl_prv
;
663 mbedtls_x509_name
*name_cur
;
664 mbedtls_x509_name
*name_prv
;
665 mbedtls_x509_crl_entry
*entry_cur
;
666 mbedtls_x509_crl_entry
*entry_prv
;
672 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
673 mbedtls_free(crl_cur
->sig_opts
);
676 name_cur
= crl_cur
->issuer
.next
;
677 while (name_cur
!= NULL
) {
679 name_cur
= name_cur
->next
;
680 mbedtls_platform_zeroize(name_prv
, sizeof(mbedtls_x509_name
));
681 mbedtls_free(name_prv
);
684 entry_cur
= crl_cur
->entry
.next
;
685 while (entry_cur
!= NULL
) {
686 entry_prv
= entry_cur
;
687 entry_cur
= entry_cur
->next
;
688 mbedtls_platform_zeroize(entry_prv
,
689 sizeof(mbedtls_x509_crl_entry
));
690 mbedtls_free(entry_prv
);
693 if (crl_cur
->raw
.p
!= NULL
) {
694 mbedtls_platform_zeroize(crl_cur
->raw
.p
, crl_cur
->raw
.len
);
695 mbedtls_free(crl_cur
->raw
.p
);
698 crl_cur
= crl_cur
->next
;
699 } while (crl_cur
!= NULL
);
704 crl_cur
= crl_cur
->next
;
706 mbedtls_platform_zeroize(crl_prv
, sizeof(mbedtls_x509_crl
));
708 mbedtls_free(crl_prv
);
709 } while (crl_cur
!= NULL
);
712 #endif /* MBEDTLS_X509_CRL_PARSE_C */