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