gpg: Use only OpenPGP public key algo ids and add the EdDSA algo id.
[gnupg.git] / g10 / keydb.c
index ab727b6..9085012 100644 (file)
@@ -1,6 +1,7 @@
 /* keydb.c - key database dispatcher
  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
- *               2008, 2009, 2011 Free Software Foundation, Inc.
+ *               2008, 2009, 2011, 2013 Free Software Foundation, Inc.
+ * Coyrright (C) 2013 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -72,10 +73,42 @@ struct keydb_handle
 };
 
 
+/* This is a simple cache used to return the last result of a
+   successful long kid search.  This works only for keybox resources
+   because (due to lack of a copy_keyblock function) we need to store
+   an image of the keyblock which is fortunately instantly available
+   for keyboxes.  */
+enum keyblock_cache_states {
+  KEYBLOCK_CACHE_EMPTY,
+  KEYBLOCK_CACHE_PREPARED,
+  KEYBLOCK_CACHE_FILLED
+};
+
+struct {
+  enum keyblock_cache_states state;
+  u32 kid[2];
+  iobuf_t iobuf; /* Image of the keyblock.  */
+  u32 *sigstatus;
+  int pk_no;
+  int uid_no;
+} keyblock_cache;
+
+
 static int lock_all (KEYDB_HANDLE hd);
 static void unlock_all (KEYDB_HANDLE hd);
 
 
+static void
+keyblock_cache_clear (void)
+{
+  keyblock_cache.state = KEYBLOCK_CACHE_EMPTY;
+  xfree (keyblock_cache.sigstatus);
+  keyblock_cache.sigstatus = NULL;
+  iobuf_close (keyblock_cache.iobuf);
+  keyblock_cache.iobuf = NULL;
+}
+
+
 /* Handle the creation of a keyring or a keybox if it does not yet
    exist.  Take into acount that other processes might have the
    keyring/keybox already locked.  This lock check does not work if
@@ -427,6 +460,9 @@ keydb_new (void)
   KEYDB_HANDLE hd;
   int i, j;
 
+  if (DBG_CLOCK)
+    log_clock ("keydb_new");
+
   hd = xmalloc_clear (sizeof *hd);
   hd->found = -1;
 
@@ -616,6 +652,161 @@ unlock_all (KEYDB_HANDLE hd)
 }
 
 
+static gpg_error_t
+parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
+                      const u32 *sigstatus, kbnode_t *r_keyblock)
+{
+  gpg_error_t err;
+  PACKET *pkt;
+  kbnode_t keyblock = NULL;
+  kbnode_t node, *tail;
+  int in_cert, save_mode;
+  u32 n_sigs;
+  int pk_count, uid_count;
+
+  *r_keyblock = NULL;
+
+  pkt = xtrymalloc (sizeof *pkt);
+  if (!pkt)
+    return gpg_error_from_syserror ();
+  init_packet (pkt);
+  save_mode = set_packet_list_mode (0);
+  in_cert = 0;
+  n_sigs = 0;
+  tail = NULL;
+  pk_count = uid_count = 0;
+  while ((err = parse_packet (iobuf, pkt)) != -1)
+    {
+      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
+        {
+          free_packet (pkt);
+          init_packet (pkt);
+          continue;
+       }
+      if (err)
+        {
+          log_error ("parse_keyblock_image: read error: %s\n",
+                     gpg_strerror (err));
+          err = gpg_error (GPG_ERR_INV_KEYRING);
+          break;
+        }
+      if (pkt->pkttype == PKT_COMPRESSED)
+        {
+          log_error ("skipped compressed packet in keybox blob\n");
+          free_packet(pkt);
+          init_packet(pkt);
+          continue;
+        }
+      if (pkt->pkttype == PKT_RING_TRUST)
+        {
+          log_info ("skipped ring trust packet in keybox blob\n");
+          free_packet(pkt);
+          init_packet(pkt);
+          continue;
+        }
+
+      if (!in_cert && pkt->pkttype != PKT_PUBLIC_KEY)
+        {
+          log_error ("parse_keyblock_image: first packet in a keybox blob "
+                     "is not a public key packet\n");
+          err = gpg_error (GPG_ERR_INV_KEYRING);
+          break;
+        }
+      if (in_cert && (pkt->pkttype == PKT_PUBLIC_KEY
+                      || pkt->pkttype == PKT_SECRET_KEY))
+        {
+          log_error ("parse_keyblock_image: "
+                     "multiple keyblocks in a keybox blob\n");
+          err = gpg_error (GPG_ERR_INV_KEYRING);
+          break;
+        }
+      in_cert = 1;
+
+      if (pkt->pkttype == PKT_SIGNATURE && sigstatus)
+        {
+          PKT_signature *sig = pkt->pkt.signature;
+
+          n_sigs++;
+          if (n_sigs > sigstatus[0])
+            {
+              log_error ("parse_keyblock_image: "
+                         "more signatures than found in the meta data\n");
+              err = gpg_error (GPG_ERR_INV_KEYRING);
+              break;
+
+            }
+          if (sigstatus[n_sigs])
+            {
+              sig->flags.checked = 1;
+              if (sigstatus[n_sigs] == 1 )
+                ; /* missing key */
+              else if (sigstatus[n_sigs] == 2 )
+                ; /* bad signature */
+              else if (sigstatus[n_sigs] < 0x10000000)
+                ; /* bad flag */
+              else
+                {
+                  sig->flags.valid = 1;
+                  /* Fixme: Shall we set the expired flag here?  */
+                }
+            }
+        }
+
+      node = new_kbnode (pkt);
+
+      switch (pkt->pkttype)
+        {
+        case PKT_PUBLIC_KEY:
+        case PKT_PUBLIC_SUBKEY:
+        case PKT_SECRET_KEY:
+        case PKT_SECRET_SUBKEY:
+          if (++pk_count == pk_no)
+            node->flag |= 1;
+          break;
+
+        case PKT_USER_ID:
+          if (++uid_count == uid_no)
+            node->flag |= 2;
+          break;
+
+        default:
+          break;
+        }
+
+      if (!keyblock)
+        keyblock = node;
+      else
+        *tail = node;
+      tail = &node->next;
+      pkt = xtrymalloc (sizeof *pkt);
+      if (!pkt)
+        {
+          err = gpg_error_from_syserror ();
+          break;
+        }
+      init_packet (pkt);
+    }
+  set_packet_list_mode (save_mode);
+
+  if (err == -1 && keyblock)
+    err = 0; /* Got the entire keyblock.  */
+
+  if (!err && sigstatus && n_sigs != sigstatus[0])
+    {
+      log_error ("parse_keyblock_image: signature count does not match\n");
+      err = gpg_error (GPG_ERR_INV_KEYRING);
+    }
+
+  if (err)
+    release_kbnode (keyblock);
+  else
+    *r_keyblock = keyblock;
+  free_packet (pkt);
+  xfree (pkt);
+  return err;
+}
+
+
 /*
  * Return the last found keyring.  Caller must free it.
  * The returned keyblock has the kbode flag bit 0 set for the node with
@@ -627,9 +818,24 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
 {
   gpg_error_t err = 0;
 
+  *ret_kb = NULL;
+
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  if (keyblock_cache.state == KEYBLOCK_CACHE_FILLED)
+    {
+      iobuf_seek (keyblock_cache.iobuf, 0);
+      err = parse_keyblock_image (keyblock_cache.iobuf,
+                                  keyblock_cache.pk_no,
+                                  keyblock_cache.uid_no,
+                                  keyblock_cache.sigstatus,
+                                  ret_kb);
+      if (err)
+        keyblock_cache_clear ();
+      return err;
+    }
+
   if (hd->found < 0 || hd->found >= hd->used)
     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
 
@@ -641,55 +847,182 @@ keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb)
     case KEYDB_RESOURCE_TYPE_KEYRING:
       err = keyring_get_keyblock (hd->active[hd->found].u.kr, ret_kb);
       break;
-    /* case KEYDB_RESOURCE_TYPE_KEYBOX: */
-    /*   err = keybox_get_keyblock (hd->active[hd->found].u.kb, ret_kb); */
-    /*   if (!err) */
-    /*     err = parse_keyblock (image, imagelen) */
-    /*   break; */
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      {
+        iobuf_t iobuf;
+        u32 *sigstatus;
+        int pk_no, uid_no;
+
+        err = keybox_get_keyblock (hd->active[hd->found].u.kb,
+                                   &iobuf, &pk_no, &uid_no, &sigstatus);
+        if (!err)
+          {
+            err = parse_keyblock_image (iobuf, pk_no, uid_no, sigstatus,
+                                        ret_kb);
+            if (!err && keyblock_cache.state == KEYBLOCK_CACHE_PREPARED)
+              {
+                keyblock_cache.state     = KEYBLOCK_CACHE_FILLED;
+                keyblock_cache.sigstatus = sigstatus;
+                keyblock_cache.iobuf     = iobuf;
+                keyblock_cache.pk_no     = pk_no;
+                keyblock_cache.uid_no    = uid_no;
+              }
+            else
+              {
+                xfree (sigstatus);
+                iobuf_close (iobuf);
+              }
+          }
+      }
+      break;
     }
 
+  if (keyblock_cache.state != KEYBLOCK_CACHE_FILLED)
+    keyblock_cache_clear ();
+
   return err;
 }
 
+
+/* Build a keyblock image from KEYBLOCK.  Returns 0 on success and
+   only then stores a new iobuf object at R_IOBUF and a signature
+   status vecotor at R_SIGSTATUS.  */
+static gpg_error_t
+build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
+{
+  gpg_error_t err;
+  iobuf_t iobuf;
+  kbnode_t kbctx, node;
+  u32 n_sigs;
+  u32 *sigstatus;
+
+  *r_iobuf = NULL;
+  if (r_sigstatus)
+    *r_sigstatus = NULL;
+
+  /* Allocate a vector for the signature cache.  This is an array of
+     u32 values with the first value giving the number of elements to
+     follow and each element descriping the cache status of the
+     signature.  */
+  if (r_sigstatus)
+    {
+      for (kbctx=NULL, n_sigs=0; (node = walk_kbnode (keyblock, &kbctx, 0));)
+        if (node->pkt->pkttype == PKT_SIGNATURE)
+          n_sigs++;
+      sigstatus = xtrycalloc (1+n_sigs, sizeof *sigstatus);
+      if (!sigstatus)
+        return gpg_error_from_syserror ();
+    }
+  else
+    sigstatus = NULL;
+
+  iobuf = iobuf_temp ();
+  for (kbctx = NULL, n_sigs = 0; (node = walk_kbnode (keyblock, &kbctx, 0));)
+    {
+      /* Make sure to use only packets valid on a keyblock.  */
+      switch (node->pkt->pkttype)
+        {
+        case PKT_PUBLIC_KEY:
+        case PKT_PUBLIC_SUBKEY:
+        case PKT_SIGNATURE:
+        case PKT_USER_ID:
+        case PKT_ATTRIBUTE:
+          /* Note that we don't want the ring trust packets.  They are
+             not useful. */
+          break;
+        default:
+          continue;
+        }
+
+      err = build_packet (iobuf, node->pkt);
+      if (err)
+        {
+          iobuf_close (iobuf);
+          return err;
+        }
+
+      /* Build signature status vector.  */
+      if (node->pkt->pkttype == PKT_SIGNATURE)
+        {
+          PKT_signature *sig = node->pkt->pkt.signature;
+
+          n_sigs++;
+          /* Fixme: Detect the "missing key" status.  */
+          if (sig->flags.checked && sigstatus)
+            {
+              if (sig->flags.valid)
+                {
+                  if (!sig->expiredate)
+                    sigstatus[n_sigs] = 0xffffffff;
+                  else if (sig->expiredate < 0x1000000)
+                    sigstatus[n_sigs] = 0x10000000;
+                  else
+                    sigstatus[n_sigs] = sig->expiredate;
+                }
+              else
+                sigstatus[n_sigs] = 0x00000002; /* Bad signature.  */
+            }
+        }
+    }
+  if (sigstatus)
+    sigstatus[0] = n_sigs;
+
+  *r_iobuf = iobuf;
+  if (r_sigstatus)
+    *r_sigstatus = sigstatus;
+  return 0;
+}
+
+
 /*
  * Update the current keyblock with the keyblock KB
  */
 gpg_error_t
 keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
 {
-  gpg_error_t rc;
+  gpg_error_t err;
 
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  keyblock_cache_clear ();
+
   if (hd->found < 0 || hd->found >= hd->used)
     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
 
   if (opt.dry_run)
     return 0;
 
-  rc = lock_all (hd);
-  if (rc)
-    return rc;
+  err = lock_all (hd);
+  if (err)
+    return err;
 
   switch (hd->active[hd->found].type)
     {
     case KEYDB_RESOURCE_TYPE_NONE:
-      rc = gpg_error (GPG_ERR_GENERAL); /* oops */
+      err = gpg_error (GPG_ERR_GENERAL); /* oops */
       break;
     case KEYDB_RESOURCE_TYPE_KEYRING:
-      rc = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
+      err = keyring_update_keyblock (hd->active[hd->found].u.kr, kb);
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      {
+        iobuf_t iobuf;
+
+        err = build_keyblock_image (kb, &iobuf, NULL);
+        if (!err)
+          {
+            err = keybox_update_keyblock (hd->active[hd->found].u.kb,
+                                          iobuf_get_temp_buffer (iobuf),
+                                          iobuf_get_temp_length (iobuf));
+            iobuf_close (iobuf);
+          }
+      }
       break;
-    /* case KEYDB_RESOURCE_TYPE_KEYRING: */
-    /*   rc = build_keyblock (kb, &image, &imagelen); */
-    /*   if (!rc) */
-    /*     rc = keybox_update_keyblock (hd->active[hd->found].u.kb, */
-    /*                                  image, imagelen); */
-    /*   break; */
     }
 
   unlock_all (hd);
-  return rc;
+  return err;
 }
 
 
@@ -699,12 +1032,14 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
 gpg_error_t
 keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
 {
-  int rc;
+  gpg_error_t err;
   int idx;
 
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  keyblock_cache_clear ();
+
   if (opt.dry_run)
     return 0;
 
@@ -715,27 +1050,42 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
   else
     return gpg_error (GPG_ERR_GENERAL);
 
-  rc = lock_all (hd);
-  if (rc)
-    return rc;
+  err = lock_all (hd);
+  if (err)
+    return err;
 
   switch (hd->active[idx].type)
     {
     case KEYDB_RESOURCE_TYPE_NONE:
-      rc = gpg_error (GPG_ERR_GENERAL); /* oops */
+      err = gpg_error (GPG_ERR_GENERAL); /* oops */
       break;
     case KEYDB_RESOURCE_TYPE_KEYRING:
-      rc = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
+      err = keyring_insert_keyblock (hd->active[idx].u.kr, kb);
+      break;
+    case KEYDB_RESOURCE_TYPE_KEYBOX:
+      { /* We need to turn our kbnode_t list of packets into a proper
+           keyblock first.  This is required by the OpenPGP key parser
+           included in the keybox code.  Eventually we can change this
+           kludge to have the caller pass the image.  */
+        iobuf_t iobuf;
+        u32 *sigstatus;
+
+        err = build_keyblock_image (kb, &iobuf, &sigstatus);
+        if (!err)
+          {
+            err = keybox_insert_keyblock (hd->active[idx].u.kb,
+                                          iobuf_get_temp_buffer (iobuf),
+                                          iobuf_get_temp_length (iobuf),
+                                          sigstatus);
+            xfree (sigstatus);
+            iobuf_close (iobuf);
+          }
+      }
       break;
-    /* case KEYDB_RESOURCE_TYPE_KEYBOX: */
-    /*   rc = build_keyblock (kb, &image, &imagelen); */
-    /*   if (!rc) */
-    /*     rc = keybox_insert_keyblock (hd->active[idx].u.kb, image, imagelen); */
-    /*   break; */
     }
 
   unlock_all (hd);
-  return rc;
+  return err;
 }
 
 
@@ -750,6 +1100,8 @@ keydb_delete_keyblock (KEYDB_HANDLE hd)
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  keyblock_cache_clear ();
+
   if (hd->found < 0 || hd->found >= hd->used)
     return gpg_error (GPG_ERR_VALUE_NOT_FOUND);
 
@@ -846,6 +1198,8 @@ keydb_rebuild_caches (int noisy)
 {
   int i, rc;
 
+  keyblock_cache_clear ();
+
   for (i=0; i < used_resources; i++)
     {
       if (!keyring_is_writable (all_resources[i].token))
@@ -860,6 +1214,9 @@ keydb_rebuild_caches (int noisy)
             log_error (_("failed to rebuild keyring cache: %s\n"),
                        g10_errstr (rc));
           break;
+        case KEYDB_RESOURCE_TYPE_KEYBOX:
+          /* N/A.  */
+          break;
         }
     }
 }
@@ -878,6 +1235,11 @@ keydb_search_reset (KEYDB_HANDLE hd)
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  keyblock_cache_clear ();
+
+  if (DBG_CLOCK)
+    log_clock ("keydb_search_reset");
+
   hd->current = 0;
   hd->found = -1;
   /* Now reset all resources.  */
@@ -899,6 +1261,52 @@ keydb_search_reset (KEYDB_HANDLE hd)
 }
 
 
+static void
+dump_search_desc (const char *text, KEYDB_SEARCH_DESC *desc, size_t ndesc)
+{
+  int n;
+  const char *s;
+
+  for (n=0; n < ndesc; n++)
+    {
+      switch (desc[n].mode)
+        {
+        case KEYDB_SEARCH_MODE_NONE:      s = "none";      break;
+        case KEYDB_SEARCH_MODE_EXACT:     s = "exact";     break;
+        case KEYDB_SEARCH_MODE_SUBSTR:    s = "substr";    break;
+        case KEYDB_SEARCH_MODE_MAIL:      s = "mail";      break;
+        case KEYDB_SEARCH_MODE_MAILSUB:   s = "mailsub";   break;
+        case KEYDB_SEARCH_MODE_MAILEND:   s = "mailend";   break;
+        case KEYDB_SEARCH_MODE_WORDS:     s = "words";     break;
+        case KEYDB_SEARCH_MODE_SHORT_KID: s = "short_kid"; break;
+        case KEYDB_SEARCH_MODE_LONG_KID:  s = "long_kid";  break;
+        case KEYDB_SEARCH_MODE_FPR16:     s = "fpr16";     break;
+        case KEYDB_SEARCH_MODE_FPR20:     s = "fpr20";     break;
+        case KEYDB_SEARCH_MODE_FPR:       s = "fpr";       break;
+        case KEYDB_SEARCH_MODE_ISSUER:    s = "issuer";    break;
+        case KEYDB_SEARCH_MODE_ISSUER_SN: s = "issuer_sn"; break;
+        case KEYDB_SEARCH_MODE_SN:        s = "sn";        break;
+        case KEYDB_SEARCH_MODE_SUBJECT:   s = "subject";   break;
+        case KEYDB_SEARCH_MODE_KEYGRIP:   s = "keygrip";   break;
+        case KEYDB_SEARCH_MODE_FIRST:     s = "first";     break;
+        case KEYDB_SEARCH_MODE_NEXT:      s = "next";      break;
+        default:                          s = "?";         break;
+        }
+      if (!n)
+        log_debug ("%s: mode=%s", text, s);
+      else
+        log_debug ("%*s  mode=%s", (int)strlen (text), "", s);
+      if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID)
+        log_printf (" %08lX%08lX", (unsigned long)desc[n].u.kid[0],
+                    (unsigned long)desc[n].u.kid[1]);
+      else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID)
+        log_printf (" %08lX", (unsigned long)desc[n].u.kid[1]);
+      else if (desc[n].mode == KEYDB_SEARCH_MODE_SUBSTR)
+        log_printf (" '%s'", desc[n].u.name);
+    }
+}
+
+
 /*
  * Search through all keydb resources, starting at the current
  * position, for a keyblock which contains one of the keys described
@@ -906,14 +1314,30 @@ keydb_search_reset (KEYDB_HANDLE hd)
  * keyring was found.
  */
 gpg_error_t
-keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
-              size_t ndesc, size_t *descindex)
+keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
+              size_t ndesc, size_t *descindex)
 {
   gpg_error_t rc;
 
   if (!hd)
     return gpg_error (GPG_ERR_INV_ARG);
 
+  if (DBG_CLOCK)
+    log_clock ("keydb_search enter");
+
+  if (DBG_CACHE)
+    dump_search_desc ("keydb_search", desc, ndesc);
+
+  if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID
+      && keyblock_cache.state  == KEYBLOCK_CACHE_FILLED
+      && keyblock_cache.kid[0] == desc[0].u.kid[0]
+      && keyblock_cache.kid[1] == desc[0].u.kid[1])
+    {
+      if (DBG_CLOCK)
+        log_clock ("keydb_search leave (cached)");
+      return 0;
+    }
+
   rc = -1;
   while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
          && hd->current >= 0 && hd->current < hd->used)
@@ -940,9 +1364,22 @@ keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         hd->found = hd->current;
     }
 
-  return ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
-          ? gpg_error (GPG_ERR_NOT_FOUND)
-          : rc);
+  rc = ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
+        ? gpg_error (GPG_ERR_NOT_FOUND)
+        : rc);
+
+  keyblock_cache_clear ();
+  if (!rc && ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID)
+    {
+      keyblock_cache.state = KEYBLOCK_CACHE_PREPARED;
+      keyblock_cache.kid[0] = desc[0].u.kid[0];
+      keyblock_cache.kid[1] = desc[0].u.kid[1];
+    }
+
+  if (DBG_CLOCK)
+    log_clock (rc? "keydb_search leave (not found)"
+                 : "keydb_search leave (found)");
+  return rc;
 }
 
 
@@ -953,7 +1390,7 @@ keydb_search_first (KEYDB_HANDLE hd)
 
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
-  return keydb_search (hd, &desc, 1);
+  return keydb_search (hd, &desc, 1, NULL);
 }
 
 gpg_error_t
@@ -963,7 +1400,7 @@ keydb_search_next (KEYDB_HANDLE hd)
 
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_NEXT;
-  return keydb_search (hd, &desc, 1);
+  return keydb_search (hd, &desc, 1, NULL);
 }
 
 gpg_error_t
@@ -975,7 +1412,7 @@ keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
   desc.u.kid[0] = kid[0];
   desc.u.kid[1] = kid[1];
-  return keydb_search (hd, &desc, 1);
+  return keydb_search (hd, &desc, 1, NULL);
 }
 
 gpg_error_t
@@ -986,5 +1423,5 @@ keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr)
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FPR;
   memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN);
-  return keydb_search (hd, &desc, 1);
+  return keydb_search (hd, &desc, 1, NULL);
 }