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