Line data Source code
1 : /* cert.c - main function for the certificate handling
2 : * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2012 g10 Code GmbH
3 : *
4 : * This file is part of KSBA.
5 : *
6 : * KSBA is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 : * License for more details.
25 : *
26 : * You should have received a copies of the GNU General Public License
27 : * and the GNU Lesser General Public License along with this program;
28 : * if not, see <http://www.gnu.org/licenses/>.
29 : */
30 :
31 : #include <config.h>
32 : #include <stdio.h>
33 : #include <stdlib.h>
34 : #include <string.h>
35 : #include <assert.h>
36 : #include <errno.h>
37 :
38 : #include "util.h"
39 : #include "ber-decoder.h"
40 : #include "ber-help.h"
41 : #include "convert.h"
42 : #include "keyinfo.h"
43 : #include "sexp-parse.h"
44 : #include "cert.h"
45 :
46 :
47 : static const char oidstr_subjectKeyIdentifier[] = "2.5.29.14";
48 : static const char oidstr_keyUsage[] = "2.5.29.15";
49 : static const char oidstr_subjectAltName[] = "2.5.29.17";
50 : static const char oidstr_issuerAltName[] = "2.5.29.18";
51 : static const char oidstr_basicConstraints[] = "2.5.29.19";
52 : static const char oidstr_crlDistributionPoints[] = "2.5.29.31";
53 : static const char oidstr_certificatePolicies[] = "2.5.29.32";
54 : static const char oidstr_authorityKeyIdentifier[] = "2.5.29.35";
55 : static const char oidstr_extKeyUsage[] = "2.5.29.37";
56 : static const char oidstr_authorityInfoAccess[] = "1.3.6.1.5.5.7.1.1";
57 : static const char oidstr_subjectInfoAccess[] = "1.3.6.1.5.5.7.1.11";
58 :
59 :
60 : /**
61 : * ksba_cert_new:
62 : *
63 : * Create a new and empty certificate object
64 : *
65 : * Return value: 0 on success or error code. For a successful
66 : * operation, ACERT is set to the new certifixate obbject, otherwise
67 : * it is set to NULL.
68 : **/
69 : gpg_error_t
70 6 : ksba_cert_new (ksba_cert_t *acert)
71 : {
72 6 : *acert = xtrycalloc (1, sizeof **acert);
73 6 : if (!*acert)
74 0 : return gpg_error_from_errno (errno);
75 6 : (*acert)->ref_count++;
76 :
77 6 : return 0;
78 : }
79 :
80 : void
81 0 : ksba_cert_ref (ksba_cert_t cert)
82 : {
83 0 : if (!cert)
84 0 : fprintf (stderr, "BUG: ksba_cert_ref for NULL\n");
85 : else
86 0 : ++cert->ref_count;
87 0 : }
88 :
89 : /**
90 : * ksba_cert_release:
91 : * @cert: A certificate object
92 : *
93 : * Release a certificate object.
94 : **/
95 : void
96 6 : ksba_cert_release (ksba_cert_t cert)
97 : {
98 : int i;
99 :
100 6 : if (!cert)
101 0 : return;
102 6 : if (cert->ref_count < 1)
103 : {
104 0 : fprintf (stderr, "BUG: trying to release an already released cert\n");
105 0 : return;
106 : }
107 6 : if (--cert->ref_count)
108 0 : return;
109 :
110 6 : if (cert->udata)
111 : {
112 0 : struct cert_user_data *ud = cert->udata;
113 0 : cert->udata = NULL;
114 : do
115 : {
116 0 : struct cert_user_data *ud2 = ud->next;
117 0 : if (ud->data && ud->data != ud->databuf)
118 0 : xfree (ud->data);
119 0 : xfree (ud);
120 0 : ud = ud2;
121 : }
122 0 : while (ud);
123 : }
124 :
125 6 : xfree (cert->cache.digest_algo);
126 6 : if (cert->cache.extns_valid)
127 : {
128 23 : for (i=0; i < cert->cache.n_extns; i++)
129 20 : xfree (cert->cache.extns[i].oid);
130 3 : xfree (cert->cache.extns);
131 : }
132 :
133 6 : _ksba_asn_release_nodes (cert->root);
134 6 : ksba_asn_tree_release (cert->asn_tree);
135 :
136 6 : xfree (cert->image);
137 :
138 6 : xfree (cert);
139 : }
140 :
141 :
142 : /* Store arbitrary data along with a certificate. The DATA of length
143 : DATALEN will be stored under the string KEY. If some data is
144 : already stored under this key it will be replaced by the new data.
145 : Using NULL for DATA will effectivly delete the data.
146 :
147 : On error (i.e. out or memory) an already existing data object
148 : stored under KEY may get deleted.
149 :
150 : This function is not thread safe because we don't employ any
151 : locking. */
152 : gpg_error_t
153 0 : ksba_cert_set_user_data (ksba_cert_t cert,
154 : const char *key, const void *data, size_t datalen)
155 : {
156 : struct cert_user_data *ud;
157 :
158 0 : if (!cert || !key || !*key)
159 0 : return gpg_error (GPG_ERR_INV_VALUE);
160 :
161 0 : for (ud=cert->udata; ud; ud = ud->next)
162 0 : if (!strcmp (ud->key, key))
163 0 : break;
164 0 : if (ud) /* Update the data stored under this key or reuse this item. */
165 : {
166 0 : if (ud->data && ud->data != ud->databuf)
167 0 : xfree (ud->data);
168 0 : ud->data = NULL;
169 0 : if (data && datalen <= sizeof ud->databuf)
170 : {
171 0 : memcpy (ud->databuf, data, datalen);
172 0 : ud->data = ud->databuf;
173 0 : ud->datalen = datalen;
174 : }
175 0 : else if (data)
176 : {
177 0 : ud->data = xtrymalloc (datalen);
178 0 : if (!ud->data)
179 0 : return gpg_error_from_errno (errno);
180 0 : memcpy (ud->data, data, datalen);
181 0 : ud->datalen = datalen;
182 : }
183 : }
184 0 : else if (data) /* Insert as a new item. */
185 : {
186 0 : ud = xtrycalloc (1, sizeof *ud + strlen (key));
187 0 : if (!ud)
188 0 : return gpg_error_from_errno (errno);
189 0 : strcpy (ud->key, key);
190 0 : if (datalen <= sizeof ud->databuf)
191 : {
192 0 : memcpy (ud->databuf, data, datalen);
193 0 : ud->data = ud->databuf;
194 0 : ud->datalen = datalen;
195 : }
196 : else
197 : {
198 0 : ud->data = xtrymalloc (datalen);
199 0 : if (!ud->data)
200 : {
201 0 : xfree (ud);
202 0 : return gpg_error_from_errno (errno);
203 : }
204 0 : memcpy (ud->data, data, datalen);
205 0 : ud->datalen = datalen;
206 : }
207 0 : ud->next = cert->udata;
208 0 : cert->udata = ud;
209 : }
210 :
211 0 : return 0;
212 : }
213 :
214 :
215 :
216 : /* Return user data for certificate CERT stored under the string
217 : KEY. The caller needs to provide a suitable large BUFFER and pass
218 : the usable length of the buffer in BUFFERLEN. If DATALEN is not
219 : NULL, the length of the data stored at BUFFER will be stored there.
220 :
221 : If BUFFER is NULL, BUFFERLEN will be ignored and the required
222 : length of the buffer will be returned at DATALEN.
223 :
224 : On success 0 is returned. If no data is stored under KEY
225 : GPG_ERR_NOT_FOUND is returned. If the provided buffer is too
226 : short, GPG_ERR_BUFFER_TOO_SHORT will be returned (note, that this
227 : is not the case if BUFFER is NULL).
228 : */
229 : gpg_error_t
230 0 : ksba_cert_get_user_data (ksba_cert_t cert, const char *key,
231 : void *buffer, size_t bufferlen, size_t *datalen)
232 : {
233 : struct cert_user_data *ud;
234 :
235 0 : if (!cert || !key || !*key)
236 0 : return gpg_error (GPG_ERR_INV_VALUE);
237 :
238 0 : for (ud=cert->udata; ud; ud = ud->next)
239 0 : if (!strcmp (ud->key, key))
240 0 : break;
241 0 : if (!ud || !ud->data)
242 0 : return gpg_error (GPG_ERR_NOT_FOUND);
243 0 : if (datalen)
244 0 : *datalen = ud->datalen;
245 0 : if (buffer)
246 : {
247 0 : if (ud->datalen > bufferlen)
248 0 : return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
249 0 : memcpy (buffer, ud->data, ud->datalen);
250 : }
251 0 : return 0;
252 : }
253 :
254 :
255 : /**
256 : * ksba_cert_read_der:
257 : * @cert: An unitialized certificate object
258 : * @reader: A KSBA Reader object
259 : *
260 : * Read the next certificate from the reader and store it in the
261 : * certificate object for future access. The certificate is parsed
262 : * and rejected if it has any syntactical or semantical error
263 : * (i.e. does not match the ASN.1 description).
264 : *
265 : * Return value: 0 on success or an error value
266 : **/
267 : gpg_error_t
268 6 : ksba_cert_read_der (ksba_cert_t cert, ksba_reader_t reader)
269 : {
270 6 : gpg_error_t err = 0;
271 6 : BerDecoder decoder = NULL;
272 :
273 6 : if (!cert || !reader)
274 0 : return gpg_error (GPG_ERR_INV_VALUE);
275 6 : if (cert->initialized)
276 0 : return gpg_error (GPG_ERR_CONFLICT); /* Fixme: should remove the old one */
277 :
278 6 : _ksba_asn_release_nodes (cert->root);
279 6 : ksba_asn_tree_release (cert->asn_tree);
280 6 : cert->root = NULL;
281 6 : cert->asn_tree = NULL;
282 :
283 6 : err = ksba_asn_create_tree ("tmttv2", &cert->asn_tree);
284 6 : if (err)
285 0 : goto leave;
286 :
287 6 : decoder = _ksba_ber_decoder_new ();
288 6 : if (!decoder)
289 : {
290 0 : err = gpg_error (GPG_ERR_ENOMEM);
291 0 : goto leave;
292 : }
293 :
294 6 : err = _ksba_ber_decoder_set_reader (decoder, reader);
295 6 : if (err)
296 0 : goto leave;
297 :
298 6 : err = _ksba_ber_decoder_set_module (decoder, cert->asn_tree);
299 6 : if (err)
300 0 : goto leave;
301 :
302 6 : err = _ksba_ber_decoder_decode (decoder, "TMTTv2.Certificate", 0,
303 : &cert->root, &cert->image, &cert->imagelen);
304 6 : if (!err)
305 3 : cert->initialized = 1;
306 :
307 : leave:
308 6 : _ksba_ber_decoder_release (decoder);
309 :
310 6 : return err;
311 : }
312 :
313 :
314 : gpg_error_t
315 0 : ksba_cert_init_from_mem (ksba_cert_t cert, const void *buffer, size_t length)
316 : {
317 : gpg_error_t err;
318 : ksba_reader_t reader;
319 :
320 0 : err = ksba_reader_new (&reader);
321 0 : if (err)
322 0 : return err;
323 0 : err = ksba_reader_set_mem (reader, buffer, length);
324 0 : if (err)
325 : {
326 0 : ksba_reader_release (reader);
327 0 : return err;
328 : }
329 0 : err = ksba_cert_read_der (cert, reader);
330 0 : ksba_reader_release (reader);
331 0 : return err;
332 : }
333 :
334 :
335 :
336 : const unsigned char *
337 0 : ksba_cert_get_image (ksba_cert_t cert, size_t *r_length )
338 : {
339 : AsnNode n;
340 :
341 0 : if (!cert)
342 0 : return NULL;
343 0 : if (!cert->initialized)
344 0 : return NULL;
345 :
346 0 : n = _ksba_asn_find_node (cert->root, "Certificate");
347 0 : if (!n)
348 0 : return NULL;
349 :
350 0 : if (n->off == -1)
351 : {
352 : /* fputs ("ksba_cert_get_image problem at node:\n", stderr); */
353 : /* _ksba_asn_node_dump_all (n, stderr); */
354 0 : return NULL;
355 : }
356 :
357 : /* Due to minor problems in our parser we might hit the assertion
358 : below. Thus we better return a error, proper. */
359 0 : if ( !(n->nhdr + n->len + n->off <= cert->imagelen) )
360 : {
361 0 : fprintf (stderr,"\nOops, ksba_cert_get_image failed: "
362 : "imagelen=%lu hdr=%d len=%d off=%d\n",
363 : (unsigned long)cert->imagelen, n->nhdr, (int)n->len, n->off);
364 0 : return NULL;
365 : }
366 : /*assert (n->nhdr + n->len + n->off <= cert->imagelen);*/
367 :
368 0 : if (r_length)
369 0 : *r_length = n->nhdr + n->len;
370 0 : return cert->image + n->off;
371 : }
372 :
373 : /* Check whether certificates A and B are identical and return o in
374 : this case. */
375 : int
376 0 : _ksba_cert_cmp (ksba_cert_t a, ksba_cert_t b)
377 : {
378 : const unsigned char *img_a, *img_b;
379 : size_t len_a, len_b;
380 :
381 0 : img_a = ksba_cert_get_image (a, &len_a);
382 0 : if (!img_a)
383 0 : return 1;
384 0 : img_b = ksba_cert_get_image (b, &len_b);
385 0 : if (!img_b)
386 0 : return 1;
387 0 : return !(len_a == len_b && !memcmp (img_a, img_b, len_a));
388 : }
389 :
390 :
391 :
392 :
393 : gpg_error_t
394 0 : ksba_cert_hash (ksba_cert_t cert, int what,
395 : void (*hasher)(void *, const void *, size_t length),
396 : void *hasher_arg)
397 : {
398 : AsnNode n;
399 :
400 0 : if (!cert /*|| !hasher*/)
401 0 : return gpg_error (GPG_ERR_INV_VALUE);
402 0 : if (!cert->initialized)
403 0 : return gpg_error (GPG_ERR_NO_DATA);
404 :
405 0 : n = _ksba_asn_find_node (cert->root,
406 : what == 1? "Certificate.tbsCertificate"
407 : : "Certificate");
408 0 : if (!n)
409 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
410 0 : if (n->off == -1)
411 : {
412 : /* fputs ("ksba_cert_hash problem at node:\n", stderr); */
413 : /* _ksba_asn_node_dump_all (n, stderr); */
414 0 : return gpg_error (GPG_ERR_NO_VALUE);
415 : }
416 :
417 0 : hasher (hasher_arg, cert->image + n->off, n->nhdr + n->len);
418 :
419 :
420 0 : return 0;
421 : }
422 :
423 :
424 :
425 : /**
426 : * ksba_cert_get_digest_algo:
427 : * @cert: Initialized certificate object
428 : *
429 : * Figure out the the digest algorithm used for the signature and
430 : * return its OID
431 : *
432 : * This function is intended as a helper for the ksba_cert_hash().
433 : *
434 : * Return value: NULL for error otherwise a constant string with the OID.
435 : * This string is valid as long the certificate object is valid.
436 : **/
437 : const char *
438 3 : ksba_cert_get_digest_algo (ksba_cert_t cert)
439 : {
440 : gpg_error_t err;
441 : AsnNode n;
442 : char *algo;
443 : size_t nread;
444 :
445 3 : if (!cert)
446 0 : return NULL; /* Ooops (can't set cert->last_error :-(). */
447 :
448 3 : if (!cert->initialized)
449 : {
450 0 : cert->last_error = gpg_error (GPG_ERR_NO_DATA);
451 0 : return NULL;
452 : }
453 :
454 3 : if (cert->cache.digest_algo)
455 0 : return cert->cache.digest_algo;
456 :
457 : /* n = _ksba_asn_find_node (cert->root, */
458 : /* "Certificate.signatureAlgorithm.algorithm"); */
459 : /* algo = _ksba_oid_node_to_str (cert->image, n); */
460 : /* if (!algo) */
461 : /* cert->last_error = gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); */
462 : /* else */
463 : /* cert->cache.digest_algo = algo; */
464 :
465 3 : n = _ksba_asn_find_node (cert->root, "Certificate.signatureAlgorithm");
466 3 : if (!n || n->off == -1)
467 0 : err = gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
468 : else
469 3 : err = _ksba_parse_algorithm_identifier (cert->image + n->off,
470 3 : n->nhdr + n->len, &nread, &algo);
471 3 : if (err)
472 0 : cert->last_error = err;
473 : else
474 3 : cert->cache.digest_algo = algo;
475 :
476 3 : return algo;
477 : }
478 :
479 :
480 :
481 :
482 : /**
483 : * ksba_cert_get_serial:
484 : * @cert: certificate object
485 : *
486 : * This function returnes the serial number of the certificate. The
487 : * serial number is an integer returned as an canonical encoded
488 : * S-expression with just one element.
489 : *
490 : * Return value: An allocated S-Exp or NULL for no value.
491 : **/
492 : ksba_sexp_t
493 3 : ksba_cert_get_serial (ksba_cert_t cert)
494 : {
495 : AsnNode n;
496 : char *p;
497 : char numbuf[22];
498 : int numbuflen;
499 :
500 3 : if (!cert || !cert->initialized)
501 0 : return NULL;
502 :
503 3 : n = _ksba_asn_find_node (cert->root,
504 : "Certificate.tbsCertificate.serialNumber");
505 3 : if (!n)
506 0 : return NULL; /* oops - should be there */
507 :
508 3 : if (n->off == -1)
509 : {
510 : /* fputs ("get_serial problem at node:\n", stderr); */
511 : /* _ksba_asn_node_dump_all (n, stderr); */
512 0 : return NULL;
513 : }
514 :
515 3 : sprintf (numbuf,"(%u:", (unsigned int)n->len);
516 3 : numbuflen = strlen (numbuf);
517 3 : p = xtrymalloc (numbuflen + n->len + 2);
518 3 : if (!p)
519 0 : return NULL;
520 3 : strcpy (p, numbuf);
521 3 : memcpy (p+numbuflen, cert->image + n->off + n->nhdr, n->len);
522 3 : p[numbuflen + n->len] = ')';
523 3 : p[numbuflen + n->len + 1] = 0;
524 3 : return p;
525 : }
526 :
527 :
528 : /* Return a pointer to the DER encoding of the serial number in CERT in
529 : PTR and the length of that field in LENGTH. */
530 : gpg_error_t
531 0 : _ksba_cert_get_serial_ptr (ksba_cert_t cert,
532 : unsigned char const **ptr, size_t *length)
533 : {
534 : asn_node_t n;
535 :
536 0 : if (!cert || !cert->initialized || !ptr || !length)
537 0 : return gpg_error (GPG_ERR_INV_VALUE);
538 0 : n = _ksba_asn_find_node (cert->root,
539 : "Certificate.tbsCertificate.serialNumber");
540 0 : if (!n || n->off == -1)
541 0 : return gpg_error (GPG_ERR_NO_VALUE);
542 :
543 0 : *ptr = cert->image + n->off + n->nhdr;
544 0 : *length = n->len;
545 0 : return 0;
546 : }
547 :
548 :
549 :
550 : /* Return a pointer to the DER encoding of the subject's DN in CERT in
551 : PTR and the length of that object in LENGTH. */
552 : gpg_error_t
553 0 : _ksba_cert_get_subject_dn_ptr (ksba_cert_t cert,
554 : unsigned char const **ptr, size_t *length)
555 : {
556 : asn_node_t n;
557 :
558 0 : if (!cert || !cert->initialized || !ptr || !length)
559 0 : return gpg_error (GPG_ERR_INV_VALUE);
560 :
561 0 : n = _ksba_asn_find_node (cert->root, "Certificate.tbsCertificate.subject");
562 0 : if (!n || !n->down)
563 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
564 0 : n = n->down; /* dereference the choice node */
565 0 : if (n->off == -1)
566 0 : return gpg_error (GPG_ERR_NO_VALUE);
567 0 : *ptr = cert->image + n->off;
568 0 : *length = n->nhdr + n->len;
569 0 : return 0;
570 : }
571 :
572 :
573 :
574 : /* Worker function for get_isssuer and get_subject. */
575 : static gpg_error_t
576 12 : get_name (ksba_cert_t cert, int idx, int use_subject, char **result)
577 : {
578 : gpg_error_t err;
579 : char *p;
580 : int i;
581 : const char *oid;
582 : struct tag_info ti;
583 : const unsigned char *der;
584 : size_t off, derlen, seqlen;
585 :
586 12 : if (!cert || !cert->initialized || !result)
587 0 : return gpg_error (GPG_ERR_INV_VALUE);
588 12 : if (idx < 0)
589 0 : return gpg_error (GPG_ERR_INV_INDEX);
590 :
591 12 : *result = NULL;
592 12 : if (!idx)
593 : { /* Get the required DN */
594 : AsnNode n;
595 :
596 6 : n = _ksba_asn_find_node (cert->root,
597 : (use_subject?
598 : "Certificate.tbsCertificate.subject":
599 : "Certificate.tbsCertificate.issuer") );
600 6 : if (!n || !n->down)
601 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
602 6 : n = n->down; /* dereference the choice node */
603 6 : if (n->off == -1)
604 0 : return gpg_error (GPG_ERR_NO_VALUE);
605 :
606 6 : err = _ksba_dn_to_str (cert->image, n, &p);
607 6 : if (err)
608 0 : return err;
609 6 : *result = p;
610 6 : return 0;
611 : }
612 :
613 : /* get {issuer,subject}AltName */
614 52 : for (i=0; !(err=ksba_cert_get_extension (cert, i, &oid, NULL,
615 40 : &off, &derlen)); i++)
616 : {
617 40 : if (!strcmp (oid, (use_subject?
618 : oidstr_subjectAltName:oidstr_issuerAltName)))
619 0 : break;
620 : }
621 6 : if (err)
622 6 : return err; /* no alt name or error*/
623 :
624 0 : der = cert->image + off;
625 :
626 :
627 : /* FIXME: We should use _ksba_name_new_from_der and ksba_name_enum here */
628 :
629 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
630 0 : if (err)
631 0 : return err;
632 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
633 0 : && ti.is_constructed) )
634 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
635 0 : if (ti.ndef)
636 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
637 0 : seqlen = ti.length;
638 0 : if (seqlen > derlen)
639 0 : return gpg_error (GPG_ERR_BAD_BER);
640 0 : if (!seqlen)
641 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* empty sequence is not allowed */
642 :
643 0 : while (seqlen)
644 : {
645 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
646 0 : if (err)
647 0 : return err;
648 0 : if (ti.class != CLASS_CONTEXT)
649 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
650 0 : if (ti.ndef)
651 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
652 0 : if (seqlen < ti.nhdr)
653 0 : return gpg_error (GPG_ERR_BAD_BER);
654 0 : seqlen -= ti.nhdr;
655 0 : if (seqlen < ti.length)
656 0 : return gpg_error (GPG_ERR_BAD_BER);
657 0 : seqlen -= ti.length;
658 0 : if (derlen < ti.length)
659 0 : return gpg_error (GPG_ERR_BAD_BER);
660 0 : if (!(ti.tag == 1 || ti.tag == 2 || ti.tag == 6))
661 : ; /* Not a supported tag: Do not change IDX. */
662 0 : else if (--idx)
663 : ; /* not yet at the desired index */
664 0 : else if (ti.tag == 1)
665 : { /* rfc822Name - this is an implicit IA5_STRING */
666 0 : p = xtrymalloc (ti.length+3);
667 0 : if (!p)
668 0 : return gpg_error (GPG_ERR_ENOMEM);
669 0 : *p = '<';
670 0 : memcpy (p+1, der, ti.length);
671 0 : p[ti.length+1] = '>';
672 0 : p[ti.length+2] = 0;
673 0 : *result = p;
674 0 : return 0;
675 : }
676 0 : else if (ti.tag == 2 || ti.tag == 6)
677 : { /* dNSName or URI - this are implicit IA5_STRINGs */
678 : char numbuf[20], *numbufp;
679 : size_t numbuflen;
680 :
681 0 : numbufp = smklen (numbuf, DIM(numbuf), ti.length, &numbuflen);
682 0 : p = xtrymalloc (11 + numbuflen + ti.length + 3);
683 0 : if (!p)
684 0 : return gpg_error (GPG_ERR_ENOMEM);
685 0 : *result = p;
686 0 : p = stpcpy (p, ti.tag == 2? "(8:dns-name" : "(3:uri");
687 0 : p = stpcpy (p, numbufp);
688 0 : memcpy (p, der, ti.length);
689 0 : p += ti.length;
690 0 : *p++ = ')';
691 0 : *p = 0;
692 0 : return 0;
693 : }
694 :
695 : /* advance pointer */
696 0 : der += ti.length;
697 0 : derlen -= ti.length;
698 : }
699 :
700 0 : return gpg_error (GPG_ERR_EOF);
701 : }
702 :
703 :
704 :
705 : /**
706 : * ksba_cert_get_issuer:
707 : * @cert: certificate object
708 : *
709 : * With @idx == 0 this function returns the Distinguished Name (DN) of
710 : * the certificate issuer which in most cases is a CA. The format of
711 : * the returned string is in accordance with RFC-2253. NULL is
712 : * returned if the DN is not available which is an error and should
713 : * have been catched by the certificate reading function.
714 : *
715 : * With @idx > 0 the function may be used to enumerate alternate
716 : * issuer names. The function returns NULL if there are no more
717 : * alternate names. The function does only return alternate names
718 : * which are recognized by libksba and ignores others. The format of
719 : * the returned name is either a RFC-2253 formated one which can be
720 : * detected by checking whether the first character is letter or
721 : * digit. rfc-2822 conform email addresses are returned enclosed in
722 : * angle brackets, the opening angle bracket should be used to
723 : * indicate this. Other formats are returned as an S-Expression in
724 : * canonical format, so a opening parenthesis may be used to detect
725 : * this encoding, the name may include binary null characters, so
726 : * strlen may return a length shorther than actually used, the real
727 : * length is implictly given by the structure of the S-Exp, an extra
728 : * null is appended for safety reasons.
729 : *
730 : * The caller must free the returned string using ksba_free() or the
731 : * function he has registered as a replacement.
732 : *
733 : * Return value: An allocated string or NULL for error.
734 : **/
735 : char *
736 6 : ksba_cert_get_issuer (ksba_cert_t cert, int idx)
737 : {
738 : gpg_error_t err;
739 : char *name;
740 :
741 6 : err = get_name (cert, idx, 0, &name);
742 6 : if (err)
743 : {
744 3 : cert->last_error = err;
745 3 : return NULL;
746 : }
747 3 : return name;
748 : }
749 :
750 : /* See ..get_issuer */
751 : char *
752 6 : ksba_cert_get_subject (ksba_cert_t cert, int idx)
753 : {
754 : gpg_error_t err;
755 : char *name;
756 :
757 6 : err = get_name (cert, idx, 1, &name);
758 6 : if (err)
759 : {
760 3 : cert->last_error = err;
761 3 : return NULL;
762 : }
763 3 : return name;
764 : }
765 :
766 :
767 :
768 : /**
769 : * ksba_cert_get_valididy:
770 : * @cert: certificate object
771 : * @what: 0 for notBefore, 1 for notAfter
772 : * @timebuf: Returns the time.
773 : *
774 : * Return the validity object from the certificate. If no value is
775 : * available 0 is returned because we can safely assume that this is
776 : * not a valid date.
777 : *
778 : * Return value: The time value an 0 or an error code.
779 : **/
780 : gpg_error_t
781 6 : ksba_cert_get_validity (ksba_cert_t cert, int what, ksba_isotime_t timebuf)
782 : {
783 : AsnNode n, n2;
784 :
785 6 : if (!cert || what < 0 || what > 1)
786 0 : return gpg_error (GPG_ERR_INV_VALUE);
787 6 : *timebuf = 0;
788 6 : if (!cert->initialized)
789 0 : return gpg_error (GPG_ERR_NO_DATA);
790 :
791 6 : n = _ksba_asn_find_node (cert->root,
792 : what == 0? "Certificate.tbsCertificate.validity.notBefore"
793 : : "Certificate.tbsCertificate.validity.notAfter");
794 6 : if (!n)
795 0 : return 0; /* no value available */
796 :
797 : /* Fixme: We should remove the choice node and don't use this ugly hack */
798 6 : for (n2=n->down; n2; n2 = n2->right)
799 : {
800 6 : if ((n2->type == TYPE_UTC_TIME || n2->type == TYPE_GENERALIZED_TIME)
801 6 : && n2->off != -1)
802 6 : break;
803 : }
804 6 : n = n2;
805 6 : if (!n)
806 0 : return 0; /* no value available */
807 :
808 6 : return_val_if_fail (n->off != -1, gpg_error (GPG_ERR_BUG));
809 :
810 6 : return _ksba_asntime_to_iso (cert->image + n->off + n->nhdr, n->len,
811 6 : n->type == TYPE_UTC_TIME, timebuf);
812 : }
813 :
814 :
815 :
816 : ksba_sexp_t
817 3 : ksba_cert_get_public_key (ksba_cert_t cert)
818 : {
819 : AsnNode n;
820 : gpg_error_t err;
821 : ksba_sexp_t string;
822 :
823 3 : if (!cert)
824 0 : return NULL;
825 3 : if (!cert->initialized)
826 0 : return NULL;
827 :
828 3 : n = _ksba_asn_find_node (cert->root,
829 : "Certificate"
830 : ".tbsCertificate.subjectPublicKeyInfo");
831 3 : if (!n)
832 : {
833 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
834 0 : return NULL;
835 : }
836 :
837 3 : err = _ksba_keyinfo_to_sexp (cert->image + n->off, n->nhdr + n->len,
838 : &string);
839 3 : if (err)
840 : {
841 0 : cert->last_error = err;
842 0 : return NULL;
843 : }
844 :
845 3 : return string;
846 : }
847 :
848 : /* Return a pointer to the DER encoding of the actual public key
849 : (i.e. the bit string) in PTR and the length of that object in
850 : LENGTH. */
851 : gpg_error_t
852 0 : _ksba_cert_get_public_key_ptr (ksba_cert_t cert,
853 : unsigned char const **ptr, size_t *length)
854 : {
855 : asn_node_t n;
856 :
857 0 : if (!cert || !cert->initialized || !ptr || !length)
858 0 : return gpg_error (GPG_ERR_INV_VALUE);
859 :
860 0 : n = _ksba_asn_find_node (cert->root,
861 : "Certificate.tbsCertificate.subjectPublicKeyInfo");
862 0 : if (!n || !n->down || !n->down->right)
863 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
864 0 : n = n->down->right;
865 0 : if (n->off == -1)
866 0 : return gpg_error (GPG_ERR_NO_VALUE);
867 0 : *ptr = cert->image + n->off + n->nhdr;
868 0 : *length = n->len;
869 : /* Somehow we end up at the preceding NULL value, and not at a
870 : sequence, we hack it way here. */
871 0 : if (*length && !**ptr)
872 : {
873 0 : (*length)--;
874 0 : (*ptr)++;
875 : }
876 :
877 0 : return 0;
878 : }
879 :
880 :
881 :
882 : ksba_sexp_t
883 0 : ksba_cert_get_sig_val (ksba_cert_t cert)
884 : {
885 : AsnNode n, n2;
886 : gpg_error_t err;
887 : ksba_sexp_t string;
888 :
889 0 : if (!cert)
890 0 : return NULL;
891 0 : if (!cert->initialized)
892 0 : return NULL;
893 :
894 0 : n = _ksba_asn_find_node (cert->root,
895 : "Certificate.signatureAlgorithm");
896 0 : if (!n)
897 : {
898 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
899 0 : return NULL;
900 : }
901 0 : if (n->off == -1)
902 : {
903 : /* fputs ("ksba_cert_get_sig_val problem at node:\n", stderr); */
904 : /* _ksba_asn_node_dump_all (n, stderr); */
905 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
906 0 : return NULL;
907 : }
908 :
909 0 : n2 = n->right;
910 0 : err = _ksba_sigval_to_sexp (cert->image + n->off,
911 0 : n->nhdr + n->len
912 0 : + ((!n2||n2->off == -1)? 0:(n2->nhdr+n2->len)),
913 : &string);
914 0 : if (err)
915 : {
916 0 : cert->last_error = err;
917 0 : return NULL;
918 : }
919 :
920 0 : return string;
921 : }
922 :
923 :
924 : /* Read all extensions into the cache */
925 : static gpg_error_t
926 3 : read_extensions (ksba_cert_t cert)
927 : {
928 : AsnNode start, n;
929 : int count;
930 :
931 3 : assert (!cert->cache.extns_valid);
932 3 : assert (!cert->cache.extns);
933 :
934 3 : start = _ksba_asn_find_node (cert->root,
935 : "Certificate.tbsCertificate.extensions..");
936 23 : for (count=0, n=start; n; n = n->right)
937 20 : count++;
938 3 : if (!count)
939 : {
940 0 : cert->cache.n_extns = 0;
941 0 : cert->cache.extns_valid = 1;
942 0 : return 0; /* no extensions at all */
943 : }
944 3 : cert->cache.extns = xtrycalloc (count, sizeof *cert->cache.extns);
945 3 : if (!cert->cache.extns)
946 0 : return gpg_error (GPG_ERR_ENOMEM);
947 3 : cert->cache.n_extns = count;
948 :
949 : {
950 23 : for (count=0; start; start = start->right, count++)
951 : {
952 20 : n = start->down;
953 20 : if (!n || n->type != TYPE_OBJECT_ID)
954 : goto no_value;
955 :
956 20 : cert->cache.extns[count].oid = _ksba_oid_node_to_str (cert->image, n);
957 20 : if (!cert->cache.extns[count].oid)
958 0 : goto no_value;
959 :
960 20 : n = n->right;
961 20 : if (n && n->type == TYPE_BOOLEAN)
962 : {
963 20 : if (n->off != -1 && n->len && cert->image[n->off + n->nhdr])
964 2 : cert->cache.extns[count].crit = 1;
965 20 : n = n->right;
966 : }
967 :
968 20 : if (!n || n->type != TYPE_OCTET_STRING || n->off == -1)
969 : goto no_value;
970 :
971 20 : cert->cache.extns[count].off = n->off + n->nhdr;
972 20 : cert->cache.extns[count].len = n->len;
973 : }
974 :
975 3 : assert (count == cert->cache.n_extns);
976 3 : cert->cache.extns_valid = 1;
977 3 : return 0;
978 :
979 : no_value:
980 0 : for (count=0; count < cert->cache.n_extns; count++)
981 0 : xfree (cert->cache.extns[count].oid);
982 0 : xfree (cert->cache.extns);
983 0 : cert->cache.extns = NULL;
984 0 : return gpg_error (GPG_ERR_NO_VALUE);
985 : }
986 : }
987 :
988 :
989 : /* Return information about the IDX nth extension */
990 : gpg_error_t
991 284 : ksba_cert_get_extension (ksba_cert_t cert, int idx,
992 : char const **r_oid, int *r_crit,
993 : size_t *r_deroff, size_t *r_derlen)
994 : {
995 : gpg_error_t err;
996 :
997 284 : if (!cert)
998 0 : return gpg_error (GPG_ERR_INV_VALUE);
999 284 : if (!cert->initialized)
1000 0 : return gpg_error (GPG_ERR_NO_DATA);
1001 :
1002 284 : if (!cert->cache.extns_valid)
1003 : {
1004 3 : err = read_extensions (cert);
1005 3 : if (err)
1006 0 : return err;
1007 3 : assert (cert->cache.extns_valid);
1008 : }
1009 :
1010 284 : if (idx == cert->cache.n_extns)
1011 36 : return gpg_error (GPG_ERR_EOF); /* No more extensions. */
1012 :
1013 248 : if (idx < 0 || idx >= cert->cache.n_extns)
1014 0 : return gpg_error (GPG_ERR_INV_INDEX);
1015 :
1016 248 : if (r_oid)
1017 248 : *r_oid = cert->cache.extns[idx].oid;
1018 248 : if (r_crit)
1019 183 : *r_crit = cert->cache.extns[idx].crit;
1020 248 : if (r_deroff)
1021 223 : *r_deroff = cert->cache.extns[idx].off;
1022 248 : if (r_derlen)
1023 223 : *r_derlen = cert->cache.extns[idx].len;
1024 248 : return 0;
1025 : }
1026 :
1027 :
1028 :
1029 : /* Return information on the basicConstraint (2.5.19.19) of CERT.
1030 : R_CA receives true if this is a CA and only in that case R_PATHLEN
1031 : is set to the maximim certification path length or -1 if there is
1032 : nosuch limitation */
1033 : gpg_error_t
1034 3 : ksba_cert_is_ca (ksba_cert_t cert, int *r_ca, int *r_pathlen)
1035 : {
1036 : gpg_error_t err;
1037 : const char *oid;
1038 : int idx, crit;
1039 : size_t off, derlen, seqlen;
1040 : const unsigned char *der;
1041 : struct tag_info ti;
1042 : unsigned long value;
1043 :
1044 : /* set default values */
1045 3 : if (r_ca)
1046 3 : *r_ca = 0;
1047 3 : if (r_pathlen)
1048 3 : *r_pathlen = -1;
1049 14 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1050 8 : &off, &derlen)); idx++)
1051 : {
1052 11 : if (!strcmp (oid, oidstr_basicConstraints))
1053 3 : break;
1054 : }
1055 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1056 0 : return 0; /* no such constraint */
1057 3 : if (err)
1058 0 : return err;
1059 :
1060 : /* check that there is only one */
1061 15 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1062 9 : NULL, NULL)); idx++)
1063 : {
1064 9 : if (!strcmp (oid, oidstr_basicConstraints))
1065 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1066 : }
1067 :
1068 3 : der = cert->image + off;
1069 :
1070 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1071 3 : if (err)
1072 0 : return err;
1073 6 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1074 3 : && ti.is_constructed) )
1075 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1076 3 : if (ti.ndef)
1077 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1078 3 : seqlen = ti.length;
1079 3 : if (seqlen > derlen)
1080 0 : return gpg_error (GPG_ERR_BAD_BER);
1081 3 : if (!seqlen)
1082 0 : return 0; /* an empty sequence is allowed because both elements
1083 : are optional */
1084 :
1085 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1086 3 : if (err)
1087 0 : return err;
1088 3 : if (seqlen < ti.nhdr)
1089 0 : return gpg_error (GPG_ERR_BAD_BER);
1090 3 : seqlen -= ti.nhdr;
1091 3 : if (seqlen < ti.length)
1092 0 : return gpg_error (GPG_ERR_BAD_BER);
1093 3 : seqlen -= ti.length;
1094 :
1095 3 : if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BOOLEAN)
1096 : {
1097 3 : if (ti.length != 1)
1098 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1099 3 : if (r_ca)
1100 3 : *r_ca = !!*der;
1101 3 : der++; derlen--;
1102 3 : if (!seqlen)
1103 3 : return 0; /* ready (no pathlength) */
1104 :
1105 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1106 0 : if (err)
1107 0 : return err;
1108 0 : if (seqlen < ti.nhdr)
1109 0 : return gpg_error (GPG_ERR_BAD_BER);
1110 0 : seqlen -= ti.nhdr;
1111 0 : if (seqlen < ti.length)
1112 0 : return gpg_error (GPG_ERR_BAD_BER);
1113 0 : seqlen -= ti.length;
1114 : }
1115 :
1116 0 : if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_INTEGER))
1117 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1118 :
1119 0 : for (value=0; ti.length; ti.length--)
1120 : {
1121 0 : value <<= 8;
1122 0 : value |= (*der++) & 0xff;
1123 0 : derlen--;
1124 : }
1125 0 : if (r_pathlen)
1126 0 : *r_pathlen = value;
1127 :
1128 : /* if the extension is marked as critical and any stuff is still
1129 : left we better return an error */
1130 0 : if (crit && seqlen)
1131 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1132 :
1133 0 : return 0;
1134 : }
1135 :
1136 :
1137 :
1138 : /* Get the key usage flags. The function returns Ksba_No_Data if no
1139 : key usage is specified. */
1140 : gpg_error_t
1141 3 : ksba_cert_get_key_usage (ksba_cert_t cert, unsigned int *r_flags)
1142 : {
1143 : gpg_error_t err;
1144 : const char *oid;
1145 : int idx, crit;
1146 : size_t off, derlen;
1147 : const unsigned char *der;
1148 : struct tag_info ti;
1149 : unsigned int bits, mask;
1150 : int i, unused, full;
1151 :
1152 3 : if (!r_flags)
1153 0 : return gpg_error (GPG_ERR_INV_VALUE);
1154 3 : *r_flags = 0;
1155 17 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1156 11 : &off, &derlen)); idx++)
1157 : {
1158 13 : if (!strcmp (oid, oidstr_keyUsage))
1159 2 : break;
1160 : }
1161 3 : if (gpg_err_code (err) == GPG_ERR_EOF
1162 2 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1163 1 : return gpg_error (GPG_ERR_NO_DATA); /* no key usage */
1164 2 : if (err)
1165 0 : return err;
1166 :
1167 : /* check that there is only one */
1168 11 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1169 7 : NULL, NULL)); idx++)
1170 : {
1171 7 : if (!strcmp (oid, oidstr_keyUsage))
1172 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1173 : }
1174 :
1175 2 : der = cert->image + off;
1176 :
1177 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1178 2 : if (err)
1179 0 : return err;
1180 4 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BIT_STRING
1181 2 : && !ti.is_constructed) )
1182 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1183 2 : if (ti.ndef)
1184 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1185 2 : if (!ti.length || ti.length > derlen)
1186 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM); /* number of unused bits missing */
1187 2 : unused = *der++; derlen--;
1188 2 : ti.length--;
1189 2 : if ((!ti.length && unused) || unused/8 > ti.length)
1190 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1191 :
1192 2 : full = ti.length - (unused+7)/8;
1193 2 : unused %= 8;
1194 2 : mask = 0;
1195 3 : for (i=1; unused; i <<= 1, unused--)
1196 1 : mask |= i;
1197 :
1198 : /* the first octet */
1199 2 : if (!ti.length)
1200 0 : return 0; /* no bits set */
1201 2 : bits = *der++; derlen--; ti.length--;
1202 2 : if (full)
1203 1 : full--;
1204 : else {
1205 1 : bits &= ~mask;
1206 1 : mask = 0;
1207 : }
1208 2 : if (bits & 0x80)
1209 0 : *r_flags |= KSBA_KEYUSAGE_DIGITAL_SIGNATURE;
1210 2 : if (bits & 0x40)
1211 0 : *r_flags |= KSBA_KEYUSAGE_NON_REPUDIATION;
1212 2 : if (bits & 0x20)
1213 0 : *r_flags |= KSBA_KEYUSAGE_KEY_ENCIPHERMENT;
1214 2 : if (bits & 0x10)
1215 0 : *r_flags |= KSBA_KEYUSAGE_DATA_ENCIPHERMENT;
1216 2 : if (bits & 0x08)
1217 0 : *r_flags |= KSBA_KEYUSAGE_KEY_AGREEMENT;
1218 2 : if (bits & 0x04)
1219 2 : *r_flags |= KSBA_KEYUSAGE_KEY_CERT_SIGN;
1220 2 : if (bits & 0x02)
1221 2 : *r_flags |= KSBA_KEYUSAGE_CRL_SIGN;
1222 2 : if (bits & 0x01)
1223 0 : *r_flags |= KSBA_KEYUSAGE_ENCIPHER_ONLY;
1224 :
1225 : /* the second octet */
1226 2 : if (!ti.length)
1227 2 : return 0; /* no bits set */
1228 0 : bits = *der++; derlen--; ti.length--;
1229 0 : if (full)
1230 0 : full--;
1231 : else {
1232 0 : bits &= mask;
1233 0 : mask = ~0;
1234 : }
1235 0 : if (bits & 0x80)
1236 0 : *r_flags |= KSBA_KEYUSAGE_DECIPHER_ONLY;
1237 :
1238 0 : return 0;
1239 : }
1240 :
1241 :
1242 :
1243 : /* Note, that this helper is also used for ext_key_usage. */
1244 : static gpg_error_t
1245 0 : append_cert_policy (char **policies, const char *oid, int crit)
1246 : {
1247 : char *p;
1248 :
1249 0 : if (!*policies)
1250 : {
1251 0 : *policies = xtrymalloc (strlen (oid) + 4);
1252 0 : if (!*policies)
1253 0 : return gpg_error (GPG_ERR_ENOMEM);
1254 0 : p = *policies;
1255 : }
1256 : else
1257 : {
1258 0 : char *tmp = xtryrealloc (*policies,
1259 : strlen(*policies) + 1 + strlen (oid) + 4);
1260 0 : if (!tmp)
1261 0 : return gpg_error (GPG_ERR_ENOMEM);
1262 0 : *policies = tmp;
1263 0 : p = stpcpy (tmp+strlen (tmp), "\n");;
1264 : }
1265 :
1266 0 : strcpy (stpcpy (p, oid), crit? ":C:": ":N:");
1267 0 : return 0;
1268 : }
1269 :
1270 :
1271 : /* Return a string with the certificatePolicies delimited by
1272 : linefeeds. The return values may be extended to carry more
1273 : information er line, so the caller should only use the first
1274 : white-space delimited token per line. The function returns
1275 : GPG_ERR_NO_DATA when this extension is not used. Caller must free
1276 : the returned value. */
1277 : gpg_error_t
1278 3 : ksba_cert_get_cert_policies (ksba_cert_t cert, char **r_policies)
1279 : {
1280 : gpg_error_t err;
1281 : const char *oid;
1282 : int idx, crit;
1283 : size_t off, derlen, seqlen;
1284 : const unsigned char *der;
1285 : struct tag_info ti;
1286 :
1287 3 : if (!cert || !r_policies)
1288 0 : return gpg_error (GPG_ERR_INV_VALUE);
1289 3 : *r_policies = NULL;
1290 :
1291 26 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1292 20 : &off, &derlen)); idx++)
1293 : {
1294 20 : if (!strcmp (oid, oidstr_certificatePolicies))
1295 : {
1296 : char *suboid;
1297 :
1298 0 : der = cert->image + off;
1299 :
1300 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1301 0 : if (err)
1302 0 : goto leave;
1303 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1304 0 : && ti.is_constructed) )
1305 : {
1306 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1307 0 : goto leave;
1308 : }
1309 0 : if (ti.ndef)
1310 : {
1311 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1312 0 : goto leave;
1313 : }
1314 0 : seqlen = ti.length;
1315 0 : if (seqlen > derlen)
1316 : {
1317 0 : err = gpg_error (GPG_ERR_BAD_BER);
1318 0 : goto leave;
1319 : }
1320 0 : while (seqlen)
1321 : {
1322 : size_t seqseqlen;
1323 :
1324 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1325 0 : if (err)
1326 0 : goto leave;
1327 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1328 0 : && ti.is_constructed) )
1329 : {
1330 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1331 0 : goto leave;
1332 : }
1333 0 : if (ti.ndef)
1334 : {
1335 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1336 0 : goto leave;
1337 : }
1338 0 : if (!ti.length)
1339 : {
1340 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ); /* no empty inner SEQ */
1341 0 : goto leave;
1342 : }
1343 0 : if (ti.nhdr+ti.length > seqlen)
1344 : {
1345 0 : err = gpg_error (GPG_ERR_BAD_BER);
1346 0 : goto leave;
1347 : }
1348 0 : seqlen -= ti.nhdr + ti.length;
1349 0 : seqseqlen = ti.length;
1350 :
1351 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1352 0 : if (err)
1353 0 : goto leave;
1354 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID))
1355 : {
1356 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1357 0 : goto leave;
1358 : }
1359 0 : if (ti.nhdr+ti.length > seqseqlen)
1360 : {
1361 0 : err = gpg_error (GPG_ERR_BAD_BER);
1362 0 : goto leave;
1363 : }
1364 0 : seqseqlen -= ti.nhdr;
1365 :
1366 0 : suboid = ksba_oid_to_str (der, ti.length);
1367 0 : if (!suboid)
1368 : {
1369 0 : err = gpg_error (GPG_ERR_ENOMEM);
1370 0 : goto leave;
1371 : }
1372 0 : der += ti.length;
1373 0 : derlen -= ti.length;
1374 0 : seqseqlen -= ti.length;
1375 :
1376 0 : err = append_cert_policy (r_policies, suboid, crit);
1377 0 : xfree (suboid);
1378 0 : if (err)
1379 0 : goto leave;
1380 :
1381 : /* skip the rest of the seq which is more or less optional */
1382 0 : der += seqseqlen;
1383 0 : derlen -= seqseqlen;
1384 : }
1385 : }
1386 : }
1387 :
1388 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1389 3 : err = 0;
1390 3 : if (!*r_policies || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1391 3 : err = gpg_error (GPG_ERR_NO_DATA);
1392 :
1393 : leave:
1394 3 : if (err)
1395 : {
1396 3 : xfree (*r_policies);
1397 3 : *r_policies = NULL;
1398 : }
1399 3 : return err;
1400 : }
1401 :
1402 :
1403 : /* Return a string with the extendedKeyUsageOIDs delimited by
1404 : linefeeds. The return values may be extended to carry more
1405 : information per line, so the caller should only use the first
1406 : white-space delimited token per line. The function returns
1407 : GPG_ERR_NO_DATA when this extension is not used. Caller must free
1408 : the returned value. */
1409 : gpg_error_t
1410 3 : ksba_cert_get_ext_key_usages (ksba_cert_t cert, char **result)
1411 : {
1412 : gpg_error_t err;
1413 : const char *oid;
1414 : int idx, crit;
1415 : size_t off, derlen;
1416 : const unsigned char *der;
1417 : struct tag_info ti;
1418 :
1419 3 : if (!cert || !result)
1420 0 : return gpg_error (GPG_ERR_INV_VALUE);
1421 3 : *result = NULL;
1422 :
1423 26 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1424 20 : &off, &derlen)); idx++)
1425 : {
1426 20 : if (!strcmp (oid, oidstr_extKeyUsage))
1427 : {
1428 : char *suboid;
1429 :
1430 0 : der = cert->image + off;
1431 :
1432 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1433 0 : if (err)
1434 0 : goto leave;
1435 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1436 0 : && ti.is_constructed) )
1437 : {
1438 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1439 0 : goto leave;
1440 : }
1441 0 : if (ti.ndef)
1442 : {
1443 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1444 0 : goto leave;
1445 : }
1446 0 : if (ti.length > derlen)
1447 : {
1448 0 : err = gpg_error (GPG_ERR_BAD_BER);
1449 0 : goto leave;
1450 : }
1451 0 : while (derlen)
1452 : {
1453 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1454 0 : if (err)
1455 0 : goto leave;
1456 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID))
1457 : {
1458 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1459 0 : goto leave;
1460 : }
1461 :
1462 0 : suboid = ksba_oid_to_str (der, ti.length);
1463 0 : if (!suboid)
1464 : {
1465 0 : err = gpg_error (GPG_ERR_ENOMEM);
1466 0 : goto leave;
1467 : }
1468 0 : der += ti.length;
1469 0 : derlen -= ti.length;
1470 :
1471 0 : err = append_cert_policy (result, suboid, crit);
1472 0 : xfree (suboid);
1473 0 : if (err)
1474 0 : goto leave;
1475 : }
1476 : }
1477 : }
1478 :
1479 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1480 3 : err = 0;
1481 3 : if (!*result || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1482 3 : err = gpg_error (GPG_ERR_NO_DATA);
1483 :
1484 : leave:
1485 3 : if (err)
1486 : {
1487 3 : xfree (*result);
1488 3 : *result = NULL;
1489 : }
1490 3 : return err;
1491 : }
1492 :
1493 :
1494 :
1495 :
1496 : /* Helper function for ksba_cert_get_crl_dist_point */
1497 : static gpg_error_t
1498 2 : parse_distribution_point (const unsigned char *der, size_t derlen,
1499 : ksba_name_t *distpoint, ksba_name_t *issuer,
1500 : ksba_crl_reason_t *reason)
1501 : {
1502 : gpg_error_t err;
1503 : struct tag_info ti;
1504 :
1505 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1506 2 : if (err)
1507 0 : return err;
1508 2 : if (ti.class != CLASS_CONTEXT)
1509 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1510 2 : if (ti.ndef)
1511 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1512 2 : if (derlen < ti.length)
1513 0 : return gpg_error (GPG_ERR_BAD_BER);
1514 :
1515 2 : if (ti.tag == 0 && derlen)
1516 : { /* distributionPointName */
1517 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1518 2 : if (err)
1519 0 : return err;
1520 2 : if (ti.class != CLASS_CONTEXT)
1521 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1522 2 : if (ti.ndef)
1523 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1524 2 : if (derlen < ti.nhdr)
1525 0 : return gpg_error (GPG_ERR_BAD_BER);
1526 2 : if (derlen < ti.length)
1527 0 : return gpg_error (GPG_ERR_BAD_BER);
1528 :
1529 2 : if (ti.tag == 0)
1530 : {
1531 2 : if (distpoint)
1532 : {
1533 2 : err = _ksba_name_new_from_der (distpoint, der, ti.length);
1534 2 : if (err)
1535 0 : return err;
1536 : }
1537 : }
1538 : else
1539 : {
1540 : /* We don't support nameRelativeToCRLIssuer yet*/
1541 : }
1542 2 : der += ti.length;
1543 2 : derlen -= ti.length;
1544 :
1545 2 : if (!derlen)
1546 2 : return 0;
1547 :
1548 : /* read the next optional element */
1549 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1550 0 : if (err)
1551 0 : return err;
1552 0 : if (ti.class != CLASS_CONTEXT)
1553 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1554 0 : if (ti.ndef)
1555 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1556 0 : if (derlen < ti.length)
1557 0 : return gpg_error (GPG_ERR_BAD_BER);
1558 : }
1559 :
1560 0 : if (ti.tag == 1 && derlen)
1561 : { /* reasonFlags */
1562 : unsigned int bits, mask;
1563 : int i, unused, full;
1564 :
1565 0 : unused = *der++; derlen--;
1566 0 : ti.length--;
1567 0 : if ((!ti.length && unused) || unused/8 > ti.length)
1568 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1569 :
1570 0 : full = ti.length - (unused+7)/8;
1571 0 : unused %= 8;
1572 0 : mask = 0;
1573 0 : for (i=1; unused; i <<= 1, unused--)
1574 0 : mask |= i;
1575 :
1576 : /* we are only required to look at the first octect */
1577 0 : if (ti.length && reason)
1578 : {
1579 0 : bits = *der;
1580 0 : if (full)
1581 0 : full--;
1582 : else {
1583 0 : bits &= ~mask;
1584 0 : mask = 0;
1585 : }
1586 :
1587 0 : if (bits & 0x80)
1588 0 : *reason |= KSBA_CRLREASON_UNSPECIFIED;
1589 0 : if (bits & 0x40)
1590 0 : *reason |= KSBA_CRLREASON_KEY_COMPROMISE;
1591 0 : if (bits & 0x20)
1592 0 : *reason |= KSBA_CRLREASON_CA_COMPROMISE;
1593 0 : if (bits & 0x10)
1594 0 : *reason |= KSBA_CRLREASON_AFFILIATION_CHANGED;
1595 0 : if (bits & 0x08)
1596 0 : *reason |= KSBA_CRLREASON_SUPERSEDED;
1597 0 : if (bits & 0x04)
1598 0 : *reason |= KSBA_CRLREASON_CESSATION_OF_OPERATION;
1599 0 : if (bits & 0x02)
1600 0 : *reason |= KSBA_CRLREASON_CERTIFICATE_HOLD;
1601 : }
1602 :
1603 0 : der += ti.length;
1604 0 : derlen -= ti.length;
1605 :
1606 0 : if (!derlen)
1607 0 : return 0;
1608 :
1609 : /* read the next optional element */
1610 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1611 0 : if (err)
1612 0 : return err;
1613 0 : if (ti.class != CLASS_CONTEXT)
1614 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1615 0 : if (ti.ndef)
1616 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1617 0 : if (derlen < ti.length)
1618 0 : return gpg_error (GPG_ERR_BAD_BER);
1619 : }
1620 :
1621 0 : if (ti.tag == 2 && derlen)
1622 : { /* crlIssuer */
1623 0 : if (issuer)
1624 : {
1625 0 : err = _ksba_name_new_from_der (issuer, der, ti.length);
1626 0 : if (err)
1627 0 : return err;
1628 : }
1629 :
1630 0 : der += ti.length;
1631 0 : derlen -= ti.length;
1632 : }
1633 :
1634 0 : if (derlen)
1635 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1636 :
1637 0 : return 0;
1638 : }
1639 :
1640 : /* Return the CRLDistPoints given in the cert extension. IDX should
1641 : be iterated started from 0 until the function returns -1.
1642 : R_DISTPOINT returns a ksba_name_t object with the distribution point
1643 : name(s) the return value may be NULL to indicate that this name is
1644 : not available. R_ISSUER returns the CRL issuer; if the returned
1645 : value is NULL the caller should assume that the CRL issuer is the
1646 : same as the certificate issuer. R_REASON returns the reason for
1647 : the CRL. This is a bit encoded value with no bit set if this has
1648 : not been specified in the cert.
1649 :
1650 : The caller may pass NULL to any of the pointer arguments if he is
1651 : not interested in this value. The return values for R_DISTPOINT
1652 : and R_ISSUER must be released by the caller using
1653 : ksba_name_release(). */
1654 :
1655 : gpg_error_t
1656 5 : ksba_cert_get_crl_dist_point (ksba_cert_t cert, int idx,
1657 : ksba_name_t *r_distpoint,
1658 : ksba_name_t *r_issuer,
1659 : ksba_crl_reason_t *r_reason)
1660 : {
1661 : gpg_error_t err;
1662 : const char *oid;
1663 : size_t off, derlen;
1664 : int myidx, crit;
1665 :
1666 5 : if (r_distpoint)
1667 5 : *r_distpoint = NULL;
1668 5 : if (r_issuer)
1669 5 : *r_issuer = NULL;
1670 5 : if (r_reason)
1671 5 : *r_reason = 0;
1672 :
1673 36 : for (myidx=0; !(err=ksba_cert_get_extension (cert, myidx, &oid, &crit,
1674 26 : &off, &derlen)); myidx++)
1675 : {
1676 28 : if (!strcmp (oid, oidstr_crlDistributionPoints))
1677 : {
1678 : const unsigned char *der;
1679 : struct tag_info ti;
1680 : size_t seqlen;
1681 :
1682 3 : der = cert->image + off;
1683 :
1684 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1685 3 : if (err)
1686 2 : return err;
1687 6 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1688 3 : && ti.is_constructed) )
1689 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1690 3 : if (ti.ndef)
1691 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1692 3 : seqlen = ti.length;
1693 3 : if (seqlen > derlen)
1694 0 : return gpg_error (GPG_ERR_BAD_BER);
1695 :
1696 : /* Note: an empty sequence is actually not allowed but we
1697 : better don't care */
1698 :
1699 9 : while (seqlen)
1700 : {
1701 5 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1702 5 : if (err)
1703 0 : return err;
1704 10 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1705 5 : && ti.is_constructed) )
1706 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1707 5 : if (derlen < ti.length)
1708 0 : return gpg_error (GPG_ERR_BAD_BER);
1709 5 : if (seqlen < ti.nhdr)
1710 0 : return gpg_error (GPG_ERR_BAD_BER);
1711 5 : seqlen -= ti.nhdr;
1712 5 : if (seqlen < ti.length)
1713 0 : return gpg_error (GPG_ERR_BAD_BER);
1714 :
1715 5 : if (idx)
1716 : { /* skip because we are not yet at the desired index */
1717 3 : der += ti.length;
1718 3 : derlen -= ti.length;
1719 3 : seqlen -= ti.length;
1720 3 : idx--;
1721 3 : continue;
1722 : }
1723 :
1724 2 : if (!ti.length)
1725 0 : return 0;
1726 :
1727 2 : err = parse_distribution_point (der, ti.length,
1728 : r_distpoint, r_issuer, r_reason);
1729 2 : if (err && r_distpoint)
1730 : {
1731 0 : ksba_name_release (*r_distpoint);
1732 0 : *r_distpoint = NULL;
1733 : }
1734 2 : if (err && r_issuer)
1735 : {
1736 0 : ksba_name_release (*r_issuer);
1737 0 : *r_issuer = NULL;
1738 : }
1739 2 : if (err && r_reason)
1740 0 : *r_reason = 0;
1741 :
1742 2 : return err;
1743 : }
1744 : }
1745 : }
1746 :
1747 3 : return err;
1748 : }
1749 :
1750 :
1751 : /* Return the authorityKeyIdentifier in R_NAME and R_SERIAL or/and in
1752 : R_KEYID. GPG_ERR_NO_DATA is returned if no authorityKeyIdentifier
1753 : or only one using the keyIdentifier method is available and R_KEYID
1754 : is NULL. */
1755 : gpg_error_t
1756 3 : ksba_cert_get_auth_key_id (ksba_cert_t cert,
1757 : ksba_sexp_t *r_keyid,
1758 : ksba_name_t *r_name,
1759 : ksba_sexp_t *r_serial)
1760 : {
1761 : gpg_error_t err;
1762 : const char *oid;
1763 : size_t off, derlen;
1764 : const unsigned char *der;
1765 3 : const unsigned char *keyid_der = NULL;
1766 3 : size_t keyid_derlen = 0;
1767 : int idx, crit;
1768 : struct tag_info ti;
1769 : char numbuf[30];
1770 : size_t numbuflen;
1771 :
1772 3 : if (r_keyid)
1773 3 : *r_keyid = NULL;
1774 3 : if (!r_name || !r_serial)
1775 0 : return gpg_error (GPG_ERR_INV_VALUE);
1776 3 : *r_name = NULL;
1777 3 : *r_serial = NULL;
1778 :
1779 24 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1780 18 : &off, &derlen)); idx++)
1781 : {
1782 19 : if (!strcmp (oid, oidstr_authorityKeyIdentifier))
1783 1 : break;
1784 : }
1785 3 : if (gpg_err_code (err) == GPG_ERR_EOF
1786 1 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1787 2 : return gpg_error (GPG_ERR_NO_DATA); /* not available */
1788 1 : if (err)
1789 0 : return err;
1790 :
1791 : /* check that there is only one */
1792 3 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1793 1 : NULL, NULL)); idx++)
1794 : {
1795 1 : if (!strcmp (oid, oidstr_authorityKeyIdentifier))
1796 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1797 : }
1798 :
1799 1 : der = cert->image + off;
1800 :
1801 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1802 1 : if (err)
1803 0 : return err;
1804 2 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1805 1 : && ti.is_constructed) )
1806 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1807 1 : if (ti.ndef)
1808 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1809 1 : if (ti.length > derlen)
1810 0 : return gpg_error (GPG_ERR_BAD_BER);
1811 :
1812 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1813 1 : if (err)
1814 0 : return err;
1815 1 : if (ti.class != CLASS_CONTEXT)
1816 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1817 1 : if (ti.ndef)
1818 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1819 1 : if (derlen < ti.length)
1820 0 : return gpg_error (GPG_ERR_BAD_BER);
1821 :
1822 1 : if (ti.tag == 0)
1823 : { /* keyIdentifier: Save it away and skip over it. */
1824 1 : keyid_der = der;
1825 1 : keyid_derlen = ti.length;
1826 :
1827 1 : der += ti.length;
1828 1 : derlen -= ti.length;
1829 : /* If the keyid has been requested but no other data follows, we
1830 : directly jump to the end. */
1831 1 : if (r_keyid && !derlen)
1832 0 : goto build_keyid;
1833 1 : if (!derlen)
1834 0 : return gpg_error (GPG_ERR_NO_DATA); /* not available */
1835 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1836 1 : if (err)
1837 0 : return err;
1838 1 : if (ti.class != CLASS_CONTEXT)
1839 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1840 1 : if (ti.ndef)
1841 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1842 1 : if (derlen < ti.length)
1843 0 : return gpg_error (GPG_ERR_BAD_BER);
1844 : }
1845 :
1846 1 : if (ti.tag != 1 || !derlen)
1847 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1848 :
1849 1 : err = _ksba_name_new_from_der (r_name, der, ti.length);
1850 1 : if (err)
1851 0 : return err;
1852 :
1853 1 : der += ti.length;
1854 1 : derlen -= ti.length;
1855 :
1856 : /* fixme: we should release r_name before returning on error */
1857 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1858 1 : if (err)
1859 0 : return err;
1860 1 : if (ti.class != CLASS_CONTEXT)
1861 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1862 1 : if (ti.ndef)
1863 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1864 1 : if (derlen < ti.length)
1865 0 : return gpg_error (GPG_ERR_BAD_BER);
1866 :
1867 1 : if (ti.tag != 2 || !derlen)
1868 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1869 :
1870 1 : sprintf (numbuf,"(%u:", (unsigned int)ti.length);
1871 1 : numbuflen = strlen (numbuf);
1872 1 : *r_serial = xtrymalloc (numbuflen + ti.length + 2);
1873 1 : if (!*r_serial)
1874 0 : return gpg_error (GPG_ERR_ENOMEM);
1875 1 : strcpy (*r_serial, numbuf);
1876 1 : memcpy (*r_serial+numbuflen, der, ti.length);
1877 1 : (*r_serial)[numbuflen + ti.length] = ')';
1878 1 : (*r_serial)[numbuflen + ti.length + 1] = 0;
1879 :
1880 : build_keyid:
1881 1 : if (r_keyid && keyid_der && keyid_derlen)
1882 : {
1883 1 : sprintf (numbuf,"(%u:", (unsigned int)keyid_derlen);
1884 1 : numbuflen = strlen (numbuf);
1885 1 : *r_keyid = xtrymalloc (numbuflen + keyid_derlen + 2);
1886 1 : if (!*r_keyid)
1887 0 : return gpg_error (GPG_ERR_ENOMEM);
1888 1 : strcpy (*r_keyid, numbuf);
1889 1 : memcpy (*r_keyid+numbuflen, keyid_der, keyid_derlen);
1890 1 : (*r_keyid)[numbuflen + keyid_derlen] = ')';
1891 1 : (*r_keyid)[numbuflen + keyid_derlen + 1] = 0;
1892 : }
1893 1 : return 0;
1894 : }
1895 :
1896 :
1897 : /* Return a simple octet string extension at the object identifier OID
1898 : from certificate CERT. The data is return as a simple S-expression
1899 : and stored at R_DATA. Returns 0 on success or an error code.
1900 : common error codes are: GPG_ERR_NO_DATA if no such extension is
1901 : available, GPG_ERR_DUP_VALUE if more than one is available. If
1902 : R_CRIT is not NULL, the critical extension flag will be stored at
1903 : that address. */
1904 : static gpg_error_t
1905 3 : get_simple_octet_string_ext (ksba_cert_t cert, const char *oid,
1906 : int *r_crit, ksba_sexp_t *r_data)
1907 : {
1908 : gpg_error_t err;
1909 : const char *tmpoid;
1910 : size_t off, derlen;
1911 : const unsigned char *der;
1912 : int idx, crit;
1913 : struct tag_info ti;
1914 : char numbuf[30];
1915 : size_t numbuflen;
1916 :
1917 3 : if (!r_data)
1918 0 : return gpg_error (GPG_ERR_INV_VALUE);
1919 3 : *r_data = NULL;
1920 :
1921 16 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &tmpoid, &crit,
1922 10 : &off, &derlen)); idx++)
1923 : {
1924 12 : if (!strcmp (tmpoid, oid))
1925 2 : break;
1926 : }
1927 3 : if (err)
1928 : {
1929 1 : if (gpg_err_code (err) == GPG_ERR_EOF
1930 0 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1931 1 : return gpg_error (GPG_ERR_NO_DATA);
1932 0 : return err;
1933 : }
1934 :
1935 : /* Check that there is only one */
1936 12 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &tmpoid, NULL,
1937 8 : NULL, NULL)); idx++)
1938 : {
1939 8 : if (!strcmp (tmpoid, oid))
1940 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1941 : }
1942 :
1943 2 : der = cert->image + off;
1944 :
1945 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1946 2 : if (err)
1947 0 : return err;
1948 4 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OCTET_STRING
1949 2 : && !ti.is_constructed) )
1950 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1951 2 : if (ti.ndef)
1952 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1953 2 : if (ti.length > derlen)
1954 0 : return gpg_error (GPG_ERR_BAD_BER);
1955 2 : if (ti.length != derlen)
1956 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* Garbage follows. */
1957 :
1958 2 : sprintf (numbuf,"(%u:", (unsigned int)ti.length);
1959 2 : numbuflen = strlen (numbuf);
1960 2 : *r_data = xtrymalloc (numbuflen + ti.length + 2);
1961 2 : if (!*r_data)
1962 0 : return gpg_error (GPG_ERR_ENOMEM);
1963 2 : strcpy (*r_data, numbuf);
1964 2 : memcpy (*r_data+numbuflen, der, ti.length);
1965 2 : (*r_data)[numbuflen + ti.length] = ')';
1966 2 : (*r_data)[numbuflen + ti.length + 1] = 0;
1967 2 : if (r_crit)
1968 0 : *r_crit = crit;
1969 2 : return 0;
1970 : }
1971 :
1972 :
1973 : /* Return the subjectKeyIdentifier extension as a simple allocated
1974 : S-expression at the address of R_KEYID. 0 is returned on success,
1975 : GPG_ERR_NO_DATA if no such extension is available or any other
1976 : error code. If R_CRIT is not passed as NULL, the criticla flag of
1977 : this is extension is stored there. */
1978 : gpg_error_t
1979 3 : ksba_cert_get_subj_key_id (ksba_cert_t cert, int *r_crit, ksba_sexp_t *r_keyid)
1980 : {
1981 3 : return get_simple_octet_string_ext (cert, oidstr_subjectKeyIdentifier,
1982 : r_crit, r_keyid);
1983 : }
1984 :
1985 :
1986 :
1987 : /* MODE 0 := authorityInfoAccess
1988 : 1 := subjectInfoAccess
1989 :
1990 : Caller must release METHOD and LOCATION if the function returned
1991 : with success; on error both variables will point to NULL.
1992 : */
1993 : static gpg_error_t
1994 6 : get_info_access (ksba_cert_t cert, int idx, int mode,
1995 : char **method, ksba_name_t *location)
1996 : {
1997 : gpg_error_t err;
1998 : const char *oid;
1999 : size_t off, derlen;
2000 : int myidx, crit;
2001 :
2002 6 : *method = NULL;
2003 6 : *location = NULL;
2004 :
2005 6 : if (!cert || !cert->initialized)
2006 0 : return gpg_error (GPG_ERR_INV_VALUE);
2007 6 : if (idx < 0)
2008 0 : return gpg_error (GPG_ERR_INV_INDEX);
2009 :
2010 52 : for (myidx=0; !(err=ksba_cert_get_extension (cert, myidx, &oid, &crit,
2011 40 : &off, &derlen)); myidx++)
2012 : {
2013 40 : if (!strcmp (oid,(mode == 0)? oidstr_authorityInfoAccess
2014 : : oidstr_subjectInfoAccess) )
2015 : {
2016 : const unsigned char *der;
2017 : struct tag_info ti;
2018 : size_t seqlen;
2019 :
2020 0 : der = cert->image + off;
2021 :
2022 : /* What we are going to parse is:
2023 : *
2024 : * AuthorityInfoAccessSyntax ::=
2025 : * SEQUENCE SIZE (1..MAX) OF AccessDescription
2026 : *
2027 : * AccessDescription ::= SEQUENCE {
2028 : * accessMethod OBJECT IDENTIFIER,
2029 : * accessLocation GeneralName }
2030 : */
2031 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2032 0 : if (err)
2033 0 : return err;
2034 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
2035 0 : && ti.is_constructed) )
2036 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2037 0 : if (ti.ndef)
2038 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
2039 0 : seqlen = ti.length;
2040 0 : if (seqlen > derlen)
2041 0 : return gpg_error (GPG_ERR_BAD_BER);
2042 :
2043 : /* Note: an empty sequence is actually not allowed but we
2044 : better don't care. */
2045 :
2046 0 : while (seqlen)
2047 : {
2048 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2049 0 : if (err)
2050 0 : return err;
2051 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
2052 0 : && ti.is_constructed) )
2053 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2054 0 : if (derlen < ti.length)
2055 0 : return gpg_error (GPG_ERR_BAD_BER);
2056 0 : if (seqlen < ti.nhdr)
2057 0 : return gpg_error (GPG_ERR_BAD_BER);
2058 0 : seqlen -= ti.nhdr;
2059 0 : if (seqlen < ti.length)
2060 0 : return gpg_error (GPG_ERR_BAD_BER);
2061 :
2062 0 : if (idx)
2063 : { /* Skip because we are not yet at the desired index. */
2064 0 : der += ti.length;
2065 0 : derlen -= ti.length;
2066 0 : seqlen -= ti.length;
2067 0 : idx--;
2068 0 : continue;
2069 : }
2070 : /* We only need the next object, thus we can (and
2071 : actually need to) limit the DERLEN to the length of
2072 : the current sequence. */
2073 0 : derlen = ti.length;
2074 0 : if (!derlen)
2075 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2076 :
2077 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2078 0 : if (err)
2079 0 : return err;
2080 :
2081 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
2082 0 : && !ti.is_constructed))
2083 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2084 0 : if (ti.ndef)
2085 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
2086 0 : if (derlen < ti.length)
2087 0 : return gpg_error (GPG_ERR_BAD_BER);
2088 :
2089 0 : *method = ksba_oid_to_str (der, ti.length);
2090 0 : if (!*method)
2091 0 : return gpg_error (GPG_ERR_ENOMEM);
2092 0 : der += ti.length;
2093 0 : derlen -= ti.length;
2094 :
2095 0 : err = _ksba_name_new_from_der (location, der, derlen);
2096 0 : if (err)
2097 : {
2098 0 : ksba_free (*method);
2099 0 : *method = NULL;
2100 0 : return err;
2101 : }
2102 0 : return 0;
2103 : }
2104 : }
2105 : }
2106 :
2107 6 : return err;
2108 : }
2109 :
2110 :
2111 : /* Return the authorityInfoAccess attributes. IDX should be iterated
2112 : starting from 0 until the function returns GPG_ERR_EOF. R_METHOD
2113 : returns an allocated string with the OID of one item and R_LOCATION
2114 : return the GeneralName for that OID. The return values for
2115 : R_METHOD and R_LOCATION must be released by the caller unless the
2116 : function returned an error; the function will however make sure
2117 : that R_METHOD and R_LOCATION will point to NULL if the function
2118 : returns an error. See RFC 2459, section 4.2.2.1 */
2119 : gpg_error_t
2120 3 : ksba_cert_get_authority_info_access (ksba_cert_t cert, int idx,
2121 : char **r_method, ksba_name_t *r_location)
2122 : {
2123 3 : if (!r_method || !r_location)
2124 0 : return gpg_error (GPG_ERR_INV_VALUE);
2125 3 : return get_info_access (cert, idx, 0, r_method, r_location);
2126 : }
2127 :
2128 : /* Return the subjectInfoAccess attributes. IDX should be iterated
2129 : starting from 0 until the function returns GPG_ERR_EOF. R_METHOD
2130 : returns an allocated string with the OID of one item and R_LOCATION
2131 : return the GeneralName for that OID. The return values for
2132 : R_METHOD and R_LOCATION must be released by the caller unless the
2133 : function returned an error; the function will however make sure
2134 : that R_METHOD and R_LOCATION will point to NULL if the function
2135 : returns an error. See RFC 2459, section 4.2.2.2 */
2136 : gpg_error_t
2137 3 : ksba_cert_get_subject_info_access (ksba_cert_t cert, int idx,
2138 : char **r_method, ksba_name_t *r_location)
2139 : {
2140 3 : if (!r_method || !r_location)
2141 0 : return gpg_error (GPG_ERR_INV_VALUE);
2142 3 : return get_info_access (cert, idx, 1, r_method, r_location);
2143 : }
|