2 * Copyright (c) 2007-2013, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * support for pubkey reading
15 #include <sys/types.h>
26 #include <rpm/rpmio.h>
27 #include <rpm/rpmpgp.h>
29 #include <rpm/header.h>
31 #include <rpm/rpmdb.h>
39 #include "repo_rpmdb.h"
40 #include "repo_pubkey.h"
42 #include "solv_pgpvrfy.h"
46 setutf8string(Repodata *repodata, Id handle, Id tag, const char *str)
48 if (str[solv_validutf8(str)])
50 char *ustr = solv_latin1toutf8(str); /* not utf8, assume latin1 */
51 repodata_set_str(repodata, handle, tag, ustr);
55 repodata_set_str(repodata, handle, tag, str);
59 r64dec1(char *p, unsigned int *vp, int *eofp)
69 if (x >= 'A' && x <= 'Z')
71 else if (x >= 'a' && x <= 'z')
73 else if (x >= '0' && x <= '9')
100 crc24(unsigned char *p, int len)
102 unsigned int crc = 0xb704ce;
108 for (i = 0; i < 8; i++)
109 if ((crc <<= 1) & 0x1000000)
112 return crc & 0xffffff;
116 unarmor(char *pubkey, unsigned char **pktp, int *pktlp, const char *startstr, const char *endstr)
118 char *p, *pubkeystart = pubkey;
120 unsigned char *buf, *bp;
127 l = strlen(startstr);
128 while (strncmp(pubkey, startstr, l) != 0)
130 pubkey = strchr(pubkey, '\n');
135 pubkey = strchr(pubkey, '\n');
138 /* skip header lines */
141 while (*pubkey == ' ' || *pubkey == '\t')
145 pubkey = strchr(pubkey, '\n');
150 p = strchr(pubkey, '=');
154 bp = buf = solv_malloc(l * 3 / 4 + 4);
158 pubkey = r64dec1(pubkey, &v, &eof);
168 while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
171 if (*pubkey != '=' || (pubkey = r64dec1(pubkey + 1, &v, &eof)) == 0)
176 if (v != crc24(buf, bp - buf))
181 while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
183 if (strncmp(pubkey, endstr, strlen(endstr)) != 0)
188 p = strchr(pubkey, '\n');
190 p = pubkey + strlen(pubkey);
193 return (p ? p + 1 : pubkey + strlen(pubkey)) - pubkeystart;
196 #define ARMOR_NLAFTER 16
199 armor(unsigned char *pkt, int pktl, const char *startstr, const char *endstr, const char *version)
201 static const char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
202 char *str = solv_malloc(strlen(startstr) + strlen(endstr) + strlen(version) + (pktl / 3) * 4 + (pktl / (ARMOR_NLAFTER * 3)) + 30);
207 v = crc24(pkt, pktl);
208 sprintf(p, "%s\nVersion: %s\n\n", startstr, version);
210 for (i = -1; pktl > 0; pktl -= 3)
212 if (++i == ARMOR_NLAFTER)
218 b = pktl > 1 ? *pkt++ : 0;
219 c = pktl > 2 ? *pkt++ : 0;
220 *p++ = bintoasc[a >> 2];
221 *p++ = bintoasc[(a & 3) << 4 | b >> 4];
222 *p++ = pktl > 1 ? bintoasc[(b & 15) << 2 | c >> 6] : '=';
223 *p++ = pktl > 2 ? bintoasc[c & 63] : '=';
227 *p++ = bintoasc[v >> 18 & 0x3f];
228 *p++ = bintoasc[v >> 12 & 0x3f];
229 *p++ = bintoasc[v >> 6 & 0x3f];
230 *p++ = bintoasc[v & 0x3f];
231 sprintf(p, "\n%s\n", endstr);
235 /* internal representation of a signature */
239 unsigned char issuer[8];
241 unsigned int created;
242 unsigned int expires;
243 unsigned int keyexpires;
244 unsigned char *sigdata;
250 pgphashalgo2type(int algo)
253 return REPOKEY_TYPE_MD5;
255 return REPOKEY_TYPE_SHA1;
257 return REPOKEY_TYPE_SHA256;
259 return REPOKEY_TYPE_SHA384;
261 return REPOKEY_TYPE_SHA512;
263 return REPOKEY_TYPE_SHA224;
267 /* hash the pubkey/userid data for self-sig verification
268 * hash the final trailer
269 * create a "sigdata" block suitable for a call to solv_pgpverify */
271 pgpsig_makesigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, Chksum *h)
273 int type = sig->type;
275 const unsigned char *cs;
278 if (!h || sig->mpioff < 2 || l <= sig->mpioff)
280 if (p[0] != 3 && p[0] != 4 && p[0] != 5)
281 return; /* unsupported signature version */
282 if ((type >= 0x10 && type <= 0x13) || type == 0x1f || type == 0x18 || type == 0x20 || type == 0x28)
289 solv_chksum_add(h, b, 3);
294 b[1] = pubkeyl >> 24;
295 b[2] = pubkeyl >> 16;
298 solv_chksum_add(h, b, 5);
300 solv_chksum_add(h, pubkey, pubkeyl);
302 if ((type >= 0x10 && type <= 0x13))
307 b[1] = useridl >> 24;
308 b[2] = useridl >> 16;
311 solv_chksum_add(h, b, 5);
313 solv_chksum_add(h, userid, useridl);
317 solv_chksum_add(h, p + 2, 5);
320 int hl = 6 + (p[4] << 8 | p[5]);
321 solv_chksum_add(h, p, hl);
328 solv_chksum_add(h, b, 6);
332 int hl = 6 + (p[4] << 8 | p[5]);
333 solv_chksum_add(h, p, hl);
334 if (type == 0 || type == 1)
337 solv_chksum_add(h, b, 6);
342 b[2] = b[3] = b[4] = b[5] = 0;
347 solv_chksum_add(h, b, 10);
351 cs = solv_chksum_get(h, &csl);
352 if (cs[0] == p[sig->mpioff - 2] && cs[1] == p[sig->mpioff - 1])
354 int ml = l - sig->mpioff;
355 sig->sigdata = solv_malloc(2 + csl + ml);
356 sig->sigdatal = 2 + csl + ml;
357 sig->sigdata[0] = p[0] == 3 ? p[15] : p[2];
358 sig->sigdata[1] = p[0] == 3 ? p[16] : p[3];
359 memcpy(sig->sigdata + 2, cs, csl);
360 memcpy(sig->sigdata + 2 + csl, p + sig->mpioff, ml);
364 /* parse the header of a subpacket contained in a signature packet
365 * returns: length of the packet header, 0 if there was an error
366 * *pktlp is set to the packet length, the tag is the first byte.
369 parsesubpkglength(unsigned char *q, int ql, int *pktlp)
372 /* decode sub-packet length, ql must be > 0 */
381 if (ql < 5 || q[0] != 0)
383 sl = q[1] << 16 | q[2] << 8 | q[3];
390 sl = ((x - 192) << 8) + q[0] + 192;
393 if (!sl || ql < sl + hl) /* sub pkg tag is included in length, i.e. sl must not be zero */
399 /* parse a signature packet, initializing the pgpsig struct */
401 pgpsig_init(struct pgpsig *sig, unsigned char *p, int l)
403 memset(sig, 0, sizeof(*sig));
407 /* printf("V3 signature packet\n"); */
408 if (l <= 19 || p[1] != 5)
412 memcpy(sig->issuer, p + 7, 8);
413 sig->created = p[3] << 24 | p[4] << 16 | p[5] << 8 | p[6];
414 sig->hashalgo = p[16];
422 /* printf("V4 signature packet\n"); */
426 sig->hashalgo = p[3];
428 sig->keyexpires = -1;
429 for (j = 0; q && j < 2; j++)
436 ql = q[0] << 8 | q[1];
446 hl = parsesubpkglength(q, ql, &sl);
454 x = q[0] & 127; /* strip critical bit */
455 /* printf("%d SIGSUB %d %d\n", j, x, sl); */
456 if (x == 16 && sl == 9 && !sig->haveissuer)
459 memcpy(sig->issuer, q + 1, 8);
461 if (x == 2 && j == 0)
462 sig->created = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
463 if (x == 3 && j == 0)
464 sig->expires = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
465 if (x == 9 && j == 0)
466 sig->keyexpires = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
471 if (q && q - p + 2 < l)
472 sig->mpioff = q - p + 2;
476 /* parse a pgp packet header
477 * returns: length of the packet header, 0 if there was an error
478 * *tagp and *pktlp is set to the packet tag and the packet length
481 parsepkgheader(unsigned char *p, int pl, int *tagp, int *pktlp)
483 unsigned char *op = p;
490 if (!(x & 128) || pl <= 0)
494 *tagp = (x & 0x3c) >> 2; /* old format */
496 if (x > 4 || pl < x || (x == 4 && p[0]))
504 *tagp = (x & 0x3f); /* new format */
509 else if (x >= 192 && x < 224)
513 l = ((x - 192) << 8) + *p++ + 192;
518 if (pl <= 4 || p[0] != 0) /* sanity: p[0] must be zero */
520 l = p[1] << 16 | p[2] << 8 | p[3];
533 /* parse the first pubkey (possible creating new packages for the subkeys)
534 * returns the number of parsed bytes.
535 * if flags contains ADD_WITH_SUBKEYS, all subkeys will be added as new
536 * solvables as well */
538 parsepubkey(Solvable *s, Repodata *data, unsigned char *p, int pl, int flags)
540 Repo *repo = s->repo;
541 Pool *pool = repo->pool;
542 unsigned char *pstart = p;
544 unsigned char keyid[8];
545 char subkeyofstr[17];
546 unsigned int kcr = 0, maxex = 0, maxsigcr = 0, rpmsigcr = 0;
547 unsigned char *pubkey = 0;
550 unsigned char *userid = 0;
552 unsigned char *pubdata = 0;
556 for (; ; p += l, pl -= l)
558 int hl = parsepkgheader(p, pl, &tag, &l);
559 if (!hl || (pubkey && (tag == 6 || tag == 14)))
563 repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, kcr);
564 if (maxex && maxex != -1)
565 repodata_set_num(data, s - pool->solvables, PUBKEY_EXPIRES, maxex);
566 s->name = pool_str2id(pool, insubkey ? "gpg-subkey" : "gpg-pubkey", 1);
569 if (userid && useridl)
571 char *useridstr = solv_malloc(useridl + 1);
572 memcpy(useridstr, userid, useridl);
573 useridstr[useridl] = 0;
574 setutf8string(data, s - pool->solvables, SOLVABLE_SUMMARY, useridstr);
580 char evr[8 + 1 + 8 + 1];
581 solv_bin2hex(keyid, 8, keyidstr);
582 repodata_set_str(data, s - pool->solvables, PUBKEY_KEYID, keyidstr);
583 /* build rpm-style evr */
584 strcpy(evr, keyidstr + 8);
585 sprintf(evr + 8, "-%08x", (flags & USE_RPM_PUBKEY_BUILTTIME) ? rpmsigcr : maxsigcr);
586 s->evr = pool_str2id(pool, evr, 1);
588 if (insubkey && *subkeyofstr)
589 repodata_set_str(data, s - pool->solvables, PUBKEY_SUBKEYOF, subkeyofstr);
590 if (pubdata) /* set data blob */
591 repodata_set_binary(data, s - pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
596 p = 0; /* parse error */
599 if (tag == 6 || (tag == 14 && !(flags & ADD_WITH_SUBKEYS)))
601 if (tag == 14 && pubdata && !insubkey)
602 solv_bin2hex(keyid, 8, subkeyofstr);
603 /* create new solvable for subkey */
604 s = pool_id2solvable(pool, repo_add_solvable(repo));
608 if (!pubkey && tag != 6)
610 if (tag == 6 || (tag == 14 && (flags & ADD_WITH_SUBKEYS) != 0)) /* Public-Key Packet */
614 pubkey = solv_memdup(p, l);
621 if (p[0] == 3 && l >= 10)
625 maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
629 ex = kcr + 24*3600 * (p[5] << 8 | p[6]);
634 if (p[7] == 1) /* RSA */
637 unsigned char fp[16];
641 ql = ((p[8] << 8 | p[9]) + 7) / 8; /* length of public modulus */
642 if (ql >= 8 && 10 + ql + 2 <= l)
644 memcpy(keyid, p + 10 + ql - 8, 8); /* keyid is last 64 bits of public modulus */
646 ql2 = ((q[0] << 8 | q[1]) + 7) / 8; /* length of encryption exponent */
647 if (10 + ql + 2 + ql2 <= l)
649 /* fingerprint is the md5 over the two MPI bodies */
650 h = solv_chksum_create(REPOKEY_TYPE_MD5);
651 solv_chksum_add(h, p + 10, ql);
652 solv_chksum_add(h, q + 2, ql2);
653 solv_chksum_free(h, fp);
654 solv_bin2hex(fp, 16, fpx);
655 repodata_set_str(data, s - pool->solvables, PUBKEY_FINGERPRINT, fpx);
662 else if (p[0] == 4 && l >= 6)
665 unsigned char hdr[3];
666 unsigned char fp[20];
667 char fpx[20 * 2 + 1];
669 maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
673 /* fingerprint is the sha1 over the packet */
674 h = solv_chksum_create(REPOKEY_TYPE_SHA1);
675 solv_chksum_add(h, hdr, 3);
676 solv_chksum_add(h, p, l);
677 solv_chksum_free(h, fp);
678 solv_bin2hex(fp, 20, fpx);
679 repodata_set_str(data, s - pool->solvables, PUBKEY_FINGERPRINT, fpx);
680 memcpy(keyid, fp + (20 - 8), 8); /* keyid is last 64 bits of fingerprint */
684 else if (p[0] == 5 && l >= 6)
687 unsigned char hdr[5];
688 unsigned char fp[32];
689 char fpx[32 * 2 + 1];
691 maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
697 /* fingerprint is the sha256 over the packet */
698 h = solv_chksum_create(REPOKEY_TYPE_SHA256);
699 solv_chksum_add(h, hdr, 5);
700 solv_chksum_add(h, p, l);
701 solv_chksum_free(h, fp);
702 solv_bin2hex(fp, 32, fpx);
703 repodata_set_str(data, s - pool->solvables, PUBKEY_FINGERPRINT, fpx);
704 memcpy(keyid, fp + (32 - 8), 8); /* keyid is last 64 bits of fingerprint */
709 if (tag == 2) /* Signature Packet */
715 pgpsig_init(&sig, p, l);
716 if (!sig.haveissuer || !((sig.type >= 0x10 && sig.type <= 0x13) || sig.type == 0x1f))
718 if (sig.type >= 0x10 && sig.type <= 0x13 && !userid)
720 htype = pgphashalgo2type(sig.hashalgo);
721 if (htype && sig.mpioff)
723 Chksum *h = solv_chksum_create(htype);
724 pgpsig_makesigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
725 solv_chksum_free(h, 0);
728 rpmsigcr = sig.created;
729 if (!memcmp(keyid, sig.issuer, 8))
731 #ifdef ENABLE_PGPVRFY
732 /* found self sig, verify */
733 if (solv_pgpvrfy(pubdata, pubdatal, sig.sigdata, sig.sigdatal))
736 if (sig.keyexpires && maxex != -1)
738 if (sig.keyexpires == -1)
740 else if (sig.keyexpires + kcr > maxex)
741 maxex = sig.keyexpires + kcr;
743 if (sig.created > maxsigcr)
744 maxsigcr = sig.created;
747 else if (flags & ADD_WITH_KEYSIGNATURES)
750 Id shandle = repodata_new_handle(data);
751 solv_bin2hex(sig.issuer, 8, issuerstr);
752 repodata_set_str(data, shandle, SIGNATURE_ISSUER, issuerstr);
754 repodata_set_num(data, shandle, SIGNATURE_TIME, sig.created);
756 repodata_set_num(data, shandle, SIGNATURE_EXPIRES, sig.created + sig.expires);
758 repodata_set_binary(data, shandle, SIGNATURE_DATA, sig.sigdata, sig.sigdatal);
759 repodata_add_flexarray(data, s - pool->solvables, PUBKEY_SIGNATURES, shandle);
761 solv_free(sig.sigdata);
763 if (tag == 13 && !insubkey) /* User ID Packet */
765 userid = solv_realloc(userid, l);
767 memcpy(userid, p, l);
773 return p ? p - pstart : 0;
776 /* parse an ascii armored pubkey
777 * adds multiple pubkeys if ADD_MULTIPLE_PUBKEYS is set */
779 pubkey2solvable(Pool *pool, Id p, Repodata *data, char *pubkey, int flags)
781 unsigned char *pkts, *pkts_orig;
782 int pktsl, pl = 0, tag, l, hl;
784 if (!unarmor(pubkey, &pkts, &pktsl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"))
786 pool_error(pool, 0, "unarmor failure");
795 setutf8string(data, p, SOLVABLE_DESCRIPTION, pubkey);
796 pl = parsepubkey(pool->solvables + p, data, pkts, pktsl, flags);
797 if (!pl || !(flags & ADD_MULTIPLE_PUBKEYS))
802 hl = parsepkgheader(pkts, pktsl, &tag, &l);
807 p = repo_add_solvable(pool->solvables[p].repo);
809 solv_free((void *)pkts_orig);
816 repo_add_rpmdb_pubkeys(Repo *repo, int flags)
818 Pool *pool = repo->pool;
823 const char *rootdir = 0;
826 data = repo_add_repodata(repo, flags);
827 if (flags & REPO_USE_ROOTDIR)
828 rootdir = pool_get_rootdir(pool);
829 state = rpm_state_create(repo->pool, rootdir);
831 rpm_installedrpmdbids(state, "Name", "gpg-pubkey", &q);
832 for (i = 0; i < q.count; i++)
836 unsigned long long itime;
838 handle = rpm_byrpmdbid(state, q.elements[i]);
841 str = rpm_query(handle, SOLVABLE_DESCRIPTION);
844 p = repo_add_solvable(repo);
845 if (!pubkey2solvable(pool, p, data, str, flags))
848 repo_free_solvable(repo, p, 1);
852 itime = rpm_query_num(handle, SOLVABLE_INSTALLTIME, 0);
853 for (p2 = p; p2 < pool->nsolvables; p2++)
856 repodata_set_num(data, p2, SOLVABLE_INSTALLTIME, itime);
858 repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
859 repo->rpmdbid[p2 - repo->start] = q.elements[i];
863 rpm_state_free(state);
864 if (!(flags & REPO_NO_INTERNALIZE))
865 repodata_internalize(data);
872 solv_slurp(FILE *fp, int *lenp)
878 for (l = 0; ; l += ll)
883 buf = solv_realloc(buf, bufl);
885 ll = fread(buf + l, 1, bufl - l, fp);
888 buf = solv_free(buf);
894 buf[l] = 0; /* always zero-terminate */
904 repo_add_pubkey(Repo *repo, const char *keyfile, int flags)
906 Pool *pool = repo->pool;
912 data = repo_add_repodata(repo, flags);
914 if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, keyfile) : keyfile, "r")) == 0)
916 pool_error(pool, -1, "%s: %s", keyfile, strerror(errno));
919 if ((buf = solv_slurp(fp, 0)) == 0)
921 pool_error(pool, -1, "%s: %s", keyfile, strerror(errno));
926 p = repo_add_solvable(repo);
927 if (!pubkey2solvable(pool, p, data, buf, flags))
929 repo_free_solvable(repo, p, 1);
933 if (!(flags & REPO_NO_LOCATION))
936 for (p2 = p; p2 < pool->nsolvables; p2++)
937 repodata_set_location(data, p2, 0, 0, keyfile);
940 if (!(flags & REPO_NO_INTERNALIZE))
941 repodata_internalize(data);
946 is_sig_packet(unsigned char *sig, int sigl)
950 if ((sig[0] & 0x80) == 0 || (sig[0] & 0x40 ? sig[0] & 0x3f : sig[0] >> 2 & 0x0f) != 2)
956 is_pubkey_packet(unsigned char *pkt, int pktl)
960 if ((pkt[0] & 0x80) == 0 || (pkt[0] & 0x40 ? pkt[0] & 0x3f : pkt[0] >> 2 & 0x0f) != 6)
966 add_one_pubkey(Pool *pool, Repo *repo, Repodata *data, unsigned char *pbuf, int pbufl, int flags)
968 Id p = repo_add_solvable(repo);
969 char *solvversion = pool_tmpjoin(pool, "libsolv-", LIBSOLV_VERSION_STRING, 0);
970 char *descr = armor(pbuf, pbufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----", solvversion);
971 setutf8string(data, p, SOLVABLE_DESCRIPTION, descr);
972 parsepubkey(pool->solvables + p, data, pbuf, pbufl, flags);
976 repo_add_keyring(Repo *repo, FILE *fp, int flags)
978 Pool *pool = repo->pool;
980 unsigned char *buf, *p, *pbuf;
981 int bufl, l, pl, pbufl;
983 data = repo_add_repodata(repo, flags);
984 buf = (unsigned char *)solv_slurp(fp, &bufl);
985 if (buf && !is_pubkey_packet(buf, bufl))
987 /* assume ascii armored */
988 unsigned char *nbuf = 0, *ubuf;
991 for (l = 0; (nl = unarmor((char *)buf + l, &ubuf, &ubufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----")) != 0; l += nl)
993 /* found another block. concat. */
994 nbuf = solv_realloc(nbuf, bufl + ubufl);
996 memcpy(nbuf + bufl, ubuf, ubufl);
1003 /* now split into pubkey parts, ignoring the packets we don't know */
1006 for (p = buf; bufl; p += pl, bufl -= pl)
1009 int hl = parsepkgheader(p, bufl, &tag, &pl);
1015 /* found new pubkey! flush old */
1018 add_one_pubkey(pool, repo, data, pbuf, pbufl, flags);
1019 pbuf = solv_free(pbuf);
1023 if (tag != 6 && !pbufl)
1025 if (tag != 6 && tag != 2 && tag != 13 && tag != 14 && tag != 17)
1027 /* we want that packet. concat. */
1028 pbuf = solv_realloc(pbuf, pbufl + pl);
1029 memcpy(pbuf + pbufl, p, pl);
1033 add_one_pubkey(pool, repo, data, pbuf, pbufl, flags);
1036 if (!(flags & REPO_NO_INTERNALIZE))
1037 repodata_internalize(data);
1042 repo_add_keydir(Repo *repo, const char *keydir, const char *suffix, int flags)
1044 Pool *pool = repo->pool;
1047 struct dirent **namelist;
1050 data = repo_add_repodata(repo, flags);
1051 nent = scandir(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, keydir) : keydir, &namelist, 0, alphasort);
1053 return pool_error(pool, -1, "%s: %s", keydir, strerror(errno));
1054 rkeydir = pool_prepend_rootdir(pool, keydir);
1055 sl = suffix ? strlen(suffix) : 0;
1056 for (i = 0; i < nent; i++)
1058 const char *dn = namelist[i]->d_name;
1060 if (*dn == '.' && !(flags & ADD_KEYDIR_WITH_DOTFILES))
1063 if (sl && (l < sl || strcmp(dn + l - sl, suffix) != 0))
1065 repo_add_pubkey(repo, pool_tmpjoin(pool, rkeydir, "/", dn), flags | REPO_REUSE_REPODATA);
1068 for (i = 0; i < nent; i++)
1069 solv_free(namelist[i]);
1070 solv_free(namelist);
1071 if (!(flags & REPO_NO_INTERNALIZE))
1072 repodata_internalize(data);
1077 solvsig_create(FILE *fp)
1081 int sigl, hl, tag, pktl;
1082 struct pgpsig pgpsig;
1084 if ((sig = (unsigned char *)solv_slurp(fp, &sigl)) == 0)
1086 if (!is_sig_packet(sig, sigl))
1088 /* not a raw sig, check armored */
1089 unsigned char *nsig;
1090 if (!unarmor((char *)sig, &nsig, &sigl, "-----BEGIN PGP SIGNATURE-----", "-----END PGP SIGNATURE-----"))
1097 if (!is_sig_packet(sig, sigl))
1103 hl = parsepkgheader(sig, sigl, &tag, &pktl);
1104 if (!hl || tag != 2 || !pktl)
1109 pgpsig_init(&pgpsig, sig + hl, pktl);
1110 if (pgpsig.type != 0 || !pgpsig.haveissuer)
1115 ss = solv_calloc(1, sizeof(*ss));
1116 ss->sigpkt = solv_memdup(sig + hl, pktl);
1119 solv_bin2hex(pgpsig.issuer, 8, ss->keyid);
1120 ss->htype = pgphashalgo2type(pgpsig.hashalgo);
1121 ss->created = pgpsig.created;
1122 ss->expires = pgpsig.expires;
1127 solvsig_free(Solvsig *ss)
1129 solv_free(ss->sigpkt);
1134 repo_find_all_pubkeys_cmp(const void *va, const void *vb, void *dp)
1139 /* cannot use evrcmp, as rpm says '0' > 'a' */
1140 return strcmp(pool_id2str(pool, pool->solvables[b].evr), pool_id2str(pool, pool->solvables[a].evr));
1144 repo_find_all_pubkeys(Repo *repo, const char *keyid, Queue *q)
1153 keyidlen = strlen(keyid);
1154 if (keyidlen < 8 || keyidlen > 64)
1156 FOR_REPO_SOLVABLES(repo, p, s)
1158 const char *kidstr, *evr = pool_id2str(s->repo->pool, s->evr);
1160 if (!evr || strncmp(evr, keyid + keyidlen - 8, 8) != 0)
1162 kidstr = solvable_lookup_str(s, keyidlen >= 32 ? PUBKEY_FINGERPRINT : PUBKEY_KEYID);
1163 if (kidstr && !strcmp(kidstr, keyid))
1167 solv_sort(q->elements, q->count, sizeof(Id), repo_find_all_pubkeys_cmp, repo->pool);
1171 repo_find_pubkey(Repo *repo, const char *keyid)
1176 repo_find_all_pubkeys(repo, keyid, &q);
1177 p = q.count ? q.elements[0] : 0;
1182 #ifdef ENABLE_PGPVRFY
1184 /* warning: does not check key expiry/revokation, same as with gpgv or rpm */
1185 /* returns the Id of the pubkey that verified the signature */
1187 repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid)
1193 if (!sigdata || !keyid)
1196 repo_find_all_pubkeys(repo, keyid, &q);
1197 for (i = 0; i < q.count; i++)
1200 const unsigned char *pubdata = repo_lookup_binary(repo, q.elements[i], PUBKEY_DATA, &pubdatal);
1201 if (pubdata && solv_pgpvrfy(pubdata, pubdatal, sigdata, sigdatal))
1204 p = i < q.count? q.elements[i] : 0;
1210 solvsig_verify(Solvsig *ss, Repo *repo, Chksum *chk)
1212 struct pgpsig pgpsig;
1216 if (!chk || solv_chksum_isfinished(chk))
1218 pgpsig_init(&pgpsig, ss->sigpkt, ss->sigpktl);
1219 chk2 = solv_chksum_create_clone(chk);
1220 pgpsig_makesigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);
1221 solv_chksum_free(chk2, 0);
1222 if (!pgpsig.sigdata)
1224 p = repo_verify_sigdata(repo, pgpsig.sigdata, pgpsig.sigdatal, ss->keyid);
1225 solv_free(pgpsig.sigdata);