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>
28 #include <rpm/rpmio.h>
29 #include <rpm/rpmpgp.h>
31 #include <rpm/header.h>
33 #include <rpm/rpmdb.h>
41 #include "repo_rpmdb.h"
42 #include "repo_pubkey.h"
44 #include "solv_pgpvrfy.h"
48 setutf8string(Repodata *repodata, Id handle, Id tag, const char *str)
50 if (str[solv_validutf8(str)])
52 char *ustr = solv_latin1toutf8(str); /* not utf8, assume latin1 */
53 repodata_set_str(repodata, handle, tag, ustr);
57 repodata_set_str(repodata, handle, tag, str);
61 r64dec1(char *p, unsigned int *vp, int *eofp)
71 if (x >= 'A' && x <= 'Z')
73 else if (x >= 'a' && x <= 'z')
75 else if (x >= '0' && x <= '9')
102 crc24(unsigned char *p, int len)
104 unsigned int crc = 0xb704ce;
110 for (i = 0; i < 8; i++)
111 if ((crc <<= 1) & 0x1000000)
114 return crc & 0xffffff;
118 unarmor(char *pubkey, unsigned char **pktp, int *pktlp, const char *startstr, const char *endstr)
120 char *p, *pubkeystart = pubkey;
122 unsigned char *buf, *bp;
129 l = strlen(startstr);
130 while (strncmp(pubkey, startstr, l) != 0)
132 pubkey = strchr(pubkey, '\n');
137 pubkey = strchr(pubkey, '\n');
140 /* skip header lines */
143 while (*pubkey == ' ' || *pubkey == '\t')
147 pubkey = strchr(pubkey, '\n');
152 p = strchr(pubkey, '=');
156 bp = buf = solv_malloc(l * 3 / 4 + 4);
160 pubkey = r64dec1(pubkey, &v, &eof);
170 while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
173 if (*pubkey != '=' || (pubkey = r64dec1(pubkey + 1, &v, &eof)) == 0)
178 if (v != crc24(buf, bp - buf))
183 while (*pubkey == ' ' || *pubkey == '\t' || *pubkey == '\n' || *pubkey == '\r')
185 if (strncmp(pubkey, endstr, strlen(endstr)) != 0)
190 p = strchr(pubkey, '\n');
192 p = pubkey + strlen(pubkey);
195 return (p ? p + 1 : pubkey + strlen(pubkey)) - pubkeystart;
198 #define ARMOR_NLAFTER 16
201 armor(unsigned char *pkt, int pktl, const char *startstr, const char *endstr, const char *version)
203 static const char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
204 char *str = solv_malloc(strlen(startstr) + strlen(endstr) + strlen(version) + (pktl / 3) * 4 + (pktl / (ARMOR_NLAFTER * 3)) + 30);
209 v = crc24(pkt, pktl);
210 sprintf(p, "%s\nVersion: %s\n\n", startstr, version);
212 for (i = -1; pktl > 0; pktl -= 3)
214 if (++i == ARMOR_NLAFTER)
220 b = pktl > 1 ? *pkt++ : 0;
221 c = pktl > 2 ? *pkt++ : 0;
222 *p++ = bintoasc[a >> 2];
223 *p++ = bintoasc[(a & 3) << 4 | b >> 4];
224 *p++ = pktl > 1 ? bintoasc[(b & 15) << 2 | c >> 6] : '=';
225 *p++ = pktl > 2 ? bintoasc[c & 63] : '=';
229 *p++ = bintoasc[v >> 18 & 0x3f];
230 *p++ = bintoasc[v >> 12 & 0x3f];
231 *p++ = bintoasc[v >> 6 & 0x3f];
232 *p++ = bintoasc[v & 0x3f];
233 sprintf(p, "\n%s\n", endstr);
240 unsigned char issuer[8];
242 unsigned int created;
243 unsigned int expires;
244 unsigned int keyexpires;
245 unsigned char *sigdata;
251 pgphashalgo2type(int algo)
254 return REPOKEY_TYPE_MD5;
256 return REPOKEY_TYPE_SHA1;
258 return REPOKEY_TYPE_SHA256;
263 createsigdata(struct pgpsig *sig, unsigned char *p, int l, unsigned char *pubkey, int pubkeyl, unsigned char *userid, int useridl, void *h)
265 int type = sig->type;
267 const unsigned char *cs;
270 if (!h || sig->mpioff < 2 || l <= sig->mpioff)
272 if ((type >= 0x10 && type <= 0x13) || type == 0x1f || type == 0x18 || type == 0x20 || type == 0x28)
277 solv_chksum_add(h, b, 3);
278 solv_chksum_add(h, pubkey, pubkeyl);
280 if ((type >= 0x10 && type <= 0x13))
285 b[1] = useridl >> 24;
286 b[2] = useridl >> 16;
289 solv_chksum_add(h, b, 5);
291 solv_chksum_add(h, userid, useridl);
295 solv_chksum_add(h, p + 2, 5);
298 int hl = 6 + (p[4] << 8 | p[5]);
299 solv_chksum_add(h, p, hl);
306 solv_chksum_add(h, b, 6);
308 cs = solv_chksum_get(h, &csl);
309 if (cs[0] == p[sig->mpioff - 2] && cs[1] == p[sig->mpioff - 1])
311 int ml = l - sig->mpioff;
312 sig->sigdata = solv_malloc(2 + csl + ml);
313 sig->sigdatal = 2 + csl + ml;
314 sig->sigdata[0] = p[0] == 3 ? p[15] : p[2];
315 sig->sigdata[1] = p[0] == 3 ? p[16] : p[3];
316 memcpy(sig->sigdata + 2, cs, csl);
317 memcpy(sig->sigdata + 2 + csl, p + sig->mpioff, ml);
322 parsesubpkglength(unsigned char *q, int ql, int *pktlp)
325 /* decode sub-packet length, ql must be > 0 */
334 if (ql < 5 || q[0] != 0)
336 sl = q[1] << 16 | q[2] << 8 | q[3];
343 sl = ((x - 192) << 8) + q[0] + 192;
346 if (!sl || ql < sl + hl) /* sub pkg tag is included in length, i.e. sl must not be zero */
353 parsesigpacket(struct pgpsig *sig, unsigned char *p, int l)
358 /* printf("V3 signature packet\n"); */
359 if (l <= 19 || p[1] != 5)
363 memcpy(sig->issuer, p + 7, 8);
364 sig->created = p[3] << 24 | p[4] << 16 | p[5] << 8 | p[6];
365 sig->hashalgo = p[16];
373 /* printf("V4 signature packet\n"); */
377 sig->hashalgo = p[3];
379 sig->keyexpires = -1;
380 for (j = 0; q && j < 2; j++)
387 ql = q[0] << 8 | q[1];
397 hl = parsesubpkglength(q, ql, &sl);
405 x = q[0] & 127; /* strip critical bit */
406 /* printf("%d SIGSUB %d %d\n", j, x, sl); */
407 if (x == 16 && sl == 9 && !sig->haveissuer)
410 memcpy(sig->issuer, q + 1, 8);
412 if (x == 2 && j == 0)
413 sig->created = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
414 if (x == 3 && j == 0)
415 sig->expires = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
416 if (x == 9 && j == 0)
417 sig->keyexpires = q[1] << 24 | q[2] << 16 | q[3] << 8 | q[4];
422 if (q && q - p + 2 < l)
423 sig->mpioff = q - p + 2;
428 parsepkgheader(unsigned char *p, int pl, int *tagp, int *pktlp)
430 unsigned char *op = p;
437 if (!(x & 128) || pl <= 0)
441 *tagp = (x & 0x3c) >> 2; /* old format */
443 if (x > 4 || pl < x || (x == 4 && p[0]))
451 *tagp = (x & 0x3f); /* new format */
456 else if (x >= 192 && x < 224)
460 l = ((x - 192) << 8) + *p++ + 192;
465 if (pl <= 4 || p[0] != 0) /* sanity: p[0] must be zero */
467 l = p[1] << 16 | p[2] << 8 | p[3];
482 parsekeydata(Solvable *s, Repodata *data, unsigned char *p, int pl)
485 unsigned char keyid[8];
486 unsigned int kcr = 0, maxex = 0, maxsigcr = 0;
487 unsigned char *pubkey = 0;
489 unsigned char *userid = 0;
491 unsigned char *pubdata = 0;
494 for (; pl; p += l, pl -= l)
496 int hl = parsepkgheader(p, pl, &tag, &l);
504 break; /* one key at a time, please */
505 pubkey = solv_malloc(l);
507 memcpy(pubkey, p, l);
509 if (p[0] == 3 && l >= 10)
513 maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
517 ex = kcr + 24*3600 * (p[5] << 8 | p[6]);
522 if (p[7] == 1) /* RSA */
525 unsigned char fp[16];
529 ql = ((p[8] << 8 | p[9]) + 7) / 8; /* length of public modulus */
530 if (ql >= 8 && 10 + ql + 2 <= l)
532 memcpy(keyid, p + 10 + ql - 8, 8); /* keyid is last 64 bits of public modulus */
534 ql2 = ((q[0] << 8 | q[1]) + 7) / 8; /* length of encryption exponent */
535 if (10 + ql + 2 + ql2 <= l)
537 /* fingerprint is the md5 over the two MPI bodies */
538 h = solv_chksum_create(REPOKEY_TYPE_MD5);
539 solv_chksum_add(h, p + 10, ql);
540 solv_chksum_add(h, q + 2, ql2);
541 solv_chksum_free(h, fp);
542 solv_bin2hex(fp, 16, fpx);
543 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
550 else if (p[0] == 4 && l >= 6)
553 unsigned char hdr[3];
554 unsigned char fp[20];
557 maxsigcr = kcr = p[1] << 24 | p[2] << 16 | p[3] << 8 | p[4];
561 /* fingerprint is the sha1 over the packet */
562 h = solv_chksum_create(REPOKEY_TYPE_SHA1);
563 solv_chksum_add(h, hdr, 3);
564 solv_chksum_add(h, p, l);
565 solv_chksum_free(h, fp);
566 solv_bin2hex(fp, 20, fpx);
567 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_FINGERPRINT, fpx);
568 memcpy(keyid, fp + 12, 8); /* keyid is last 64 bits of fingerprint */
579 memset(&sig, 0, sizeof(sig));
580 parsesigpacket(&sig, p, l);
581 if (!sig.haveissuer || !((sig.type >= 0x10 && sig.type <= 0x13) || sig.type == 0x1f))
583 if (sig.type >= 0x10 && sig.type <= 0x13 && !userid)
585 htype = pgphashalgo2type(sig.hashalgo);
586 if (htype && sig.mpioff)
588 void *h = solv_chksum_create(htype);
589 createsigdata(&sig, p, l, pubkey, pubkeyl, userid, useridl, h);
590 solv_chksum_free(h, 0);
592 if (!memcmp(keyid, sig.issuer, 8))
594 #ifdef ENABLE_PGPVRFY
595 /* found self sig, verify */
596 if (solv_pgpvrfy(pubdata, pubdatal, sig.sigdata, sig.sigdatal))
599 if (sig.keyexpires && maxex != -1)
601 if (sig.keyexpires == -1)
603 else if (sig.keyexpires + kcr > maxex)
604 maxex = sig.keyexpires + kcr;
606 if (sig.created > maxsigcr)
607 maxsigcr = sig.created;
613 Id shandle = repodata_new_handle(data);
614 solv_bin2hex(sig.issuer, 8, issuerstr);
615 repodata_set_str(data, shandle, SIGNATURE_ISSUER, issuerstr);
617 repodata_set_num(data, shandle, SIGNATURE_TIME, sig.created);
619 repodata_set_num(data, shandle, SIGNATURE_EXPIRES, sig.created + sig.expires);
621 repodata_set_binary(data, shandle, SIGNATURE_DATA, sig.sigdata, sig.sigdatal);
622 repodata_add_flexarray(data, s - s->repo->pool->solvables, PUBKEY_SIGNATURES, shandle);
624 solv_free(sig.sigdata);
628 userid = solv_realloc(userid, l);
630 memcpy(userid, p, l);
635 repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, kcr);
636 if (maxex && maxex != -1)
637 repodata_set_num(data, s - s->repo->pool->solvables, PUBKEY_EXPIRES, maxex);
638 s->name = pool_str2id(s->repo->pool, "gpg-pubkey", 1);
641 if (userid && useridl)
643 char *useridstr = solv_malloc(useridl + 1);
644 memcpy(useridstr, userid, useridl);
645 useridstr[useridl] = 0;
646 setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, useridstr);
652 solv_bin2hex(keyid, 8, keyidstr);
653 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyidstr);
657 /* build rpm-style evr */
658 char evr[8 + 1 + 8 + 1];
659 solv_bin2hex(keyid + 4, 4, evr);
660 sprintf(evr + 8, "-%08x", maxsigcr);
661 s->evr = pool_str2id(s->repo->pool, evr, 1);
663 repodata_set_binary(data, s - s->repo->pool->solvables, PUBKEY_DATA, pubdata, pubdatal);
672 /* this is private to rpm, but rpm lacks an interface to retrieve
673 * the values. Sigh. */
674 struct pgpDigParams_s {
676 const unsigned char * hash;
677 #ifndef HAVE_PGPDIGGETPARAMS
678 const char * params[4];
681 unsigned char version; /*!< version number. */
682 unsigned char time[4]; /*!< time that the key was created. */
683 unsigned char pubkey_algo; /*!< public key algorithm. */
684 unsigned char hash_algo;
685 unsigned char sigtype;
686 unsigned char hashlen;
687 unsigned char signhash16[2];
688 unsigned char signid[8];
692 #ifndef HAVE_PGPDIGGETPARAMS
694 struct pgpDigParams_s signature;
695 struct pgpDigParams_s pubkey;
700 /* only rpm knows how to do the release calculation, we don't dare
701 * to recreate all the bugs in libsolv */
703 parsekeydata_rpm(Solvable *s, Repodata *data, unsigned char *pkts, int pktsl)
705 Pool *pool = s->repo->pool;
706 struct pgpDigParams_s *digpubkey;
709 char evrbuf[8 + 1 + 8 + 1];
715 dig = pgpDigNew(RPMVSF_DEFAULT, 0);
717 (void) pgpPrtPkts(pkts, pktsl, dig, 0);
718 #ifdef HAVE_PGPDIGGETPARAMS
719 digpubkey = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY);
721 digpubkey = &dig->pubkey;
725 btime = digpubkey->time[0] << 24 | digpubkey->time[1] << 16 | digpubkey->time[2] << 8 | digpubkey->time[3];
726 solv_bin2hex(digpubkey->signid, 8, keyid);
727 solv_bin2hex(digpubkey->signid + 4, 4, evrbuf);
729 solv_bin2hex(digpubkey->time, 4, evrbuf + 9);
730 s->evr = pool_str2id(pool, evrbuf, 1);
731 repodata_set_str(data, s - s->repo->pool->solvables, PUBKEY_KEYID, keyid);
732 if (digpubkey->userid)
733 setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_SUMMARY, digpubkey->userid);
735 repodata_set_num(data, s - s->repo->pool->solvables, SOLVABLE_BUILDTIME, btime);
738 (void)pgpFreeDig(dig);
740 (void)pgpDigFree(dig);
744 #endif /* ENABLE_RPMDB */
747 pubkey2solvable(Solvable *s, Repodata *data, char *pubkey)
752 if (!unarmor(pubkey, &pkts, &pktsl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"))
754 pool_error(s->repo->pool, 0, "unarmor failure");
757 setutf8string(data, s - s->repo->pool->solvables, SOLVABLE_DESCRIPTION, pubkey);
758 parsekeydata(s, data, pkts, pktsl);
760 parsekeydata_rpm(s, data, pkts, pktsl);
762 solv_free((void *)pkts);
769 repo_add_rpmdb_pubkeys(Repo *repo, int flags)
771 Pool *pool = repo->pool;
777 const char *rootdir = 0;
780 data = repo_add_repodata(repo, flags);
781 if (flags & REPO_USE_ROOTDIR)
782 rootdir = pool_get_rootdir(pool);
783 state = rpm_state_create(repo->pool, rootdir);
785 rpm_installedrpmdbids(state, "Name", "gpg-pubkey", &q);
786 for (i = 0; i < q.count; i++)
789 unsigned long long itime;
791 handle = rpm_byrpmdbid(state, q.elements[i]);
794 str = rpm_query(handle, SOLVABLE_DESCRIPTION);
797 s = pool_id2solvable(pool, repo_add_solvable(repo));
798 pubkey2solvable(s, data, str);
800 itime = rpm_query_num(handle, SOLVABLE_INSTALLTIME, 0);
802 repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLTIME, itime);
804 repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
805 repo->rpmdbid[s - pool->solvables - repo->start] = q.elements[i];
808 rpm_state_free(state);
809 if (!(flags & REPO_NO_INTERNALIZE))
810 repodata_internalize(data);
817 solv_slurp(FILE *fp, int *lenp)
823 for (l = 0; ; l += ll)
828 buf = solv_realloc(buf, bufl);
830 ll = fread(buf + l, 1, bufl - l, fp);
833 buf = solv_free(buf);
839 buf[l] = 0; /* always zero-terminate */
849 repo_add_pubkey(Repo *repo, const char *key, int flags)
851 Pool *pool = repo->pool;
857 data = repo_add_repodata(repo, flags);
859 if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, key) : key, "r")) == 0)
861 pool_error(pool, -1, "%s: %s", key, strerror(errno));
864 if ((buf = solv_slurp(fp, 0)) == 0)
866 pool_error(pool, -1, "%s: %s", key, strerror(errno));
871 s = pool_id2solvable(pool, repo_add_solvable(repo));
872 if (!pubkey2solvable(s, data, buf))
874 repo_free_solvable(repo, s - pool->solvables, 1);
878 if (!(flags & REPO_NO_LOCATION))
879 repodata_set_location(data, s - pool->solvables, 0, 0, key);
881 if (!(flags & REPO_NO_INTERNALIZE))
882 repodata_internalize(data);
883 return s - pool->solvables;
887 is_sig_packet(unsigned char *sig, int sigl)
891 if ((sig[0] & 0x80) == 0 || (sig[0] & 0x40 ? sig[0] & 0x3f : sig[0] >> 2 & 0x0f) != 2)
897 is_pubkey_packet(unsigned char *pkt, int pktl)
901 if ((pkt[0] & 0x80) == 0 || (pkt[0] & 0x40 ? pkt[0] & 0x3f : pkt[0] >> 2 & 0x0f) != 6)
907 add_one_pubkey(Pool *pool, Repo *repo, Repodata *data, unsigned char *pbuf, int pbufl)
909 Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo));
910 char *solvversion = pool_tmpjoin(pool, "libsolv-", LIBSOLV_VERSION_STRING, 0);
911 char *descr = armor(pbuf, pbufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----", solvversion);
912 setutf8string(data, s - pool->solvables, SOLVABLE_DESCRIPTION, descr);
913 parsekeydata(s, data, pbuf, pbufl);
915 parsekeydata_rpm(s, data, pbuf, pbufl);
920 repo_add_keyring(Repo *repo, FILE *fp, int flags)
922 Pool *pool = repo->pool;
924 unsigned char *buf, *p, *pbuf;
925 int bufl, l, pl, pbufl;
927 data = repo_add_repodata(repo, flags);
928 buf = (unsigned char *)solv_slurp(fp, &bufl);
929 if (buf && !is_pubkey_packet(buf, bufl))
931 /* assume ascii armored */
932 unsigned char *nbuf = 0, *ubuf;
935 for (l = 0; (nl = unarmor((char *)buf + l, &ubuf, &ubufl, "-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----")) != 0; l += nl)
937 /* found another block. concat. */
938 nbuf = solv_realloc(nbuf, bufl + ubufl);
940 memcpy(nbuf + bufl, ubuf, ubufl);
947 /* now split into pubkey parts, ignoring the packets we don't know */
950 for (p = buf; bufl; p += pl, bufl -= pl)
953 int hl = parsepkgheader(p, bufl, &tag, &pl);
959 /* found new pubkey! flush old */
962 add_one_pubkey(pool, repo, data, pbuf, pbufl);
963 pbuf = solv_free(pbuf);
967 if (tag != 6 && !pbufl)
969 if (tag != 6 && tag != 2 && tag != 13 && tag != 14 && tag != 17)
971 /* we want that packet. concat. */
972 pbuf = solv_realloc(pbuf, pbufl + pl);
973 memcpy(pbuf + pbufl, p, pl);
977 add_one_pubkey(pool, repo, data, pbuf, pbufl);
980 if (!(flags & REPO_NO_INTERNALIZE))
981 repodata_internalize(data);
986 repo_add_keydir(Repo *repo, const char *keydir, int flags, const char *suffix)
988 Pool *pool = repo->pool;
991 struct dirent **namelist;
994 data = repo_add_repodata(repo, flags);
995 nent = scandir(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, keydir) : keydir, &namelist, 0, alphasort);
997 return pool_error(pool, -1, "%s: %s", keydir, strerror(errno));
998 rkeydir = pool_prepend_rootdir(pool, keydir);
999 sl = suffix ? strlen(suffix) : 0;
1000 for (i = 0; i < nent; i++)
1002 const char *dn = namelist[i]->d_name;
1004 if (*dn == '.' && !(flags & ADD_KEYDIR_WITH_DOTFILES))
1007 if (sl && (l < sl || strcmp(dn + l - sl, suffix) != 0))
1009 repo_add_pubkey(repo, pool_tmpjoin(pool, rkeydir, "/", dn), flags);
1012 for (i = 0; i < nent; i++)
1013 solv_free(namelist[i]);
1014 solv_free(namelist);
1015 if (!(flags & REPO_NO_INTERNALIZE))
1016 repodata_internalize(data);
1021 solvsig_create(FILE *fp)
1025 int sigl, hl, tag, pktl;
1026 struct pgpsig pgpsig;
1028 if ((sig = (unsigned char *)solv_slurp(fp, &sigl)) == 0)
1030 if (!is_sig_packet(sig, sigl))
1032 /* not a raw sig, check armored */
1033 unsigned char *nsig;
1034 if (!unarmor((char *)sig, &nsig, &sigl, "-----BEGIN PGP SIGNATURE-----", "-----END PGP SIGNATURE-----"))
1041 if (!is_sig_packet(sig, sigl))
1047 hl = parsepkgheader(sig, sigl, &tag, &pktl);
1048 if (!hl || tag != 2 || !pktl)
1053 memset(&pgpsig, 0, sizeof(pgpsig));
1054 parsesigpacket(&pgpsig, sig + hl, pktl);
1055 if (pgpsig.type != 0 || !pgpsig.haveissuer)
1060 ss = solv_calloc(1, sizeof(*ss));
1061 ss->sigpkt = solv_memdup(sig + hl, pktl);
1064 solv_bin2hex(pgpsig.issuer, 8, ss->keyid);
1065 ss->htype = pgphashalgo2type(pgpsig.hashalgo);
1066 ss->created = pgpsig.created;
1067 ss->expires = pgpsig.expires;
1072 solvsig_free(Solvsig *ss)
1074 solv_free(ss->sigpkt);
1078 #ifdef ENABLE_PGPVRFY
1081 solv_verify_sig(const unsigned char *pubdata, int pubdatal, unsigned char *sigpkt, int sigpktl, void *chk)
1083 struct pgpsig pgpsig;
1088 memset(&pgpsig, 0, sizeof(pgpsig));
1089 parsesigpacket(&pgpsig, sigpkt, sigpktl);
1090 if (pgpsig.type != 0)
1092 htype = pgphashalgo2type(pgpsig.hashalgo);
1093 if (!htype || htype != solv_chksum_get_type(chk))
1094 return 0; /* wrong hash type? */
1095 chk2 = solv_chksum_create_clone(chk);
1096 createsigdata(&pgpsig, sigpkt, sigpktl, 0, 0, 0, 0, chk2);
1097 solv_chksum_free(chk2, 0);
1098 if (!pgpsig.sigdata)
1100 res = solv_pgpvrfy(pubdata, pubdatal, pgpsig.sigdata, pgpsig.sigdatal);
1101 solv_free(pgpsig.sigdata);
1105 /* warning: does not check key expiry/revokation, like gpgv or rpm */
1106 /* returns the Id of the pubkey that verified the signature */
1108 repo_verify_sigdata(Repo *repo, unsigned char *sigdata, int sigdatal, const char *keyid)
1113 if (!sigdata || !keyid)
1115 FOR_REPO_SOLVABLES(repo, p, s)
1117 const char *evr = pool_id2str(s->repo->pool, s->evr);
1119 const unsigned char *pubdata;
1122 if (!evr || strncmp(evr, keyid + 8, 8) != 0)
1124 kidstr = solvable_lookup_str(s, PUBKEY_KEYID);
1125 if (!kidstr || strcmp(kidstr, keyid) != 0)
1127 pubdata = repo_lookup_binary(repo, p, PUBKEY_DATA, &pubdatal);
1128 if (solv_pgpvrfy(pubdata, pubdatal, sigdata, sigdatal))
1135 solvsig_verify(Solvsig *ss, Repo *repo, void *chk)
1137 struct pgpsig pgpsig;
1141 parsesigpacket(&pgpsig, ss->sigpkt, ss->sigpktl);
1142 chk2 = solv_chksum_create_clone(chk);
1143 createsigdata(&pgpsig, ss->sigpkt, ss->sigpktl, 0, 0, 0, 0, chk2);
1144 solv_chksum_free(chk2, 0);
1145 if (!pgpsig.sigdata)
1147 p = repo_verify_sigdata(repo, pgpsig.sigdata, pgpsig.sigdatal, ss->keyid);
1148 solv_free(pgpsig.sigdata);