summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/libsolvext.ver5
-rw-r--r--ext/repo_pubkey.c89
-rw-r--r--ext/repo_pubkey.h18
3 files changed, 89 insertions, 23 deletions
diff --git a/ext/libsolvext.ver b/ext/libsolvext.ver
index ac00e0d..7722c22 100644
--- a/ext/libsolvext.ver
+++ b/ext/libsolvext.ver
@@ -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;
diff --git a/ext/repo_pubkey.c b/ext/repo_pubkey.c
index 3dffa20..5f157d1 100644
--- a/ext/repo_pubkey.c
+++ b/ext/repo_pubkey.c
@@ -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
diff --git a/ext/repo_pubkey.h b/ext/repo_pubkey.h
index 193512a..dec9e16 100644
--- a/ext/repo_pubkey.h
+++ b/ext/repo_pubkey.h
@@ -10,6 +10,22 @@
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);
+