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

Generated by: LCOV version 1.11