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