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