1 /*
2 * Copyright (C) 2003-2016 Free Software Foundation, Inc.
3 * Copyright (C) 2015-2016 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 #include "gnutls_int.h"
25 #include <libtasn1.h>
26
27 #include <datum.h>
28 #include <global.h>
29 #include "errors.h"
30 #include <common.h>
31 #include <x509_b64.h>
32 #include <x509_int.h>
33 #include <x509.h>
34
crl_reinit(gnutls_x509_crl_t crl)35 static int crl_reinit(gnutls_x509_crl_t crl)
36 {
37 int result;
38
39 if (crl->crl)
40 asn1_delete_structure(&crl->crl);
41
42 result = asn1_create_element(_gnutls_get_pkix(),
43 "PKIX1.CertificateList",
44 &crl->crl);
45 if (result != ASN1_SUCCESS) {
46 gnutls_assert();
47 return _gnutls_asn2err(result);
48 }
49 crl->rcache = NULL;
50 crl->rcache_idx = 0;
51 crl->raw_issuer_dn.size = 0;
52
53 return 0;
54 }
55
56 /**
57 * gnutls_x509_crl_init:
58 * @crl: A pointer to the type to be initialized
59 *
60 * This function will initialize a CRL structure. CRL stands for
61 * Certificate Revocation List. A revocation list usually contains
62 * lists of certificate serial numbers that have been revoked by an
63 * Authority. The revocation lists are always signed with the
64 * authority's private key.
65 *
66 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
67 * negative error value.
68 **/
gnutls_x509_crl_init(gnutls_x509_crl_t * crl)69 int gnutls_x509_crl_init(gnutls_x509_crl_t * crl)
70 {
71 FAIL_IF_LIB_ERROR;
72
73 *crl = gnutls_calloc(1, sizeof(gnutls_x509_crl_int));
74
75 if (*crl) {
76 int result = crl_reinit(*crl);
77 if (result < 0) {
78 gnutls_assert();
79 gnutls_free(*crl);
80 return result;
81 }
82 return 0; /* success */
83 }
84 return GNUTLS_E_MEMORY_ERROR;
85 }
86
87 /**
88 * gnutls_x509_crl_deinit:
89 * @crl: The data to be deinitialized
90 *
91 * This function will deinitialize a CRL structure.
92 **/
gnutls_x509_crl_deinit(gnutls_x509_crl_t crl)93 void gnutls_x509_crl_deinit(gnutls_x509_crl_t crl)
94 {
95 if (!crl)
96 return;
97
98 if (crl->crl)
99 asn1_delete_structure(&crl->crl);
100 gnutls_free(crl->der.data);
101
102 gnutls_free(crl);
103 }
104
105 /**
106 * gnutls_x509_crl_import:
107 * @crl: The data to store the parsed CRL.
108 * @data: The DER or PEM encoded CRL.
109 * @format: One of DER or PEM
110 *
111 * This function will convert the given DER or PEM encoded CRL
112 * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
113 *
114 * If the CRL is PEM encoded it should have a header of "X509 CRL".
115 *
116 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
117 * negative error value.
118 **/
119 int
gnutls_x509_crl_import(gnutls_x509_crl_t crl,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format)120 gnutls_x509_crl_import(gnutls_x509_crl_t crl,
121 const gnutls_datum_t * data,
122 gnutls_x509_crt_fmt_t format)
123 {
124 int result = 0;
125
126 if (crl == NULL) {
127 gnutls_assert();
128 return GNUTLS_E_INVALID_REQUEST;
129 }
130
131 _gnutls_free_datum(&crl->der);
132
133 /* If the CRL is in PEM format then decode it
134 */
135 if (format == GNUTLS_X509_FMT_PEM) {
136 result =
137 _gnutls_fbase64_decode(PEM_CRL, data->data, data->size,
138 &crl->der);
139
140 if (result < 0) {
141 gnutls_assert();
142 return result;
143 }
144 } else {
145 result = _gnutls_set_datum(&crl->der, data->data, data->size);
146 if (result < 0) {
147 gnutls_assert();
148 return result;
149 }
150 }
151
152 if (crl->expanded) {
153 result = crl_reinit(crl);
154 if (result < 0) {
155 gnutls_assert();
156 goto cleanup;
157 }
158 }
159 crl->expanded = 1;
160
161 result =
162 _asn1_strict_der_decode(&crl->crl, crl->der.data, crl->der.size, NULL);
163 if (result != ASN1_SUCCESS) {
164 result = _gnutls_asn2err(result);
165 gnutls_assert();
166 goto cleanup;
167 }
168
169 result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der,
170 "tbsCertList.issuer.rdnSequence",
171 &crl->raw_issuer_dn);
172 if (result < 0) {
173 gnutls_assert();
174 goto cleanup;
175 }
176
177 return 0;
178
179 cleanup:
180 _gnutls_free_datum(&crl->der);
181 return result;
182 }
183
184
185 /**
186 * gnutls_x509_crl_get_issuer_dn:
187 * @crl: should contain a gnutls_x509_crl_t type
188 * @buf: a pointer to a structure to hold the peer's name (may be null)
189 * @sizeof_buf: initially holds the size of @buf
190 *
191 * This function will copy the name of the CRL issuer in the provided
192 * buffer. The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
193 * described in RFC4514. The output string will be ASCII or UTF-8
194 * encoded, depending on the certificate data.
195 *
196 * If buf is %NULL then only the size will be filled.
197 *
198 * This function does not output a fully RFC4514 compliant string, if
199 * that is required see gnutls_x509_crl_get_issuer_dn3().
200 *
201 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
202 * not long enough, and in that case the sizeof_buf will be updated
203 * with the required size, and 0 on success.
204 *
205 **/
206 int
gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl_t crl,char * buf,size_t * sizeof_buf)207 gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl_t crl, char *buf,
208 size_t * sizeof_buf)
209 {
210 if (crl == NULL) {
211 gnutls_assert();
212 return GNUTLS_E_INVALID_REQUEST;
213 }
214
215 return _gnutls_x509_parse_dn(crl->crl,
216 "tbsCertList.issuer.rdnSequence",
217 buf, sizeof_buf, GNUTLS_X509_DN_FLAG_COMPAT);
218 }
219
220 /**
221 * gnutls_x509_crl_get_issuer_dn_by_oid:
222 * @crl: should contain a gnutls_x509_crl_t type
223 * @oid: holds an Object Identified in null terminated string
224 * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use (0) to get the first one.
225 * @raw_flag: If non-zero returns the raw DER data of the DN part.
226 * @buf: a pointer to a structure to hold the peer's name (may be null)
227 * @sizeof_buf: initially holds the size of @buf
228 *
229 * This function will extract the part of the name of the CRL issuer
230 * specified by the given OID. The output will be encoded as described
231 * in RFC4514. The output string will be ASCII or UTF-8 encoded,
232 * depending on the certificate data.
233 *
234 * Some helper macros with popular OIDs can be found in gnutls/x509.h
235 * If raw flag is (0), this function will only return known OIDs as
236 * text. Other OIDs will be DER encoded, as described in RFC4514 -- in
237 * hex format with a '#' prefix. You can check about known OIDs
238 * using gnutls_x509_dn_oid_known().
239 *
240 * If buf is null then only the size will be filled.
241 *
242 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
243 * not long enough, and in that case the sizeof_buf will be updated
244 * with the required size, and 0 on success.
245 **/
246 int
gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl_t crl,const char * oid,unsigned indx,unsigned int raw_flag,void * buf,size_t * sizeof_buf)247 gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl_t crl,
248 const char *oid, unsigned indx,
249 unsigned int raw_flag, void *buf,
250 size_t * sizeof_buf)
251 {
252 gnutls_datum_t td;
253 int ret;
254
255 if (crl == NULL) {
256 gnutls_assert();
257 return GNUTLS_E_INVALID_REQUEST;
258 }
259
260 ret = _gnutls_x509_parse_dn_oid(crl->crl,
261 "tbsCertList.issuer.rdnSequence",
262 oid, indx, raw_flag, &td);
263 if (ret < 0)
264 return gnutls_assert_val(ret);
265
266 return _gnutls_strdatum_to_buf(&td, buf, sizeof_buf);
267 }
268
269
270 /**
271 * gnutls_x509_crl_get_dn_oid:
272 * @crl: should contain a gnutls_x509_crl_t type
273 * @indx: Specifies which DN OID to send. Use (0) to get the first one.
274 * @oid: a pointer to store the OID (may be null)
275 * @sizeof_oid: initially holds the size of 'oid'
276 *
277 * This function will extract the requested OID of the name of the CRL
278 * issuer, specified by the given index.
279 *
280 * If oid is null then only the size will be filled.
281 *
282 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
283 * not long enough, and in that case the sizeof_oid will be updated
284 * with the required size. On success 0 is returned.
285 **/
286 int
gnutls_x509_crl_get_dn_oid(gnutls_x509_crl_t crl,unsigned indx,void * oid,size_t * sizeof_oid)287 gnutls_x509_crl_get_dn_oid(gnutls_x509_crl_t crl,
288 unsigned indx, void *oid, size_t * sizeof_oid)
289 {
290 if (crl == NULL) {
291 gnutls_assert();
292 return GNUTLS_E_INVALID_REQUEST;
293 }
294
295 return _gnutls_x509_get_dn_oid(crl->crl,
296 "tbsCertList.issuer.rdnSequence",
297 indx, oid, sizeof_oid);
298 }
299
300 /**
301 * gnutls_x509_crl_get_issuer_dn2:
302 * @crl: should contain a #gnutls_x509_crl_t type
303 * @dn: a pointer to a structure to hold the name
304 *
305 * This function will allocate buffer and copy the name of the CRL issuer.
306 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
307 * described in RFC4514. The output string will be ASCII or UTF-8
308 * encoded, depending on the certificate data.
309 *
310 * This function does not output a fully RFC4514 compliant string, if
311 * that is required see gnutls_x509_crl_get_issuer_dn3().
312 *
313 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
314 * negative error value.
315 *
316 * Since: 3.1.10
317 **/
318 int
gnutls_x509_crl_get_issuer_dn2(gnutls_x509_crl_t crl,gnutls_datum_t * dn)319 gnutls_x509_crl_get_issuer_dn2(gnutls_x509_crl_t crl, gnutls_datum_t * dn)
320 {
321 if (crl == NULL) {
322 gnutls_assert();
323 return GNUTLS_E_INVALID_REQUEST;
324 }
325
326 return _gnutls_x509_get_dn(crl->crl,
327 "tbsCertList.issuer.rdnSequence",
328 dn, GNUTLS_X509_DN_FLAG_COMPAT);
329 }
330
331 /**
332 * gnutls_x509_crl_get_issuer_dn3:
333 * @crl: should contain a #gnutls_x509_crl_t type
334 * @dn: a pointer to a structure to hold the name
335 * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
336 *
337 * This function will allocate buffer and copy the name of the CRL issuer.
338 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
339 * described in RFC4514. The output string will be ASCII or UTF-8
340 * encoded, depending on the certificate data.
341 *
342 * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
343 * format will match the format output by previous to 3.5.6 versions of GnuTLS
344 * which was not not fully RFC4514-compliant.
345 *
346 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
347 * negative error value.
348 *
349 * Since: 3.5.7
350 **/
351 int
gnutls_x509_crl_get_issuer_dn3(gnutls_x509_crl_t crl,gnutls_datum_t * dn,unsigned flags)352 gnutls_x509_crl_get_issuer_dn3(gnutls_x509_crl_t crl, gnutls_datum_t * dn, unsigned flags)
353 {
354 if (crl == NULL) {
355 gnutls_assert();
356 return GNUTLS_E_INVALID_REQUEST;
357 }
358
359 return _gnutls_x509_get_dn(crl->crl,
360 "tbsCertList.issuer.rdnSequence",
361 dn, flags);
362 }
363
364 /**
365 * gnutls_x509_crl_get_signature_algorithm:
366 * @crl: should contain a #gnutls_x509_crl_t type
367 *
368 * This function will return a value of the #gnutls_sign_algorithm_t
369 * enumeration that is the signature algorithm.
370 *
371 * Since 3.6.0 this function never returns a negative error code.
372 * Error cases and unknown/unsupported signature algorithms are
373 * mapped to %GNUTLS_SIGN_UNKNOWN.
374 *
375 * Returns: a #gnutls_sign_algorithm_t value
376 **/
gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl_t crl)377 int gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl_t crl)
378 {
379 return map_errs_to_zero(_gnutls_x509_get_signature_algorithm(crl->crl,
380 "signatureAlgorithm"));
381 }
382
383 /**
384 * gnutls_x509_crl_get_signature_oid:
385 * @crl: should contain a #gnutls_x509_crl_t type
386 * @oid: a pointer to a buffer to hold the OID (may be null)
387 * @oid_size: initially holds the size of @oid
388 *
389 * This function will return the OID of the signature algorithm
390 * that has been used to sign this CRL. This is function
391 * is useful in the case gnutls_x509_crl_get_signature_algorithm()
392 * returned %GNUTLS_SIGN_UNKNOWN.
393 *
394 * Returns: zero or a negative error code on error.
395 *
396 * Since: 3.5.0
397 **/
gnutls_x509_crl_get_signature_oid(gnutls_x509_crl_t crl,char * oid,size_t * oid_size)398 int gnutls_x509_crl_get_signature_oid(gnutls_x509_crl_t crl, char *oid, size_t *oid_size)
399 {
400 char str[MAX_OID_SIZE];
401 int len, result, ret;
402 gnutls_datum_t out;
403
404 len = sizeof(str);
405 result = asn1_read_value(crl->crl, "signatureAlgorithm.algorithm", str, &len);
406 if (result != ASN1_SUCCESS) {
407 gnutls_assert();
408 return _gnutls_asn2err(result);
409 }
410
411 out.data = (void*)str;
412 out.size = len;
413
414 ret = _gnutls_copy_string(&out, (void*)oid, oid_size);
415 if (ret < 0) {
416 gnutls_assert();
417 return ret;
418 }
419
420 return 0;
421 }
422
423 /**
424 * gnutls_x509_crl_get_signature:
425 * @crl: should contain a gnutls_x509_crl_t type
426 * @sig: a pointer where the signature part will be copied (may be null).
427 * @sizeof_sig: initially holds the size of @sig
428 *
429 * This function will extract the signature field of a CRL.
430 *
431 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
432 * negative error value.
433 **/
434 int
gnutls_x509_crl_get_signature(gnutls_x509_crl_t crl,char * sig,size_t * sizeof_sig)435 gnutls_x509_crl_get_signature(gnutls_x509_crl_t crl,
436 char *sig, size_t * sizeof_sig)
437 {
438 int result;
439 unsigned int bits;
440 int len;
441
442 if (crl == NULL) {
443 gnutls_assert();
444 return GNUTLS_E_INVALID_REQUEST;
445 }
446
447 len = 0;
448 result = asn1_read_value(crl->crl, "signature", NULL, &len);
449
450 if (result != ASN1_MEM_ERROR) {
451 gnutls_assert();
452 return _gnutls_asn2err(result);
453 }
454
455 bits = len;
456 if (bits % 8 != 0) {
457 gnutls_assert();
458 return GNUTLS_E_CERTIFICATE_ERROR;
459 }
460
461 len = bits / 8;
462
463 if (*sizeof_sig < (unsigned) len) {
464 *sizeof_sig = bits / 8;
465 return GNUTLS_E_SHORT_MEMORY_BUFFER;
466 }
467
468 result = asn1_read_value(crl->crl, "signature", sig, &len);
469 if (result != ASN1_SUCCESS) {
470 gnutls_assert();
471 return _gnutls_asn2err(result);
472 }
473
474 return 0;
475 }
476
477 /**
478 * gnutls_x509_crl_get_version:
479 * @crl: should contain a #gnutls_x509_crl_t type
480 *
481 * This function will return the version of the specified CRL.
482 *
483 * Returns: The version number, or a negative error code on error.
484 **/
gnutls_x509_crl_get_version(gnutls_x509_crl_t crl)485 int gnutls_x509_crl_get_version(gnutls_x509_crl_t crl)
486 {
487 if (crl == NULL) {
488 gnutls_assert();
489 return GNUTLS_E_INVALID_REQUEST;
490 }
491
492 return _gnutls_x509_get_version(crl->crl, "tbsCertList.version");
493 }
494
495 /**
496 * gnutls_x509_crl_get_this_update:
497 * @crl: should contain a #gnutls_x509_crl_t type
498 *
499 * This function will return the time this CRL was issued.
500 *
501 * Returns: when the CRL was issued, or (time_t)-1 on error.
502 **/
gnutls_x509_crl_get_this_update(gnutls_x509_crl_t crl)503 time_t gnutls_x509_crl_get_this_update(gnutls_x509_crl_t crl)
504 {
505 if (crl == NULL) {
506 gnutls_assert();
507 return (time_t) - 1;
508 }
509
510 return _gnutls_x509_get_time(crl->crl, "tbsCertList.thisUpdate",
511 0);
512 }
513
514 /**
515 * gnutls_x509_crl_get_next_update:
516 * @crl: should contain a #gnutls_x509_crl_t type
517 *
518 * This function will return the time the next CRL will be issued.
519 * This field is optional in a CRL so it might be normal to get an
520 * error instead.
521 *
522 * Returns: when the next CRL will be issued, or (time_t)-1 on error.
523 **/
gnutls_x509_crl_get_next_update(gnutls_x509_crl_t crl)524 time_t gnutls_x509_crl_get_next_update(gnutls_x509_crl_t crl)
525 {
526 if (crl == NULL) {
527 gnutls_assert();
528 return (time_t) - 1;
529 }
530
531 return _gnutls_x509_get_time(crl->crl, "tbsCertList.nextUpdate",
532 0);
533 }
534
535 /**
536 * gnutls_x509_crl_get_crt_count:
537 * @crl: should contain a #gnutls_x509_crl_t type
538 *
539 * This function will return the number of revoked certificates in the
540 * given CRL.
541 *
542 * Returns: number of certificates, a negative error code on failure.
543 **/
gnutls_x509_crl_get_crt_count(gnutls_x509_crl_t crl)544 int gnutls_x509_crl_get_crt_count(gnutls_x509_crl_t crl)
545 {
546
547 int count, result;
548
549 if (crl == NULL) {
550 gnutls_assert();
551 return GNUTLS_E_INVALID_REQUEST;
552 }
553
554 result =
555 asn1_number_of_elements(crl->crl,
556 "tbsCertList.revokedCertificates",
557 &count);
558
559 if (result != ASN1_SUCCESS) {
560 gnutls_assert();
561 return 0; /* no certificates */
562 }
563
564 return count;
565 }
566
567 /**
568 * gnutls_x509_crl_get_crt_serial:
569 * @crl: should contain a #gnutls_x509_crl_t type
570 * @indx: the index of the certificate to extract (starting from 0)
571 * @serial: where the serial number will be copied
572 * @serial_size: initially holds the size of serial
573 * @t: if non null, will hold the time this certificate was revoked
574 *
575 * This function will retrieve the serial number of the specified, by
576 * the index, revoked certificate.
577 *
578 * Note that this function will have performance issues in large sequences
579 * of revoked certificates. In that case use gnutls_x509_crl_iter_crt_serial().
580 *
581 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
582 * negative error value.
583 **/
584 int
gnutls_x509_crl_get_crt_serial(gnutls_x509_crl_t crl,unsigned indx,unsigned char * serial,size_t * serial_size,time_t * t)585 gnutls_x509_crl_get_crt_serial(gnutls_x509_crl_t crl, unsigned indx,
586 unsigned char *serial,
587 size_t * serial_size, time_t * t)
588 {
589
590 int result, _serial_size;
591 char serial_name[MAX_NAME_SIZE];
592 char date_name[MAX_NAME_SIZE];
593
594 if (crl == NULL) {
595 gnutls_assert();
596 return GNUTLS_E_INVALID_REQUEST;
597 }
598
599 snprintf(serial_name, sizeof(serial_name),
600 "tbsCertList.revokedCertificates.?%u.userCertificate",
601 indx + 1);
602 snprintf(date_name, sizeof(date_name),
603 "tbsCertList.revokedCertificates.?%u.revocationDate",
604 indx + 1);
605
606 _serial_size = *serial_size;
607 result =
608 asn1_read_value(crl->crl, serial_name, serial, &_serial_size);
609
610 *serial_size = _serial_size;
611 if (result != ASN1_SUCCESS) {
612 gnutls_assert();
613 if (result == ASN1_ELEMENT_NOT_FOUND)
614 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
615 return _gnutls_asn2err(result);
616 }
617
618 if (t) {
619 *t = _gnutls_x509_get_time(crl->crl, date_name, 0);
620 }
621
622 return 0;
623 }
624
625 /**
626 * gnutls_x509_crl_iter_deinit:
627 * @iter: The iterator to be deinitialized
628 *
629 * This function will deinitialize an iterator type.
630 **/
gnutls_x509_crl_iter_deinit(gnutls_x509_crl_iter_t iter)631 void gnutls_x509_crl_iter_deinit(gnutls_x509_crl_iter_t iter)
632 {
633 if (!iter)
634 return;
635
636 gnutls_free(iter);
637 }
638
639 /**
640 * gnutls_x509_crl_iter_crt_serial:
641 * @crl: should contain a #gnutls_x509_crl_t type
642 * @iter: A pointer to an iterator (initially the iterator should be %NULL)
643 * @serial: where the serial number will be copied
644 * @serial_size: initially holds the size of serial
645 * @t: if non null, will hold the time this certificate was revoked
646 *
647 * This function performs the same as gnutls_x509_crl_get_crt_serial(),
648 * but reads sequentially and keeps state in the iterator
649 * between calls. That allows it to provide better performance in sequences
650 * with many elements (50000+).
651 *
652 * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
653 * is returned and the iterator is reset.
654 *
655 * After use, the iterator must be deinitialized using gnutls_x509_crl_iter_deinit().
656 *
657 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
658 * negative error value.
659 **/
660 int
gnutls_x509_crl_iter_crt_serial(gnutls_x509_crl_t crl,gnutls_x509_crl_iter_t * iter,unsigned char * serial,size_t * serial_size,time_t * t)661 gnutls_x509_crl_iter_crt_serial(gnutls_x509_crl_t crl,
662 gnutls_x509_crl_iter_t *iter,
663 unsigned char *serial,
664 size_t * serial_size, time_t * t)
665 {
666
667 int result, _serial_size;
668 char serial_name[MAX_NAME_SIZE];
669 char date_name[MAX_NAME_SIZE];
670
671 if (crl == NULL || iter == NULL) {
672 gnutls_assert();
673 return GNUTLS_E_INVALID_REQUEST;
674 }
675
676 if (*iter == NULL) {
677 *iter = gnutls_calloc(1, sizeof(struct gnutls_x509_crl_iter));
678 if (*iter == NULL)
679 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
680 }
681
682 if ((*iter)->rcache == NULL) {
683 (*iter)->rcache = asn1_find_node (crl->crl, "tbsCertList.revokedCertificates.?1");
684 (*iter)->rcache_idx = 1;
685 } else {
686 snprintf(serial_name, sizeof(serial_name),
687 "?%d", (*iter)->rcache_idx);
688 (*iter)->rcache = asn1_find_node ((*iter)->rcache, serial_name);
689 }
690 if ((*iter)->rcache == NULL) {
691 /* reset */
692 (*iter)->rcache = NULL;
693 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
694 }
695
696 snprintf(serial_name, sizeof(serial_name),
697 "?%d.userCertificate", (*iter)->rcache_idx);
698
699 _serial_size = *serial_size;
700 result =
701 asn1_read_value((*iter)->rcache, serial_name, serial, &_serial_size);
702
703 *serial_size = _serial_size;
704 if (result != ASN1_SUCCESS) {
705 gnutls_assert();
706 if (result == ASN1_ELEMENT_NOT_FOUND) {
707 /* reset */
708 (*iter)->rcache = NULL;
709 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
710 }
711 return _gnutls_asn2err(result);
712 }
713
714 if (t) {
715 snprintf(date_name, sizeof(date_name),
716 "?%d.revocationDate", (*iter)->rcache_idx);
717 *t = _gnutls_x509_get_time((*iter)->rcache, date_name, 0);
718 }
719
720 (*iter)->rcache_idx++;
721
722 return 0;
723 }
724
725 /**
726 * gnutls_x509_crl_get_raw_issuer_dn:
727 * @crl: should contain a gnutls_x509_crl_t type
728 * @dn: will hold the starting point of the DN
729 *
730 * This function will return a pointer to the DER encoded DN structure
731 * and the length.
732 *
733 * Returns: a negative error code on error, and (0) on success.
734 *
735 * Since: 2.12.0
736 **/
737 int
gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl,gnutls_datum_t * dn)738 gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl,
739 gnutls_datum_t * dn)
740 {
741 if (crl->raw_issuer_dn.size != 0) {
742 return _gnutls_set_datum(dn, crl->raw_issuer_dn.data,
743 crl->raw_issuer_dn.size);
744 } else {
745 return _gnutls_x509_get_raw_field(crl->crl, "tbsCertList.issuer.rdnSequence", dn);
746 }
747 }
748
749 /**
750 * gnutls_x509_crl_export:
751 * @crl: Holds the revocation list
752 * @format: the format of output params. One of PEM or DER.
753 * @output_data: will contain a private key PEM or DER encoded
754 * @output_data_size: holds the size of output_data (and will
755 * be replaced by the actual size of parameters)
756 *
757 * This function will export the revocation list to DER or PEM format.
758 *
759 * If the buffer provided is not long enough to hold the output, then
760 * %GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
761 *
762 * If the structure is PEM encoded, it will have a header
763 * of "BEGIN X509 CRL".
764 *
765 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
766 * negative error value.
767 **/
768 int
gnutls_x509_crl_export(gnutls_x509_crl_t crl,gnutls_x509_crt_fmt_t format,void * output_data,size_t * output_data_size)769 gnutls_x509_crl_export(gnutls_x509_crl_t crl,
770 gnutls_x509_crt_fmt_t format, void *output_data,
771 size_t * output_data_size)
772 {
773 if (crl == NULL) {
774 gnutls_assert();
775 return GNUTLS_E_INVALID_REQUEST;
776 }
777
778 return _gnutls_x509_export_int(crl->crl, format, PEM_CRL,
779 output_data, output_data_size);
780 }
781
782 /**
783 * gnutls_x509_crl_export2:
784 * @crl: Holds the revocation list
785 * @format: the format of output params. One of PEM or DER.
786 * @out: will contain a private key PEM or DER encoded
787 *
788 * This function will export the revocation list to DER or PEM format.
789 *
790 * The output buffer is allocated using gnutls_malloc().
791 *
792 * If the structure is PEM encoded, it will have a header
793 * of "BEGIN X509 CRL".
794 *
795 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
796 * negative error value.
797 *
798 * Since 3.1.3
799 **/
800 int
gnutls_x509_crl_export2(gnutls_x509_crl_t crl,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)801 gnutls_x509_crl_export2(gnutls_x509_crl_t crl,
802 gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
803 {
804 if (crl == NULL) {
805 gnutls_assert();
806 return GNUTLS_E_INVALID_REQUEST;
807 }
808
809 return _gnutls_x509_export_int2(crl->crl, format, PEM_CRL, out);
810 }
811
812 /*-
813 * _gnutls_x509_crl_cpy - This function copies a gnutls_x509_crl_t type
814 * @dest: The data where to copy
815 * @src: The data to be copied
816 *
817 * This function will copy an X.509 certificate structure.
818 *
819 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
820 * negative error value.
821 -*/
_gnutls_x509_crl_cpy(gnutls_x509_crl_t dest,gnutls_x509_crl_t src)822 int _gnutls_x509_crl_cpy(gnutls_x509_crl_t dest, gnutls_x509_crl_t src)
823 {
824 int ret;
825 gnutls_datum_t tmp;
826
827 ret = gnutls_x509_crl_export2(src, GNUTLS_X509_FMT_DER, &tmp);
828 if (ret < 0)
829 return gnutls_assert_val(ret);
830
831 ret = gnutls_x509_crl_import(dest, &tmp, GNUTLS_X509_FMT_DER);
832
833 gnutls_free(tmp.data);
834
835 if (ret < 0) {
836 gnutls_assert();
837 return ret;
838 }
839
840 return 0;
841
842 }
843
844 static int
_get_authority_key_id(gnutls_x509_crl_t cert,ASN1_TYPE * c2,unsigned int * critical)845 _get_authority_key_id(gnutls_x509_crl_t cert, ASN1_TYPE * c2,
846 unsigned int *critical)
847 {
848 int ret;
849 gnutls_datum_t id;
850
851 *c2 = ASN1_TYPE_EMPTY;
852
853 if (cert == NULL) {
854 gnutls_assert();
855 return GNUTLS_E_INVALID_REQUEST;
856 }
857
858 if ((ret =
859 _gnutls_x509_crl_get_extension(cert, "2.5.29.35", 0, &id,
860 critical)) < 0) {
861 return gnutls_assert_val(ret);
862 }
863
864 if (id.size == 0 || id.data == NULL) {
865 gnutls_assert();
866 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
867 }
868
869 ret = asn1_create_element
870 (_gnutls_get_pkix(), "PKIX1.AuthorityKeyIdentifier", c2);
871 if (ret != ASN1_SUCCESS) {
872 gnutls_assert();
873 _gnutls_free_datum(&id);
874 return _gnutls_asn2err(ret);
875 }
876
877 ret = _asn1_strict_der_decode(c2, id.data, id.size, NULL);
878 _gnutls_free_datum(&id);
879
880 if (ret != ASN1_SUCCESS) {
881 gnutls_assert();
882 asn1_delete_structure(c2);
883 return _gnutls_asn2err(ret);
884 }
885
886 return 0;
887 }
888
889 /**
890 * gnutls_x509_crl_get_authority_key_gn_serial:
891 * @crl: should contain a #gnutls_x509_crl_t type
892 * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
893 * @alt: is the place where the alternative name will be copied to
894 * @alt_size: holds the size of alt.
895 * @alt_type: holds the type of the alternative name (one of gnutls_x509_subject_alt_name_t).
896 * @serial: buffer to store the serial number (may be null)
897 * @serial_size: Holds the size of the serial field (may be null)
898 * @critical: will be non-zero if the extension is marked as critical (may be null)
899 *
900 * This function will return the X.509 authority key
901 * identifier when stored as a general name (authorityCertIssuer)
902 * and serial number.
903 *
904 * Because more than one general names might be stored
905 * @seq can be used as a counter to request them all until
906 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
907 *
908 * Returns: Returns 0 on success, or an error code.
909 *
910 * Since: 3.0
911 **/
912 int
gnutls_x509_crl_get_authority_key_gn_serial(gnutls_x509_crl_t crl,unsigned int seq,void * alt,size_t * alt_size,unsigned int * alt_type,void * serial,size_t * serial_size,unsigned int * critical)913 gnutls_x509_crl_get_authority_key_gn_serial(gnutls_x509_crl_t crl,
914 unsigned int seq,
915 void *alt,
916 size_t * alt_size,
917 unsigned int *alt_type,
918 void *serial,
919 size_t * serial_size,
920 unsigned int *critical)
921 {
922 int ret, result, len;
923 ASN1_TYPE c2;
924
925 ret = _get_authority_key_id(crl, &c2, critical);
926 if (ret < 0)
927 return gnutls_assert_val(ret);
928
929 ret =
930 _gnutls_parse_general_name(c2, "authorityCertIssuer", seq, alt,
931 alt_size, alt_type, 0);
932 if (ret < 0) {
933 ret = gnutls_assert_val(ret);
934 goto fail;
935 }
936
937 if (serial) {
938 len = *serial_size;
939 result =
940 asn1_read_value(c2, "authorityCertSerialNumber",
941 serial, &len);
942
943 *serial_size = len;
944
945 if (result < 0) {
946 ret = _gnutls_asn2err(result);
947 goto fail;
948 }
949
950 }
951
952 ret = 0;
953
954 fail:
955 asn1_delete_structure(&c2);
956
957 return ret;
958 }
959
960
961 /**
962 * gnutls_x509_crl_get_authority_key_id:
963 * @crl: should contain a #gnutls_x509_crl_t type
964 * @id: The place where the identifier will be copied
965 * @id_size: Holds the size of the result field.
966 * @critical: will be non-zero if the extension is marked as critical
967 * (may be null)
968 *
969 * This function will return the CRL authority's key identifier. This
970 * is obtained by the X.509 Authority Key identifier extension field
971 * (2.5.29.35). Note that this function
972 * only returns the keyIdentifier field of the extension and
973 * %GNUTLS_E_X509_UNSUPPORTED_EXTENSION, if the extension contains
974 * the name and serial number of the certificate. In that case
975 * gnutls_x509_crl_get_authority_key_gn_serial() may be used.
976 *
977 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
978 * negative error code in case of an error.
979 *
980 * Since: 2.8.0
981 **/
982 int
gnutls_x509_crl_get_authority_key_id(gnutls_x509_crl_t crl,void * id,size_t * id_size,unsigned int * critical)983 gnutls_x509_crl_get_authority_key_id(gnutls_x509_crl_t crl, void *id,
984 size_t * id_size,
985 unsigned int *critical)
986 {
987 int result, len, ret;
988 ASN1_TYPE c2;
989
990 ret = _get_authority_key_id(crl, &c2, critical);
991 if (ret < 0)
992 return gnutls_assert_val(ret);
993
994 len = *id_size;
995 result = asn1_read_value(c2, "keyIdentifier", id, &len);
996
997 *id_size = len;
998 asn1_delete_structure(&c2);
999
1000 if (result == ASN1_VALUE_NOT_FOUND
1001 || result == ASN1_ELEMENT_NOT_FOUND)
1002 return
1003 gnutls_assert_val(GNUTLS_E_X509_UNSUPPORTED_EXTENSION);
1004
1005 if (result != ASN1_SUCCESS) {
1006 gnutls_assert();
1007 return _gnutls_asn2err(result);
1008 }
1009
1010 return 0;
1011 }
1012
1013 /**
1014 * gnutls_x509_crl_get_number:
1015 * @crl: should contain a #gnutls_x509_crl_t type
1016 * @ret: The place where the number will be copied
1017 * @ret_size: Holds the size of the result field.
1018 * @critical: will be non-zero if the extension is marked as critical
1019 * (may be null)
1020 *
1021 * This function will return the CRL number extension. This is
1022 * obtained by the CRL Number extension field (2.5.29.20).
1023 *
1024 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1025 * negative error code in case of an error.
1026 *
1027 * Since: 2.8.0
1028 **/
1029 int
gnutls_x509_crl_get_number(gnutls_x509_crl_t crl,void * ret,size_t * ret_size,unsigned int * critical)1030 gnutls_x509_crl_get_number(gnutls_x509_crl_t crl, void *ret,
1031 size_t * ret_size, unsigned int *critical)
1032 {
1033 int result;
1034 gnutls_datum_t id;
1035
1036 if (crl == NULL) {
1037 gnutls_assert();
1038 return GNUTLS_E_INVALID_REQUEST;
1039 }
1040
1041 if (ret)
1042 memset(ret, 0, *ret_size);
1043 else
1044 *ret_size = 0;
1045
1046 if ((result =
1047 _gnutls_x509_crl_get_extension(crl, "2.5.29.20", 0, &id,
1048 critical)) < 0) {
1049 return result;
1050 }
1051
1052 if (id.size == 0 || id.data == NULL) {
1053 gnutls_assert();
1054 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1055 }
1056
1057 result =
1058 _gnutls_x509_ext_extract_number(ret, ret_size, id.data,
1059 id.size);
1060
1061 _gnutls_free_datum(&id);
1062
1063 if (result < 0) {
1064 gnutls_assert();
1065 return result;
1066 }
1067
1068 return 0;
1069 }
1070
1071 /**
1072 * gnutls_x509_crl_get_extension_oid:
1073 * @crl: should contain a #gnutls_x509_crl_t type
1074 * @indx: Specifies which extension OID to send, use (0) to get the first one.
1075 * @oid: a pointer to store the OID (may be null)
1076 * @sizeof_oid: initially holds the size of @oid
1077 *
1078 * This function will return the requested extension OID in the CRL.
1079 * The extension OID will be stored as a string in the provided
1080 * buffer.
1081 *
1082 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1083 * negative error code in case of an error. If your have reached the
1084 * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1085 * will be returned.
1086 *
1087 * Since: 2.8.0
1088 **/
1089 int
gnutls_x509_crl_get_extension_oid(gnutls_x509_crl_t crl,unsigned indx,void * oid,size_t * sizeof_oid)1090 gnutls_x509_crl_get_extension_oid(gnutls_x509_crl_t crl, unsigned indx,
1091 void *oid, size_t * sizeof_oid)
1092 {
1093 int result;
1094
1095 if (crl == NULL) {
1096 gnutls_assert();
1097 return GNUTLS_E_INVALID_REQUEST;
1098 }
1099
1100 result =
1101 _gnutls_x509_crl_get_extension_oid(crl, indx, oid, sizeof_oid);
1102 if (result < 0) {
1103 return result;
1104 }
1105
1106 return 0;
1107
1108 }
1109
1110 /**
1111 * gnutls_x509_crl_get_extension_info:
1112 * @crl: should contain a #gnutls_x509_crl_t type
1113 * @indx: Specifies which extension OID to send, use (0) to get the first one.
1114 * @oid: a pointer to store the OID
1115 * @sizeof_oid: initially holds the maximum size of @oid, on return
1116 * holds actual size of @oid.
1117 * @critical: output variable with critical flag, may be NULL.
1118 *
1119 * This function will return the requested extension OID in the CRL,
1120 * and the critical flag for it. The extension OID will be stored as
1121 * a string in the provided buffer. Use
1122 * gnutls_x509_crl_get_extension_data() to extract the data.
1123 *
1124 * If the buffer provided is not long enough to hold the output, then
1125 * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be
1126 * returned.
1127 *
1128 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1129 * negative error code in case of an error. If your have reached the
1130 * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1131 * will be returned.
1132 *
1133 * Since: 2.8.0
1134 **/
1135 int
gnutls_x509_crl_get_extension_info(gnutls_x509_crl_t crl,unsigned indx,void * oid,size_t * sizeof_oid,unsigned int * critical)1136 gnutls_x509_crl_get_extension_info(gnutls_x509_crl_t crl, unsigned indx,
1137 void *oid, size_t * sizeof_oid,
1138 unsigned int *critical)
1139 {
1140 int result;
1141 char str_critical[10];
1142 char name[MAX_NAME_SIZE];
1143 int len;
1144
1145 if (!crl) {
1146 gnutls_assert();
1147 return GNUTLS_E_INVALID_REQUEST;
1148 }
1149
1150 snprintf(name, sizeof(name),
1151 "tbsCertList.crlExtensions.?%u.extnID", indx + 1);
1152
1153 len = *sizeof_oid;
1154 result = asn1_read_value(crl->crl, name, oid, &len);
1155 *sizeof_oid = len;
1156
1157 if (result == ASN1_ELEMENT_NOT_FOUND)
1158 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1159 else if (result != ASN1_SUCCESS) {
1160 gnutls_assert();
1161 return _gnutls_asn2err(result);
1162 }
1163
1164 snprintf(name, sizeof(name),
1165 "tbsCertList.crlExtensions.?%u.critical", indx + 1);
1166 len = sizeof(str_critical);
1167 result = asn1_read_value(crl->crl, name, str_critical, &len);
1168 if (result != ASN1_SUCCESS) {
1169 gnutls_assert();
1170 return _gnutls_asn2err(result);
1171 }
1172
1173 if (critical) {
1174 if (str_critical[0] == 'T')
1175 *critical = 1;
1176 else
1177 *critical = 0;
1178 }
1179
1180 return 0;
1181
1182 }
1183
1184 /**
1185 * gnutls_x509_crl_get_extension_data:
1186 * @crl: should contain a #gnutls_x509_crl_t type
1187 * @indx: Specifies which extension OID to send. Use (0) to get the first one.
1188 * @data: a pointer to a structure to hold the data (may be null)
1189 * @sizeof_data: initially holds the size of @oid
1190 *
1191 * This function will return the requested extension data in the CRL.
1192 * The extension data will be stored as a string in the provided
1193 * buffer.
1194 *
1195 * Use gnutls_x509_crl_get_extension_info() to extract the OID and
1196 * critical flag. Use gnutls_x509_crl_get_extension_info() instead,
1197 * if you want to get data indexed by the extension OID rather than
1198 * sequence.
1199 *
1200 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1201 * negative error code in case of an error. If your have reached the
1202 * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1203 * will be returned.
1204 *
1205 * Since: 2.8.0
1206 **/
1207 int
gnutls_x509_crl_get_extension_data(gnutls_x509_crl_t crl,unsigned indx,void * data,size_t * sizeof_data)1208 gnutls_x509_crl_get_extension_data(gnutls_x509_crl_t crl, unsigned indx,
1209 void *data, size_t * sizeof_data)
1210 {
1211 int result, len;
1212 char name[MAX_NAME_SIZE];
1213
1214 if (!crl) {
1215 gnutls_assert();
1216 return GNUTLS_E_INVALID_REQUEST;
1217 }
1218
1219 snprintf(name, sizeof(name),
1220 "tbsCertList.crlExtensions.?%u.extnValue", indx + 1);
1221
1222 len = *sizeof_data;
1223 result = asn1_read_value(crl->crl, name, data, &len);
1224 *sizeof_data = len;
1225
1226 if (result == ASN1_ELEMENT_NOT_FOUND)
1227 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1228 else if (result < 0) {
1229 gnutls_assert();
1230 return _gnutls_asn2err(result);
1231 }
1232
1233 return 0;
1234 }
1235
1236 /**
1237 * gnutls_x509_crl_list_import2:
1238 * @crls: Will contain the parsed crl list.
1239 * @size: It will contain the size of the list.
1240 * @data: The PEM encoded CRL.
1241 * @format: One of DER or PEM.
1242 * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags.
1243 *
1244 * This function will convert the given PEM encoded CRL list
1245 * to the native gnutls_x509_crl_t format. The output will be stored
1246 * in @crls. They will be automatically initialized.
1247 *
1248 * If the Certificate is PEM encoded it should have a header of "X509
1249 * CRL".
1250 *
1251 * Returns: the number of certificates read or a negative error value.
1252 *
1253 * Since: 3.0
1254 **/
1255 int
gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls,unsigned int * size,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format,unsigned int flags)1256 gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls,
1257 unsigned int *size,
1258 const gnutls_datum_t * data,
1259 gnutls_x509_crt_fmt_t format,
1260 unsigned int flags)
1261 {
1262 unsigned int init = 1024;
1263 int ret;
1264
1265 *crls = gnutls_malloc(sizeof(gnutls_x509_crl_t) * init);
1266 if (*crls == NULL) {
1267 gnutls_assert();
1268 return GNUTLS_E_MEMORY_ERROR;
1269 }
1270
1271 ret =
1272 gnutls_x509_crl_list_import(*crls, &init, data, format,
1273 flags | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1274 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
1275 *crls =
1276 gnutls_realloc_fast(*crls,
1277 sizeof(gnutls_x509_crl_t) * init);
1278 if (*crls == NULL) {
1279 gnutls_assert();
1280 return GNUTLS_E_MEMORY_ERROR;
1281 }
1282
1283 ret =
1284 gnutls_x509_crl_list_import(*crls, &init, data, format,
1285 flags);
1286 }
1287
1288 if (ret < 0) {
1289 gnutls_free(*crls);
1290 *crls = NULL;
1291 return ret;
1292 }
1293
1294 *size = init;
1295 return 0;
1296 }
1297
1298 /**
1299 * gnutls_x509_crl_list_import:
1300 * @crls: Indicates where the parsed CRLs will be copied to. Must not be initialized.
1301 * @crl_max: Initially must hold the maximum number of crls. It will be updated with the number of crls available.
1302 * @data: The PEM encoded CRLs
1303 * @format: One of DER or PEM.
1304 * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags.
1305 *
1306 * This function will convert the given PEM encoded CRL list
1307 * to the native gnutls_x509_crl_t format. The output will be stored
1308 * in @crls. They will be automatically initialized.
1309 *
1310 * If the Certificate is PEM encoded it should have a header of "X509 CRL".
1311 *
1312 * Returns: the number of certificates read or a negative error value.
1313 *
1314 * Since: 3.0
1315 **/
1316 int
gnutls_x509_crl_list_import(gnutls_x509_crl_t * crls,unsigned int * crl_max,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format,unsigned int flags)1317 gnutls_x509_crl_list_import(gnutls_x509_crl_t * crls,
1318 unsigned int *crl_max,
1319 const gnutls_datum_t * data,
1320 gnutls_x509_crt_fmt_t format,
1321 unsigned int flags)
1322 {
1323 int size;
1324 const char *ptr;
1325 gnutls_datum_t tmp;
1326 int ret, nocopy = 0;
1327 unsigned int count = 0, j;
1328
1329 if (format == GNUTLS_X509_FMT_DER) {
1330 if (*crl_max < 1) {
1331 *crl_max = 1;
1332 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1333 }
1334
1335 count = 1; /* import only the first one */
1336
1337 ret = gnutls_x509_crl_init(&crls[0]);
1338 if (ret < 0) {
1339 gnutls_assert();
1340 goto error;
1341 }
1342
1343 ret = gnutls_x509_crl_import(crls[0], data, format);
1344 if (ret < 0) {
1345 gnutls_assert();
1346 goto error;
1347 }
1348
1349 *crl_max = 1;
1350 return 1;
1351 }
1352
1353 /* move to the certificate
1354 */
1355 ptr = memmem(data->data, data->size,
1356 PEM_CRL_SEP, sizeof(PEM_CRL_SEP) - 1);
1357 if (ptr == NULL) {
1358 gnutls_assert();
1359 return GNUTLS_E_BASE64_DECODING_ERROR;
1360 }
1361
1362 count = 0;
1363
1364 do {
1365 if (count >= *crl_max) {
1366 if (!
1367 (flags &
1368 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) {
1369 break;
1370 } else if (nocopy == 0) {
1371 for (j = 0; j < count; j++)
1372 gnutls_x509_crl_deinit(crls[j]);
1373 nocopy = 1;
1374 }
1375 }
1376
1377 if (!nocopy) {
1378 ret = gnutls_x509_crl_init(&crls[count]);
1379 if (ret < 0) {
1380 gnutls_assert();
1381 goto error;
1382 }
1383
1384 tmp.data = (void *) ptr;
1385 tmp.size =
1386 data->size - (ptr - (char *) data->data);
1387 ret =
1388 gnutls_x509_crl_import(crls[count], &tmp,
1389 GNUTLS_X509_FMT_PEM);
1390 if (ret < 0) {
1391 gnutls_assert();
1392 count++;
1393 goto error;
1394 }
1395 }
1396
1397 /* now we move ptr after the pem header
1398 */
1399 ptr++;
1400 /* find the next certificate (if any)
1401 */
1402 size = data->size - (ptr - (char *) data->data);
1403
1404 if (size > 0) {
1405 ptr =
1406 memmem(ptr, size, PEM_CRL_SEP,
1407 sizeof(PEM_CRL_SEP) - 1);
1408 } else
1409 ptr = NULL;
1410
1411 count++;
1412 }
1413 while (ptr != NULL);
1414
1415 *crl_max = count;
1416
1417 if (nocopy == 0)
1418 return count;
1419 else
1420 return GNUTLS_E_SHORT_MEMORY_BUFFER;
1421
1422 error:
1423 for (j = 0; j < count; j++)
1424 gnutls_x509_crl_deinit(crls[j]);
1425 return ret;
1426 }
1427