LCOV - code coverage report
Current view: top level - src - cert.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 457 1077 42.4 %
Date: 2015-11-05 17:05:02 Functions: 24 36 66.7 %

          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             : }

Generated by: LCOV version 1.11