add repo_verify_sigdata, refactor solv_parse_sig into solvsig_create/free/verify
authorMichael Schroeder <mls@suse.de>
Fri, 25 Oct 2013 12:43:26 +0000 (14:43 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 25 Oct 2013 12:43:26 +0000 (14:43 +0200)
ext/libsolvext.ver
ext/repo_pubkey.c
ext/repo_pubkey.h

index ac00e0d7accc4adc231465688b3720ecf8c7e2f9..7722c22df242a9c3a02253fefe28d0d370f71f4e 100644 (file)
@@ -35,6 +35,7 @@ SOLV_1.0 {
                repo_add_susetags;
                repo_add_updateinfoxml;
                repo_add_zyppdb_products;
+               repo_verify_sigdata;
                rpm_byfp;
                rpm_byrpmdbid;
                rpm_byrpmh;
@@ -44,12 +45,14 @@ SOLV_1.0 {
                rpm_query_num;
                rpm_state_create;
                rpm_state_free;
-               solv_parse_sig;
                solv_verify_sig;
                solv_xfopen;
                solv_xfopen_buf;
                solv_xfopen_fd;
                solv_xfopen_iscompressed;
+               solvsig_create;
+               solvsig_free;
+               solvsig_verify;
                testcase_add_testtags;
                testcase_job2str;
                testcase_solvid2str;
index 3dffa20e5b34ccfea01309751c8c7608b65d3a62..5f157d11940b215d1b34f7098043cdbbb4e3167c 100644 (file)
@@ -222,7 +222,7 @@ createsigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey
   const unsigned char *cs;
   int csl;
 
-  if (sig->mpioff < 2 || l <= sig->mpioff)
+  if (!h || sig->mpioff < 2 || l <= sig->mpioff)
     return;
   if ((type >= 0x10 && type <= 0x13) || type == 0x1f || type == 0x18 || type == 0x20 || type == 0x28)
     {
@@ -847,19 +847,14 @@ is_sig_packet(unsigned char *sig, int sigl)
   return 1;
 }
 
-Id
-solv_parse_sig(FILE *fp, unsigned char **sigpktp, int *sigpktlp, char *keyidstr)
+Solvsig *
+solvsig_create(FILE *fp)
 {
+  Solvsig *ss;
   unsigned char *sig;
   int sigl, hl, tag, pktl;
   struct pgpsig pgpsig;
-  Id htype;
 
-  if (sigpktp)
-    {
-      *sigpktp = 0;
-      *sigpktlp = 0;
-    }
   if ((sig = (unsigned char *)solv_slurp(fp, &sigl)) == 0)
     return 0;
   if (!is_sig_packet(sig, sigl))
@@ -885,22 +880,27 @@ solv_parse_sig(FILE *fp, unsigned char **sigpktp, int *sigpktlp, char *keyidstr)
     }
   memset(&pgpsig, 0, sizeof(pgpsig));
   parsesigpacket(&pgpsig, sig + hl, pktl);
-  htype = pgphashalgo2type(pgpsig.hashalgo);
-  if (pgpsig.type != 0 || !htype || !pgpsig.haveissuer)
+  if (pgpsig.type != 0 || !pgpsig.haveissuer)
     {
       solv_free(sig);
       return 0;
     }
-  if (sigpktp)
-    {
-      *sigpktp = solv_malloc(pktl);
-      memcpy(*sigpktp, sig + hl, pktl);
-      *sigpktlp = pktl;
-    }
+  ss = solv_calloc(1, sizeof(*ss));
+  ss->sigpkt = solv_memdup(sig + hl, pktl);
+  ss->sigpktl = pktl;
   solv_free(sig);
-  if (keyidstr)
-    solv_bin2hex(pgpsig.issuer, 8, keyidstr);
-  return htype;
+  solv_bin2hex(pgpsig.issuer, 8, ss->keyid);
+  ss->htype = pgphashalgo2type(pgpsig.hashalgo);
+  ss->created = pgpsig.created;
+  ss->expires = pgpsig.expires;
+  return ss;
+}
+
+void
+solvsig_free(Solvsig *ss)
+{
+  solv_free(ss->sigpkt);
+  solv_free(ss);
 }
 
 #ifdef ENABLE_PGPVRFY
@@ -918,7 +918,7 @@ solv_verify_sig(const unsigned char *pubdata, int pubdatal, unsigned char *sigpk
   if (pgpsig.type != 0)
     return 0;
   htype = pgphashalgo2type(pgpsig.hashalgo);
-  if (htype != solv_chksum_get_type(chk))
+  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);
@@ -930,5 +930,52 @@ solv_verify_sig(const unsigned char *pubdata, int pubdatal, unsigned char *sigpk
   return res;
 }
 
+/* warning: does not check key expiry/revokation, like 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;
+
+  if (!sigdata || !keyid)
+    return 0;
+  FOR_REPO_SOLVABLES(repo, p, s)
+    {
+      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;
+    }
+  return 0;
+}
+
+Id
+solvsig_verify(Solvsig *ss, Repo *repo, void *chk)
+{
+  struct pgpsig pgpsig;
+  void *chk2;
+  Id p;
+
+  parsesigpacket(&pgpsig, ss->sigpkt, ss->sigpktl);
+  chk2 = solv_chksum_create_clone(chk);
+  createsigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);
+  solv_chksum_free(chk2, 0);
+  if (!pgpsig.sigdata)
+    return 0;
+  p = repo_verify_sigdata(repo, pgpsig.sigdata, pgpsig.sigdatal, ss->keyid);
+  solv_free(pgpsig.sigdata);
+  return p;
+}
+
 #endif
 
index 193512a7557fcea01c56f4a53cb5d710da0079cb..dec9e16a05eb35fef69c95bd2ae637b8ea609303 100644 (file)
 extern int repo_add_rpmdb_pubkeys(Repo *repo, int flags);
 extern Id repo_add_pubkey(Repo *repo, const char *key, int flags);
 
-Id solv_parse_sig(FILE *fp, unsigned char **sigpktp, int *sigpktlp, char *keyidstr);
+/* signature parsing */
+typedef struct _solvsig {
+  unsigned char *sigpkt;
+  int sigpktl;
+  Id htype;
+  unsigned int created;
+  unsigned int expires;
+  char keyid[17];
+} Solvsig;
+
+Solvsig *solvsig_create(FILE *fp);
+void solvsig_free(Solvsig *ss);
+Id solvsig_verify(Solvsig *ss, Repo *repo, void *chk);
+
+/* raw signature verification */
 int solv_verify_sig(const unsigned char *pubdata, int pubdatal, unsigned char *sigpkt, int sigpktl, void *chk);
+Id repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid);
+