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 0 : (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 : {
468 0 : algo = NULL;
469 0 : err = gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
470 : }
471 : else
472 3 : err = _ksba_parse_algorithm_identifier (cert->image + n->off,
473 3 : n->nhdr + n->len, &nread, &algo);
474 3 : if (err)
475 0 : cert->last_error = err;
476 : else
477 3 : cert->cache.digest_algo = algo;
478 :
479 3 : return algo;
480 : }
481 :
482 :
483 :
484 :
485 : /**
486 : * ksba_cert_get_serial:
487 : * @cert: certificate object
488 : *
489 : * This function returnes the serial number of the certificate. The
490 : * serial number is an integer returned as an canonical encoded
491 : * S-expression with just one element.
492 : *
493 : * Return value: An allocated S-Exp or NULL for no value.
494 : **/
495 : ksba_sexp_t
496 3 : ksba_cert_get_serial (ksba_cert_t cert)
497 : {
498 : AsnNode n;
499 : char *p;
500 : char numbuf[22];
501 : int numbuflen;
502 :
503 3 : if (!cert || !cert->initialized)
504 0 : return NULL;
505 :
506 3 : n = _ksba_asn_find_node (cert->root,
507 : "Certificate.tbsCertificate.serialNumber");
508 3 : if (!n)
509 0 : return NULL; /* oops - should be there */
510 :
511 3 : if (n->off == -1)
512 : {
513 : /* fputs ("get_serial problem at node:\n", stderr); */
514 : /* _ksba_asn_node_dump_all (n, stderr); */
515 0 : return NULL;
516 : }
517 :
518 3 : sprintf (numbuf,"(%u:", (unsigned int)n->len);
519 3 : numbuflen = strlen (numbuf);
520 3 : p = xtrymalloc (numbuflen + n->len + 2);
521 3 : if (!p)
522 0 : return NULL;
523 3 : strcpy (p, numbuf);
524 3 : memcpy (p+numbuflen, cert->image + n->off + n->nhdr, n->len);
525 3 : p[numbuflen + n->len] = ')';
526 3 : p[numbuflen + n->len + 1] = 0;
527 3 : return p;
528 : }
529 :
530 :
531 : /* Return a pointer to the DER encoding of the serial number in CERT in
532 : PTR and the length of that field in LENGTH. */
533 : gpg_error_t
534 0 : _ksba_cert_get_serial_ptr (ksba_cert_t cert,
535 : unsigned char const **ptr, size_t *length)
536 : {
537 : asn_node_t n;
538 :
539 0 : if (!cert || !cert->initialized || !ptr || !length)
540 0 : return gpg_error (GPG_ERR_INV_VALUE);
541 0 : n = _ksba_asn_find_node (cert->root,
542 : "Certificate.tbsCertificate.serialNumber");
543 0 : if (!n || n->off == -1)
544 0 : return gpg_error (GPG_ERR_NO_VALUE);
545 :
546 0 : *ptr = cert->image + n->off + n->nhdr;
547 0 : *length = n->len;
548 0 : return 0;
549 : }
550 :
551 :
552 :
553 : /* Return a pointer to the DER encoding of the subject's DN in CERT in
554 : PTR and the length of that object in LENGTH. */
555 : gpg_error_t
556 0 : _ksba_cert_get_subject_dn_ptr (ksba_cert_t cert,
557 : unsigned char const **ptr, size_t *length)
558 : {
559 : asn_node_t n;
560 :
561 0 : if (!cert || !cert->initialized || !ptr || !length)
562 0 : return gpg_error (GPG_ERR_INV_VALUE);
563 :
564 0 : n = _ksba_asn_find_node (cert->root, "Certificate.tbsCertificate.subject");
565 0 : if (!n || !n->down)
566 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
567 0 : n = n->down; /* dereference the choice node */
568 0 : if (n->off == -1)
569 0 : return gpg_error (GPG_ERR_NO_VALUE);
570 0 : *ptr = cert->image + n->off;
571 0 : *length = n->nhdr + n->len;
572 0 : return 0;
573 : }
574 :
575 :
576 :
577 : /* Worker function for get_isssuer and get_subject. */
578 : static gpg_error_t
579 12 : get_name (ksba_cert_t cert, int idx, int use_subject, char **result)
580 : {
581 : gpg_error_t err;
582 : char *p;
583 : int i;
584 : const char *oid;
585 : struct tag_info ti;
586 : const unsigned char *der;
587 : size_t off, derlen, seqlen;
588 :
589 12 : if (!cert || !cert->initialized || !result)
590 0 : return gpg_error (GPG_ERR_INV_VALUE);
591 12 : if (idx < 0)
592 0 : return gpg_error (GPG_ERR_INV_INDEX);
593 :
594 12 : *result = NULL;
595 12 : if (!idx)
596 : { /* Get the required DN */
597 : AsnNode n;
598 :
599 6 : n = _ksba_asn_find_node (cert->root,
600 : (use_subject?
601 : "Certificate.tbsCertificate.subject":
602 : "Certificate.tbsCertificate.issuer") );
603 6 : if (!n || !n->down)
604 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
605 6 : n = n->down; /* dereference the choice node */
606 6 : if (n->off == -1)
607 0 : return gpg_error (GPG_ERR_NO_VALUE);
608 :
609 6 : err = _ksba_dn_to_str (cert->image, n, &p);
610 6 : if (err)
611 0 : return err;
612 6 : *result = p;
613 6 : return 0;
614 : }
615 :
616 : /* get {issuer,subject}AltName */
617 52 : for (i=0; !(err=ksba_cert_get_extension (cert, i, &oid, NULL,
618 40 : &off, &derlen)); i++)
619 : {
620 40 : if (!strcmp (oid, (use_subject?
621 : oidstr_subjectAltName:oidstr_issuerAltName)))
622 0 : break;
623 : }
624 6 : if (err)
625 6 : return err; /* no alt name or error*/
626 :
627 0 : der = cert->image + off;
628 :
629 :
630 : /* FIXME: We should use _ksba_name_new_from_der and ksba_name_enum here */
631 :
632 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
633 0 : if (err)
634 0 : return err;
635 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
636 0 : && ti.is_constructed) )
637 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
638 0 : if (ti.ndef)
639 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
640 0 : seqlen = ti.length;
641 0 : if (seqlen > derlen)
642 0 : return gpg_error (GPG_ERR_BAD_BER);
643 0 : if (!seqlen)
644 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* empty sequence is not allowed */
645 :
646 0 : while (seqlen)
647 : {
648 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
649 0 : if (err)
650 0 : return err;
651 0 : if (ti.class != CLASS_CONTEXT)
652 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
653 0 : if (ti.ndef)
654 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
655 0 : if (seqlen < ti.nhdr)
656 0 : return gpg_error (GPG_ERR_BAD_BER);
657 0 : seqlen -= ti.nhdr;
658 0 : if (seqlen < ti.length)
659 0 : return gpg_error (GPG_ERR_BAD_BER);
660 0 : seqlen -= ti.length;
661 0 : if (derlen < ti.length)
662 0 : return gpg_error (GPG_ERR_BAD_BER);
663 0 : if (!(ti.tag == 1 || ti.tag == 2 || ti.tag == 6))
664 : ; /* Not a supported tag: Do not change IDX. */
665 0 : else if (--idx)
666 : ; /* not yet at the desired index */
667 0 : else if (ti.tag == 1)
668 : { /* rfc822Name - this is an implicit IA5_STRING */
669 0 : p = xtrymalloc (ti.length+3);
670 0 : if (!p)
671 0 : return gpg_error (GPG_ERR_ENOMEM);
672 0 : *p = '<';
673 0 : memcpy (p+1, der, ti.length);
674 0 : p[ti.length+1] = '>';
675 0 : p[ti.length+2] = 0;
676 0 : *result = p;
677 0 : return 0;
678 : }
679 0 : else if (ti.tag == 2 || ti.tag == 6)
680 : { /* dNSName or URI - this are implicit IA5_STRINGs */
681 : char numbuf[20], *numbufp;
682 : size_t numbuflen;
683 :
684 0 : numbufp = smklen (numbuf, DIM(numbuf), ti.length, &numbuflen);
685 0 : p = xtrymalloc (11 + numbuflen + ti.length + 3);
686 0 : if (!p)
687 0 : return gpg_error (GPG_ERR_ENOMEM);
688 0 : *result = p;
689 0 : p = stpcpy (p, ti.tag == 2? "(8:dns-name" : "(3:uri");
690 0 : p = stpcpy (p, numbufp);
691 0 : memcpy (p, der, ti.length);
692 0 : p += ti.length;
693 0 : *p++ = ')';
694 0 : *p = 0;
695 0 : return 0;
696 : }
697 :
698 : /* advance pointer */
699 0 : der += ti.length;
700 0 : derlen -= ti.length;
701 : }
702 :
703 0 : return gpg_error (GPG_ERR_EOF);
704 : }
705 :
706 :
707 :
708 : /**
709 : * ksba_cert_get_issuer:
710 : * @cert: certificate object
711 : *
712 : * With @idx == 0 this function returns the Distinguished Name (DN) of
713 : * the certificate issuer which in most cases is a CA. The format of
714 : * the returned string is in accordance with RFC-2253. NULL is
715 : * returned if the DN is not available which is an error and should
716 : * have been catched by the certificate reading function.
717 : *
718 : * With @idx > 0 the function may be used to enumerate alternate
719 : * issuer names. The function returns NULL if there are no more
720 : * alternate names. The function does only return alternate names
721 : * which are recognized by libksba and ignores others. The format of
722 : * the returned name is either a RFC-2253 formated one which can be
723 : * detected by checking whether the first character is letter or
724 : * digit. rfc-2822 conform email addresses are returned enclosed in
725 : * angle brackets, the opening angle bracket should be used to
726 : * indicate this. Other formats are returned as an S-Expression in
727 : * canonical format, so a opening parenthesis may be used to detect
728 : * this encoding, the name may include binary null characters, so
729 : * strlen may return a length shorther than actually used, the real
730 : * length is implictly given by the structure of the S-Exp, an extra
731 : * null is appended for safety reasons.
732 : *
733 : * The caller must free the returned string using ksba_free() or the
734 : * function he has registered as a replacement.
735 : *
736 : * Return value: An allocated string or NULL for error.
737 : **/
738 : char *
739 6 : ksba_cert_get_issuer (ksba_cert_t cert, int idx)
740 : {
741 : gpg_error_t err;
742 : char *name;
743 :
744 6 : err = get_name (cert, idx, 0, &name);
745 6 : if (err)
746 : {
747 3 : cert->last_error = err;
748 3 : return NULL;
749 : }
750 3 : return name;
751 : }
752 :
753 : /* See ..get_issuer */
754 : char *
755 6 : ksba_cert_get_subject (ksba_cert_t cert, int idx)
756 : {
757 : gpg_error_t err;
758 : char *name;
759 :
760 6 : err = get_name (cert, idx, 1, &name);
761 6 : if (err)
762 : {
763 3 : cert->last_error = err;
764 3 : return NULL;
765 : }
766 3 : return name;
767 : }
768 :
769 :
770 :
771 : /**
772 : * ksba_cert_get_valididy:
773 : * @cert: certificate object
774 : * @what: 0 for notBefore, 1 for notAfter
775 : * @timebuf: Returns the time.
776 : *
777 : * Return the validity object from the certificate. If no value is
778 : * available 0 is returned because we can safely assume that this is
779 : * not a valid date.
780 : *
781 : * Return value: The time value an 0 or an error code.
782 : **/
783 : gpg_error_t
784 6 : ksba_cert_get_validity (ksba_cert_t cert, int what, ksba_isotime_t timebuf)
785 : {
786 : AsnNode n, n2;
787 :
788 6 : if (!cert || what < 0 || what > 1)
789 0 : return gpg_error (GPG_ERR_INV_VALUE);
790 6 : *timebuf = 0;
791 6 : if (!cert->initialized)
792 0 : return gpg_error (GPG_ERR_NO_DATA);
793 :
794 6 : n = _ksba_asn_find_node (cert->root,
795 : what == 0? "Certificate.tbsCertificate.validity.notBefore"
796 : : "Certificate.tbsCertificate.validity.notAfter");
797 6 : if (!n)
798 0 : return 0; /* no value available */
799 :
800 : /* Fixme: We should remove the choice node and don't use this ugly hack */
801 6 : for (n2=n->down; n2; n2 = n2->right)
802 : {
803 6 : if ((n2->type == TYPE_UTC_TIME || n2->type == TYPE_GENERALIZED_TIME)
804 6 : && n2->off != -1)
805 6 : break;
806 : }
807 6 : n = n2;
808 6 : if (!n)
809 0 : return 0; /* no value available */
810 :
811 6 : return_val_if_fail (n->off != -1, gpg_error (GPG_ERR_BUG));
812 :
813 6 : return _ksba_asntime_to_iso (cert->image + n->off + n->nhdr, n->len,
814 6 : n->type == TYPE_UTC_TIME, timebuf);
815 : }
816 :
817 :
818 :
819 : ksba_sexp_t
820 3 : ksba_cert_get_public_key (ksba_cert_t cert)
821 : {
822 : AsnNode n;
823 : gpg_error_t err;
824 : ksba_sexp_t string;
825 :
826 3 : if (!cert)
827 0 : return NULL;
828 3 : if (!cert->initialized)
829 0 : return NULL;
830 :
831 3 : n = _ksba_asn_find_node (cert->root,
832 : "Certificate"
833 : ".tbsCertificate.subjectPublicKeyInfo");
834 3 : if (!n)
835 : {
836 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
837 0 : return NULL;
838 : }
839 :
840 3 : err = _ksba_keyinfo_to_sexp (cert->image + n->off, n->nhdr + n->len,
841 : &string);
842 3 : if (err)
843 : {
844 0 : cert->last_error = err;
845 0 : return NULL;
846 : }
847 :
848 3 : return string;
849 : }
850 :
851 : /* Return a pointer to the DER encoding of the actual public key
852 : (i.e. the bit string) in PTR and the length of that object in
853 : LENGTH. */
854 : gpg_error_t
855 0 : _ksba_cert_get_public_key_ptr (ksba_cert_t cert,
856 : unsigned char const **ptr, size_t *length)
857 : {
858 : asn_node_t n;
859 :
860 0 : if (!cert || !cert->initialized || !ptr || !length)
861 0 : return gpg_error (GPG_ERR_INV_VALUE);
862 :
863 0 : n = _ksba_asn_find_node (cert->root,
864 : "Certificate.tbsCertificate.subjectPublicKeyInfo");
865 0 : if (!n || !n->down || !n->down->right)
866 0 : return gpg_error (GPG_ERR_NO_VALUE); /* oops - should be there */
867 0 : n = n->down->right;
868 0 : if (n->off == -1)
869 0 : return gpg_error (GPG_ERR_NO_VALUE);
870 0 : *ptr = cert->image + n->off + n->nhdr;
871 0 : *length = n->len;
872 : /* Somehow we end up at the preceding NULL value, and not at a
873 : sequence, we hack it way here. */
874 0 : if (*length && !**ptr)
875 : {
876 0 : (*length)--;
877 0 : (*ptr)++;
878 : }
879 :
880 0 : return 0;
881 : }
882 :
883 :
884 :
885 : ksba_sexp_t
886 0 : ksba_cert_get_sig_val (ksba_cert_t cert)
887 : {
888 : AsnNode n, n2;
889 : gpg_error_t err;
890 : ksba_sexp_t string;
891 :
892 0 : if (!cert)
893 0 : return NULL;
894 0 : if (!cert->initialized)
895 0 : return NULL;
896 :
897 0 : n = _ksba_asn_find_node (cert->root,
898 : "Certificate.signatureAlgorithm");
899 0 : if (!n)
900 : {
901 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
902 0 : return NULL;
903 : }
904 0 : if (n->off == -1)
905 : {
906 : /* fputs ("ksba_cert_get_sig_val problem at node:\n", stderr); */
907 : /* _ksba_asn_node_dump_all (n, stderr); */
908 0 : cert->last_error = gpg_error (GPG_ERR_NO_VALUE);
909 0 : return NULL;
910 : }
911 :
912 0 : n2 = n->right;
913 0 : err = _ksba_sigval_to_sexp (cert->image + n->off,
914 0 : n->nhdr + n->len
915 0 : + ((!n2||n2->off == -1)? 0:(n2->nhdr+n2->len)),
916 : &string);
917 0 : if (err)
918 : {
919 0 : cert->last_error = err;
920 0 : return NULL;
921 : }
922 :
923 0 : return string;
924 : }
925 :
926 :
927 : /* Read all extensions into the cache */
928 : static gpg_error_t
929 3 : read_extensions (ksba_cert_t cert)
930 : {
931 : AsnNode start, n;
932 : int count;
933 :
934 3 : assert (!cert->cache.extns_valid);
935 3 : assert (!cert->cache.extns);
936 :
937 3 : start = _ksba_asn_find_node (cert->root,
938 : "Certificate.tbsCertificate.extensions..");
939 23 : for (count=0, n=start; n; n = n->right)
940 20 : count++;
941 3 : if (!count)
942 : {
943 0 : cert->cache.n_extns = 0;
944 0 : cert->cache.extns_valid = 1;
945 0 : return 0; /* no extensions at all */
946 : }
947 3 : cert->cache.extns = xtrycalloc (count, sizeof *cert->cache.extns);
948 3 : if (!cert->cache.extns)
949 0 : return gpg_error (GPG_ERR_ENOMEM);
950 3 : cert->cache.n_extns = count;
951 :
952 : {
953 23 : for (count=0; start; start = start->right, count++)
954 : {
955 20 : n = start->down;
956 20 : if (!n || n->type != TYPE_OBJECT_ID)
957 : goto no_value;
958 :
959 20 : cert->cache.extns[count].oid = _ksba_oid_node_to_str (cert->image, n);
960 20 : if (!cert->cache.extns[count].oid)
961 0 : goto no_value;
962 :
963 20 : n = n->right;
964 20 : if (n && n->type == TYPE_BOOLEAN)
965 : {
966 20 : if (n->off != -1 && n->len && cert->image[n->off + n->nhdr])
967 2 : cert->cache.extns[count].crit = 1;
968 20 : n = n->right;
969 : }
970 :
971 20 : if (!n || n->type != TYPE_OCTET_STRING || n->off == -1)
972 : goto no_value;
973 :
974 20 : cert->cache.extns[count].off = n->off + n->nhdr;
975 20 : cert->cache.extns[count].len = n->len;
976 : }
977 :
978 3 : assert (count == cert->cache.n_extns);
979 3 : cert->cache.extns_valid = 1;
980 3 : return 0;
981 :
982 : no_value:
983 0 : for (count=0; count < cert->cache.n_extns; count++)
984 0 : xfree (cert->cache.extns[count].oid);
985 0 : xfree (cert->cache.extns);
986 0 : cert->cache.extns = NULL;
987 0 : return gpg_error (GPG_ERR_NO_VALUE);
988 : }
989 : }
990 :
991 :
992 : /* Return information about the IDX nth extension */
993 : gpg_error_t
994 284 : ksba_cert_get_extension (ksba_cert_t cert, int idx,
995 : char const **r_oid, int *r_crit,
996 : size_t *r_deroff, size_t *r_derlen)
997 : {
998 : gpg_error_t err;
999 :
1000 284 : if (!cert)
1001 0 : return gpg_error (GPG_ERR_INV_VALUE);
1002 284 : if (!cert->initialized)
1003 0 : return gpg_error (GPG_ERR_NO_DATA);
1004 :
1005 284 : if (!cert->cache.extns_valid)
1006 : {
1007 3 : err = read_extensions (cert);
1008 3 : if (err)
1009 0 : return err;
1010 3 : assert (cert->cache.extns_valid);
1011 : }
1012 :
1013 284 : if (idx == cert->cache.n_extns)
1014 36 : return gpg_error (GPG_ERR_EOF); /* No more extensions. */
1015 :
1016 248 : if (idx < 0 || idx >= cert->cache.n_extns)
1017 0 : return gpg_error (GPG_ERR_INV_INDEX);
1018 :
1019 248 : if (r_oid)
1020 248 : *r_oid = cert->cache.extns[idx].oid;
1021 248 : if (r_crit)
1022 183 : *r_crit = cert->cache.extns[idx].crit;
1023 248 : if (r_deroff)
1024 223 : *r_deroff = cert->cache.extns[idx].off;
1025 248 : if (r_derlen)
1026 223 : *r_derlen = cert->cache.extns[idx].len;
1027 248 : return 0;
1028 : }
1029 :
1030 :
1031 :
1032 : /* Return information on the basicConstraint (2.5.19.19) of CERT.
1033 : R_CA receives true if this is a CA and only in that case R_PATHLEN
1034 : is set to the maximim certification path length or -1 if there is
1035 : nosuch limitation */
1036 : gpg_error_t
1037 3 : ksba_cert_is_ca (ksba_cert_t cert, int *r_ca, int *r_pathlen)
1038 : {
1039 : gpg_error_t err;
1040 : const char *oid;
1041 : int idx, crit;
1042 : size_t off, derlen, seqlen;
1043 : const unsigned char *der;
1044 : struct tag_info ti;
1045 : unsigned long value;
1046 :
1047 : /* set default values */
1048 3 : if (r_ca)
1049 3 : *r_ca = 0;
1050 3 : if (r_pathlen)
1051 3 : *r_pathlen = -1;
1052 14 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1053 8 : &off, &derlen)); idx++)
1054 : {
1055 11 : if (!strcmp (oid, oidstr_basicConstraints))
1056 3 : break;
1057 : }
1058 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1059 0 : return 0; /* no such constraint */
1060 3 : if (err)
1061 0 : return err;
1062 :
1063 : /* check that there is only one */
1064 15 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1065 9 : NULL, NULL)); idx++)
1066 : {
1067 9 : if (!strcmp (oid, oidstr_basicConstraints))
1068 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1069 : }
1070 :
1071 3 : der = cert->image + off;
1072 :
1073 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1074 3 : if (err)
1075 0 : return err;
1076 6 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1077 3 : && ti.is_constructed) )
1078 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1079 3 : if (ti.ndef)
1080 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1081 3 : seqlen = ti.length;
1082 3 : if (seqlen > derlen)
1083 0 : return gpg_error (GPG_ERR_BAD_BER);
1084 3 : if (!seqlen)
1085 0 : return 0; /* an empty sequence is allowed because both elements
1086 : are optional */
1087 :
1088 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1089 3 : if (err)
1090 0 : return err;
1091 3 : if (seqlen < ti.nhdr)
1092 0 : return gpg_error (GPG_ERR_BAD_BER);
1093 3 : seqlen -= ti.nhdr;
1094 3 : if (seqlen < ti.length)
1095 0 : return gpg_error (GPG_ERR_BAD_BER);
1096 3 : seqlen -= ti.length;
1097 :
1098 3 : if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BOOLEAN)
1099 : {
1100 3 : if (ti.length != 1)
1101 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1102 3 : if (r_ca)
1103 3 : *r_ca = !!*der;
1104 3 : der++; derlen--;
1105 3 : if (!seqlen)
1106 3 : return 0; /* ready (no pathlength) */
1107 :
1108 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1109 0 : if (err)
1110 0 : return err;
1111 0 : if (seqlen < ti.nhdr)
1112 0 : return gpg_error (GPG_ERR_BAD_BER);
1113 0 : seqlen -= ti.nhdr;
1114 0 : if (seqlen < ti.length)
1115 0 : return gpg_error (GPG_ERR_BAD_BER);
1116 0 : seqlen -= ti.length;
1117 : }
1118 :
1119 0 : if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_INTEGER))
1120 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1121 :
1122 0 : for (value=0; ti.length; ti.length--)
1123 : {
1124 0 : value <<= 8;
1125 0 : value |= (*der++) & 0xff;
1126 0 : derlen--;
1127 : }
1128 0 : if (r_pathlen)
1129 0 : *r_pathlen = value;
1130 :
1131 : /* if the extension is marked as critical and any stuff is still
1132 : left we better return an error */
1133 0 : if (crit && seqlen)
1134 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1135 :
1136 0 : return 0;
1137 : }
1138 :
1139 :
1140 :
1141 : /* Get the key usage flags. The function returns Ksba_No_Data if no
1142 : key usage is specified. */
1143 : gpg_error_t
1144 3 : ksba_cert_get_key_usage (ksba_cert_t cert, unsigned int *r_flags)
1145 : {
1146 : gpg_error_t err;
1147 : const char *oid;
1148 : int idx, crit;
1149 : size_t off, derlen;
1150 : const unsigned char *der;
1151 : struct tag_info ti;
1152 : unsigned int bits, mask;
1153 : int i, unused, full;
1154 :
1155 3 : if (!r_flags)
1156 0 : return gpg_error (GPG_ERR_INV_VALUE);
1157 3 : *r_flags = 0;
1158 17 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1159 11 : &off, &derlen)); idx++)
1160 : {
1161 13 : if (!strcmp (oid, oidstr_keyUsage))
1162 2 : break;
1163 : }
1164 3 : if (gpg_err_code (err) == GPG_ERR_EOF
1165 2 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1166 1 : return gpg_error (GPG_ERR_NO_DATA); /* no key usage */
1167 2 : if (err)
1168 0 : return err;
1169 :
1170 : /* check that there is only one */
1171 11 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1172 7 : NULL, NULL)); idx++)
1173 : {
1174 7 : if (!strcmp (oid, oidstr_keyUsage))
1175 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1176 : }
1177 :
1178 2 : der = cert->image + off;
1179 :
1180 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1181 2 : if (err)
1182 0 : return err;
1183 4 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BIT_STRING
1184 2 : && !ti.is_constructed) )
1185 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1186 2 : if (ti.ndef)
1187 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1188 2 : if (!ti.length || ti.length > derlen)
1189 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM); /* number of unused bits missing */
1190 2 : unused = *der++; derlen--;
1191 2 : ti.length--;
1192 2 : if ((!ti.length && unused) || unused/8 > ti.length)
1193 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1194 :
1195 2 : full = ti.length - (unused+7)/8;
1196 2 : unused %= 8;
1197 2 : mask = 0;
1198 3 : for (i=1; unused; i <<= 1, unused--)
1199 1 : mask |= i;
1200 :
1201 : /* the first octet */
1202 2 : if (!ti.length)
1203 0 : return 0; /* no bits set */
1204 2 : bits = *der++; derlen--; ti.length--;
1205 2 : if (full)
1206 1 : full--;
1207 : else {
1208 1 : bits &= ~mask;
1209 1 : mask = 0;
1210 : }
1211 2 : if (bits & 0x80)
1212 0 : *r_flags |= KSBA_KEYUSAGE_DIGITAL_SIGNATURE;
1213 2 : if (bits & 0x40)
1214 0 : *r_flags |= KSBA_KEYUSAGE_NON_REPUDIATION;
1215 2 : if (bits & 0x20)
1216 0 : *r_flags |= KSBA_KEYUSAGE_KEY_ENCIPHERMENT;
1217 2 : if (bits & 0x10)
1218 0 : *r_flags |= KSBA_KEYUSAGE_DATA_ENCIPHERMENT;
1219 2 : if (bits & 0x08)
1220 0 : *r_flags |= KSBA_KEYUSAGE_KEY_AGREEMENT;
1221 2 : if (bits & 0x04)
1222 2 : *r_flags |= KSBA_KEYUSAGE_KEY_CERT_SIGN;
1223 2 : if (bits & 0x02)
1224 2 : *r_flags |= KSBA_KEYUSAGE_CRL_SIGN;
1225 2 : if (bits & 0x01)
1226 0 : *r_flags |= KSBA_KEYUSAGE_ENCIPHER_ONLY;
1227 :
1228 : /* the second octet */
1229 2 : if (!ti.length)
1230 2 : return 0; /* no bits set */
1231 0 : bits = *der++; derlen--; ti.length--;
1232 0 : if (full)
1233 0 : full--;
1234 : else {
1235 0 : bits &= mask;
1236 0 : mask = ~0;
1237 : }
1238 0 : if (bits & 0x80)
1239 0 : *r_flags |= KSBA_KEYUSAGE_DECIPHER_ONLY;
1240 :
1241 0 : return 0;
1242 : }
1243 :
1244 :
1245 :
1246 : /* Note, that this helper is also used for ext_key_usage. */
1247 : static gpg_error_t
1248 0 : append_cert_policy (char **policies, const char *oid, int crit)
1249 : {
1250 : char *p;
1251 :
1252 0 : if (!*policies)
1253 : {
1254 0 : *policies = xtrymalloc (strlen (oid) + 4);
1255 0 : if (!*policies)
1256 0 : return gpg_error (GPG_ERR_ENOMEM);
1257 0 : p = *policies;
1258 : }
1259 : else
1260 : {
1261 0 : char *tmp = xtryrealloc (*policies,
1262 : strlen(*policies) + 1 + strlen (oid) + 4);
1263 0 : if (!tmp)
1264 0 : return gpg_error (GPG_ERR_ENOMEM);
1265 0 : *policies = tmp;
1266 0 : p = stpcpy (tmp+strlen (tmp), "\n");;
1267 : }
1268 :
1269 0 : strcpy (stpcpy (p, oid), crit? ":C:": ":N:");
1270 0 : return 0;
1271 : }
1272 :
1273 :
1274 : /* Return a string with the certificatePolicies delimited by
1275 : linefeeds. The return values may be extended to carry more
1276 : information er line, so the caller should only use the first
1277 : white-space delimited token per line. The function returns
1278 : GPG_ERR_NO_DATA when this extension is not used. Caller must free
1279 : the returned value. */
1280 : gpg_error_t
1281 3 : ksba_cert_get_cert_policies (ksba_cert_t cert, char **r_policies)
1282 : {
1283 : gpg_error_t err;
1284 : const char *oid;
1285 : int idx, crit;
1286 : size_t off, derlen, seqlen;
1287 : const unsigned char *der;
1288 : struct tag_info ti;
1289 :
1290 3 : if (!cert || !r_policies)
1291 0 : return gpg_error (GPG_ERR_INV_VALUE);
1292 3 : *r_policies = NULL;
1293 :
1294 26 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1295 20 : &off, &derlen)); idx++)
1296 : {
1297 20 : if (!strcmp (oid, oidstr_certificatePolicies))
1298 : {
1299 : char *suboid;
1300 :
1301 0 : der = cert->image + off;
1302 :
1303 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1304 0 : if (err)
1305 0 : goto leave;
1306 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1307 0 : && ti.is_constructed) )
1308 : {
1309 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1310 0 : goto leave;
1311 : }
1312 0 : if (ti.ndef)
1313 : {
1314 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1315 0 : goto leave;
1316 : }
1317 0 : seqlen = ti.length;
1318 0 : if (seqlen > derlen)
1319 : {
1320 0 : err = gpg_error (GPG_ERR_BAD_BER);
1321 0 : goto leave;
1322 : }
1323 0 : while (seqlen)
1324 : {
1325 : size_t seqseqlen;
1326 :
1327 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1328 0 : if (err)
1329 0 : goto leave;
1330 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1331 0 : && ti.is_constructed) )
1332 : {
1333 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1334 0 : goto leave;
1335 : }
1336 0 : if (ti.ndef)
1337 : {
1338 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1339 0 : goto leave;
1340 : }
1341 0 : if (ti.length > derlen)
1342 : {
1343 0 : err = gpg_error (GPG_ERR_BAD_BER);
1344 0 : goto leave;
1345 : }
1346 0 : if (!ti.length)
1347 : {
1348 : /* We do not accept an empty inner SEQ */
1349 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1350 0 : goto leave;
1351 : }
1352 0 : if (ti.nhdr+ti.length > seqlen)
1353 : {
1354 0 : err = gpg_error (GPG_ERR_BAD_BER);
1355 0 : goto leave;
1356 : }
1357 0 : seqlen -= ti.nhdr + ti.length;
1358 0 : seqseqlen = ti.length;
1359 :
1360 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1361 0 : if (err)
1362 0 : goto leave;
1363 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID))
1364 : {
1365 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1366 0 : goto leave;
1367 : }
1368 0 : if (ti.length > derlen)
1369 : {
1370 0 : err = gpg_error (GPG_ERR_BAD_BER);
1371 0 : goto leave;
1372 : }
1373 0 : if (ti.nhdr+ti.length > seqseqlen)
1374 : {
1375 0 : err = gpg_error (GPG_ERR_BAD_BER);
1376 0 : goto leave;
1377 : }
1378 0 : seqseqlen -= ti.nhdr;
1379 :
1380 0 : suboid = ksba_oid_to_str (der, ti.length);
1381 0 : if (!suboid)
1382 : {
1383 0 : err = gpg_error (GPG_ERR_ENOMEM);
1384 0 : goto leave;
1385 : }
1386 0 : der += ti.length;
1387 0 : derlen -= ti.length;
1388 0 : seqseqlen -= ti.length;
1389 :
1390 0 : err = append_cert_policy (r_policies, suboid, crit);
1391 0 : xfree (suboid);
1392 0 : if (err)
1393 0 : goto leave;
1394 :
1395 : /* skip the rest of the seq which is more or less optional */
1396 0 : der += seqseqlen;
1397 0 : derlen -= seqseqlen;
1398 : }
1399 : }
1400 : }
1401 :
1402 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1403 3 : err = 0;
1404 3 : if (!*r_policies || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1405 3 : err = gpg_error (GPG_ERR_NO_DATA);
1406 :
1407 : leave:
1408 3 : if (err)
1409 : {
1410 3 : xfree (*r_policies);
1411 3 : *r_policies = NULL;
1412 : }
1413 3 : return err;
1414 : }
1415 :
1416 :
1417 : /* Return a string with the extendedKeyUsageOIDs delimited by
1418 : linefeeds. The return values may be extended to carry more
1419 : information per line, so the caller should only use the first
1420 : white-space delimited token per line. The function returns
1421 : GPG_ERR_NO_DATA when this extension is not used. Caller must free
1422 : the returned value. */
1423 : gpg_error_t
1424 3 : ksba_cert_get_ext_key_usages (ksba_cert_t cert, char **result)
1425 : {
1426 : gpg_error_t err;
1427 : const char *oid;
1428 : int idx, crit;
1429 : size_t off, derlen;
1430 : const unsigned char *der;
1431 : struct tag_info ti;
1432 :
1433 3 : if (!cert || !result)
1434 0 : return gpg_error (GPG_ERR_INV_VALUE);
1435 3 : *result = NULL;
1436 :
1437 26 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1438 20 : &off, &derlen)); idx++)
1439 : {
1440 20 : if (!strcmp (oid, oidstr_extKeyUsage))
1441 : {
1442 : char *suboid;
1443 :
1444 0 : der = cert->image + off;
1445 :
1446 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1447 0 : if (err)
1448 0 : goto leave;
1449 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1450 0 : && ti.is_constructed) )
1451 : {
1452 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1453 0 : goto leave;
1454 : }
1455 0 : if (ti.ndef)
1456 : {
1457 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1458 0 : goto leave;
1459 : }
1460 0 : if (ti.length > derlen)
1461 : {
1462 0 : err = gpg_error (GPG_ERR_BAD_BER);
1463 0 : goto leave;
1464 : }
1465 0 : while (derlen)
1466 : {
1467 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1468 0 : if (err)
1469 0 : goto leave;
1470 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID))
1471 : {
1472 0 : err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1473 0 : goto leave;
1474 : }
1475 0 : if (ti.ndef)
1476 : {
1477 0 : err = gpg_error (GPG_ERR_NOT_DER_ENCODED);
1478 0 : goto leave;
1479 : }
1480 0 : if (ti.length > derlen)
1481 : {
1482 0 : err = gpg_error (GPG_ERR_BAD_BER);
1483 0 : goto leave;
1484 : }
1485 :
1486 0 : suboid = ksba_oid_to_str (der, ti.length);
1487 0 : if (!suboid)
1488 : {
1489 0 : err = gpg_error (GPG_ERR_ENOMEM);
1490 0 : goto leave;
1491 : }
1492 0 : der += ti.length;
1493 0 : derlen -= ti.length;
1494 :
1495 0 : err = append_cert_policy (result, suboid, crit);
1496 0 : xfree (suboid);
1497 0 : if (err)
1498 0 : goto leave;
1499 : }
1500 : }
1501 : }
1502 :
1503 3 : if (gpg_err_code (err) == GPG_ERR_EOF)
1504 3 : err = 0;
1505 3 : if (!*result || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1506 3 : err = gpg_error (GPG_ERR_NO_DATA);
1507 :
1508 : leave:
1509 3 : if (err)
1510 : {
1511 3 : xfree (*result);
1512 3 : *result = NULL;
1513 : }
1514 3 : return err;
1515 : }
1516 :
1517 :
1518 :
1519 :
1520 : /* Helper function for ksba_cert_get_crl_dist_point */
1521 : static gpg_error_t
1522 2 : parse_distribution_point (const unsigned char *der, size_t derlen,
1523 : ksba_name_t *distpoint, ksba_name_t *issuer,
1524 : ksba_crl_reason_t *reason)
1525 : {
1526 : gpg_error_t err;
1527 : struct tag_info ti;
1528 :
1529 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1530 2 : if (err)
1531 0 : return err;
1532 2 : if (ti.class != CLASS_CONTEXT)
1533 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1534 2 : if (ti.ndef)
1535 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1536 2 : if (derlen < ti.length)
1537 0 : return gpg_error (GPG_ERR_BAD_BER);
1538 :
1539 2 : if (ti.tag == 0 && derlen)
1540 : { /* distributionPointName */
1541 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1542 2 : if (err)
1543 0 : return err;
1544 2 : if (ti.class != CLASS_CONTEXT)
1545 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1546 2 : if (ti.ndef)
1547 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1548 2 : if (derlen < ti.nhdr)
1549 0 : return gpg_error (GPG_ERR_BAD_BER);
1550 2 : if (derlen < ti.length)
1551 0 : return gpg_error (GPG_ERR_BAD_BER);
1552 :
1553 2 : if (ti.tag == 0)
1554 : {
1555 2 : if (distpoint)
1556 : {
1557 2 : err = _ksba_name_new_from_der (distpoint, der, ti.length);
1558 2 : if (err)
1559 0 : return err;
1560 : }
1561 : }
1562 : else
1563 : {
1564 : /* We don't support nameRelativeToCRLIssuer yet*/
1565 : }
1566 2 : der += ti.length;
1567 2 : derlen -= ti.length;
1568 :
1569 2 : if (!derlen)
1570 2 : return 0;
1571 :
1572 : /* read the next optional element */
1573 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1574 0 : if (err)
1575 0 : return err;
1576 0 : if (ti.class != CLASS_CONTEXT)
1577 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1578 0 : if (ti.ndef)
1579 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1580 0 : if (derlen < ti.length)
1581 0 : return gpg_error (GPG_ERR_BAD_BER);
1582 : }
1583 :
1584 0 : if (ti.tag == 1 && derlen)
1585 : { /* reasonFlags */
1586 : unsigned int bits, mask;
1587 : int i, unused, full;
1588 :
1589 0 : if (!ti.length || ti.length > derlen)
1590 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1591 0 : unused = *der++; derlen--;
1592 0 : ti.length--;
1593 0 : if ((!ti.length && unused) || unused/8 > ti.length)
1594 0 : return gpg_error (GPG_ERR_ENCODING_PROBLEM);
1595 :
1596 0 : full = ti.length - (unused+7)/8;
1597 0 : unused %= 8;
1598 0 : mask = 0;
1599 0 : for (i=1; unused; i <<= 1, unused--)
1600 0 : mask |= i;
1601 :
1602 : /* we are only required to look at the first octect */
1603 0 : if (ti.length && reason)
1604 : {
1605 0 : bits = *der;
1606 0 : if (full)
1607 0 : full--;
1608 : else {
1609 0 : bits &= ~mask;
1610 0 : mask = 0;
1611 : }
1612 :
1613 0 : if (bits & 0x80)
1614 0 : *reason |= KSBA_CRLREASON_UNSPECIFIED;
1615 0 : if (bits & 0x40)
1616 0 : *reason |= KSBA_CRLREASON_KEY_COMPROMISE;
1617 0 : if (bits & 0x20)
1618 0 : *reason |= KSBA_CRLREASON_CA_COMPROMISE;
1619 0 : if (bits & 0x10)
1620 0 : *reason |= KSBA_CRLREASON_AFFILIATION_CHANGED;
1621 0 : if (bits & 0x08)
1622 0 : *reason |= KSBA_CRLREASON_SUPERSEDED;
1623 0 : if (bits & 0x04)
1624 0 : *reason |= KSBA_CRLREASON_CESSATION_OF_OPERATION;
1625 0 : if (bits & 0x02)
1626 0 : *reason |= KSBA_CRLREASON_CERTIFICATE_HOLD;
1627 : }
1628 :
1629 0 : der += ti.length;
1630 0 : derlen -= ti.length;
1631 :
1632 0 : if (!derlen)
1633 0 : return 0;
1634 :
1635 : /* read the next optional element */
1636 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1637 0 : if (err)
1638 0 : return err;
1639 0 : if (ti.class != CLASS_CONTEXT)
1640 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1641 0 : if (ti.ndef)
1642 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1643 0 : if (derlen < ti.length)
1644 0 : return gpg_error (GPG_ERR_BAD_BER);
1645 : }
1646 :
1647 0 : if (ti.tag == 2 && derlen)
1648 : { /* crlIssuer */
1649 0 : if (issuer)
1650 : {
1651 0 : err = _ksba_name_new_from_der (issuer, der, ti.length);
1652 0 : if (err)
1653 0 : return err;
1654 : }
1655 :
1656 0 : der += ti.length;
1657 0 : derlen -= ti.length;
1658 : }
1659 :
1660 0 : if (derlen)
1661 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1662 :
1663 0 : return 0;
1664 : }
1665 :
1666 : /* Return the CRLDistPoints given in the cert extension. IDX should
1667 : be iterated started from 0 until the function returns -1.
1668 : R_DISTPOINT returns a ksba_name_t object with the distribution point
1669 : name(s) the return value may be NULL to indicate that this name is
1670 : not available. R_ISSUER returns the CRL issuer; if the returned
1671 : value is NULL the caller should assume that the CRL issuer is the
1672 : same as the certificate issuer. R_REASON returns the reason for
1673 : the CRL. This is a bit encoded value with no bit set if this has
1674 : not been specified in the cert.
1675 :
1676 : The caller may pass NULL to any of the pointer arguments if he is
1677 : not interested in this value. The return values for R_DISTPOINT
1678 : and R_ISSUER must be released by the caller using
1679 : ksba_name_release(). */
1680 :
1681 : gpg_error_t
1682 5 : ksba_cert_get_crl_dist_point (ksba_cert_t cert, int idx,
1683 : ksba_name_t *r_distpoint,
1684 : ksba_name_t *r_issuer,
1685 : ksba_crl_reason_t *r_reason)
1686 : {
1687 : gpg_error_t err;
1688 : const char *oid;
1689 : size_t off, derlen;
1690 : int myidx, crit;
1691 :
1692 5 : if (r_distpoint)
1693 5 : *r_distpoint = NULL;
1694 5 : if (r_issuer)
1695 5 : *r_issuer = NULL;
1696 5 : if (r_reason)
1697 5 : *r_reason = 0;
1698 :
1699 36 : for (myidx=0; !(err=ksba_cert_get_extension (cert, myidx, &oid, &crit,
1700 26 : &off, &derlen)); myidx++)
1701 : {
1702 28 : if (!strcmp (oid, oidstr_crlDistributionPoints))
1703 : {
1704 : const unsigned char *der;
1705 : struct tag_info ti;
1706 : size_t seqlen;
1707 :
1708 3 : der = cert->image + off;
1709 :
1710 3 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1711 3 : if (err)
1712 2 : return err;
1713 6 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1714 3 : && ti.is_constructed) )
1715 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1716 3 : if (ti.ndef)
1717 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1718 3 : seqlen = ti.length;
1719 3 : if (seqlen > derlen)
1720 0 : return gpg_error (GPG_ERR_BAD_BER);
1721 :
1722 : /* Note: an empty sequence is actually not allowed but we
1723 : better don't care */
1724 :
1725 9 : while (seqlen)
1726 : {
1727 5 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1728 5 : if (err)
1729 0 : return err;
1730 10 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1731 5 : && ti.is_constructed) )
1732 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1733 5 : if (derlen < ti.length)
1734 0 : return gpg_error (GPG_ERR_BAD_BER);
1735 5 : if (seqlen < ti.nhdr)
1736 0 : return gpg_error (GPG_ERR_BAD_BER);
1737 5 : seqlen -= ti.nhdr;
1738 5 : if (seqlen < ti.length)
1739 0 : return gpg_error (GPG_ERR_BAD_BER);
1740 :
1741 5 : if (idx)
1742 : { /* skip because we are not yet at the desired index */
1743 3 : der += ti.length;
1744 3 : derlen -= ti.length;
1745 3 : seqlen -= ti.length;
1746 3 : idx--;
1747 3 : continue;
1748 : }
1749 :
1750 2 : if (!ti.length)
1751 0 : return 0;
1752 :
1753 2 : err = parse_distribution_point (der, ti.length,
1754 : r_distpoint, r_issuer, r_reason);
1755 2 : if (err && r_distpoint)
1756 : {
1757 0 : ksba_name_release (*r_distpoint);
1758 0 : *r_distpoint = NULL;
1759 : }
1760 2 : if (err && r_issuer)
1761 : {
1762 0 : ksba_name_release (*r_issuer);
1763 0 : *r_issuer = NULL;
1764 : }
1765 2 : if (err && r_reason)
1766 0 : *r_reason = 0;
1767 :
1768 2 : return err;
1769 : }
1770 : }
1771 : }
1772 :
1773 3 : return err;
1774 : }
1775 :
1776 :
1777 : /* Return the authorityKeyIdentifier in R_NAME and R_SERIAL or/and in
1778 : R_KEYID. GPG_ERR_NO_DATA is returned if no authorityKeyIdentifier
1779 : or only one using the keyIdentifier method is available and R_KEYID
1780 : is NULL. */
1781 : gpg_error_t
1782 3 : ksba_cert_get_auth_key_id (ksba_cert_t cert,
1783 : ksba_sexp_t *r_keyid,
1784 : ksba_name_t *r_name,
1785 : ksba_sexp_t *r_serial)
1786 : {
1787 : gpg_error_t err;
1788 : const char *oid;
1789 : size_t off, derlen;
1790 : const unsigned char *der;
1791 3 : const unsigned char *keyid_der = NULL;
1792 3 : size_t keyid_derlen = 0;
1793 : int idx, crit;
1794 : struct tag_info ti;
1795 : char numbuf[30];
1796 : size_t numbuflen;
1797 :
1798 3 : if (r_keyid)
1799 3 : *r_keyid = NULL;
1800 3 : if (!r_name || !r_serial)
1801 0 : return gpg_error (GPG_ERR_INV_VALUE);
1802 3 : *r_name = NULL;
1803 3 : *r_serial = NULL;
1804 :
1805 24 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &oid, &crit,
1806 18 : &off, &derlen)); idx++)
1807 : {
1808 19 : if (!strcmp (oid, oidstr_authorityKeyIdentifier))
1809 1 : break;
1810 : }
1811 3 : if (gpg_err_code (err) == GPG_ERR_EOF
1812 1 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1813 2 : return gpg_error (GPG_ERR_NO_DATA); /* not available */
1814 1 : if (err)
1815 0 : return err;
1816 :
1817 : /* check that there is only one */
1818 3 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &oid, NULL,
1819 1 : NULL, NULL)); idx++)
1820 : {
1821 1 : if (!strcmp (oid, oidstr_authorityKeyIdentifier))
1822 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1823 : }
1824 :
1825 1 : der = cert->image + off;
1826 :
1827 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1828 1 : if (err)
1829 0 : return err;
1830 2 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
1831 1 : && ti.is_constructed) )
1832 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1833 1 : if (ti.ndef)
1834 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1835 1 : if (ti.length > derlen)
1836 0 : return gpg_error (GPG_ERR_BAD_BER);
1837 :
1838 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1839 1 : if (err)
1840 0 : return err;
1841 1 : if (ti.class != CLASS_CONTEXT)
1842 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1843 1 : if (ti.ndef)
1844 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1845 1 : if (derlen < ti.length)
1846 0 : return gpg_error (GPG_ERR_BAD_BER);
1847 :
1848 1 : if (ti.tag == 0)
1849 : { /* keyIdentifier: Save it away and skip over it. */
1850 1 : keyid_der = der;
1851 1 : keyid_derlen = ti.length;
1852 :
1853 1 : der += ti.length;
1854 1 : derlen -= ti.length;
1855 : /* If the keyid has been requested but no other data follows, we
1856 : directly jump to the end. */
1857 1 : if (r_keyid && !derlen)
1858 0 : goto build_keyid;
1859 1 : if (!derlen)
1860 0 : return gpg_error (GPG_ERR_NO_DATA); /* not available */
1861 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1862 1 : if (err)
1863 0 : return err;
1864 1 : if (ti.class != CLASS_CONTEXT)
1865 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1866 1 : if (ti.ndef)
1867 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1868 1 : if (derlen < ti.length)
1869 0 : return gpg_error (GPG_ERR_BAD_BER);
1870 : }
1871 :
1872 1 : if (ti.tag != 1 || !derlen)
1873 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1874 :
1875 1 : err = _ksba_name_new_from_der (r_name, der, ti.length);
1876 1 : if (err)
1877 0 : return err;
1878 :
1879 1 : der += ti.length;
1880 1 : derlen -= ti.length;
1881 :
1882 : /* fixme: we should release r_name before returning on error */
1883 1 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1884 1 : if (err)
1885 0 : return err;
1886 1 : if (ti.class != CLASS_CONTEXT)
1887 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
1888 1 : if (ti.ndef)
1889 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1890 1 : if (derlen < ti.length)
1891 0 : return gpg_error (GPG_ERR_BAD_BER);
1892 :
1893 1 : if (ti.tag != 2 || !derlen)
1894 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1895 :
1896 1 : sprintf (numbuf,"(%u:", (unsigned int)ti.length);
1897 1 : numbuflen = strlen (numbuf);
1898 1 : *r_serial = xtrymalloc (numbuflen + ti.length + 2);
1899 1 : if (!*r_serial)
1900 0 : return gpg_error (GPG_ERR_ENOMEM);
1901 1 : strcpy (*r_serial, numbuf);
1902 1 : memcpy (*r_serial+numbuflen, der, ti.length);
1903 1 : (*r_serial)[numbuflen + ti.length] = ')';
1904 1 : (*r_serial)[numbuflen + ti.length + 1] = 0;
1905 :
1906 : build_keyid:
1907 1 : if (r_keyid && keyid_der && keyid_derlen)
1908 : {
1909 1 : sprintf (numbuf,"(%u:", (unsigned int)keyid_derlen);
1910 1 : numbuflen = strlen (numbuf);
1911 1 : *r_keyid = xtrymalloc (numbuflen + keyid_derlen + 2);
1912 1 : if (!*r_keyid)
1913 0 : return gpg_error (GPG_ERR_ENOMEM);
1914 1 : strcpy (*r_keyid, numbuf);
1915 1 : memcpy (*r_keyid+numbuflen, keyid_der, keyid_derlen);
1916 1 : (*r_keyid)[numbuflen + keyid_derlen] = ')';
1917 1 : (*r_keyid)[numbuflen + keyid_derlen + 1] = 0;
1918 : }
1919 1 : return 0;
1920 : }
1921 :
1922 :
1923 : /* Return a simple octet string extension at the object identifier OID
1924 : from certificate CERT. The data is return as a simple S-expression
1925 : and stored at R_DATA. Returns 0 on success or an error code.
1926 : common error codes are: GPG_ERR_NO_DATA if no such extension is
1927 : available, GPG_ERR_DUP_VALUE if more than one is available. If
1928 : R_CRIT is not NULL, the critical extension flag will be stored at
1929 : that address. */
1930 : static gpg_error_t
1931 3 : get_simple_octet_string_ext (ksba_cert_t cert, const char *oid,
1932 : int *r_crit, ksba_sexp_t *r_data)
1933 : {
1934 : gpg_error_t err;
1935 : const char *tmpoid;
1936 : size_t off, derlen;
1937 : const unsigned char *der;
1938 : int idx, crit;
1939 : struct tag_info ti;
1940 : char numbuf[30];
1941 : size_t numbuflen;
1942 :
1943 3 : if (!r_data)
1944 0 : return gpg_error (GPG_ERR_INV_VALUE);
1945 3 : *r_data = NULL;
1946 :
1947 16 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx, &tmpoid, &crit,
1948 10 : &off, &derlen)); idx++)
1949 : {
1950 12 : if (!strcmp (tmpoid, oid))
1951 2 : break;
1952 : }
1953 3 : if (err)
1954 : {
1955 1 : if (gpg_err_code (err) == GPG_ERR_EOF
1956 0 : || gpg_err_code (err) == GPG_ERR_NO_VALUE)
1957 1 : return gpg_error (GPG_ERR_NO_DATA);
1958 0 : return err;
1959 : }
1960 :
1961 : /* Check that there is only one */
1962 12 : for (idx++; !(err=ksba_cert_get_extension (cert, idx, &tmpoid, NULL,
1963 8 : NULL, NULL)); idx++)
1964 : {
1965 8 : if (!strcmp (tmpoid, oid))
1966 0 : return gpg_error (GPG_ERR_DUP_VALUE);
1967 : }
1968 :
1969 2 : der = cert->image + off;
1970 :
1971 2 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
1972 2 : if (err)
1973 0 : return err;
1974 4 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OCTET_STRING
1975 2 : && !ti.is_constructed) )
1976 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
1977 2 : if (ti.ndef)
1978 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
1979 2 : if (ti.length > derlen)
1980 0 : return gpg_error (GPG_ERR_BAD_BER);
1981 2 : if (ti.length != derlen)
1982 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ); /* Garbage follows. */
1983 :
1984 2 : sprintf (numbuf,"(%u:", (unsigned int)ti.length);
1985 2 : numbuflen = strlen (numbuf);
1986 2 : *r_data = xtrymalloc (numbuflen + ti.length + 2);
1987 2 : if (!*r_data)
1988 0 : return gpg_error (GPG_ERR_ENOMEM);
1989 2 : strcpy (*r_data, numbuf);
1990 2 : memcpy (*r_data+numbuflen, der, ti.length);
1991 2 : (*r_data)[numbuflen + ti.length] = ')';
1992 2 : (*r_data)[numbuflen + ti.length + 1] = 0;
1993 2 : if (r_crit)
1994 0 : *r_crit = crit;
1995 2 : return 0;
1996 : }
1997 :
1998 :
1999 : /* Return the subjectKeyIdentifier extension as a simple allocated
2000 : S-expression at the address of R_KEYID. 0 is returned on success,
2001 : GPG_ERR_NO_DATA if no such extension is available or any other
2002 : error code. If R_CRIT is not passed as NULL, the criticla flag of
2003 : this is extension is stored there. */
2004 : gpg_error_t
2005 3 : ksba_cert_get_subj_key_id (ksba_cert_t cert, int *r_crit, ksba_sexp_t *r_keyid)
2006 : {
2007 3 : return get_simple_octet_string_ext (cert, oidstr_subjectKeyIdentifier,
2008 : r_crit, r_keyid);
2009 : }
2010 :
2011 :
2012 :
2013 : /* MODE 0 := authorityInfoAccess
2014 : 1 := subjectInfoAccess
2015 :
2016 : Caller must release METHOD and LOCATION if the function returned
2017 : with success; on error both variables will point to NULL.
2018 : */
2019 : static gpg_error_t
2020 6 : get_info_access (ksba_cert_t cert, int idx, int mode,
2021 : char **method, ksba_name_t *location)
2022 : {
2023 : gpg_error_t err;
2024 : const char *oid;
2025 : size_t off, derlen;
2026 : int myidx, crit;
2027 :
2028 6 : *method = NULL;
2029 6 : *location = NULL;
2030 :
2031 6 : if (!cert || !cert->initialized)
2032 0 : return gpg_error (GPG_ERR_INV_VALUE);
2033 6 : if (idx < 0)
2034 0 : return gpg_error (GPG_ERR_INV_INDEX);
2035 :
2036 52 : for (myidx=0; !(err=ksba_cert_get_extension (cert, myidx, &oid, &crit,
2037 40 : &off, &derlen)); myidx++)
2038 : {
2039 40 : if (!strcmp (oid,(mode == 0)? oidstr_authorityInfoAccess
2040 : : oidstr_subjectInfoAccess) )
2041 : {
2042 : const unsigned char *der;
2043 : struct tag_info ti;
2044 : size_t seqlen;
2045 :
2046 0 : der = cert->image + off;
2047 :
2048 : /* What we are going to parse is:
2049 : *
2050 : * AuthorityInfoAccessSyntax ::=
2051 : * SEQUENCE SIZE (1..MAX) OF AccessDescription
2052 : *
2053 : * AccessDescription ::= SEQUENCE {
2054 : * accessMethod OBJECT IDENTIFIER,
2055 : * accessLocation GeneralName }
2056 : */
2057 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2058 0 : if (err)
2059 0 : return err;
2060 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
2061 0 : && ti.is_constructed) )
2062 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2063 0 : if (ti.ndef)
2064 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
2065 0 : seqlen = ti.length;
2066 0 : if (seqlen > derlen)
2067 0 : return gpg_error (GPG_ERR_BAD_BER);
2068 :
2069 : /* Note: an empty sequence is actually not allowed but we
2070 : better don't care. */
2071 :
2072 0 : while (seqlen)
2073 : {
2074 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2075 0 : if (err)
2076 0 : return err;
2077 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
2078 0 : && ti.is_constructed) )
2079 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2080 0 : if (derlen < ti.length)
2081 0 : return gpg_error (GPG_ERR_BAD_BER);
2082 0 : if (seqlen < ti.nhdr)
2083 0 : return gpg_error (GPG_ERR_BAD_BER);
2084 0 : seqlen -= ti.nhdr;
2085 0 : if (seqlen < ti.length)
2086 0 : return gpg_error (GPG_ERR_BAD_BER);
2087 :
2088 0 : if (idx)
2089 : { /* Skip because we are not yet at the desired index. */
2090 0 : der += ti.length;
2091 0 : derlen -= ti.length;
2092 0 : seqlen -= ti.length;
2093 0 : idx--;
2094 0 : continue;
2095 : }
2096 : /* We only need the next object, thus we can (and
2097 : actually need to) limit the DERLEN to the length of
2098 : the current sequence. */
2099 0 : derlen = ti.length;
2100 0 : if (!derlen)
2101 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2102 :
2103 0 : err = _ksba_ber_parse_tl (&der, &derlen, &ti);
2104 0 : if (err)
2105 0 : return err;
2106 :
2107 0 : if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
2108 0 : && !ti.is_constructed))
2109 0 : return gpg_error (GPG_ERR_INV_CERT_OBJ);
2110 0 : if (ti.ndef)
2111 0 : return gpg_error (GPG_ERR_NOT_DER_ENCODED);
2112 0 : if (derlen < ti.length)
2113 0 : return gpg_error (GPG_ERR_BAD_BER);
2114 :
2115 0 : *method = ksba_oid_to_str (der, ti.length);
2116 0 : if (!*method)
2117 0 : return gpg_error (GPG_ERR_ENOMEM);
2118 0 : der += ti.length;
2119 0 : derlen -= ti.length;
2120 :
2121 0 : err = _ksba_name_new_from_der (location, der, derlen);
2122 0 : if (err)
2123 : {
2124 0 : ksba_free (*method);
2125 0 : *method = NULL;
2126 0 : return err;
2127 : }
2128 0 : return 0;
2129 : }
2130 : }
2131 : }
2132 :
2133 6 : return err;
2134 : }
2135 :
2136 :
2137 : /* Return the authorityInfoAccess attributes. IDX should be iterated
2138 : starting from 0 until the function returns GPG_ERR_EOF. R_METHOD
2139 : returns an allocated string with the OID of one item and R_LOCATION
2140 : return the GeneralName for that OID. The return values for
2141 : R_METHOD and R_LOCATION must be released by the caller unless the
2142 : function returned an error; the function will however make sure
2143 : that R_METHOD and R_LOCATION will point to NULL if the function
2144 : returns an error. See RFC 2459, section 4.2.2.1 */
2145 : gpg_error_t
2146 3 : ksba_cert_get_authority_info_access (ksba_cert_t cert, int idx,
2147 : char **r_method, ksba_name_t *r_location)
2148 : {
2149 3 : if (!r_method || !r_location)
2150 0 : return gpg_error (GPG_ERR_INV_VALUE);
2151 3 : return get_info_access (cert, idx, 0, r_method, r_location);
2152 : }
2153 :
2154 : /* Return the subjectInfoAccess attributes. IDX should be iterated
2155 : starting from 0 until the function returns GPG_ERR_EOF. R_METHOD
2156 : returns an allocated string with the OID of one item and R_LOCATION
2157 : return the GeneralName for that OID. The return values for
2158 : R_METHOD and R_LOCATION must be released by the caller unless the
2159 : function returned an error; the function will however make sure
2160 : that R_METHOD and R_LOCATION will point to NULL if the function
2161 : returns an error. See RFC 2459, section 4.2.2.2 */
2162 : gpg_error_t
2163 3 : ksba_cert_get_subject_info_access (ksba_cert_t cert, int idx,
2164 : char **r_method, ksba_name_t *r_location)
2165 : {
2166 3 : if (!r_method || !r_location)
2167 0 : return gpg_error (GPG_ERR_INV_VALUE);
2168 3 : return get_info_access (cert, idx, 1, r_method, r_location);
2169 : }
|