LCOV - code coverage report
Current view: top level - kbx - keybox-search.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 230 593 38.8 %
Date: 2015-11-05 17:10:59 Functions: 13 26 50.0 %

          Line data    Source code
       1             : /* keybox-search.c - Search operations
       2             :  * Copyright (C) 2001, 2002, 2003, 2004, 2012,
       3             :  *               2013 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdlib.h>
      23             : #include <stdio.h>
      24             : #include <string.h>
      25             : #include <assert.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "../common/stringhelp.h" /* ascii_xxxx() */
      29             : 
      30             : #include "keybox-defs.h"
      31             : #include <gcrypt.h>
      32             : #include "host2net.h"
      33             : #include "mbox-util.h"
      34             : 
      35             : #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
      36             :                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
      37             : #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
      38             : 
      39             : 
      40             : struct sn_array_s {
      41             :     int snlen;
      42             :     unsigned char *sn;
      43             : };
      44             : 
      45             : 
      46             : #define get32(a) buf32_to_ulong ((a))
      47             : #define get16(a) buf16_to_ulong ((a))
      48             : 
      49             : 
      50             : static inline unsigned int
      51       81174 : blob_get_blob_flags (KEYBOXBLOB blob)
      52             : {
      53             :   const unsigned char *buffer;
      54             :   size_t length;
      55             : 
      56       81174 :   buffer = _keybox_get_blob_image (blob, &length);
      57       81174 :   if (length < 8)
      58           0 :     return 0; /* oops */
      59             : 
      60       81174 :   return get16 (buffer + 6);
      61             : }
      62             : 
      63             : 
      64             : /* Return the first keyid from the blob.  Returns true if
      65             :    available.  */
      66             : static int
      67         192 : blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
      68             : {
      69             :   const unsigned char *buffer;
      70             :   size_t length, nkeys, keyinfolen;
      71             : 
      72         192 :   buffer = _keybox_get_blob_image (blob, &length);
      73         192 :   if (length < 48)
      74           0 :     return 0; /* blob too short */
      75             : 
      76         192 :   nkeys = get16 (buffer + 16);
      77         192 :   keyinfolen = get16 (buffer + 18);
      78         192 :   if (!nkeys || keyinfolen < 28)
      79           0 :     return 0; /* invalid blob */
      80             : 
      81         192 :   kid[0] = get32 (buffer + 32);
      82         192 :   kid[1] = get32 (buffer + 36);
      83             : 
      84         192 :   return 1;
      85             : }
      86             : 
      87             : 
      88             : /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
      89             :    Return the offset and the length (in bytes) of the flag in
      90             :    FLAGOFF,FLAG_SIZE. */
      91             : gpg_err_code_t
      92        2460 : _keybox_get_flag_location (const unsigned char *buffer, size_t length,
      93             :                            int what, size_t *flag_off, size_t *flag_size)
      94             : {
      95             :   size_t pos;
      96             :   size_t nkeys, keyinfolen;
      97             :   size_t nuids, uidinfolen;
      98             :   size_t nserial;
      99             :   size_t nsigs, siginfolen, siginfooff;
     100             : 
     101        2460 :   switch (what)
     102             :     {
     103             :     case KEYBOX_FLAG_BLOB:
     104           1 :       if (length < 8)
     105           0 :         return GPG_ERR_INV_OBJ;
     106           1 :       *flag_off = 6;
     107           1 :       *flag_size = 2;
     108           1 :       break;
     109             : 
     110             :     case KEYBOX_FLAG_OWNERTRUST:
     111             :     case KEYBOX_FLAG_VALIDITY:
     112             :     case KEYBOX_FLAG_CREATED_AT:
     113             :     case KEYBOX_FLAG_SIG_INFO:
     114        2459 :       if (length < 20)
     115           0 :         return GPG_ERR_INV_OBJ;
     116             :       /* Key info. */
     117        2459 :       nkeys = get16 (buffer + 16);
     118        2459 :       keyinfolen = get16 (buffer + 18 );
     119        2459 :       if (keyinfolen < 28)
     120           0 :         return GPG_ERR_INV_OBJ;
     121        2459 :       pos = 20 + keyinfolen*nkeys;
     122        2459 :       if (pos+2 > length)
     123           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     124             :       /* Serial number. */
     125        2459 :       nserial = get16 (buffer+pos);
     126        2459 :       pos += 2 + nserial;
     127        2459 :       if (pos+4 > length)
     128           0 :         return GPG_ERR_INV_OBJ; /* Out of bounds. */
     129             :       /* User IDs. */
     130        2459 :       nuids = get16 (buffer + pos); pos += 2;
     131        2459 :       uidinfolen = get16 (buffer + pos); pos += 2;
     132        2459 :       if (uidinfolen < 12 )
     133           0 :         return GPG_ERR_INV_OBJ;
     134        2459 :       pos += uidinfolen*nuids;
     135        2459 :       if (pos+4 > length)
     136           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     137             :       /* Signature info. */
     138        2459 :       siginfooff = pos;
     139        2459 :       nsigs = get16 (buffer + pos); pos += 2;
     140        2459 :       siginfolen = get16 (buffer + pos); pos += 2;
     141        2459 :       if (siginfolen < 4 )
     142           0 :         return GPG_ERR_INV_OBJ;
     143        2459 :       pos += siginfolen*nsigs;
     144        2459 :       if (pos+1+1+2+4+4+4+4 > length)
     145           0 :         return GPG_ERR_INV_OBJ ; /* Out of bounds. */
     146        2459 :       *flag_size = 1;
     147        2459 :       *flag_off = pos;
     148        2459 :       switch (what)
     149             :         {
     150             :         case KEYBOX_FLAG_VALIDITY:
     151           0 :           *flag_off += 1;
     152           0 :           break;
     153             :         case KEYBOX_FLAG_CREATED_AT:
     154           0 :           *flag_size = 4;
     155           0 :           *flag_off += 1+2+4+4+4;
     156           0 :           break;
     157             :         case KEYBOX_FLAG_SIG_INFO:
     158        2459 :           *flag_size = siginfolen * nsigs;
     159        2459 :           *flag_off = siginfooff;
     160        2459 :           break;
     161             :         default:
     162           0 :           break;
     163             :         }
     164        2459 :       break;
     165             : 
     166             :     default:
     167           0 :       return GPG_ERR_INV_FLAG;
     168             :     }
     169        2460 :   return 0;
     170             : }
     171             : 
     172             : 
     173             : 
     174             : /* Return one of the flags WHAT in VALUE from the blob BUFFER of
     175             :    LENGTH bytes.  Return 0 on success or an raw error code. */
     176             : static gpg_err_code_t
     177           0 : get_flag_from_image (const unsigned char *buffer, size_t length,
     178             :                      int what, unsigned int *value)
     179             : {
     180             :   gpg_err_code_t ec;
     181             :   size_t pos, size;
     182             : 
     183           0 :   *value = 0;
     184           0 :   ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
     185           0 :   if (!ec)
     186           0 :     switch (size)
     187             :       {
     188           0 :       case 1: *value = buffer[pos]; break;
     189           0 :       case 2: *value = get16 (buffer + pos); break;
     190           0 :       case 4: *value = get32 (buffer + pos); break;
     191           0 :       default: ec = GPG_ERR_BUG; break;
     192             :       }
     193             : 
     194           0 :   return ec;
     195             : }
     196             : 
     197             : 
     198             : static int
     199           0 : blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
     200             : {
     201             :   const unsigned char *buffer;
     202             :   size_t length;
     203             :   size_t pos, off;
     204             :   size_t nkeys, keyinfolen;
     205             :   size_t nserial;
     206             : 
     207           0 :   buffer = _keybox_get_blob_image (blob, &length);
     208           0 :   if (length < 40)
     209           0 :     return 0; /* blob too short */
     210             : 
     211             :   /*keys*/
     212           0 :   nkeys = get16 (buffer + 16);
     213           0 :   keyinfolen = get16 (buffer + 18 );
     214           0 :   if (keyinfolen < 28)
     215           0 :     return 0; /* invalid blob */
     216           0 :   pos = 20 + keyinfolen*nkeys;
     217           0 :   if (pos+2 > length)
     218           0 :     return 0; /* out of bounds */
     219             : 
     220             :   /*serial*/
     221           0 :   nserial = get16 (buffer+pos);
     222           0 :   off = pos + 2;
     223           0 :   if (off+nserial > length)
     224           0 :     return 0; /* out of bounds */
     225             : 
     226           0 :   return nserial == snlen && !memcmp (buffer+off, sn, snlen);
     227             : }
     228             : 
     229             : 
     230             : /* Returns 0 if not found or the number of the key which was found.
     231             :    For X.509 this is always 1, for OpenPGP this is 1 for the primary
     232             :    key and 2 and more for the subkeys.  */
     233             : static int
     234        4743 : blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
     235             : {
     236             :   const unsigned char *buffer;
     237             :   size_t length;
     238             :   size_t pos, off;
     239             :   size_t nkeys, keyinfolen;
     240             :   int idx;
     241             : 
     242        4743 :   buffer = _keybox_get_blob_image (blob, &length);
     243        4743 :   if (length < 40)
     244           0 :     return 0; /* blob too short */
     245             : 
     246             :   /*keys*/
     247        4743 :   nkeys = get16 (buffer + 16);
     248        4743 :   keyinfolen = get16 (buffer + 18 );
     249        4743 :   if (keyinfolen < 28)
     250           0 :     return 0; /* invalid blob */
     251        4743 :   pos = 20;
     252        4743 :   if (pos + keyinfolen*nkeys > length)
     253           0 :     return 0; /* out of bounds */
     254             : 
     255       13410 :   for (idx=0; idx < nkeys; idx++)
     256             :     {
     257        8795 :       off = pos + idx*keyinfolen;
     258        8795 :       if (!memcmp (buffer + off, fpr, 20))
     259         128 :         return idx+1; /* found */
     260             :     }
     261        4615 :   return 0; /* not found */
     262             : }
     263             : 
     264             : static int
     265       72064 : blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
     266             :                    int fproff, int fprlen)
     267             : {
     268             :   const unsigned char *buffer;
     269             :   size_t length;
     270             :   size_t pos, off;
     271             :   size_t nkeys, keyinfolen;
     272             :   int idx;
     273             : 
     274       72064 :   buffer = _keybox_get_blob_image (blob, &length);
     275       72064 :   if (length < 40)
     276           0 :     return 0; /* blob too short */
     277             : 
     278             :   /*keys*/
     279       72064 :   nkeys = get16 (buffer + 16);
     280       72064 :   keyinfolen = get16 (buffer + 18 );
     281       72064 :   if (keyinfolen < 28)
     282           0 :     return 0; /* invalid blob */
     283       72064 :   pos = 20;
     284       72064 :   if (pos + keyinfolen*nkeys > length)
     285           0 :     return 0; /* out of bounds */
     286             : 
     287      203628 :   for (idx=0; idx < nkeys; idx++)
     288             :     {
     289      133679 :       off = pos + idx*keyinfolen;
     290      133679 :       if (!memcmp (buffer + off + fproff, fpr, fprlen))
     291        2115 :         return idx+1; /* found */
     292             :     }
     293       69949 :   return 0; /* not found */
     294             : }
     295             : 
     296             : 
     297             : static int
     298        4346 : blob_cmp_name (KEYBOXBLOB blob, int idx,
     299             :                const char *name, size_t namelen, int substr, int x509)
     300             : {
     301             :   const unsigned char *buffer;
     302             :   size_t length;
     303             :   size_t pos, off, len;
     304             :   size_t nkeys, keyinfolen;
     305             :   size_t nuids, uidinfolen;
     306             :   size_t nserial;
     307             : 
     308        4346 :   buffer = _keybox_get_blob_image (blob, &length);
     309        4346 :   if (length < 40)
     310           0 :     return 0; /* blob too short */
     311             : 
     312             :   /*keys*/
     313        4346 :   nkeys = get16 (buffer + 16);
     314        4346 :   keyinfolen = get16 (buffer + 18 );
     315        4346 :   if (keyinfolen < 28)
     316           0 :     return 0; /* invalid blob */
     317        4346 :   pos = 20 + keyinfolen*nkeys;
     318        4346 :   if (pos+2 > length)
     319           0 :     return 0; /* out of bounds */
     320             : 
     321             :   /*serial*/
     322        4346 :   nserial = get16 (buffer+pos);
     323        4346 :   pos += 2 + nserial;
     324        4346 :   if (pos+4 > length)
     325           0 :     return 0; /* out of bounds */
     326             : 
     327             :   /* user ids*/
     328        4346 :   nuids = get16 (buffer + pos);  pos += 2;
     329        4346 :   uidinfolen = get16 (buffer + pos);  pos += 2;
     330        4346 :   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
     331           0 :     return 0; /* invalid blob */
     332        4346 :   if (pos + uidinfolen*nuids > length)
     333           0 :     return 0; /* out of bounds */
     334             : 
     335        4346 :   if (idx < 0)
     336             :     { /* Compare all names.  Note that for X.509 we start with index 1
     337             :          so to skip the issuer at index 0.  */
     338        9422 :       for (idx = !!x509; idx < nuids; idx++)
     339             :         {
     340        5222 :           size_t mypos = pos;
     341             : 
     342        5222 :           mypos += idx*uidinfolen;
     343        5222 :           off = get32 (buffer+mypos);
     344        5222 :           len = get32 (buffer+mypos+4);
     345        5222 :           if (off+len > length)
     346           0 :             return 0; /* error: better stop here out of bounds */
     347        5222 :           if (len < 1)
     348           0 :             continue; /* empty name */
     349        5222 :           if (substr)
     350             :             {
     351        5222 :               if (ascii_memcasemem (buffer+off, len, name, namelen))
     352         146 :                 return idx+1; /* found */
     353             :             }
     354             :           else
     355             :             {
     356           0 :               if (len == namelen && !memcmp (buffer+off, name, len))
     357           0 :                 return idx+1; /* found */
     358             :             }
     359             :         }
     360             :     }
     361             :   else
     362             :     {
     363           0 :       if (idx > nuids)
     364           0 :         return 0; /* no user ID with that idx */
     365           0 :       pos += idx*uidinfolen;
     366           0 :       off = get32 (buffer+pos);
     367           0 :       len = get32 (buffer+pos+4);
     368           0 :       if (off+len > length)
     369           0 :         return 0; /* out of bounds */
     370           0 :       if (len < 1)
     371           0 :         return 0; /* empty name */
     372             : 
     373           0 :       if (substr)
     374             :         {
     375           0 :           if (ascii_memcasemem (buffer+off, len, name, namelen))
     376           0 :             return idx+1; /* found */
     377             :         }
     378             :       else
     379             :         {
     380           0 :           if (len == namelen && !memcmp (buffer+off, name, len))
     381           0 :             return idx+1; /* found */
     382             :         }
     383             :     }
     384        4200 :   return 0; /* not found */
     385             : }
     386             : 
     387             : 
     388             : /* Compare all email addresses of the subject.  With SUBSTR given as
     389             :    True a substring search is done in the mail address.  The X509 flag
     390             :    indicated whether the search is done on an X.509 blob.  */
     391             : static int
     392           0 : blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
     393             :                int x509)
     394             : {
     395             :   const unsigned char *buffer;
     396             :   size_t length;
     397             :   size_t pos, off, len;
     398             :   size_t nkeys, keyinfolen;
     399             :   size_t nuids, uidinfolen;
     400             :   size_t nserial;
     401             :   int idx;
     402             : 
     403             :   /* fixme: this code is common to blob_cmp_mail */
     404           0 :   buffer = _keybox_get_blob_image (blob, &length);
     405           0 :   if (length < 40)
     406           0 :     return 0; /* blob too short */
     407             : 
     408             :   /*keys*/
     409           0 :   nkeys = get16 (buffer + 16);
     410           0 :   keyinfolen = get16 (buffer + 18 );
     411           0 :   if (keyinfolen < 28)
     412           0 :     return 0; /* invalid blob */
     413           0 :   pos = 20 + keyinfolen*nkeys;
     414           0 :   if (pos+2 > length)
     415           0 :     return 0; /* out of bounds */
     416             : 
     417             :   /*serial*/
     418           0 :   nserial = get16 (buffer+pos);
     419           0 :   pos += 2 + nserial;
     420           0 :   if (pos+4 > length)
     421           0 :     return 0; /* out of bounds */
     422             : 
     423             :   /* user ids*/
     424           0 :   nuids = get16 (buffer + pos);  pos += 2;
     425           0 :   uidinfolen = get16 (buffer + pos);  pos += 2;
     426           0 :   if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
     427           0 :     return 0; /* invalid blob */
     428           0 :   if (pos + uidinfolen*nuids > length)
     429           0 :     return 0; /* out of bounds */
     430             : 
     431           0 :   if (namelen < 1)
     432           0 :     return 0;
     433             : 
     434             :   /* Note that for X.509 we start at index 1 becuase index 0 is used
     435             :      for the issuer name.  */
     436           0 :   for (idx=!!x509 ;idx < nuids; idx++)
     437             :     {
     438           0 :       size_t mypos = pos;
     439             :       size_t mylen;
     440             : 
     441           0 :       mypos += idx*uidinfolen;
     442           0 :       off = get32 (buffer+mypos);
     443           0 :       len = get32 (buffer+mypos+4);
     444           0 :       if (off+len > length)
     445           0 :         return 0; /* error: better stop here - out of bounds */
     446           0 :       if (x509)
     447             :         {
     448           0 :           if (len < 2 || buffer[off] != '<')
     449           0 :             continue; /* empty name or trailing 0 not stored */
     450           0 :           len--; /* one back */
     451           0 :           if ( len < 3 || buffer[off+len] != '>')
     452           0 :             continue; /* not a proper email address */
     453           0 :           off++;
     454           0 :           len--;
     455             :         }
     456             :       else /* OpenPGP.  */
     457             :         {
     458             :           /* We need to forward to the mailbox part.  */
     459           0 :           mypos = off;
     460           0 :           mylen = len;
     461           0 :           for ( ; len && buffer[off] != '<'; len--, off++)
     462             :             ;
     463           0 :           if (len < 2 || buffer[off] != '<')
     464             :             {
     465             :               /* Mailbox not explicitly given or too short.  Restore
     466             :                  OFF and LEN and check whether the entire string
     467             :                  resembles a mailbox without the angle brackets.  */
     468           0 :               off = mypos;
     469           0 :               len = mylen;
     470           0 :               if (!is_valid_mailbox_mem (buffer+off, len))
     471           0 :                 continue; /* Not a mail address. */
     472             :             }
     473             :           else /* Seems to be standard user id with mail address.  */
     474             :             {
     475           0 :               off++; /* Point to first char of the mail address.  */
     476           0 :               len--;
     477             :               /* Search closing '>'.  */
     478           0 :               for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
     479             :                 ;
     480           0 :               if (!len || buffer[mypos] != '>' || off == mypos)
     481           0 :                 continue; /* Not a proper mail address.  */
     482           0 :               len = mypos - off;
     483             :             }
     484             : 
     485             :         }
     486             : 
     487           0 :       if (substr)
     488             :         {
     489           0 :           if (ascii_memcasemem (buffer+off, len, name, namelen))
     490           0 :             return idx+1; /* found */
     491             :         }
     492             :       else
     493             :         {
     494           0 :           if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
     495           0 :             return idx+1; /* found */
     496             :         }
     497             :     }
     498           0 :   return 0; /* not found */
     499             : }
     500             : 
     501             : 
     502             : #ifdef KEYBOX_WITH_X509
     503             : /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
     504             :    We don't have the keygrips as meta data, thus we need to parse the
     505             :    certificate. Fixme: We might want to return proper error codes
     506             :    instead of failing a search for invalid certificates etc.  */
     507             : static int
     508           0 : blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
     509             : {
     510             :   int rc;
     511             :   const unsigned char *buffer;
     512             :   size_t length;
     513             :   size_t cert_off, cert_len;
     514           0 :   ksba_reader_t reader = NULL;
     515           0 :   ksba_cert_t cert = NULL;
     516           0 :   ksba_sexp_t p = NULL;
     517             :   gcry_sexp_t s_pkey;
     518             :   unsigned char array[20];
     519             :   unsigned char *rcp;
     520             :   size_t n;
     521             : 
     522           0 :   buffer = _keybox_get_blob_image (blob, &length);
     523           0 :   if (length < 40)
     524           0 :     return 0; /* Too short. */
     525           0 :   cert_off = get32 (buffer+8);
     526           0 :   cert_len = get32 (buffer+12);
     527           0 :   if (cert_off+cert_len > length)
     528           0 :     return 0; /* Too short.  */
     529             : 
     530           0 :   rc = ksba_reader_new (&reader);
     531           0 :   if (rc)
     532           0 :     return 0; /* Problem with ksba. */
     533           0 :   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
     534           0 :   if (rc)
     535           0 :     goto failed;
     536           0 :   rc = ksba_cert_new (&cert);
     537           0 :   if (rc)
     538           0 :     goto failed;
     539           0 :   rc = ksba_cert_read_der (cert, reader);
     540           0 :   if (rc)
     541           0 :     goto failed;
     542           0 :   p = ksba_cert_get_public_key (cert);
     543           0 :   if (!p)
     544           0 :     goto failed;
     545           0 :   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
     546           0 :   if (!n)
     547           0 :     goto failed;
     548           0 :   rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
     549           0 :   if (rc)
     550             :     {
     551           0 :       gcry_sexp_release (s_pkey);
     552           0 :       goto failed;
     553             :     }
     554           0 :   rcp = gcry_pk_get_keygrip (s_pkey, array);
     555           0 :   gcry_sexp_release (s_pkey);
     556           0 :   if (!rcp)
     557           0 :     goto failed; /* Can't calculate keygrip. */
     558             : 
     559           0 :   xfree (p);
     560           0 :   ksba_cert_release (cert);
     561           0 :   ksba_reader_release (reader);
     562           0 :   return !memcmp (array, grip, 20);
     563             :  failed:
     564           0 :   xfree (p);
     565           0 :   ksba_cert_release (cert);
     566           0 :   ksba_reader_release (reader);
     567           0 :   return 0;
     568             : }
     569             : #endif /*KEYBOX_WITH_X509*/
     570             : 
     571             : 
     572             : 
     573             : /*
     574             :   The has_foo functions are used as helpers for search
     575             : */
     576             : static inline int
     577       11694 : has_short_kid (KEYBOXBLOB blob, u32 lkid)
     578             : {
     579             :   unsigned char buf[4];
     580       11694 :   buf[0] = lkid >> 24;
     581       11694 :   buf[1] = lkid >> 16;
     582       11694 :   buf[2] = lkid >> 8;
     583       11694 :   buf[3] = lkid;
     584       11694 :   return blob_cmp_fpr_part (blob, buf, 16, 4);
     585             : }
     586             : 
     587             : static inline int
     588       60370 : has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
     589             : {
     590             :   unsigned char buf[8];
     591       60370 :   buf[0] = mkid >> 24;
     592       60370 :   buf[1] = mkid >> 16;
     593       60370 :   buf[2] = mkid >> 8;
     594       60370 :   buf[3] = mkid;
     595       60370 :   buf[4] = lkid >> 24;
     596       60370 :   buf[5] = lkid >> 16;
     597       60370 :   buf[6] = lkid >> 8;
     598       60370 :   buf[7] = lkid;
     599       60370 :   return blob_cmp_fpr_part (blob, buf, 12, 8);
     600             : }
     601             : 
     602             : static inline int
     603        4743 : has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
     604             : {
     605        4743 :   return blob_cmp_fpr (blob, fpr);
     606             : }
     607             : 
     608             : static inline int
     609           0 : has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
     610             : {
     611             : #ifdef KEYBOX_WITH_X509
     612           0 :   if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
     613           0 :     return blob_x509_has_grip (blob, grip);
     614             : #else
     615             :   (void)blob;
     616             :   (void)grip;
     617             : #endif
     618           0 :   return 0;
     619             : }
     620             : 
     621             : 
     622             : static inline int
     623           0 : has_issuer (KEYBOXBLOB blob, const char *name)
     624             : {
     625             :   size_t namelen;
     626             : 
     627           0 :   return_val_if_fail (name, 0);
     628             : 
     629           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     630           0 :     return 0;
     631             : 
     632           0 :   namelen = strlen (name);
     633           0 :   return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
     634             : }
     635             : 
     636             : static inline int
     637           0 : has_issuer_sn (KEYBOXBLOB blob, const char *name,
     638             :                const unsigned char *sn, int snlen)
     639             : {
     640             :   size_t namelen;
     641             : 
     642           0 :   return_val_if_fail (name, 0);
     643           0 :   return_val_if_fail (sn, 0);
     644             : 
     645           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     646           0 :     return 0;
     647             : 
     648           0 :   namelen = strlen (name);
     649             : 
     650           0 :   return (blob_cmp_sn (blob, sn, snlen)
     651           0 :           && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
     652             : }
     653             : 
     654             : static inline int
     655           0 : has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
     656             : {
     657           0 :   return_val_if_fail (sn, 0);
     658             : 
     659           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     660           0 :     return 0;
     661           0 :   return blob_cmp_sn (blob, sn, snlen);
     662             : }
     663             : 
     664             : static inline int
     665           0 : has_subject (KEYBOXBLOB blob, const char *name)
     666             : {
     667             :   size_t namelen;
     668             : 
     669           0 :   return_val_if_fail (name, 0);
     670             : 
     671           0 :   if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
     672           0 :     return 0;
     673             : 
     674           0 :   namelen = strlen (name);
     675           0 :   return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
     676             : }
     677             : 
     678             : 
     679             : static inline int
     680        4346 : has_username (KEYBOXBLOB blob, const char *name, int substr)
     681             : {
     682             :   size_t namelen;
     683             :   int btype;
     684             : 
     685        4346 :   return_val_if_fail (name, 0);
     686             : 
     687        4346 :   btype = blob_get_type (blob);
     688        4346 :   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
     689           0 :     return 0;
     690             : 
     691        4346 :   namelen = strlen (name);
     692        4346 :   return blob_cmp_name (blob, -1 /* all subject/user names */, name,
     693             :                         namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
     694             : }
     695             : 
     696             : 
     697             : static inline int
     698           0 : has_mail (KEYBOXBLOB blob, const char *name, int substr)
     699             : {
     700             :   size_t namelen;
     701             :   int btype;
     702             : 
     703           0 :   return_val_if_fail (name, 0);
     704             : 
     705           0 :   btype = blob_get_type (blob);
     706           0 :   if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
     707           0 :     return 0;
     708             : 
     709           0 :   if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
     710           0 :     name++; /* Hack to remove the leading '<' for gpg.  */
     711             : 
     712           0 :   namelen = strlen (name);
     713           0 :   if (namelen && name[namelen-1] == '>')
     714           0 :     namelen--;
     715           0 :   return blob_cmp_mail (blob, name, namelen, substr,
     716             :                         (btype == KEYBOX_BLOBTYPE_X509));
     717             : }
     718             : 
     719             : 
     720             : static void
     721           0 : release_sn_array (struct sn_array_s *array, size_t size)
     722             : {
     723             :   size_t n;
     724             : 
     725           0 :   for (n=0; n < size; n++)
     726           0 :     xfree (array[n].sn);
     727           0 :   xfree (array);
     728           0 : }
     729             : 
     730             : 
     731             : /*
     732             : 
     733             :   The search API
     734             : 
     735             : */
     736             : 
     737             : int
     738         140 : keybox_search_reset (KEYBOX_HANDLE hd)
     739             : {
     740         140 :   if (!hd)
     741           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     742             : 
     743         140 :   if (hd->found.blob)
     744             :     {
     745           0 :       _keybox_release_blob (hd->found.blob);
     746           0 :       hd->found.blob = NULL;
     747             :     }
     748             : 
     749         140 :   if (hd->fp)
     750             :     {
     751           3 :       fclose (hd->fp);
     752           3 :       hd->fp = NULL;
     753             :     }
     754         140 :   hd->error = 0;
     755         140 :   hd->eof = 0;
     756         140 :   return 0;
     757             : }
     758             : 
     759             : 
     760             : /* Note: When in ephemeral mode the search function does visit all
     761             :    blobs but in standard mode, blobs flagged as ephemeral are ignored.
     762             :    If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
     763             :    The value at R_SKIPPED is updated by the number of skipped long
     764             :    records (counts PGP and X.509). */
     765             : int
     766        2667 : keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
     767             :                keybox_blobtype_t want_blobtype,
     768             :                size_t *r_descindex, unsigned long *r_skipped)
     769             : {
     770             :   int rc;
     771             :   size_t n;
     772             :   int need_words, any_skip;
     773        2667 :   KEYBOXBLOB blob = NULL;
     774        2667 :   struct sn_array_s *sn_array = NULL;
     775             :   int pk_no, uid_no;
     776             : 
     777        2667 :   if (!hd)
     778           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     779             : 
     780             :   /* clear last found result */
     781        2667 :   if (hd->found.blob)
     782             :     {
     783         142 :       _keybox_release_blob (hd->found.blob);
     784         142 :       hd->found.blob = NULL;
     785             :     }
     786             : 
     787        2667 :   if (hd->error)
     788           0 :     return hd->error; /* still in error state */
     789        2667 :   if (hd->eof)
     790           0 :     return -1; /* still EOF */
     791             : 
     792             :   /* figure out what information we need */
     793        2667 :   need_words = any_skip = 0;
     794        5337 :   for (n=0; n < ndesc; n++)
     795             :     {
     796        2670 :       switch (desc[n].mode)
     797             :         {
     798             :         case KEYDB_SEARCH_MODE_WORDS:
     799           0 :           need_words = 1;
     800           0 :           break;
     801             :         case KEYDB_SEARCH_MODE_FIRST:
     802             :           /* always restart the search in this mode */
     803          70 :           keybox_search_reset (hd);
     804          70 :           break;
     805             :         default:
     806        2600 :           break;
     807             :         }
     808        2670 :       if (desc[n].skipfnc)
     809         192 :         any_skip = 1;
     810        2670 :       if (desc[n].snlen == -1 && !sn_array)
     811             :         {
     812           0 :           sn_array = xtrycalloc (ndesc, sizeof *sn_array);
     813           0 :           if (!sn_array)
     814           0 :             return (hd->error = gpg_error_from_syserror ());
     815             :         }
     816             :     }
     817             : 
     818             :   (void)need_words;  /* Not yet implemented.  */
     819             : 
     820        2667 :   if (!hd->fp)
     821             :     {
     822        2525 :       hd->fp = fopen (hd->kb->fname, "rb");
     823        2525 :       if (!hd->fp)
     824             :         {
     825           0 :           hd->error = gpg_error_from_syserror ();
     826           0 :           xfree (sn_array);
     827           0 :           return hd->error;
     828             :         }
     829             :     }
     830             : 
     831             :   /* Kludge: We need to convert an SN given as hexstring to its binary
     832             :      representation - in some cases we are not able to store it in the
     833             :      search descriptor, because due to the way we use it, it is not
     834             :      possible to free allocated memory. */
     835        2667 :   if (sn_array)
     836             :     {
     837             :       const unsigned char *s;
     838             :       int i, odd;
     839             :       size_t snlen;
     840             : 
     841           0 :       for (n=0; n < ndesc; n++)
     842             :         {
     843           0 :           if (!desc[n].sn)
     844             :             ;
     845           0 :           else if (desc[n].snlen == -1)
     846             :             {
     847             :               unsigned char *sn;
     848             : 
     849           0 :               s = desc[n].sn;
     850           0 :               for (i=0; *s && *s != '/'; s++, i++)
     851             :                 ;
     852           0 :               odd = (i & 1);
     853           0 :               snlen = (i+1)/2;
     854           0 :               sn_array[n].sn = xtrymalloc (snlen);
     855           0 :               if (!sn_array[n].sn)
     856             :                 {
     857           0 :                   hd->error = gpg_error_from_syserror ();
     858           0 :                   release_sn_array (sn_array, n);
     859           0 :                   return hd->error;
     860             :                 }
     861           0 :               sn_array[n].snlen = snlen;
     862           0 :               sn = sn_array[n].sn;
     863           0 :               s = desc[n].sn;
     864           0 :               if (odd)
     865             :                 {
     866           0 :                   *sn++ = xtoi_1 (s);
     867           0 :                   s++;
     868             :                 }
     869           0 :               for (; *s && *s != '/';  s += 2)
     870           0 :                 *sn++ = xtoi_2 (s);
     871             :             }
     872             :           else
     873             :             {
     874             :               const unsigned char *sn;
     875             : 
     876           0 :               sn = desc[n].sn;
     877           0 :               snlen = desc[n].snlen;
     878           0 :               sn_array[n].sn = xtrymalloc (snlen);
     879           0 :               if (!sn_array[n].sn)
     880             :                 {
     881           0 :                   hd->error = gpg_error_from_syserror ();
     882           0 :                   release_sn_array (sn_array, n);
     883           0 :                   return hd->error;
     884             :                 }
     885           0 :               sn_array[n].snlen = snlen;
     886           0 :               memcpy (sn_array[n].sn, sn, snlen);
     887             :             }
     888             :         }
     889             :     }
     890             : 
     891             : 
     892        2667 :   pk_no = uid_no = 0;
     893             :   for (;;)
     894             :     {
     895             :       unsigned int blobflags;
     896             :       int blobtype;
     897             : 
     898       83906 :       _keybox_release_blob (blob); blob = NULL;
     899       83906 :       rc = _keybox_read_blob (&blob, hd->fp);
     900       83906 :       if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
     901           0 :           && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
     902             :         {
     903           0 :           ++*r_skipped;
     904           0 :           continue; /* Skip too large records.  */
     905             :         }
     906             : 
     907       83906 :       if (rc)
     908         208 :         break;
     909             : 
     910       83698 :       blobtype = blob_get_type (blob);
     911       83698 :       if (blobtype == KEYBOX_BLOBTYPE_HEADER)
     912        2524 :         continue;
     913       81174 :       if (want_blobtype && blobtype != want_blobtype)
     914           0 :         continue;
     915             : 
     916       81174 :       blobflags = blob_get_blob_flags (blob);
     917       81174 :       if (!hd->ephemeral && (blobflags & 2))
     918           0 :         continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
     919             : 
     920      159938 :       for (n=0; n < ndesc; n++)
     921             :         {
     922       81223 :           switch (desc[n].mode)
     923             :             {
     924             :             case KEYDB_SEARCH_MODE_NONE:
     925           0 :               never_reached ();
     926           0 :               break;
     927             :             case KEYDB_SEARCH_MODE_EXACT:
     928           0 :               uid_no = has_username (blob, desc[n].u.name, 0);
     929           0 :               if (uid_no)
     930           0 :                 goto found;
     931           0 :               break;
     932             :             case KEYDB_SEARCH_MODE_MAIL:
     933           0 :               uid_no = has_mail (blob, desc[n].u.name, 0);
     934           0 :               if (uid_no)
     935           0 :                 goto found;
     936           0 :               break;
     937             :             case KEYDB_SEARCH_MODE_MAILSUB:
     938           0 :               uid_no = has_mail (blob, desc[n].u.name, 1);
     939           0 :               if (uid_no)
     940           0 :                 goto found;
     941           0 :               break;
     942             :             case KEYDB_SEARCH_MODE_SUBSTR:
     943        4346 :               uid_no =  has_username (blob, desc[n].u.name, 1);
     944        4346 :               if (uid_no)
     945         146 :                 goto found;
     946        4200 :               break;
     947             :             case KEYDB_SEARCH_MODE_MAILEND:
     948             :             case KEYDB_SEARCH_MODE_WORDS:
     949             :               /* not yet implemented */
     950           0 :               break;
     951             :             case KEYDB_SEARCH_MODE_ISSUER:
     952           0 :               if (has_issuer (blob, desc[n].u.name))
     953           0 :                 goto found;
     954           0 :               break;
     955             :             case KEYDB_SEARCH_MODE_ISSUER_SN:
     956           0 :               if (has_issuer_sn (blob, desc[n].u.name,
     957           0 :                                  sn_array? sn_array[n].sn : desc[n].sn,
     958           0 :                                  sn_array? sn_array[n].snlen : desc[n].snlen))
     959           0 :                 goto found;
     960           0 :               break;
     961             :             case KEYDB_SEARCH_MODE_SN:
     962           0 :               if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
     963           0 :                                 sn_array? sn_array[n].snlen : desc[n].snlen))
     964           0 :                 goto found;
     965           0 :               break;
     966             :             case KEYDB_SEARCH_MODE_SUBJECT:
     967           0 :               if (has_subject (blob, desc[n].u.name))
     968           0 :                 goto found;
     969           0 :               break;
     970             :             case KEYDB_SEARCH_MODE_SHORT_KID:
     971       11694 :               pk_no = has_short_kid (blob, desc[n].u.kid[1]);
     972       11694 :               if (pk_no)
     973         232 :                 goto found;
     974       11462 :               break;
     975             :             case KEYDB_SEARCH_MODE_LONG_KID:
     976       60370 :               pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
     977       60370 :               if (pk_no)
     978        1883 :                 goto found;
     979       58487 :               break;
     980             :             case KEYDB_SEARCH_MODE_FPR:
     981             :             case KEYDB_SEARCH_MODE_FPR20:
     982        4743 :               pk_no = has_fingerprint (blob, desc[n].u.fpr);
     983        4743 :               if (pk_no)
     984         128 :                 goto found;
     985        4615 :               break;
     986             :             case KEYDB_SEARCH_MODE_KEYGRIP:
     987           0 :               if (has_keygrip (blob, desc[n].u.grip))
     988           0 :                 goto found;
     989           0 :               break;
     990             :             case KEYDB_SEARCH_MODE_FIRST:
     991          70 :               goto found;
     992             :               break;
     993             :             case KEYDB_SEARCH_MODE_NEXT:
     994           0 :               goto found;
     995             :               break;
     996             :             default:
     997           0 :               rc = gpg_error (GPG_ERR_INV_VALUE);
     998           0 :               goto found;
     999             :             }
    1000             :         }
    1001       78715 :       continue;
    1002             :     found:
    1003             :       /* Record which DESC we matched on.  Note this value is only
    1004             :          meaningful if this function returns with no errors. */
    1005        2459 :       if(r_descindex)
    1006           0 :         *r_descindex = n;
    1007        2651 :       for (n=any_skip?0:ndesc; n < ndesc; n++)
    1008             :         {
    1009             :           u32 kid[2];
    1010             : 
    1011         192 :           if (desc[n].skipfnc
    1012         192 :               && blob_get_first_keyid (blob, kid)
    1013         192 :               && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
    1014           0 :                 break;
    1015             :         }
    1016        2459 :       if (n == ndesc)
    1017        2459 :         break; /* got it */
    1018       81239 :     }
    1019             : 
    1020        2667 :   if (!rc)
    1021             :     {
    1022        2459 :       hd->found.blob = blob;
    1023        2459 :       hd->found.pk_no = pk_no;
    1024        2459 :       hd->found.uid_no = uid_no;
    1025             :     }
    1026         208 :   else if (rc == -1)
    1027             :     {
    1028         208 :       _keybox_release_blob (blob);
    1029         208 :       hd->eof = 1;
    1030             :     }
    1031             :   else
    1032             :     {
    1033           0 :       _keybox_release_blob (blob);
    1034           0 :       hd->error = rc;
    1035             :     }
    1036             : 
    1037        2667 :   if (sn_array)
    1038           0 :     release_sn_array (sn_array, ndesc);
    1039             : 
    1040        2667 :   return rc;
    1041             : }
    1042             : 
    1043             : 
    1044             : 
    1045             : 
    1046             : /*
    1047             :    Functions to return a certificate or a keyblock.  To be used after
    1048             :    a successful search operation.
    1049             : */
    1050             : 
    1051             : 
    1052             : /* Return the last found keyblock.  Returns 0 on success and stores a
    1053             :    new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
    1054             :    in that case.  R_UID_NO and R_PK_NO are used to retun the number of
    1055             :    the key or user id which was matched the search criteria; if not
    1056             :    known they are set to 0. */
    1057             : gpg_error_t
    1058        2459 : keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
    1059             :                      int *r_pk_no, int *r_uid_no, u32 **r_sigstatus)
    1060             : {
    1061             :   gpg_error_t err;
    1062             :   const unsigned char *buffer, *p;
    1063             :   size_t length;
    1064             :   size_t image_off, image_len;
    1065             :   size_t siginfo_off, siginfo_len;
    1066             :   u32 *sigstatus, n, n_sigs, sigilen;
    1067             : 
    1068        2459 :   *r_iobuf = NULL;
    1069        2459 :   *r_sigstatus = NULL;
    1070             : 
    1071        2459 :   if (!hd)
    1072           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1073        2459 :   if (!hd->found.blob)
    1074           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1075             : 
    1076        2459 :   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
    1077           0 :     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
    1078             : 
    1079        2459 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1080        2459 :   if (length < 40)
    1081           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1082        2459 :   image_off = get32 (buffer+8);
    1083        2459 :   image_len = get32 (buffer+12);
    1084        2459 :   if (image_off+image_len > length)
    1085           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1086             : 
    1087        2459 :   err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
    1088             :                                    &siginfo_off, &siginfo_len);
    1089        2459 :   if (err)
    1090           0 :     return err;
    1091        2459 :   n_sigs  = get16 (buffer + siginfo_off);
    1092        2459 :   sigilen = get16 (buffer + siginfo_off + 2);
    1093        2459 :   p = buffer + siginfo_off + 4;
    1094        2459 :   sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
    1095        2459 :   if (!sigstatus)
    1096           0 :     return gpg_error_from_syserror ();
    1097        2459 :   sigstatus[0] = n_sigs;
    1098        8308 :   for (n=1; n <= n_sigs; n++, p += sigilen)
    1099        5849 :     sigstatus[n] = get32 (p);
    1100             : 
    1101        2459 :   *r_pk_no  = hd->found.pk_no;
    1102        2459 :   *r_uid_no = hd->found.uid_no;
    1103        2459 :   *r_sigstatus = sigstatus;
    1104        2459 :   *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
    1105        2459 :   return 0;
    1106             : }
    1107             : 
    1108             : 
    1109             : #ifdef KEYBOX_WITH_X509
    1110             : /*
    1111             :   Return the last found cert.  Caller must free it.
    1112             :  */
    1113             : int
    1114           0 : keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
    1115             : {
    1116             :   const unsigned char *buffer;
    1117             :   size_t length;
    1118             :   size_t cert_off, cert_len;
    1119           0 :   ksba_reader_t reader = NULL;
    1120           0 :   ksba_cert_t cert = NULL;
    1121             :   int rc;
    1122             : 
    1123           0 :   if (!hd)
    1124           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1125           0 :   if (!hd->found.blob)
    1126           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1127             : 
    1128           0 :   if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
    1129           0 :     return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
    1130             : 
    1131           0 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1132           0 :   if (length < 40)
    1133           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1134           0 :   cert_off = get32 (buffer+8);
    1135           0 :   cert_len = get32 (buffer+12);
    1136           0 :   if (cert_off+cert_len > length)
    1137           0 :     return gpg_error (GPG_ERR_TOO_SHORT);
    1138             : 
    1139           0 :   rc = ksba_reader_new (&reader);
    1140           0 :   if (rc)
    1141           0 :     return rc;
    1142           0 :   rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
    1143           0 :   if (rc)
    1144             :     {
    1145           0 :       ksba_reader_release (reader);
    1146             :       /* fixme: need to map the error codes */
    1147           0 :       return gpg_error (GPG_ERR_GENERAL);
    1148             :     }
    1149             : 
    1150           0 :   rc = ksba_cert_new (&cert);
    1151           0 :   if (rc)
    1152             :     {
    1153           0 :       ksba_reader_release (reader);
    1154           0 :       return rc;
    1155             :     }
    1156             : 
    1157           0 :   rc = ksba_cert_read_der (cert, reader);
    1158           0 :   if (rc)
    1159             :     {
    1160           0 :       ksba_cert_release (cert);
    1161           0 :       ksba_reader_release (reader);
    1162             :       /* fixme: need to map the error codes */
    1163           0 :       return gpg_error (GPG_ERR_GENERAL);
    1164             :     }
    1165             : 
    1166           0 :   *r_cert = cert;
    1167           0 :   ksba_reader_release (reader);
    1168           0 :   return 0;
    1169             : }
    1170             : 
    1171             : #endif /*KEYBOX_WITH_X509*/
    1172             : 
    1173             : /* Return the flags named WHAT at the address of VALUE. IDX is used
    1174             :    only for certain flags and should be 0 if not required. */
    1175             : int
    1176           0 : keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
    1177             : {
    1178             :   const unsigned char *buffer;
    1179             :   size_t length;
    1180             :   gpg_err_code_t ec;
    1181             : 
    1182             :   (void)idx; /* Not yet used.  */
    1183             : 
    1184           0 :   if (!hd)
    1185           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1186           0 :   if (!hd->found.blob)
    1187           0 :     return gpg_error (GPG_ERR_NOTHING_FOUND);
    1188             : 
    1189           0 :   buffer = _keybox_get_blob_image (hd->found.blob, &length);
    1190           0 :   ec = get_flag_from_image (buffer, length, what, value);
    1191           0 :   return ec? gpg_error (ec):0;
    1192             : }

Generated by: LCOV version 1.11