2 * \file lib/signature.c
9 #include <rpm/rpmtag.h>
10 #include <rpm/rpmlib.h> /* XXX RPMSIGTAG* & related */
11 #include <rpm/rpmmacro.h> /* XXX for rpmGetPath() */
12 #include <rpm/rpmdb.h>
13 #include <rpm/rpmstring.h>
14 #include <rpm/rpmfileutil.h>
15 #include <rpm/rpmlog.h>
16 #include <rpm/rpmts.h>
18 #include "rpmio/digest.h"
19 #include "lib/misc.h" /* XXX for dosetenv() */
20 #include "lib/rpmlead.h"
21 #include "lib/signature.h"
22 #include "rpmdb/header_internal.h"
26 #if !defined(__GLIBC__) && !defined(__APPLE__)
27 char ** environ = NULL;
30 int rpmLookupSignatureType(int action)
32 static int disabled = 0;
36 case RPMLOOKUPSIG_DISABLE:
39 case RPMLOOKUPSIG_ENABLE:
41 case RPMLOOKUPSIG_QUERY:
44 { char *name = rpmExpand("%{?_signature}", NULL);
45 if (!(name && *name != '\0'))
47 else if (!rstrcasecmp(name, "none"))
49 else if (!rstrcasecmp(name, "pgp"))
51 else if (!rstrcasecmp(name, "pgp5")) /* XXX legacy */
53 else if (!rstrcasecmp(name, "gpg"))
56 rc = -1; /* Invalid %_signature spec in macro file */
63 /* rpmDetectPGPVersion() returns the absolute path to the "pgp" */
64 /* executable of the requested version, or NULL when none found. */
66 const char * rpmDetectPGPVersion(pgpVersion * pgpVer)
68 /* Actually this should support having more then one pgp version. */
69 /* At the moment only one version is possible since we only */
70 /* have one %_pgpbin and one %_pgp_path. */
72 static pgpVersion saved_pgp_version = PGP_UNKNOWN;
73 char *pgpbin = rpmGetPath("%{?_pgpbin}", NULL);
75 if (saved_pgp_version == PGP_UNKNOWN) {
79 if (!(pgpbin && pgpbin[0] != '\0')) {
80 pgpbin = _free(pgpbin);
81 saved_pgp_version = -1;
84 pgpvbin = (char *)alloca(strlen(pgpbin) + sizeof("v"));
85 (void)stpcpy(stpcpy(pgpvbin, pgpbin), "v");
87 if (stat(pgpvbin, &st) == 0)
88 saved_pgp_version = PGP_5;
89 else if (stat(pgpbin, &st) == 0)
90 saved_pgp_version = PGP_2;
92 saved_pgp_version = PGP_NOTDETECTED;
96 *pgpVer = saved_pgp_version;
101 * Print package size.
102 * @todo rpmio: use fdSize rather than fstat(2) to get file size.
103 * @param fd package file handle
104 * @param siglen signature header size
105 * @param pad signature padding
106 * @param datalen length of header+payload
107 * @return rpmRC return code
109 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, rpm_off_t datalen)
112 int fdno = Fileno(fd);
114 if (fstat(fdno, &st) < 0)
118 "Expected size: %12zd = lead(%d)+sigs(%zd)+pad(%zd)+data(%d)\n",
119 RPMLEAD_SIZE+siglen+pad+datalen,
120 RPMLEAD_SIZE, siglen, pad, datalen);
122 " Actual size: %12d\n", (int)st.st_size);
127 /* XXX sigh yet another duplicate.. */
128 static unsigned char const header_magic[8] = {
129 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
132 rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
142 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
143 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
144 unsigned char * dataStart;
145 unsigned char * dataEnd = NULL;
147 rpmRC rc = RPMRC_FAIL; /* assume failure */
154 if (sig_type != RPMSIGTYPE_HEADERSIG)
157 memset(block, 0, sizeof(block));
158 if ((xx = timedRead(fd, (void *)block, sizeof(block))) != sizeof(block)) {
159 rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"),
160 (int)sizeof(block), xx);
163 if (memcmp(block, header_magic, sizeof(header_magic))) {
164 rasprintf(&buf, _("sigh magic: BAD\n"));
167 il = ntohl(block[2]);
168 if (il < 0 || il > 32) {
170 _("sigh tags: BAD, no. of tags(%d) out of range\n"), il);
173 dl = ntohl(block[3]);
174 if (dl < 0 || dl > 8192) {
176 _("sigh data: BAD, no. of bytes(%d) out of range\n"), dl);
180 nb = (il * sizeof(struct entryInfo_s)) + dl;
181 ei = xmalloc(sizeof(il) + sizeof(dl) + nb);
184 pe = (entryInfo) &ei[2];
185 dataStart = (unsigned char *) (pe + il);
186 if ((xx = timedRead(fd, (void *)pe, nb)) != nb) {
188 _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
192 /* Check (and convert) the 1st tag element. */
193 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
195 rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
196 0, entry->info.tag, entry->info.type,
197 entry->info.offset, entry->info.count);
201 /* Is there an immutable header region tag? */
202 if (entry->info.tag == RPMTAG_HEADERSIGNATURES
203 && entry->info.type == RPM_BIN_TYPE
204 && entry->info.count == REGION_TAG_COUNT)
207 if (entry->info.offset >= dl) {
209 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
210 entry->info.tag, entry->info.type,
211 entry->info.offset, entry->info.count);
215 /* Is there an immutable header region tag trailer? */
216 dataEnd = dataStart + entry->info.offset;
217 (void) memcpy(info, dataEnd, REGION_TAG_COUNT);
218 /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
219 if (info->tag == htonl(RPMTAG_HEADERIMAGE)) {
220 rpmSigTag stag = htonl(RPMTAG_HEADERSIGNATURES);
222 memcpy(dataEnd, &stag, sizeof(stag));
224 dataEnd += REGION_TAG_COUNT;
226 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
228 !((entry->info.tag == RPMTAG_HEADERSIGNATURES || entry->info.tag == RPMTAG_HEADERIMAGE)
229 && entry->info.type == RPM_BIN_TYPE
230 && entry->info.count == REGION_TAG_COUNT))
233 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
234 entry->info.tag, entry->info.type,
235 entry->info.offset, entry->info.count);
238 memset(info, 0, sizeof(*info));
240 /* Is the no. of tags in the region less than the total no. of tags? */
241 ril = entry->info.offset/sizeof(*pe);
242 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
243 rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
248 /* Sanity check signature tags */
249 memset(info, 0, sizeof(*info));
250 for (i = 1; i < il; i++) {
251 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
254 _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
255 i, entry->info.tag, entry->info.type,
256 entry->info.offset, entry->info.count);
261 /* OK, blob looks sane, load the header. */
262 sigh = headerLoad(ei);
264 rasprintf(&buf, _("sigh load: BAD\n"));
267 sigh->flags |= HEADERFLAG_ALLOCATED;
269 { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
270 size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
272 rpm_off_t * archSize = NULL;
274 /* Position at beginning of header. */
275 if (pad && (trc = timedRead(fd, (void *)block, pad)) != pad) {
277 _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
281 /* Print package component sizes. */
282 if (headerGetEntry(sigh, RPMSIGTAG_SIZE, NULL,(rpm_data_t *)&archSize, NULL)) {
283 rc = printSize(fd, sigSize, pad, *archSize);
284 if (rc != RPMRC_OK) {
286 _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize);
293 if (sighp && sigh && rc == RPMRC_OK)
294 *sighp = headerLink(sigh);
295 sigh = headerFree(sigh);
306 int rpmWriteSignature(FD_t fd, Header sigh)
308 static uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
312 rc = headerWrite(fd, sigh, HEADER_MAGIC_YES);
316 sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
317 pad = (8 - (sigSize % 8)) % 8;
319 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
322 rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad);
326 Header rpmNewSignature(void)
328 Header sigh = headerNew();
332 Header rpmFreeSignature(Header sigh)
334 return headerFree(sigh);
338 * Generate PGP signature(s) for a header+payload file.
339 * @param file header+payload file name
340 * @retval *sigTagp signature tag
341 * @retval *pktp signature packet(s)
342 * @retval *pktlenp signature packet(s) length
343 * @param passPhrase private key pass phrase
344 * @return 0 on success, 1 on failure
346 static int makePGPSignature(const char * file, rpmSigTag * sigTagp,
347 uint8_t ** pktp, size_t * pktlenp,
348 const char * passPhrase)
350 char * sigfile = alloca(1024);
358 pgpDigParams sigp = NULL;
362 (void) stpcpy( stpcpy(sigfile, file), ".sig");
364 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
365 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
367 inpipe[0] = inpipe[1] = 0;
370 if (!(pid = fork())) {
371 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
375 (void) dup2(inpipe[0], 3);
376 (void) close(inpipe[1]);
378 (void) dosetenv("PGPPASSFD", "3", 1);
379 if (pgp_path && *pgp_path != '\0')
380 (void) dosetenv("PGPPATH", pgp_path, 1);
382 /* dosetenv("PGPPASS", passPhrase, 1); */
384 unsetenv("MALLOC_CHECK_");
385 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
388 cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
389 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
391 rc = execve(av[0], av+1, environ);
394 cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
395 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
397 rc = execve(av[0], av+1, environ);
400 case PGP_NOTDETECTED:
405 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
410 delMacro(NULL, "__plaintext_filename");
411 delMacro(NULL, "__signature_filename");
413 (void) close(inpipe[0]);
415 (void) write(inpipe[1], passPhrase, strlen(passPhrase));
416 (void) write(inpipe[1], "\n", 1);
417 (void) close(inpipe[1]);
419 (void)waitpid(pid, &status, 0);
420 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
421 rpmlog(RPMLOG_ERR, _("pgp failed\n"));
425 if (stat(sigfile, &st)) {
426 /* PGP failed to write signature */
427 if (sigfile) (void) unlink(sigfile); /* Just in case */
428 rpmlog(RPMLOG_ERR, _("pgp failed to write signature\n"));
432 *pktlenp = st.st_size;
433 rpmlog(RPMLOG_DEBUG, "PGP sig size: %zd\n", *pktlenp);
434 *pktp = xmalloc(*pktlenp);
439 fd = Fopen(sigfile, "r.fdio");
440 if (fd != NULL && !Ferror(fd)) {
441 rc = timedRead(fd, (void *)*pktp, *pktlenp);
442 if (sigfile) (void) unlink(sigfile);
445 if (rc != *pktlenp) {
446 *pktp = _free(*pktp);
447 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
452 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of PGP sig\n", *pktlenp);
455 /* Parse the signature, change signature tag as appropriate. */
458 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
459 sigp = &dig->signature;
461 dig = pgpFreeDig(dig);
468 * Generate GPG signature(s) for a header+payload file.
469 * @param file header+payload file name
470 * @retval *sigTagp signature tag
471 * @retval *pktp signature packet(s)
472 * @retval *pktlenp signature packet(s) length
473 * @param passPhrase private key pass phrase
474 * @return 0 on success, 1 on failure
476 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
477 uint8_t ** pktp, size_t * pktlenp,
478 const char * passPhrase)
480 char * sigfile = alloca(strlen(file)+sizeof(".sig"));
488 pgpDigParams sigp = NULL;
491 (void) stpcpy( stpcpy(sigfile, file), ".sig");
493 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
494 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
496 inpipe[0] = inpipe[1] = 0;
499 if (!(pid = fork())) {
500 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
502 (void) dup2(inpipe[0], 3);
503 (void) close(inpipe[1]);
505 if (gpg_path && *gpg_path != '\0')
506 (void) dosetenv("GNUPGHOME", gpg_path, 1);
507 (void) dosetenv("LC_ALL", "C", 1);
509 unsetenv("MALLOC_CHECK_");
510 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
511 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
513 rc = execve(av[0], av+1, environ);
515 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
520 delMacro(NULL, "__plaintext_filename");
521 delMacro(NULL, "__signature_filename");
523 fpipe = fdopen(inpipe[1], "w");
524 (void) close(inpipe[0]);
526 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
527 (void) fclose(fpipe);
530 (void) waitpid(pid, &status, 0);
531 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
532 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
536 if (stat(sigfile, &st)) {
537 /* GPG failed to write signature */
538 if (sigfile) (void) unlink(sigfile); /* Just in case */
539 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
543 *pktlenp = st.st_size;
544 rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
545 *pktp = xmalloc(*pktlenp);
550 fd = Fopen(sigfile, "r.fdio");
551 if (fd != NULL && !Ferror(fd)) {
552 rc = timedRead(fd, (void *)*pktp, *pktlenp);
553 if (sigfile) (void) unlink(sigfile);
556 if (rc != *pktlenp) {
557 *pktp = _free(*pktp);
558 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
563 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
565 /* Parse the signature, change signature tag as appropriate. */
568 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
569 sigp = &dig->signature;
577 /* XXX check MD5 hash too? */
578 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
579 *sigTagp = RPMSIGTAG_PGP;
581 case RPMSIGTAG_PGP5: /* XXX legacy */
583 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
584 *sigTagp = RPMSIGTAG_GPG;
587 /* XXX check MD5 hash too? */
588 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
589 *sigTagp = RPMSIGTAG_RSA;
592 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
593 *sigTagp = RPMSIGTAG_DSA;
596 case RPMSIGTAG_LEMD5_1:
597 case RPMSIGTAG_LEMD5_2:
598 case RPMSIGTAG_BADSHA1_1:
599 case RPMSIGTAG_BADSHA1_2:
600 case RPMSIGTAG_PAYLOADSIZE:
604 dig = pgpFreeDig(dig);
610 * Generate header only signature(s) from a header+payload file.
611 * @param sigh signature header
612 * @param file header+payload file name
613 * @param sigTag type of signature(s) to add
614 * @param passPhrase private key pass phrase
615 * @return 0 on success, -1 on failure
617 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
618 const char * passPhrase)
626 int ret = -1; /* assume failure. */
631 case RPMSIGTAG_PGP5: /* XXX legacy */
637 fd = Fopen(file, "r.fdio");
638 if (fd == NULL || Ferror(fd))
640 h = headerRead(fd, HEADER_MAGIC_YES);
643 (void) Fclose(fd); fd = NULL;
645 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
651 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)
657 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
658 (void) rpmDigestUpdate(ctx, header_magic, sizeof(header_magic));
659 (void) rpmDigestUpdate(ctx, uh, uhc);
660 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
661 uh = headerFreeData(uh, uht);
667 if (!headerAddEntry(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
672 fd = Fopen(file, "r.fdio");
673 if (fd == NULL || Ferror(fd))
675 h = headerRead(fd, HEADER_MAGIC_YES);
678 (void) Fclose(fd); fd = NULL;
679 if (rpmMkTempFile(NULL, &fn, &fd))
681 if (headerWrite(fd, h, HEADER_MAGIC_YES))
683 (void) Fclose(fd); fd = NULL;
684 if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
685 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
690 fd = Fopen(file, "r.fdio");
691 if (fd == NULL || Ferror(fd))
693 h = headerRead(fd, HEADER_MAGIC_YES);
696 (void) Fclose(fd); fd = NULL;
697 if (rpmMkTempFile(NULL, &fn, &fd))
699 if (headerWrite(fd, h, HEADER_MAGIC_YES))
701 (void) Fclose(fd); fd = NULL;
702 if (makePGPSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
703 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
708 case RPMSIGTAG_LEMD5_1:
709 case RPMSIGTAG_LEMD5_2:
710 case RPMSIGTAG_BADSHA1_1:
711 case RPMSIGTAG_BADSHA1_2:
712 case RPMSIGTAG_PAYLOADSIZE:
723 if (fd != NULL) (void) Fclose(fd);
727 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
728 const char * passPhrase)
733 int ret = -1; /* assume failure. */
737 if (stat(file, &st) != 0)
740 if (!headerAddEntry(sigh, sigTag, RPM_INT32_TYPE, &pktlen, 1))
746 pkt = memset(alloca(pktlen), 0, pktlen);
747 if (rpmDoDigest(PGPHASHALGO_MD5, file, 0, pkt, NULL)
748 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
752 case RPMSIGTAG_PGP5: /* XXX legacy */
754 if (makePGPSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
755 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
757 #ifdef NOTYET /* XXX needs hdrmd5ctx, like hdrsha1ctx. */
758 /* XXX Piggyback a header-only RSA signature as well. */
759 ret = makeHDRSignature(sigh, file, RPMSIGTAG_RSA, passPhrase);
764 if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
765 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
767 /* XXX Piggyback a header-only DSA signature as well. */
768 ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
773 ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
776 case RPMSIGTAG_LEMD5_1:
777 case RPMSIGTAG_LEMD5_2:
778 case RPMSIGTAG_BADSHA1_1:
779 case RPMSIGTAG_BADSHA1_2:
780 case RPMSIGTAG_PAYLOADSIZE:
787 static int checkPassPhrase(const char * passPhrase, const rpmSigTag sigTag)
789 int passPhrasePipe[2];
794 passPhrasePipe[0] = passPhrasePipe[1] = 0;
795 xx = pipe(passPhrasePipe);
796 if (!(pid = fork())) {
801 xx = close(STDIN_FILENO);
802 xx = close(STDOUT_FILENO);
803 xx = close(passPhrasePipe[1]);
804 if (! rpmIsVerbose())
805 xx = close(STDERR_FILENO);
806 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
807 xx = dup2(fdno, STDIN_FILENO);
810 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
811 xx = dup2(fdno, STDOUT_FILENO);
814 xx = dup2(passPhrasePipe[0], 3);
816 unsetenv("MALLOC_CHECK_");
820 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
822 if (gpg_path && *gpg_path != '\0')
823 (void) dosetenv("GNUPGHOME", gpg_path, 1);
825 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
826 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
828 rc = execve(av[0], av+1, environ);
830 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
834 case RPMSIGTAG_PGP5: /* XXX legacy */
836 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
840 (void) dosetenv("PGPPASSFD", "3", 1);
841 if (pgp_path && *pgp_path != '\0')
842 xx = dosetenv("PGPPATH", pgp_path, 1);
844 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
847 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
848 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
850 rc = execve(av[0], av+1, environ);
852 case PGP_5: /* XXX legacy */
853 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
854 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
856 rc = execve(av[0], av+1, environ);
859 case PGP_NOTDETECTED:
863 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
867 default: /* This case should have been screened out long ago. */
868 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
874 xx = close(passPhrasePipe[0]);
875 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
876 xx = write(passPhrasePipe[1], "\n", 1);
877 xx = close(passPhrasePipe[1]);
879 (void) waitpid(pid, &status, 0);
881 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
884 char * rpmGetPassPhrase(const char * prompt, const rpmSigTag sigTag)
892 { char *name = rpmExpand("%{?_gpg_name}", NULL);
893 aok = (name && *name != '\0');
899 _("You must set \"%%_gpg_name\" in your macro file\n"));
902 case RPMSIGTAG_PGP5: /* XXX legacy */
904 { char *name = rpmExpand("%{?_pgp_name}", NULL);
905 aok = (name && *name != '\0');
911 _("You must set \"%%_pgp_name\" in your macro file\n"));
914 /* Currently the calling function (rpm.c:main) is checking this and
915 * doing a better job. This section should never be accessed.
917 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
922 pass = getpass( (prompt ? prompt : "") );
924 if (checkPassPhrase(pass, sigTag))
931 static const char * rpmSigString(rpmRC res)
935 case RPMRC_OK: str = "OK"; break;
936 case RPMRC_FAIL: str = "BAD"; break;
937 case RPMRC_NOKEY: str = "NOKEY"; break;
938 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
940 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
946 verifySizeSignature(const rpmts ts, char ** msg)
948 rpm_constdata_t sig = rpmtsSig(ts);
949 pgpDig dig = rpmtsDig(ts);
951 size_t size = 0x7fffffff;
952 const char * title = _("Header+Payload size:");
957 if (sig == NULL || dig == NULL || dig->nbytes == 0) {
959 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
963 memcpy(&size, sig, sizeof(size));
965 if (size != dig->nbytes) {
967 rasprintf(msg, "%s %s Expected(%zd) != (%zd)\n", title,
968 rpmSigString(res), size, dig->nbytes);
971 rasprintf(msg, "%s %s (%zd)\n", title, rpmSigString(res), dig->nbytes);
979 verifyMD5Signature(const rpmts ts, char ** msg,
982 rpm_constdata_t sig = rpmtsSig(ts);
983 size_t siglen = rpmtsSiglen(ts);
984 pgpDig dig = rpmtsDig(ts);
986 uint8_t * md5sum = NULL;
989 const char *title = _("MD5 digest:");
994 if (md5ctx == NULL || sig == NULL || dig == NULL) {
996 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1000 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1001 (void) rpmDigestFinal(rpmDigestDup(md5ctx),
1002 (void **)&md5sum, &md5len, 0);
1003 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1004 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1006 md5 = pgpHexStr(md5sum, md5len);
1007 if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
1009 char *hex = pgpHexStr(sig, siglen);
1010 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1011 rpmSigString(res), hex, md5);
1015 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5);
1020 md5sum = _free(md5sum);
1025 * Verify header immutable region SHA1 digest.
1026 * @param ts transaction set
1027 * @retval msg verbose success/failure text
1029 * @return RPMRC_OK on success
1032 verifySHA1Signature(const rpmts ts, char ** msg,
1035 const char *sig = rpmtsSig(ts);
1037 size_t siglen = rpmtsSiglen(ts);
1039 pgpDig dig = rpmtsDig(ts);
1042 const char *title = _("Header SHA1 digest:");
1044 assert(msg != NULL);
1047 if (sha1ctx == NULL || sig == NULL || dig == NULL) {
1049 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1053 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1054 (void) rpmDigestFinal(rpmDigestDup(sha1ctx),
1055 (void **)&SHA1, NULL, 1);
1056 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1058 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
1060 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1061 rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)");
1064 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1);
1073 * Verify RSA signature.
1074 * @param ts transaction set
1075 * @retval msg rbose success/failure text
1077 * @return RPMRC_OK on success
1080 verifyRSASignature(rpmts ts, char ** msg,
1083 rpm_constdata_t sig = rpmtsSig(ts);
1085 size_t siglen = rpmtsSiglen(ts);
1087 rpmSigTag sigtag = rpmtsSigtag(ts);
1088 pgpDig dig = rpmtsDig(ts);
1089 pgpDigParams sigp = rpmtsSignature(ts);
1091 rpmRC res = RPMRC_OK;
1096 *msg = xmalloc(BUFSIZ); /* XXX FIXME, calculate string size instead */
1099 if (dig != NULL && dig->hdrmd5ctx == md5ctx)
1100 t = stpcpy(t, _("Header "));
1102 switch (sigp->version) {
1103 case 3: *t++ = '3'; break;
1104 case 4: *t++ = '4'; break;
1107 if (md5ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1111 /* Verify the desired signature match. */
1112 switch (sigp->pubkey_algo) {
1113 case PGPPUBKEYALGO_RSA:
1114 if (sigtag == RPMSIGTAG_PGP || sigtag == RPMSIGTAG_PGP5 || sigtag == RPMSIGTAG_RSA)
1121 /* Verify the desired hash match. */
1122 /* XXX Values from PKCS#1 v2.1 (aka RFC-3447) */
1123 switch (sigp->hash_algo) {
1124 case PGPHASHALGO_MD5:
1125 t = stpcpy(t, " RSA/MD5");
1126 sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1128 case PGPHASHALGO_SHA1:
1129 t = stpcpy(t, " RSA/SHA1");
1130 sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1132 case PGPHASHALGO_RIPEMD160:
1135 case PGPHASHALGO_MD2:
1136 t = stpcpy(t, " RSA/MD2");
1137 sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1139 case PGPHASHALGO_TIGER192:
1142 case PGPHASHALGO_HAVAL_5_160:
1145 case PGPHASHALGO_SHA256:
1146 t = stpcpy(t, " RSA/SHA256");
1147 sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1149 case PGPHASHALGO_SHA384:
1150 t = stpcpy(t, " RSA/SHA384");
1151 sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1153 case PGPHASHALGO_SHA512:
1154 t = stpcpy(t, " RSA/SHA512");
1155 sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1159 sigalg = SEC_OID_UNKNOWN;
1163 t = stpcpy(t, _(" signature: "));
1164 if (res != RPMRC_OK) {
1168 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1169 { DIGEST_CTX ctx = rpmDigestDup(md5ctx);
1171 if (sigp->hash != NULL)
1172 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1174 #ifdef NOTYET /* XXX not for binary/text signatures as in packages. */
1175 if (!(sigp->sigtype == PGPSIGTYPE_BINARY || sigp->sigtype == PGP_SIGTYPE_TEXT)) {
1176 size_t nb = dig->nbytes + sigp->hashlen;
1181 memcpy(trailer+2, &nb, sizeof(nb));
1182 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1186 xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
1187 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1188 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1190 /* Compare leading 16 bits of digest for quick check. */
1191 if (memcmp(dig->md5, sigp->signhash16, 2)) {
1195 digest.type = siBuffer;
1196 digest.data = dig->md5;
1197 digest.len = dig->md5len;
1200 /* Retrieve the matching public key. */
1201 res = rpmtsFindPubkey(ts);
1202 if (res != RPMRC_OK)
1205 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1206 if (VFY_VerifyDigest(&digest, dig->rsa, dig->rsasig, sigalg, NULL) == SECSuccess)
1210 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1213 t = stpcpy(t, rpmSigString(res));
1215 char * signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1216 t = stpcpy(t, ", key ID ");
1217 t = stpcpy(t, signid);
1220 t = stpcpy(t, "\n");
1225 * Verify DSA signature.
1226 * @param ts transaction set
1227 * @retval t verbose success/failure text
1229 * @return RPMRC_OK on success
1232 verifyDSASignature(rpmts ts, char ** msg,
1235 rpm_constdata_t sig = rpmtsSig(ts);
1237 size_t siglen = rpmtsSiglen(ts);
1239 rpmSigTag sigtag = rpmtsSigtag(ts);
1240 pgpDig dig = rpmtsDig(ts);
1241 pgpDigParams sigp = rpmtsSignature(ts);
1248 hdr = (dig != NULL && dig->hdrsha1ctx == sha1ctx) ? _("Header ") : "";
1249 sigver = sigp !=NULL ? sigp->version : 0;
1251 if (sha1ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1256 /* XXX sanity check on sigtag and signature agreement. */
1257 if (!((sigtag == RPMSIGTAG_GPG || sigtag == RPMSIGTAG_DSA)
1258 && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
1259 && sigp->hash_algo == PGPHASHALGO_SHA1))
1265 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1266 { DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
1268 if (sigp->hash != NULL)
1269 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1271 if (sigp->version == 4) {
1272 size_t nb = sigp->hashlen;
1275 trailer[0] = sigp->version;
1277 memcpy(trailer+2, &nb, sizeof(nb));
1278 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1280 xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
1281 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1282 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1284 /* Compare leading 16 bits of digest for quick check. */
1285 if (memcmp(dig->sha1, sigp->signhash16, 2)) {
1289 digest.type = siBuffer;
1290 digest.data = dig->sha1;
1291 digest.len = dig->sha1len;
1294 /* Retrieve the matching public key. */
1295 res = rpmtsFindPubkey(ts);
1296 if (res != RPMRC_OK)
1299 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1300 if (VFY_VerifyDigest(&digest, dig->dsa, dig->dsasig,
1301 SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
1305 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1309 char *signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1310 rasprintf(msg, _("%sV%d DSA signature: %s, key ID %s\n"),
1311 hdr, sigver, rpmSigString(res), signid);
1314 rasprintf(msg, _("%sV%d DSA signature: %s\n"),
1315 hdr, sigver, rpmSigString(res));
1322 rpmVerifySignature(const rpmts ts, char ** result)
1324 rpm_constdata_t sig = rpmtsSig(ts);
1325 size_t siglen = rpmtsSiglen(ts);
1326 rpmSigTag sigtag = rpmtsSigtag(ts);
1327 pgpDig dig = rpmtsDig(ts);
1330 assert(result != NULL);
1332 if (sig == NULL || siglen <= 0 || dig == NULL) {
1333 rasprintf(result, _("Verify signature: BAD PARAMETERS\n"));
1334 return RPMRC_NOTFOUND;
1338 case RPMSIGTAG_SIZE:
1339 res = verifySizeSignature(ts, result);
1342 res = verifyMD5Signature(ts, result, dig->md5ctx);
1344 case RPMSIGTAG_SHA1:
1345 res = verifySHA1Signature(ts, result, dig->hdrsha1ctx);
1348 res = verifyRSASignature(ts, result, dig->hdrmd5ctx);
1350 case RPMSIGTAG_PGP5: /* XXX legacy */
1352 res = verifyRSASignature(ts, result,
1353 ((dig->signature.hash_algo == PGPHASHALGO_MD5)
1354 ? dig->md5ctx : dig->sha1ctx));
1357 res = verifyDSASignature(ts, result, dig->hdrsha1ctx);
1360 res = verifyDSASignature(ts, result, dig->sha1ctx);
1362 case RPMSIGTAG_LEMD5_1:
1363 case RPMSIGTAG_LEMD5_2:
1364 rasprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
1365 res = RPMRC_NOTFOUND;
1368 rasprintf(result, _("Signature: UNKNOWN (%d)\n"), sigtag);
1369 res = RPMRC_NOTFOUND;