2 * \file lib/signature.c
10 #include <rpm/rpmtypes.h>
11 #include <rpm/rpmlib.h> /* XXX RPMSIGTAG* & related */
12 #include <rpm/rpmmacro.h> /* XXX for rpmGetPath() */
13 #include <rpm/rpmdb.h>
14 #include <rpm/rpmstring.h>
15 #include <rpm/rpmfileutil.h>
16 #include <rpm/rpmlog.h>
17 #include <rpm/rpmts.h>
19 #include "rpmio/digest.h"
20 #include "lib/rpmlead.h"
21 #include "lib/signature.h"
22 #include "lib/header_internal.h"
26 #if !defined(__GLIBC__) && !defined(__APPLE__)
27 char ** environ = NULL;
30 static int sighdrPut(Header h, rpmSigTag tag, rpmTagType type,
31 rpm_data_t p, rpm_count_t c)
39 return headerPut(h, &sigtd, HEADERPUT_DEFAULT);
42 int rpmLookupSignatureType(int action)
44 static int disabled = 0;
48 case RPMLOOKUPSIG_DISABLE:
51 case RPMLOOKUPSIG_ENABLE:
53 case RPMLOOKUPSIG_QUERY:
56 { char *name = rpmExpand("%{?_signature}", NULL);
57 if (!(name && *name != '\0'))
59 else if (!rstrcasecmp(name, "none"))
61 else if (!rstrcasecmp(name, "pgp"))
63 else if (!rstrcasecmp(name, "pgp5")) /* XXX legacy */
65 else if (!rstrcasecmp(name, "gpg"))
68 rc = -1; /* Invalid %_signature spec in macro file */
75 /* rpmDetectPGPVersion() returns the absolute path to the "pgp" */
76 /* executable of the requested version, or NULL when none found. */
78 const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
80 /* Actually this should support having more then one pgp version. */
81 /* At the moment only one version is possible since we only */
82 /* have one %_pgpbin and one %_pgp_path. */
84 static pgpVersion saved_pgp_version = PGP_UNKNOWN;
85 char *pgpbin = rpmGetPath("%{?_pgpbin}", NULL);
87 if (saved_pgp_version == PGP_UNKNOWN) {
91 if (!(pgpbin && pgpbin[0] != '\0')) {
92 pgpbin = _free(pgpbin);
93 saved_pgp_version = -1;
96 rasprintf(&pgpvbin, "%sv", pgpbin);
98 if (stat(pgpvbin, &st) == 0)
99 saved_pgp_version = PGP_5;
100 else if (stat(pgpbin, &st) == 0)
101 saved_pgp_version = PGP_2;
103 saved_pgp_version = PGP_NOTDETECTED;
107 if (pgpVer && pgpbin)
108 *pgpVer = saved_pgp_version;
113 * Print package size.
114 * @todo rpmio: use fdSize rather than fstat(2) to get file size.
115 * @param fd package file handle
116 * @param siglen signature header size
117 * @param pad signature padding
118 * @param datalen length of header+payload
119 * @return rpmRC return code
121 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, rpm_loff_t datalen)
124 int fdno = Fileno(fd);
126 if (fstat(fdno, &st) < 0)
130 "Expected size: %12" PRIu64 \
131 " = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
132 RPMLEAD_SIZE+siglen+pad+datalen,
133 RPMLEAD_SIZE, siglen, pad, datalen);
135 " Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);
140 /* XXX sigh yet another duplicate.. */
141 static unsigned char const header_magic[8] = {
142 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
145 rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
155 struct indexEntry_s entry;
156 struct entryInfo_s info;
157 unsigned char * dataStart;
158 unsigned char * dataEnd = NULL;
160 rpmRC rc = RPMRC_FAIL; /* assume failure */
167 if (sig_type != RPMSIGTYPE_HEADERSIG)
170 memset(block, 0, sizeof(block));
171 if ((xx = timedRead(fd, (void *)block, sizeof(block))) != sizeof(block)) {
172 rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"),
173 (int)sizeof(block), xx);
176 if (memcmp(block, header_magic, sizeof(header_magic))) {
177 rasprintf(&buf, _("sigh magic: BAD\n"));
180 il = ntohl(block[2]);
181 if (il < 0 || il > 32) {
183 _("sigh tags: BAD, no. of tags(%d) out of range\n"), il);
186 dl = ntohl(block[3]);
187 if (dl < 0 || dl > 8192) {
189 _("sigh data: BAD, no. of bytes(%d) out of range\n"), dl);
193 memset(&entry, 0, sizeof(entry));
194 memset(&info, 0, sizeof(info));
196 nb = (il * sizeof(struct entryInfo_s)) + dl;
197 ei = xmalloc(sizeof(il) + sizeof(dl) + nb);
200 pe = (entryInfo) &ei[2];
201 dataStart = (unsigned char *) (pe + il);
202 if ((xx = timedRead(fd, (void *)pe, nb)) != nb) {
204 _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
208 /* Check (and convert) the 1st tag element. */
209 xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
211 rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
212 0, entry.info.tag, entry.info.type,
213 entry.info.offset, entry.info.count);
217 /* Is there an immutable header region tag? */
218 if (entry.info.tag == RPMTAG_HEADERSIGNATURES
219 && entry.info.type == RPM_BIN_TYPE
220 && entry.info.count == REGION_TAG_COUNT)
223 if (entry.info.offset >= dl) {
225 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
226 entry.info.tag, entry.info.type,
227 entry.info.offset, entry.info.count);
231 /* Is there an immutable header region tag trailer? */
232 dataEnd = dataStart + entry.info.offset;
233 (void) memcpy(&info, dataEnd, REGION_TAG_COUNT);
234 /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
235 if (info.tag == htonl(RPMTAG_HEADERIMAGE)) {
236 rpmSigTag stag = htonl(RPMTAG_HEADERSIGNATURES);
238 memcpy(dataEnd, &stag, sizeof(stag));
240 dataEnd += REGION_TAG_COUNT;
242 xx = headerVerifyInfo(1, dl, &info, &entry.info, 1);
244 !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE)
245 && entry.info.type == RPM_BIN_TYPE
246 && entry.info.count == REGION_TAG_COUNT))
249 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
250 entry.info.tag, entry.info.type,
251 entry.info.offset, entry.info.count);
254 memset(&info, 0, sizeof(info));
256 /* Is the no. of tags in the region less than the total no. of tags? */
257 ril = entry.info.offset/sizeof(*pe);
258 if ((entry.info.offset % sizeof(*pe)) || ril > il) {
259 rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
264 /* Sanity check signature tags */
265 memset(&info, 0, sizeof(info));
266 for (i = 1; i < il; i++) {
267 xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
270 _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
271 i, entry.info.tag, entry.info.type,
272 entry.info.offset, entry.info.count);
277 /* OK, blob looks sane, load the header. */
278 sigh = headerLoad(ei);
280 rasprintf(&buf, _("sigh load: BAD\n"));
283 sigh->flags |= HEADERFLAG_ALLOCATED;
285 { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
286 size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
288 struct rpmtd_s sizetag;
289 rpm_loff_t archSize = 0;
291 /* Position at beginning of header. */
292 if (pad && (trc = timedRead(fd, (void *)block, pad)) != pad) {
294 _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
298 /* Print package component sizes. */
299 if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
300 rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
301 archSize = (tsize) ? *tsize : 0;
302 } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
303 rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
304 archSize = (tsize) ? *tsize : 0;
306 rpmtdFreeData(&sizetag);
307 rc = printSize(fd, sigSize, pad, archSize);
308 if (rc != RPMRC_OK) {
310 _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize);
316 if (sighp && sigh && rc == RPMRC_OK)
317 *sighp = headerLink(sigh);
318 sigh = headerFree(sigh);
329 int rpmWriteSignature(FD_t fd, Header sigh)
331 static uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
335 rc = headerWrite(fd, sigh, HEADER_MAGIC_YES);
339 sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
340 pad = (8 - (sigSize % 8)) % 8;
342 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
345 rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad);
349 Header rpmNewSignature(void)
351 Header sigh = headerNew();
355 Header rpmFreeSignature(Header sigh)
357 return headerFree(sigh);
361 * Generate PGP signature(s) for a header+payload file.
362 * @param file header+payload file name
363 * @retval *sigTagp signature tag
364 * @retval *pktp signature packet(s)
365 * @retval *pktlenp signature packet(s) length
366 * @param passPhrase private key pass phrase
367 * @return 0 on success, 1 on failure
369 static int makePGPSignature(const char * file, rpmSigTag * sigTagp,
370 uint8_t ** pktp, size_t * pktlenp,
371 const char * passPhrase)
373 char * sigfile = NULL;
382 pgpDigParams sigp = NULL;
384 int rc = 1; /* assume failure */
386 rasprintf(&sigfile, "%s.sig", file);
388 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
389 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
391 inpipe[0] = inpipe[1] = 0;
392 if (pipe(inpipe) < 0) {
393 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
397 if (!(pid = fork())) {
398 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
402 (void) dup2(inpipe[0], 3);
403 (void) close(inpipe[1]);
405 (void) setenv("PGPPASSFD", "3", 1);
406 if (pgp_path && *pgp_path != '\0')
407 (void) setenv("PGPPATH", pgp_path, 1);
409 /* setenv("PGPPASS", passPhrase, 1); */
411 unsetenv("MALLOC_CHECK_");
412 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
415 cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
416 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
418 rc = execve(av[0], av+1, environ);
421 cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
422 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
424 rc = execve(av[0], av+1, environ);
427 case PGP_NOTDETECTED:
432 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
437 delMacro(NULL, "__plaintext_filename");
438 delMacro(NULL, "__signature_filename");
440 fpipe = fdopen(inpipe[1], "w");
441 (void) close(inpipe[0]);
443 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
444 (void) fclose(fpipe);
447 (void)waitpid(pid, &status, 0);
448 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
449 rpmlog(RPMLOG_ERR, _("pgp failed\n"));
453 if (stat(sigfile, &st)) {
454 /* PGP failed to write signature */
455 if (sigfile) (void) unlink(sigfile); /* Just in case */
456 rpmlog(RPMLOG_ERR, _("pgp failed to write signature\n"));
460 *pktlenp = st.st_size;
461 rpmlog(RPMLOG_DEBUG, "PGP sig size: %zd\n", *pktlenp);
462 *pktp = xmalloc(*pktlenp);
467 fd = Fopen(sigfile, "r.fdio");
468 if (fd != NULL && !Ferror(fd)) {
469 rc = timedRead(fd, (void *)*pktp, *pktlenp);
470 if (sigfile) (void) unlink(sigfile);
473 if (rc != *pktlenp) {
474 *pktp = _free(*pktp);
475 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
480 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of PGP sig\n", *pktlenp);
484 /* Parse the signature, change signature tag as appropriate. */
487 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
488 sigp = &dig->signature;
490 dig = pgpFreeDig(dig);
500 * Generate GPG signature(s) for a header+payload file.
501 * @param file header+payload file name
502 * @retval *sigTagp signature tag
503 * @retval *pktp signature packet(s)
504 * @retval *pktlenp signature packet(s) length
505 * @param passPhrase private key pass phrase
506 * @return 0 on success, 1 on failure
508 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
509 uint8_t ** pktp, size_t * pktlenp,
510 const char * passPhrase)
512 char * sigfile = NULL;
520 pgpDigParams sigp = NULL;
521 int rc = 1; /* assume failure */
523 rasprintf(&sigfile, "%s.sig", file);
525 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
526 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
528 inpipe[0] = inpipe[1] = 0;
529 if (pipe(inpipe) < 0) {
530 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
534 if (!(pid = fork())) {
535 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
537 (void) dup2(inpipe[0], 3);
538 (void) close(inpipe[1]);
540 if (gpg_path && *gpg_path != '\0')
541 (void) setenv("GNUPGHOME", gpg_path, 1);
542 (void) setenv("LC_ALL", "C", 1);
544 unsetenv("MALLOC_CHECK_");
545 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
546 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
548 rc = execve(av[0], av+1, environ);
550 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
555 delMacro(NULL, "__plaintext_filename");
556 delMacro(NULL, "__signature_filename");
558 fpipe = fdopen(inpipe[1], "w");
559 (void) close(inpipe[0]);
561 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
562 (void) fclose(fpipe);
565 (void) waitpid(pid, &status, 0);
566 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
567 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
571 if (stat(sigfile, &st)) {
572 /* GPG failed to write signature */
573 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
577 *pktlenp = st.st_size;
578 rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
579 *pktp = xmalloc(*pktlenp);
584 fd = Fopen(sigfile, "r.fdio");
585 if (fd != NULL && !Ferror(fd)) {
586 rc = timedRead(fd, (void *)*pktp, *pktlenp);
589 if (rc != *pktlenp) {
590 *pktp = _free(*pktp);
591 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
596 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
598 /* Parse the signature, change signature tag as appropriate. */
601 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
602 sigp = &dig->signature;
606 case RPMSIGTAG_LONGSIZE:
611 /* XXX check MD5 hash too? */
612 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
613 *sigTagp = RPMSIGTAG_PGP;
615 case RPMSIGTAG_PGP5: /* XXX legacy */
617 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
618 *sigTagp = RPMSIGTAG_GPG;
621 /* XXX check MD5 hash too? */
622 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
623 *sigTagp = RPMSIGTAG_RSA;
626 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
627 *sigTagp = RPMSIGTAG_DSA;
630 case RPMSIGTAG_LEMD5_1:
631 case RPMSIGTAG_LEMD5_2:
632 case RPMSIGTAG_BADSHA1_1:
633 case RPMSIGTAG_BADSHA1_2:
634 case RPMSIGTAG_PAYLOADSIZE:
635 case RPMSIGTAG_LONGARCHIVESIZE:
639 dig = pgpFreeDig(dig);
643 (void) unlink(sigfile);
650 * Generate header only signature(s) from a header+payload file.
651 * @param sigh signature header
652 * @param file header+payload file name
653 * @param sigTag type of signature(s) to add
654 * @param passPhrase private key pass phrase
655 * @return 0 on success, -1 on failure
657 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
658 const char * passPhrase)
662 uint8_t * pkt = NULL;
666 int ret = -1; /* assume failure. */
670 case RPMSIGTAG_LONGSIZE:
672 case RPMSIGTAG_PGP5: /* XXX legacy */
678 fd = Fopen(file, "r.fdio");
679 if (fd == NULL || Ferror(fd))
681 h = headerRead(fd, HEADER_MAGIC_YES);
684 (void) Fclose(fd); fd = NULL;
686 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
690 if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, HEADERGET_DEFAULT)
694 _("Immutable header region could not be read. "
695 "Corrupted package?\n"));
699 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
700 (void) rpmDigestUpdate(ctx, header_magic, sizeof(header_magic));
701 (void) rpmDigestUpdate(ctx, utd.data, utd.count);
702 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
709 if (!sighdrPut(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
714 fd = Fopen(file, "r.fdio");
715 if (fd == NULL || Ferror(fd))
717 h = headerRead(fd, HEADER_MAGIC_YES);
721 fd = rpmMkTempFile(NULL, &fn);
722 if (fd == NULL || Ferror(fd))
724 if (headerWrite(fd, h, HEADER_MAGIC_YES))
726 (void) Fclose(fd); fd = NULL;
727 if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
728 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
733 fd = Fopen(file, "r.fdio");
734 if (fd == NULL || Ferror(fd))
736 h = headerRead(fd, HEADER_MAGIC_YES);
740 fd = rpmMkTempFile(NULL, &fn);
741 if (fd == NULL || Ferror(fd))
743 if (headerWrite(fd, h, HEADER_MAGIC_YES))
745 (void) Fclose(fd); fd = NULL;
746 if (makePGPSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
747 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
752 case RPMSIGTAG_LEMD5_1:
753 case RPMSIGTAG_LEMD5_2:
754 case RPMSIGTAG_BADSHA1_1:
755 case RPMSIGTAG_BADSHA1_2:
756 case RPMSIGTAG_PAYLOADSIZE:
757 case RPMSIGTAG_LONGARCHIVESIZE:
769 if (fd != NULL) (void) Fclose(fd);
773 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
774 const char * passPhrase)
777 uint8_t * pkt = NULL;
779 int ret = -1; /* assume failure. */
782 case RPMSIGTAG_SIZE: {
784 if (stat(file, &st) != 0)
787 if (!sighdrPut(sigh, sigTag, RPM_INT32_TYPE, &size, 1))
791 case RPMSIGTAG_LONGSIZE: {
793 if (stat(file, &st) != 0)
796 if (!sighdrPut(sigh, sigTag, RPM_INT64_TYPE, &size, 1))
802 pkt = xcalloc(pktlen, sizeof(*pkt));
803 if (rpmDoDigest(PGPHASHALGO_MD5, file, 0, pkt, NULL)
804 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
808 case RPMSIGTAG_PGP5: /* XXX legacy */
810 if (makePGPSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
811 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
813 #ifdef NOTYET /* XXX needs hdrmd5ctx, like hdrsha1ctx. */
814 /* XXX Piggyback a header-only RSA signature as well. */
815 ret = makeHDRSignature(sigh, file, RPMSIGTAG_RSA, passPhrase);
820 if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
821 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
823 /* XXX Piggyback a header-only DSA signature as well. */
824 ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
829 ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
832 case RPMSIGTAG_LEMD5_1:
833 case RPMSIGTAG_LEMD5_2:
834 case RPMSIGTAG_BADSHA1_1:
835 case RPMSIGTAG_BADSHA1_2:
836 case RPMSIGTAG_PAYLOADSIZE:
837 case RPMSIGTAG_LONGARCHIVESIZE:
845 static int checkPassPhrase(const char * passPhrase, const rpmSigTag sigTag)
847 int passPhrasePipe[2];
852 passPhrasePipe[0] = passPhrasePipe[1] = 0;
853 xx = pipe(passPhrasePipe);
854 if (!(pid = fork())) {
859 xx = close(STDIN_FILENO);
860 xx = close(STDOUT_FILENO);
861 xx = close(passPhrasePipe[1]);
862 if (! rpmIsVerbose())
863 xx = close(STDERR_FILENO);
864 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
865 xx = dup2(fdno, STDIN_FILENO);
868 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
869 xx = dup2(fdno, STDOUT_FILENO);
872 xx = dup2(passPhrasePipe[0], 3);
874 unsetenv("MALLOC_CHECK_");
878 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
880 if (gpg_path && *gpg_path != '\0')
881 (void) setenv("GNUPGHOME", gpg_path, 1);
883 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
884 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
886 rc = execve(av[0], av+1, environ);
888 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
892 case RPMSIGTAG_PGP5: /* XXX legacy */
894 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
898 (void) setenv("PGPPASSFD", "3", 1);
899 if (pgp_path && *pgp_path != '\0')
900 xx = setenv("PGPPATH", pgp_path, 1);
902 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
905 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
906 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
908 rc = execve(av[0], av+1, environ);
910 case PGP_5: /* XXX legacy */
911 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
912 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
914 rc = execve(av[0], av+1, environ);
917 case PGP_NOTDETECTED:
921 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
925 default: /* This case should have been screened out long ago. */
926 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
932 xx = close(passPhrasePipe[0]);
933 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
934 xx = write(passPhrasePipe[1], "\n", 1);
935 xx = close(passPhrasePipe[1]);
937 (void) waitpid(pid, &status, 0);
939 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
942 char * rpmGetPassPhrase(const char * prompt, const rpmSigTag sigTag)
950 { char *name = rpmExpand("%{?_gpg_name}", NULL);
951 aok = (name && *name != '\0');
957 _("You must set \"%%_gpg_name\" in your macro file\n"));
960 case RPMSIGTAG_PGP5: /* XXX legacy */
962 { char *name = rpmExpand("%{?_pgp_name}", NULL);
963 aok = (name && *name != '\0');
969 _("You must set \"%%_pgp_name\" in your macro file\n"));
972 /* Currently the calling function (rpm.c:main) is checking this and
973 * doing a better job. This section should never be accessed.
975 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
980 pass = getpass( (prompt ? prompt : "") );
982 if (checkPassPhrase(pass, sigTag))
989 static const char * rpmSigString(rpmRC res)
993 case RPMRC_OK: str = "OK"; break;
994 case RPMRC_FAIL: str = "BAD"; break;
995 case RPMRC_NOKEY: str = "NOKEY"; break;
996 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
998 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
1004 verifySizeSignature(const rpmts ts, rpmtd sigtd, char ** msg)
1006 pgpDig dig = rpmtsDig(ts);
1008 size_t size = 0x7fffffff;
1009 const char * title = _("Header+Payload size:");
1011 assert(msg != NULL);
1014 if (sigtd->data == NULL || dig == NULL || dig->nbytes == 0) {
1016 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1020 memcpy(&size, sigtd->data, sizeof(size));
1022 if (size != dig->nbytes) {
1024 rasprintf(msg, "%s %s Expected(%zd) != (%zd)\n", title,
1025 rpmSigString(res), size, dig->nbytes);
1028 rasprintf(msg, "%s %s (%zd)\n", title, rpmSigString(res), dig->nbytes);
1036 verifyMD5Signature(const rpmts ts, rpmtd sigtd, char ** msg,
1039 pgpDig dig = rpmtsDig(ts);
1041 uint8_t * md5sum = NULL;
1044 const char *title = _("MD5 digest:");
1046 assert(msg != NULL);
1049 if (md5ctx == NULL || sigtd->data == NULL || dig == NULL) {
1051 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1055 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1056 (void) rpmDigestFinal(rpmDigestDup(md5ctx),
1057 (void **)&md5sum, &md5len, 0);
1058 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1059 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1061 md5 = pgpHexStr(md5sum, md5len);
1062 if (md5len != sigtd->count || memcmp(md5sum, sigtd->data, md5len)) {
1064 char *hex = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL);
1065 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1066 rpmSigString(res), hex, md5);
1070 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5);
1075 md5sum = _free(md5sum);
1080 * Verify header immutable region SHA1 digest.
1081 * @param ts transaction set
1082 * @retval msg verbose success/failure text
1084 * @return RPMRC_OK on success
1087 verifySHA1Signature(const rpmts ts, rpmtd sigtd, char ** msg,
1090 pgpDig dig = rpmtsDig(ts);
1093 const char *title = _("Header SHA1 digest:");
1094 const char *sig = sigtd->data;
1096 assert(msg != NULL);
1099 if (sha1ctx == NULL || sigtd->data == NULL || dig == NULL) {
1101 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1105 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1106 (void) rpmDigestFinal(rpmDigestDup(sha1ctx),
1107 (void **)&SHA1, NULL, 1);
1108 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1110 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
1112 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1113 rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)");
1116 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1);
1125 * Verify RSA signature.
1126 * @param ts transaction set
1127 * @retval msg rbose success/failure text
1129 * @return RPMRC_OK on success
1132 verifyRSASignature(rpmts ts, rpmtd sigtd, char ** msg,
1135 pgpDig dig = rpmtsDig(ts);
1136 pgpDigParams sigp = rpmtsSignature(ts);
1138 rpmRC res = RPMRC_OK;
1141 const char *hdr, *signame = _("Unknown");;
1142 const char *sig = sigtd->data;
1145 assert(msg != NULL);
1148 hdr = (dig != NULL && dig->hdrmd5ctx == md5ctx) ? _("Header ") : "";
1149 sigver = sigp !=NULL ? sigp->version : 0;
1151 if (md5ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1157 /* Verify the desired signature match. */
1158 switch (sigp->pubkey_algo) {
1159 case PGPPUBKEYALGO_RSA:
1160 if (sigtd->tag == RPMSIGTAG_PGP || sigtd->tag == RPMSIGTAG_PGP5 || sigtd->tag == RPMSIGTAG_RSA)
1167 /* Verify the desired hash match. */
1168 /* XXX Values from PKCS#1 v2.1 (aka RFC-3447) */
1169 switch (sigp->hash_algo) {
1170 case PGPHASHALGO_MD5:
1171 signame = "RSA/MD5";
1172 sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1174 case PGPHASHALGO_SHA1:
1175 signame = "RSA/SHA1";
1176 sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1178 case PGPHASHALGO_MD2:
1179 signame = "RSA/MD2";
1180 sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1182 case PGPHASHALGO_SHA256:
1183 signame = "RSA/SHA256";
1184 sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1186 case PGPHASHALGO_SHA384:
1187 signame = "RSA/SHA384";
1188 sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1190 case PGPHASHALGO_SHA512:
1191 signame = "RSA/SHA512";
1192 sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1194 /* fallthrough for unsupported / unknown types */
1195 case PGPHASHALGO_TIGER192:
1196 case PGPHASHALGO_HAVAL_5_160:
1197 case PGPHASHALGO_RIPEMD160:
1200 sigalg = SEC_OID_UNKNOWN;
1204 if (res != RPMRC_OK) {
1208 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1209 { DIGEST_CTX ctx = rpmDigestDup(md5ctx);
1211 if (sigp->hash != NULL)
1212 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1214 #ifdef NOTYET /* XXX not for binary/text signatures as in packages. */
1215 if (!(sigp->sigtype == PGPSIGTYPE_BINARY || sigp->sigtype == PGP_SIGTYPE_TEXT)) {
1216 size_t nb = dig->nbytes + sigp->hashlen;
1221 memcpy(trailer+2, &nb, sizeof(nb));
1222 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1226 xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
1227 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1228 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1230 /* Compare leading 16 bits of digest for quick check. */
1231 if (memcmp(dig->md5, sigp->signhash16, 2)) {
1235 digest.type = siBuffer;
1236 digest.data = dig->md5;
1237 digest.len = dig->md5len;
1240 /* Retrieve the matching public key. */
1241 res = rpmtsFindPubkey(ts);
1242 if (res != RPMRC_OK)
1245 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1246 if (VFY_VerifyDigest(&digest, dig->rsa, dig->rsasig, sigalg, NULL) == SECSuccess)
1250 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1254 char *signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1255 rasprintf(msg, _("%sV%d %s signature: %s, key ID %s\n"),
1256 hdr, sigver, signame, rpmSigString(res), signid);
1259 rasprintf(msg, _("%sV%d %s signature: %s\n"),
1260 hdr, sigver, signame, rpmSigString(res));
1266 * Verify DSA signature.
1267 * @param ts transaction set
1268 * @retval t verbose success/failure text
1270 * @return RPMRC_OK on success
1273 verifyDSASignature(rpmts ts, rpmtd sigtd, char ** msg,
1276 pgpDig dig = rpmtsDig(ts);
1277 pgpDigParams sigp = rpmtsSignature(ts);
1283 const char *sig = sigtd->data;
1285 assert(msg != NULL);
1288 hdr = (dig != NULL && dig->hdrsha1ctx == sha1ctx) ? _("Header ") : "";
1289 sigver = sigp !=NULL ? sigp->version : 0;
1291 if (sha1ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1296 /* XXX sanity check on sigtag and signature agreement. */
1297 if (!((sigtd->tag == RPMSIGTAG_GPG || sigtd->tag == RPMSIGTAG_DSA)
1298 && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
1299 && sigp->hash_algo == PGPHASHALGO_SHA1))
1305 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1306 { DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
1308 if (sigp->hash != NULL)
1309 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1311 if (sigp->version == 4) {
1312 /* V4 trailer is six octets long (rfc4880) */
1314 uint32_t nb = sigp->hashlen;
1316 trailer[0] = sigp->version;
1318 memcpy(trailer+2, &nb, 4);
1319 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1321 xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
1322 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1323 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1325 /* Compare leading 16 bits of digest for quick check. */
1326 if (memcmp(dig->sha1, sigp->signhash16, 2)) {
1330 digest.type = siBuffer;
1331 digest.data = dig->sha1;
1332 digest.len = dig->sha1len;
1335 /* Retrieve the matching public key. */
1336 res = rpmtsFindPubkey(ts);
1337 if (res != RPMRC_OK)
1340 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1341 if (VFY_VerifyDigest(&digest, dig->dsa, dig->dsasig,
1342 SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
1346 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1350 char *signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1351 rasprintf(msg, _("%sV%d DSA signature: %s, key ID %s\n"),
1352 hdr, sigver, rpmSigString(res), signid);
1355 rasprintf(msg, _("%sV%d DSA signature: %s\n"),
1356 hdr, sigver, rpmSigString(res));
1362 rpmVerifySignature(const rpmts ts, char ** result)
1364 struct rpmtd_s sigtd;
1365 pgpDig dig = rpmtsDig(ts);
1369 sigtd.tag = rpmtsSigtag(ts);
1370 sigtd.type = rpmtsSigtype(ts);
1371 sigtd.data = (void *) rpmtsSig(ts);
1372 sigtd.count = rpmtsSiglen(ts);
1374 assert(result != NULL);
1376 if (sigtd.data == NULL || sigtd.count <= 0 || dig == NULL) {
1377 rasprintf(result, _("Verify signature: BAD PARAMETERS\n"));
1378 return RPMRC_NOTFOUND;
1381 switch (sigtd.tag) {
1382 case RPMSIGTAG_SIZE:
1383 res = verifySizeSignature(ts, &sigtd, result);
1386 res = verifyMD5Signature(ts, &sigtd, result, dig->md5ctx);
1388 case RPMSIGTAG_SHA1:
1389 res = verifySHA1Signature(ts, &sigtd, result, dig->hdrsha1ctx);
1392 res = verifyRSASignature(ts, &sigtd, result, dig->hdrmd5ctx);
1394 case RPMSIGTAG_PGP5: /* XXX legacy */
1396 res = verifyRSASignature(ts, &sigtd, result,
1397 ((dig->signature.hash_algo == PGPHASHALGO_MD5)
1398 ? dig->md5ctx : dig->sha1ctx));
1401 res = verifyDSASignature(ts, &sigtd, result, dig->hdrsha1ctx);
1404 res = verifyDSASignature(ts, &sigtd, result, dig->sha1ctx);
1406 case RPMSIGTAG_LEMD5_1:
1407 case RPMSIGTAG_LEMD5_2:
1408 rasprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
1409 res = RPMRC_NOTFOUND;
1412 rasprintf(result, _("Signature: UNKNOWN (%d)\n"), sigtd.tag);
1413 res = RPMRC_NOTFOUND;