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 final trailer
* create a "sigdata" block suitable for a call to solv_pgpverify */
static void
-pgpsig_makesigdata(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];
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;
unsigned char *pubdata = 0;
int pubdatal = 0;
+ *subkeyofstr = 0;
for (; ; p += l, pl -= l)
{
int hl = parsepkgheader(p, pl, &tag, &l);
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)
}
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));
}
}
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])
}
else if (p[0] == 4 && l >= 6)
{
- void *h;
+ Chksum *h;
unsigned char hdr[3];
unsigned char fp[20];
char fpx[40 + 1];
htype = pgphashalgo2type(sig.hashalgo);
if (htype && sig.mpioff)
{
- void *h = solv_chksum_create(htype);
+ Chksum *h = solv_chksum_create(htype);
pgpsig_makesigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
solv_chksum_free(h, 0);
}
}
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;
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++)
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;
- pgpsig_init(&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);
- pgpsig_makesigdata(&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;
+ if (!chk || solv_chksum_isfinished(chk))
+ return 0;
pgpsig_init(&pgpsig, ss->sigpkt, ss->sigpktl);
chk2 = solv_chksum_create_clone(chk);
pgpsig_makesigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);