Imported Upstream version 0.6.27
[platform/upstream/libsolv.git] / ext / repo_pubkey.c
index 7cf6da1..eb83839 100644 (file)
@@ -14,8 +14,6 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <limits.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -234,6 +232,7 @@ armor(unsigned char *pkt, int pktl, const char *startstr, const char *endstr, co
   return str;
 }
 
+/* internal representation of a signature */
 struct pgpsig {
   int type;
   Id hashalgo;
@@ -256,11 +255,20 @@ pgphashalgo2type(int algo)
     return REPOKEY_TYPE_SHA1;
   if (algo == 8)
     return REPOKEY_TYPE_SHA256;
+  if (algo == 9)
+    return REPOKEY_TYPE_SHA384;
+  if (algo == 10)
+    return REPOKEY_TYPE_SHA512;
+  if (algo == 11)
+    return REPOKEY_TYPE_SHA224;
   return 0;
 }
 
+/* hash the pubkey/userid data for self-sig verification
+ * hash the final trailer
+ * create a "sigdata" block suitable for a call to solv_pgpverify */
 static void
-createsigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, void *h)
+pgpsig_makesigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, Chksum *h)
 {
   int type = sig->type;
   unsigned char b[6];
@@ -318,6 +326,10 @@ createsigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey
     }
 }
 
+/* parse the header of a subpacket contained in a signature packet
+ * returns: length of the packet header, 0 if there was an error
+ * *pktlp is set to the packet length, the tag is the first byte.
+ */
 static inline int
 parsesubpkglength(unsigned char *q, int ql, int *pktlp)
 {
@@ -349,9 +361,11 @@ parsesubpkglength(unsigned char *q, int ql, int *pktlp)
   return hl;
 }
 
+/* parse a signature packet, initializing the pgpsig struct */
 static void
-parsesigpacket(struct pgpsig *sig, unsigned char *p, int l)
+pgpsig_init(struct pgpsig *sig, unsigned char *p, int l)
 {
+  memset(sig, 0, sizeof(*sig));
   sig->type = -1;
   if (p[0] == 3)
     {
@@ -424,6 +438,10 @@ parsesigpacket(struct pgpsig *sig, unsigned char *p, int l)
     }
 }
 
+/* parse a pgp packet header
+ * returns: length of the packet header, 0 if there was an error
+ * *tagp and *pktlp is set to the packet tag and the packet length
+ */
 static int
 parsepkgheader(unsigned char *p, int pl, int *tagp, int *pktlp)
 {
@@ -477,39 +495,97 @@ parsepkgheader(unsigned char *p, int pl, int *tagp, int *pktlp)
   return p - op;
 }
 
-
-static void
-parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
+/* parse the first pubkey (possible creating new packages for the subkeys)
+ * returns the number of parsed bytes.
+ * if flags contains ADD_WITH_SUBKEYS, all subkeys will be added as new
+ * solvables as well */
+static int
+parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
 {
+  Repo *repo = s->repo;
+  unsigned char *pstart = p;
   int tag, l;
   unsigned char keyid[8];
+  char subkeyofstr[17];
   unsigned int kcr = 0, maxex = 0, maxsigcr = 0;
   unsigned char *pubkey = 0;
   int pubkeyl = 0;
+  int insubkey = 0;
   unsigned char *userid = 0;
   int useridl = 0;
   unsigned char *pubdata = 0;
   int pubdatal = 0;
 
-  for (; pl; p += l, pl -= l)
+  *subkeyofstr = 0;
+  for (; ; p += l, pl -= l)
     {
       int hl = parsepkgheader(p, pl, &tag, &l);
-      if (!hl)
-       break;
+      if (!hl || (pubkey && (tag == 6 || tag == 14)))
+       {
+         /* finish old key */
+         if (kcr)
+           repodata_set_num(data, s - repo->pool->solvables, SOLVABLE_BUILDTIME, kcr);
+         if (maxex && maxex != -1)
+           repodata_set_num(data, s - repo->pool->solvables, PUBKEY_EXPIRES, maxex);
+         s->name = pool_str2id(s->repo->pool, insubkey ? "gpg-subkey" : "gpg-pubkey", 1);
+         s->evr = 1;
+         s->arch = 1;
+         if (userid && useridl)
+           {
+             char *useridstr = solv_malloc(useridl + 1);
+             memcpy(useridstr, userid, useridl);
+             useridstr[useridl] = 0;
+             setutf8string(data, s - repo->pool->solvables, SOLVABLE_SUMMARY, useridstr);
+             free(useridstr);
+           }
+         if (pubdata)
+           {
+             char keyidstr[17];
+             char evr[8 + 1 + 8 + 1];
+             solv_bin2hex(keyid, 8, keyidstr);
+             repodata_set_str(data, s - repo->pool->solvables, PUBKEY_KEYID, keyidstr);
+             /* build rpm-style evr */
+             strcpy(evr, keyidstr + 8);
+             sprintf(evr + 8, "-%08x", maxsigcr);
+             s->evr = pool_str2id(repo->pool, evr, 1);
+           }
+         if (insubkey && *subkeyofstr)
+           repodata_set_str(data, s - repo->pool->solvables, PUBKEY_SUBKEYOF, subkeyofstr);
+         if (pubdata)          /* set data blob */
+           repodata_set_binary(data, s - repo->pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
+         if (!pl)
+           break;
+         if (!hl)
+           {
+             p = 0;    /* parse error */
+             break;
+           }
+         if (tag == 6 || (tag == 14 && !(flags & ADD_WITH_SUBKEYS)))
+           break;
+         if (tag == 14 && pubdata && !insubkey)
+           solv_bin2hex(keyid, 8, subkeyofstr);
+         /* create new solvable for subkey */
+         s = pool_id2solvable(repo->pool, repo_add_solvable(repo));
+       }
       p += hl;
       pl -= hl;
-      if (tag == 6)
+      if (!pubkey && tag != 6)
+       continue;
+      if (tag == 6 || (tag == 14 && (flags & ADD_WITH_SUBKEYS) != 0))          /* Public-Key Packet */
        {
-         if (pubkey)
-           break;      /* one key at a time, please */
-         pubkey = solv_malloc(l);
-         if (l)
-           memcpy(pubkey, p, l);
-         pubkeyl = l;
+         if (tag == 6)
+           {
+             pubkey = solv_memdup(p, l);
+             pubkeyl = l;
+           }
+         else
+           insubkey = 1;
+         pubdata = 0;
+         pubdatal = 0;
          if (p[0] == 3 && l >= 10)
            {
              unsigned int ex;
-             void *h;
+             Chksum *h;
              maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
              ex = 0;
              if (p[5] || p[6])
@@ -549,7 +625,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
            }
          else if (p[0] == 4 && l >= 6)
            {
-             void *h;
+             Chksum *h;
              unsigned char hdr[3];
              unsigned char fp[20];
              char fpx[40 + 1];
@@ -570,14 +646,13 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
              pubdatal = l - 5;
            }
        }
-      if (tag == 2)
+      if (tag == 2)            /* Signature Packet */
        {
          struct pgpsig sig;
          Id htype;
          if (!pubdata)
            continue;
-         memset(&sig, 0, sizeof(sig));
-         parsesigpacket(&sig, p, l);
+         pgpsig_init(&sig, p, l);
          if (!sig.haveissuer || !((sig.type >= 0x10 && sig.type <= 0x13) || sig.type == 0x1f))
            continue;
          if (sig.type >= 0x10 && sig.type <= 0x13 && !userid)
@@ -585,8 +660,8 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
          htype = pgphashalgo2type(sig.hashalgo);
          if (htype && sig.mpioff)
            {
-             void *h = solv_chksum_create(htype);
-             createsigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
+             Chksum *h = solv_chksum_create(htype);
+             pgpsig_makesigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
              solv_chksum_free(h, 0);
            }
          if (!memcmp(keyid, sig.issuer, 8))
@@ -607,7 +682,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
                    maxsigcr = sig.created;
                }
            }
-         else
+         else if (flags & ADD_WITH_KEYSIGNATURES)
            {
              char issuerstr[17];
              Id shandle = repodata_new_handle(data);
@@ -623,7 +698,7 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
            }
          solv_free(sig.sigdata);
        }
-      if (tag == 13)
+      if (tag == 13 && !insubkey)              /* User ID Packet */
        {
          userid = solv_realloc(userid, l);
          if (l)
@@ -631,39 +706,9 @@ parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
          useridl = l;
        }
     }
-  if (kcr)
-    repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, kcr);
-  if (maxex && maxex != -1)
-    repodata_set_num(data, s - s->repo->pool->solvables, PUBKEY_EXPIRES, maxex);
-  s->name = pool_str2id(s->repo->pool, "gpg-pubkey", 1);
-  s->evr = 1;
-  s->arch = 1;
-  if (userid && useridl)
-    {
-      char *useridstr = solv_malloc(useridl + 1);
-      memcpy(useridstr, userid, useridl);
-      useridstr[useridl] = 0;
-      setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, useridstr);
-      free(useridstr);
-    }
-  if (pubdata)
-    {
-      char keyidstr[17];
-      solv_bin2hex(keyid, 8, keyidstr);
-      repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyidstr);
-    }
-  if (pubdata)
-    {
-      /* build rpm-style evr */
-      char evr[8 + 1 + 8 + 1];
-      solv_bin2hex(keyid + 4, 4, evr);
-      sprintf(evr + 8, "-%08x", maxsigcr);
-      s->evr = pool_str2id(s->repo->pool, evr, 1);
-      /* set data blob */
-      repodata_set_binary(data, s - s->repo->pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
-    }
   solv_free(pubkey);
   solv_free(userid);
+  return p ? p - pstart : 0;
 }
 
 
@@ -700,7 +745,7 @@ struct pgpDig_s {
 /* only rpm knows how to do the release calculation, we don't dare
  * to recreate all the bugs in libsolv */
 static void
-parsekeydata_rpm(Solvable *s, Repodata *data, unsigned char *pkts, int pktsl)
+parsepubkey_rpm(Solvable *s, Repodata *data, unsigned char *pkts, int pktsl)
 {
   Pool *pool = s->repo->pool;
   struct pgpDigParams_s *digpubkey;
@@ -743,23 +788,43 @@ parsekeydata_rpm(Solvable *s, Repodata *data, unsigned char *pkts, int pktsl)
 
 #endif /* ENABLE_RPMDB */
 
+/* parse an ascii armored pubkey
+ * adds multiple pubkeys if ADD_MULTIPLE_PUBKEYS is set */
 static int
-pubkey2solvable(Solvable *s, Repodata *data, char *pubkey)
+pubkey2solvable(Pool *pool, Id p, Repodata *data, char *pubkey, int flags)
 {
-  unsigned char *pkts;
-  int pktsl;
+  unsigned char *pkts, *pkts_orig;
+  int pktsl, pl = 0, tag, l, hl;
 
   if (!unarmor(pubkey, &pkts, &pktsl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"))
     {
-      pool_error(s->repo->pool, 0, "unarmor failure");
+      pool_error(pool, 0, "unarmor failure");
       return 0;
     }
-  setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_DESCRIPTION, pubkey);
-  parsekeydata(s, data, pkts, pktsl);
+  pkts_orig = pkts;
+  tag = 6;
+  while (pktsl)
+    {
+      if (tag == 6)
+       {
+         setutf8string(data, p, SOLVABLE_DESCRIPTION, pubkey);
+         pl = parsepubkey(pool->solvables + p, data, pkts, pktsl, flags);
 #ifdef ENABLE_RPMDB
-  parsekeydata_rpm(s, data, pkts, pktsl);
+         parsepubkey_rpm(pool->solvables + p, data, pkts, pktsl);
 #endif
-  solv_free((void *)pkts);
+         if (!pl || !(flags & ADD_MULTIPLE_PUBKEYS))
+           break;
+       }
+      pkts += pl;
+      pktsl -= pl;
+      hl = parsepkgheader(pkts, pktsl, &tag, &l);
+      if (!hl)
+       break;
+      pl = l + hl;
+      if (tag == 6)
+        p = repo_add_solvable(pool->solvables[p].repo);
+    }
+  solv_free((void *)pkts_orig);
   return 1;
 }
 
@@ -773,7 +838,6 @@ repo_add_rpmdb_pubkeys(Repo *repo, int flags)
   int i;
   char *str;
   Repodata *data;
-  Solvable *s;
   const char *rootdir = 0;
   void *state;
 
@@ -785,6 +849,7 @@ repo_add_rpmdb_pubkeys(Repo *repo, int flags)
   rpm_installedrpmdbids(state, "Name", "gpg-pubkey", &q);
   for (i = 0; i < q.count; i++)
     {
+      Id p, p2;
       void *handle;
       unsigned long long itime;
 
@@ -794,15 +859,23 @@ repo_add_rpmdb_pubkeys(Repo *repo, int flags)
       str = rpm_query(handle, SOLVABLE_DESCRIPTION);
       if (!str)
        continue;
-      s = pool_id2solvable(pool, repo_add_solvable(repo));
-      pubkey2solvable(s, data, str);
+      p = repo_add_solvable(repo);
+      if (!pubkey2solvable(pool, p, data, str, flags))
+       {
+         solv_free(str);
+         repo_free_solvable(repo, p, 1);
+         continue;
+       }
       solv_free(str);
       itime = rpm_query_num(handle, SOLVABLE_INSTALLTIME, 0);
-      if (itime)
-        repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLTIME, itime);
-      if (!repo->rpmdbid)
-       repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
-      repo->rpmdbid[s - pool->solvables - repo->start] = q.elements[i];
+      for (p2 = p; p2 < pool->nsolvables; p2++)
+       {
+         if (itime)
+           repodata_set_num(data, p2, SOLVABLE_INSTALLTIME, itime);
+         if (!repo->rpmdbid)
+           repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
+         repo->rpmdbid[p2 - repo->start] = q.elements[i];
+       }
     }
   queue_free(&q);
   rpm_state_free(state);
@@ -846,41 +919,45 @@ solv_slurp(FILE *fp, int *lenp)
 }
 
 Id
-repo_add_pubkey(Repo *repo, const char *key, int flags)
+repo_add_pubkey(Repo *repo, const char *keyfile, int flags)
 {
   Pool *pool = repo->pool;
   Repodata *data;
-  Solvable *s;
+  Id p;
   char *buf;
   FILE *fp;
 
   data = repo_add_repodata(repo, flags);
   buf = 0;
-  if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, key) : key, "r")) == 0)
+  if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, keyfile) : keyfile, "r")) == 0)
     {
-      pool_error(pool, -1, "%s: %s", key, strerror(errno));
+      pool_error(pool, -1, "%s: %s", keyfile, strerror(errno));
       return 0;
     }
   if ((buf = solv_slurp(fp, 0)) == 0)
     {
-      pool_error(pool, -1, "%s: %s", key, strerror(errno));
+      pool_error(pool, -1, "%s: %s", keyfile, strerror(errno));
       fclose(fp);
       return 0;
     }
   fclose(fp);
-  s = pool_id2solvable(pool, repo_add_solvable(repo));
-  if (!pubkey2solvable(s, data, buf))
+  p = repo_add_solvable(repo);
+  if (!pubkey2solvable(pool, p, data, buf, flags))
     {
-      repo_free_solvable(repo, s - pool->solvables, 1);
+      repo_free_solvable(repo, p, 1);
       solv_free(buf);
       return 0;
     }
   if (!(flags & REPO_NO_LOCATION))
-    repodata_set_location(data, s - pool->solvables, 0, 0, key);
+    {
+      Id p2;
+      for (p2 = p; p2 < pool->nsolvables; p2++)
+        repodata_set_location(data, p2, 0, 0, keyfile);
+    }
   solv_free(buf);
   if (!(flags & REPO_NO_INTERNALIZE))
     repodata_internalize(data);
-  return s - pool->solvables;
+  return p;
 }
 
 static int
@@ -904,15 +981,15 @@ is_pubkey_packet(unsigned char *pkt, int pktl)
 }
 
 static void
-add_one_pubkey(Pool *pool, Repo *repo, Repodata *data, unsigned char *pbuf, int pbufl)
+add_one_pubkey(Pool *pool, Repo *repo, Repodata *data, unsigned char *pbuf, int pbufl, int flags)
 {
-  Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo));
+  Id p = repo_add_solvable(repo);
   char *solvversion = pool_tmpjoin(pool, "libsolv-", LIBSOLV_VERSION_STRING, 0);
   char *descr = armor(pbuf, pbufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----", solvversion);
-  setutf8string(data, s - pool->solvables, SOLVABLE_DESCRIPTION, descr);
-  parsekeydata(s, data, pbuf, pbufl);
+  setutf8string(data, p, SOLVABLE_DESCRIPTION, descr);
+  parsepubkey(pool->solvables + p, data, pbuf, pbufl, flags);
 #ifdef ENABLE_RPMDB
-  parsekeydata_rpm(s, data, pbuf, pbufl);
+  parsepubkey_rpm(pool->solvables + p, data, pbuf, pbufl);
 #endif
 }
 
@@ -959,7 +1036,7 @@ repo_add_keyring(Repo *repo, FILE *fp, int flags)
          /* found new pubkey! flush old */
          if (pbufl)
            {
-             add_one_pubkey(pool, repo, data, pbuf, pbufl);
+             add_one_pubkey(pool, repo, data, pbuf, pbufl, flags);
              pbuf = solv_free(pbuf);
              pbufl = 0;
            }
@@ -974,7 +1051,7 @@ repo_add_keyring(Repo *repo, FILE *fp, int flags)
       pbufl += pl;
     }
   if (pbufl)
-    add_one_pubkey(pool, repo, data, pbuf, pbufl);
+    add_one_pubkey(pool, repo, data, pbuf, pbufl, flags);
   solv_free(pbuf);
   solv_free(buf);
   if (!(flags & REPO_NO_INTERNALIZE))
@@ -983,7 +1060,7 @@ repo_add_keyring(Repo *repo, FILE *fp, int flags)
 }
 
 int
-repo_add_keydir(Repo *repo, const char *keydir, int flags, const char *suffix)
+repo_add_keydir(Repo *repo, const char *keydir, const char *suffix, int flags)
 {
   Pool *pool = repo->pool;
   Repodata *data;
@@ -1006,7 +1083,7 @@ repo_add_keydir(Repo *repo, const char *keydir, int flags, const char *suffix)
       l = strlen(dn);
       if (sl && (l < sl || strcmp(dn + l - sl, suffix) != 0))
        continue;
-      repo_add_pubkey(repo, pool_tmpjoin(pool, rkeydir, "/", dn), flags);
+      repo_add_pubkey(repo, pool_tmpjoin(pool, rkeydir, "/", dn), flags | REPO_REUSE_REPODATA);
     }
   solv_free(rkeydir);
   for (i = 0; i < nent; i++)
@@ -1050,8 +1127,7 @@ solvsig_create(FILE *fp)
       solv_free(sig);
       return 0;
     }
-  memset(&pgpsig, 0, sizeof(pgpsig));
-  parsesigpacket(&pgpsig, sig + hl, pktl);
+  pgpsig_init(&pgpsig, sig + hl, pktl);
   if (pgpsig.type != 0 || !pgpsig.haveissuer)
     {
       solv_free(sig);
@@ -1075,72 +1151,91 @@ solvsig_free(Solvsig *ss)
   solv_free(ss);
 }
 
-#ifdef ENABLE_PGPVRFY
+static int
+repo_find_all_pubkeys_cmp(const void *va, const void *vb, void *dp)
+{
+  Pool *pool = dp;
+  Id a = *(Id *)va;
+  Id b = *(Id *)vb;
+  /* cannot use evrcmp, as rpm says '0' > 'a' */
+  return strcmp(pool_id2str(pool, pool->solvables[b].evr), pool_id2str(pool, pool->solvables[a].evr));
+}
 
-int
-solv_verify_sig(const unsigned char *pubdata, int pubdatal, unsigned char *sigpkt, int sigpktl, void *chk)
+void
+repo_find_all_pubkeys(Repo *repo, const char *keyid, Queue *q)
 {
-  struct pgpsig pgpsig;
-  int res;
-  Id htype;
-  void *chk2;
+  Id p;
+  Solvable *s;
 
-  memset(&pgpsig, 0, sizeof(pgpsig));
-  parsesigpacket(&pgpsig, sigpkt, sigpktl);
-  if (pgpsig.type != 0)
-    return 0;
-  htype = pgphashalgo2type(pgpsig.hashalgo);
-  if (!htype || htype != solv_chksum_get_type(chk))
-     return 0; /* wrong hash type? */
-  chk2 = solv_chksum_create_clone(chk);
-  createsigdata(&pgpsig, sigpkt, sigpktl, 0, 0, 0, 0, chk2);
-  solv_chksum_free(chk2, 0);
-  if (!pgpsig.sigdata)
-    return 0;
-  res = solv_pgpvrfy(pubdata, pubdatal, pgpsig.sigdata, pgpsig.sigdatal);
-  solv_free(pgpsig.sigdata);
-  return res;
+  queue_empty(q);
+  if (!keyid)
+    return;
+  queue_init(q);
+  FOR_REPO_SOLVABLES(repo, p, s)
+    {
+      const char *kidstr, *evr = pool_id2str(s->repo->pool, s->evr);
+
+      if (!evr || strncmp(evr, keyid + 8, 8) != 0)
+       continue;
+      kidstr = solvable_lookup_str(s, PUBKEY_KEYID);
+      if (kidstr && !strcmp(kidstr, keyid))
+        queue_push(q, p);
+    }
+  if (q->count > 1)
+    solv_sort(q->elements, q->count, sizeof(Id), repo_find_all_pubkeys_cmp, repo->pool);
+}
+
+Id
+repo_find_pubkey(Repo *repo, const char *keyid)
+{
+  Queue q;
+  Id p;
+  queue_init(&q);
+  repo_find_all_pubkeys(repo, keyid, &q);
+  p = q.count ? q.elements[0] : 0;
+  queue_free(&q);
+  return p;
 }
 
-/* warning: does not check key expiry/revokation, like gpgv or rpm */
+#ifdef ENABLE_PGPVRFY
+
+/* warning: does not check key expiry/revokation, same as with gpgv or rpm */
 /* returns the Id of the pubkey that verified the signature */
 Id
 repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid)
 {
   Id p;
-  Solvable *s;
+  Queue q;
+  int i;
 
   if (!sigdata || !keyid)
     return 0;
-  FOR_REPO_SOLVABLES(repo, p, s)
+  queue_init(&q);
+  repo_find_all_pubkeys(repo, keyid, &q);
+  for (i = 0; i < q.count; i++)
     {
-      const char *evr = pool_id2str(s->repo->pool, s->evr);
-      const char *kidstr;
-      const unsigned char *pubdata;
       int pubdatal;
-
-      if (!evr || strncmp(evr, keyid + 8, 8) != 0)
-       continue;
-      kidstr = solvable_lookup_str(s, PUBKEY_KEYID);
-      if (!kidstr || strcmp(kidstr, keyid) != 0)
-        continue;
-      pubdata = repo_lookup_binary(repo, p, PUBKEY_DATA, &pubdatal);
-      if (solv_pgpvrfy(pubdata, pubdatal, sigdata, sigdatal))
-        return p;
+      const unsigned char *pubdata = repo_lookup_binary(repo, q.elements[i], PUBKEY_DATA, &pubdatal);
+      if (pubdata && solv_pgpvrfy(pubdata, pubdatal, sigdata, sigdatal))
+       break;
     }
-  return 0;
+  p = i < q.count? q.elements[i] : 0;
+  queue_free(&q);
+  return p;
 }
 
 Id
-solvsig_verify(Solvsig *ss, Repo *repo, void *chk)
+solvsig_verify(Solvsig *ss, Repo *repo, Chksum *chk)
 {
   struct pgpsig pgpsig;
   void *chk2;
   Id p;
 
-  parsesigpacket(&pgpsig, ss->sigpkt, ss->sigpktl);
+  if (!chk || solv_chksum_isfinished(chk))
+    return 0;
+  pgpsig_init(&pgpsig, ss->sigpkt, ss->sigpktl);
   chk2 = solv_chksum_create_clone(chk);
-  createsigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);
+  pgpsig_makesigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);
   solv_chksum_free(chk2, 0);
   if (!pgpsig.sigdata)
     return 0;